# HG changeset patch # User Bram Moolenaar # Date 1275077206 -7200 # Node ID cd6e6876308e4e0fb621431646ebeec4b49a2504 # Parent ea7c2d89b76bf42eb0da3459e8813104d76bca02 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) diff --git a/src/eval.c b/src/eval.c --- 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)); @@ -7997,9 +7997,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" */ @@ -8023,18 +8023,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 name() and s:name() to K_SNR 123_name(). * Change 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) { @@ -8205,9 +8209,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; } diff --git a/src/testdir/test34.in b/src/testdir/test34.in --- 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 ( ListItem() :inoremap [ ListReset() @@ -47,6 +52,7 @@ C=Table("xxx", 4, "asdf") =retval =Compute(45, 5, "retval") =retval + =g:FuncRef(333) XX+-XX ---*--- diff --git a/src/testdir/test34.ok b/src/testdir/test34.ok --- a/src/testdir/test34.ok +++ b/src/testdir/test34.ok @@ -1,4 +1,4 @@ -xxx4asdf fail nop ok 9 +xxx4asdf fail nop ok 9 333 XX111XX ---222--- 1. one diff --git a/src/version.c b/src/version.c --- a/src/version.c +++ b/src/version.c @@ -682,6 +682,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ /**/ + 440, +/**/ 439, /**/ 438,