Mercurial > vim
changeset 2228:f5bd6753cdc4 vim73
updated for version 7.2.440
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)
author | Bram Moolenaar <bram@vim.org> |
---|---|
date | Fri, 28 May 2010 22:06:46 +0200 |
parents | 9c510840e896 |
children | d45902a5c61c |
files | src/eval.c src/testdir/test34.in src/testdir/test34.ok |
diffstat | 3 files changed, 18 insertions(+), 8 deletions(-) [+] |
line wrap: on
line diff
--- a/src/eval.c +++ b/src/eval.c @@ -464,7 +464,7 @@ static int get_env_tv __ARGS((char_u **a 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, first * 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, ar 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, ar } } - name[len] = cc; if (fname != name && fname != fname_buf) vim_free(fname); + vim_free(name); return ret; }
--- a/src/testdir/test34.in +++ b/src/testdir/test34.in @@ -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=Table("xxx", 4, "asdf") =retval =Compute(45, 5, "retval") =retval + =g:FuncRef(333) XX+-XX ---*---