]> granicus.if.org Git - vim/commitdiff
patch 8.0.1647: terminal API may call any user function v8.0.1647
authorBram Moolenaar <Bram@vim.org>
Mon, 26 Mar 2018 19:38:52 +0000 (21:38 +0200)
committerBram Moolenaar <Bram@vim.org>
Mon, 26 Mar 2018 19:38:52 +0000 (21:38 +0200)
Problem:    Terminal API may call a function not meant to be called by this
            API.
Solution:   Require the function to start with Tapi_.

runtime/doc/terminal.txt
src/terminal.c
src/testdir/test_terminal.vim
src/version.c

index 0c47fb637239aec3945a07e0736364ec15135f27..53dd946b1e89d809b6bd0ef3371b7decf42b1aa2 100644 (file)
@@ -423,20 +423,26 @@ Currently supported commands:
 
        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.
+               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", "Impression", ["play", 14]]
+                       ["call", "Tapi_Impression", ["play", 14]]
 <              Calls a function defined like this: >
-                       function Impression(bufnum, arglist)
+                       function Tapi_Impression(bufnum, arglist)
                          if len(a:arglist) == 2
-                           echo "impression " . a:arglist[0]
-                           echo "count " . a:arglist[1]
+                           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,7 +453,7 @@ Currently supported commands:
 
 A trick to have Vim send this escape sequence: >
        exe "set t_ts=\<Esc>]51; t_fs=\x07"
-       let &titlestring = '["call","TryThis",["hello",123]]'
+       let &titlestring = '["call","Tapi_TryThis",["hello",123]]'
        redraw
        set t_ts& t_fs&
 
index 50e87c9e450e74ad70dcdeed4b8a31cc0d1f3b0d..5875af6e68a791810a7bb392cc1bb30b251abfcf 100644 (file)
@@ -3193,7 +3193,7 @@ handle_call_command(term_T *term, channel_T *channel, listitem_T *item)
     }
     func = get_tv_string(&item->li_tv);
 
-    if (!ASCII_ISUPPER(*func))
+    if (STRNCMP(func, "Tapi_", 5) != 0)
     {
        ch_log(channel, "Invalid function name: %s", func);
        return;
index ff5056832132f4d3213d48d42e93c070882f299d..892da50d13441fe7bb177dfb133d3dbfe019ec43 100644 (file)
@@ -1072,24 +1072,28 @@ func Test_terminal_api_drop_oldwin()
   bwipe Xtextfile
 endfunc
 
-func TryThis(bufnum, arg)
+func Tapi_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
-
+func WriteApiCall(funcname)
   " Use the title termcap entries to output the escape sequence.
   call writefile([
        \ 'set title',
        \ 'exe "set t_ts=\<Esc>]51; t_fs=\x07"',
-       \ 'let &titlestring = ''["call","TryThis",["hello",123]]''',
+       \ '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,3 +1104,19 @@ func Test_terminal_api_call()
   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
index 14bf136adabaf769d439e0993d2052584a7095ed..df56277e7e1e09d967a70d8e09e6d141e542db51 100644 (file)
@@ -766,6 +766,8 @@ static char *(features[]) =
 
 static int included_patches[] =
 {   /* Add new patch number below this line */
+/**/
+    1647,
 /**/
     1646,
 /**/