summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBram Moolenaar <bram@vim.org>2010-05-28 22:06:46 +0200
committerBram Moolenaar <bram@vim.org>2010-05-28 22:06:46 +0200
commit1bed7a6892c79088c43113693dcac2bff613fb75 (patch)
tree49a1852345a68f39c1bf77a2f8318db4c4cd3f0b
parent20bdb6c898f35a496e74dbb5d9c6aaa7dda645c2 (diff)
downloadvim-1bed7a6892c79088c43113693dcac2bff613fb75.tar.gz
updated for version 7.2.440v7.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)
-rw-r--r--src/eval.c18
-rw-r--r--src/testdir/test34.in6
-rw-r--r--src/testdir/test34.ok2
-rw-r--r--src/version.c2
4 files changed, 20 insertions, 8 deletions
diff --git a/src/eval.c b/src/eval.c
index be59f982..1114c95f 100644
--- a/src/eval.c
+++ b/src/eval.c
@@ -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));
@@ -7997,9 +7997,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" */
@@ -8023,18 +8023,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)
{
@@ -8205,9 +8209,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;
}
diff --git a/src/testdir/test34.in b/src/testdir/test34.in
index 5eef7150..28fd00c4 100644
--- 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
---*---
diff --git a/src/testdir/test34.ok b/src/testdir/test34.ok
index 368ae10e..951dd8bc 100644
--- 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
index f2a5992d..ca7cccf1 100644
--- 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,