]> granicus.if.org Git - vim/commitdiff
updated for version 7.2.440
authorBram Moolenaar <Bram@vim.org>
Fri, 28 May 2010 20:06:46 +0000 (22:06 +0200)
committerBram Moolenaar <Bram@vim.org>
Fri, 28 May 2010 20:06:46 +0000 (22:06 +0200)
Problem:    Calling a function through a funcref, where the function deletes
            the funcref, leads to an invalid memory access.
Solution:   Make a copy of the function name. (Lech Lorens)

src/eval.c
src/testdir/test34.in
src/testdir/test34.ok

index 3c238fcbec50b7b59148da3609197905970247d0..06615ae9063a7cfe53b26165cb1c36a6b0f91908 100644 (file)
@@ -464,7 +464,7 @@ static int get_env_tv __ARGS((char_u **arg, typval_T *rettv, int evaluate));
 static int find_internal_func __ARGS((char_u *name));
 static char_u *deref_func_name __ARGS((char_u *name, int *lenp));
 static int get_func_tv __ARGS((char_u *name, int len, typval_T *rettv, char_u **arg, linenr_T firstline, linenr_T lastline, int *doesrange, int evaluate, dict_T *selfdict));
-static int call_func __ARGS((char_u *name, int len, typval_T *rettv, int argcount, typval_T *argvars, linenr_T firstline, linenr_T lastline, int *doesrange, int evaluate, dict_T *selfdict));
+static int call_func __ARGS((char_u *func_name, int len, typval_T *rettv, int argcount, typval_T *argvars, linenr_T firstline, linenr_T lastline, int *doesrange, int evaluate, dict_T *selfdict));
 static void emsg_funcname __ARGS((char *ermsg, char_u *name));
 static int non_zero_arg __ARGS((typval_T *argvars));
 
@@ -8029,9 +8029,9 @@ get_func_tv(name, len, rettv, arg, firstline, lastline, doesrange,
  * Also returns OK when an error was encountered while executing the function.
  */
     static int
-call_func(name, len, rettv, argcount, argvars, firstline, lastline,
+call_func(func_name, len, rettv, argcount, argvars, firstline, lastline,
                                                doesrange, evaluate, selfdict)
-    char_u     *name;          /* name of the function */
+    char_u     *func_name;     /* name of the function */
     int                len;            /* length of "name" */
     typval_T   *rettv;         /* return value goes here */
     int                argcount;       /* number of "argvars" */
@@ -8055,18 +8055,22 @@ call_func(name, len, rettv, argcount, argvars, firstline, lastline,
     int                i;
     int                llen;
     ufunc_T    *fp;
-    int                cc;
 #define FLEN_FIXED 40
     char_u     fname_buf[FLEN_FIXED + 1];
     char_u     *fname;
+    char_u     *name;
+
+    /* Make a copy of the name, if it comes from a funcref variable it could
+     * be changed or deleted in the called function. */
+    name = vim_strnsave(func_name, len);
+    if (name == NULL)
+       return ret;
 
     /*
      * In a script change <SID>name() and s:name() to K_SNR 123_name().
      * Change <SNR>123_name() to K_SNR 123_name().
      * Use fname_buf[] when it fits, otherwise allocate memory (slow).
      */
-    cc = name[len];
-    name[len] = NUL;
     llen = eval_fname_script(name);
     if (llen > 0)
     {
@@ -8237,9 +8241,9 @@ call_func(name, len, rettv, argcount, argvars, firstline, lastline,
        }
     }
 
-    name[len] = cc;
     if (fname != name && fname != fname_buf)
        vim_free(fname);
+    vim_free(name);
 
     return ret;
 }
index 5eef7150066eb8eb7b4091c586ff78b27e0d0ff2..28fd00c4b95ecbf393696d5ea6e9417c1deaaa7b 100644 (file)
@@ -35,6 +35,11 @@ STARTTEST
 :  let g:counter = 0
 :  return ''
 :endfunc
+:func FuncWithRef(a)
+:  unlet g:FuncRef
+:  return a:a
+:endfunc
+:let g:FuncRef=function("FuncWithRef")
 :let counter = 0
 :inoremap <expr> ( ListItem()
 :inoremap <expr> [ ListReset()
@@ -47,6 +52,7 @@ C\12=Table("xxx", 4, "asdf")
  \12=retval
  \12=Compute(45, 5, "retval")
  \12=retval
\12=g:FuncRef(333)
 
 XX+-XX
 ---*---
index 368ae10efd96c8a4ea5a0c55fc126c54829cea17..951dd8bc69ea839782810b55365fa6150c2c941b 100644 (file)
@@ -1,4 +1,4 @@
-xxx4asdf fail nop ok 9
+xxx4asdf fail nop ok 9 333
 XX111XX
 ---222---
 1. one