To: vim_dev@googlegroups.com Subject: Patch 8.0.1647 Fcc: outbox From: Bram Moolenaar Mime-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ------------ Patch 8.0.1647 Problem: Terminal API may call a function not meant to be called by this API. Solution: Require the function to start with Tapi_. Files: runtime/doc/terminal.txt, src/terminal.c, src/testdir/test_terminal.vim *** ../vim-8.0.1646/runtime/doc/terminal.txt 2018-03-25 18:19:47.221066088 +0200 --- runtime/doc/terminal.txt 2018-03-26 21:25:31.372777477 +0200 *************** *** 423,442 **** call {funcname} {argument} ! Call a user defined function with [argument]. The function is ! called with the buffer number of the terminal and the decoded ! argument. The user function must sanity check the argument. The function can use |term_sendkeys()| to send back a reply. Example in JSON: > ! ["call", "Impression", ["play", 14]] < Calls a function defined like this: > ! function Impression(bufnum, arglist) if len(a:arglist) == 2 ! echo "impression " . a:arglist[0] ! echo "count " . a:arglist[1] endif endfunc ! < drop {filename} Let Vim open a file, like the `:drop` command. If {filename} --- 423,448 ---- call {funcname} {argument} ! Call a user defined function with {argument}. ! The function is called with two arguments: the buffer number ! of the terminal and {argument}, the decoded JSON argument. ! The function name must start with "Tapi_" to avoid ! accidentally calling a function not meant to be used for the ! terminal API ! The user function should sanity check the argument. The function can use |term_sendkeys()| to send back a reply. Example in JSON: > ! ["call", "Tapi_Impression", ["play", 14]] < Calls a function defined like this: > ! function Tapi_Impression(bufnum, arglist) if len(a:arglist) == 2 ! echomsg "impression " . a:arglist[0] ! echomsg "count " . a:arglist[1] endif endfunc ! < Output from `:echo` may be erased by a redraw, use `:echomsg` ! to be able to see it with `:messages`. ! drop {filename} Let Vim open a file, like the `:drop` command. If {filename} *************** *** 447,453 **** A trick to have Vim send this escape sequence: > exe "set t_ts=\]51; t_fs=\x07" ! let &titlestring = '["call","TryThis",["hello",123]]' redraw set t_ts& t_fs& --- 453,459 ---- A trick to have Vim send this escape sequence: > exe "set t_ts=\]51; t_fs=\x07" ! let &titlestring = '["call","Tapi_TryThis",["hello",123]]' redraw set t_ts& t_fs& *** ../vim-8.0.1646/src/terminal.c 2018-03-25 18:19:47.217066110 +0200 --- src/terminal.c 2018-03-26 21:27:30.720061009 +0200 *************** *** 3193,3199 **** } func = get_tv_string(&item->li_tv); ! if (!ASCII_ISUPPER(*func)) { ch_log(channel, "Invalid function name: %s", func); return; --- 3193,3199 ---- } func = get_tv_string(&item->li_tv); ! if (STRNCMP(func, "Tapi_", 5) != 0) { ch_log(channel, "Invalid function name: %s", func); return; *** ../vim-8.0.1646/src/testdir/test_terminal.vim 2018-03-25 21:24:06.281680744 +0200 --- src/testdir/test_terminal.vim 2018-03-26 21:35:46.737323757 +0200 *************** *** 1072,1095 **** bwipe Xtextfile endfunc ! func TryThis(bufnum, arg) let g:called_bufnum = a:bufnum let g:called_arg = a:arg endfunc ! func Test_terminal_api_call() ! if !CanRunVimInTerminal() ! return ! endif ! " Use the title termcap entries to output the escape sequence. call writefile([ \ 'set title', \ 'exe "set t_ts=\]51; t_fs=\x07"', ! \ 'let &titlestring = ''["call","TryThis",["hello",123]]''', \ 'redraw', \ "set t_ts=", \ ], 'Xscript') let buf = RunVimInTerminal('-S Xscript', {}) call WaitFor({-> exists('g:called_bufnum')}) call assert_equal(buf, g:called_bufnum) --- 1072,1099 ---- bwipe Xtextfile endfunc ! func Tapi_TryThis(bufnum, arg) let g:called_bufnum = a:bufnum let g:called_arg = a:arg endfunc ! func WriteApiCall(funcname) " Use the title termcap entries to output the escape sequence. call writefile([ \ 'set title', \ 'exe "set t_ts=\]51; t_fs=\x07"', ! \ 'let &titlestring = ''["call","' . a:funcname . '",["hello",123]]''', \ 'redraw', \ "set t_ts=", \ ], 'Xscript') + endfunc + + func Test_terminal_api_call() + if !CanRunVimInTerminal() + return + endif + + call WriteApiCall('Tapi_TryThis') let buf = RunVimInTerminal('-S Xscript', {}) call WaitFor({-> exists('g:called_bufnum')}) call assert_equal(buf, g:called_bufnum) *************** *** 1100,1102 **** --- 1104,1122 ---- unlet g:called_bufnum unlet g:called_arg endfunc + + func Test_terminal_api_call_fails() + if !CanRunVimInTerminal() + return + endif + + call WriteApiCall('TryThis') + call ch_logfile('Xlog', 'w') + let buf = RunVimInTerminal('-S Xscript', {}) + call WaitFor({-> string(readfile('Xlog')) =~ 'Invalid function name: TryThis'}) + + call StopVimInTerminal(buf) + call delete('Xscript') + call ch_logfile('', '') + call delete('Xlog') + endfunc *** ../vim-8.0.1646/src/version.c 2018-03-26 20:55:04.472369451 +0200 --- src/version.c 2018-03-26 21:26:41.172358325 +0200 *************** *** 768,769 **** --- 768,771 ---- { /* Add new patch number below this line */ + /**/ + 1647, /**/ -- I got a new desk stapler. It broke on the first desk I tried. /// Bram Moolenaar -- Bram@Moolenaar.net -- http://www.Moolenaar.net \\\ /// sponsor Vim, vote for features -- http://www.Vim.org/sponsor/ \\\ \\\ an exciting new programming language -- http://www.Zimbu.org /// \\\ help me help AIDS victims -- http://ICCF-Holland.org ///