Skip to content

Commit b54c3ff

Browse files
committed
patch 7.4.2134
Problem: No error for using function() badly. Solution: Check for passing wrong function name. (Ken Takata)
1 parent fc1f201 commit b54c3ff

7 files changed

Lines changed: 25 additions & 10 deletions

File tree

src/eval.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7813,7 +7813,7 @@ var_check_func_name(
78137813
/* Don't allow hiding a function. When "v" is not NULL we might be
78147814
* assigning another function to the same var, the type is checked
78157815
* below. */
7816-
if (new_var && function_exists(name))
7816+
if (new_var && function_exists(name, FALSE))
78177817
{
78187818
EMSG2(_("E705: Variable name conflicts with existing function: %s"),
78197819
name);

src/evalfunc.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2845,7 +2845,7 @@ f_exists(typval_T *argvars, typval_T *rettv)
28452845
}
28462846
else if (*p == '*') /* internal or user defined function */
28472847
{
2848-
n = function_exists(p + 1);
2848+
n = function_exists(p + 1, FALSE);
28492849
}
28502850
else if (*p == ':')
28512851
{
@@ -3577,7 +3577,7 @@ f_function(typval_T *argvars, typval_T *rettv)
35773577
EMSG2(_(e_invarg2), s);
35783578
/* Don't check an autoload name for existence here. */
35793579
else if (use_string && vim_strchr(s, AUTOLOAD_CHAR) == NULL
3580-
&& !function_exists(s))
3580+
&& !function_exists(s, TRUE))
35813581
EMSG2(_("E700: Unknown function: %s"), s);
35823582
else
35833583
{

src/proto/userfunc.pro

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ int call_func(char_u *funcname, int len, typval_T *rettv, int argcount_in, typva
99
void ex_function(exarg_T *eap);
1010
int eval_fname_script(char_u *p);
1111
int translated_function_exists(char_u *name);
12-
int function_exists(char_u *name);
12+
int function_exists(char_u *name, int no_deref);
1313
char_u *get_expanded_name(char_u *name, int check);
1414
void func_dump_profile(FILE *fd);
1515
void prof_child_enter(proftime_T *tm);

src/testdir/test_expr.vim

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -172,3 +172,10 @@ func Test_substitute_expr_arg()
172172
call assert_fails("call substitute('xxx', '.', {m -> string(extend(m, ['x']))}, '')", 'E742:')
173173
call assert_fails("call substitute('xxx', '.', {m -> string(remove(m, 1))}, '')", 'E742:')
174174
endfunc
175+
176+
func Test_function_with_funcref()
177+
let s:f = function('type')
178+
let s:fref = function(s:f)
179+
call assert_equal(v:t_string, s:fref('x'))
180+
call assert_fails("call function('s:f')", 'E700:')
181+
endfunc

src/userfunc.c

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -295,7 +295,7 @@ get_lambda_tv(char_u **arg, typval_T *rettv, int evaluate)
295295
if (ret == FAIL || **arg != '>')
296296
goto errret;
297297

298-
/* Set up dictionaries for checking local variables and arguments. */
298+
/* Set up a flag for checking local variables and arguments. */
299299
if (evaluate)
300300
eval_lavars_used = &eval_lavars;
301301

@@ -1504,6 +1504,7 @@ list_func_head(ufunc_T *fp, int indent)
15041504
* TFN_INT: internal function name OK
15051505
* TFN_QUIET: be quiet
15061506
* TFN_NO_AUTOLOAD: do not use script autoloading
1507+
* TFN_NO_DEREF: do not dereference a Funcref
15071508
* Advances "pp" to just after the function name (if no error).
15081509
*/
15091510
static char_u *
@@ -1618,7 +1619,7 @@ trans_function_name(
16181619
if (name == lv.ll_exp_name)
16191620
name = NULL;
16201621
}
1621-
else
1622+
else if (!(flags & TFN_NO_DEREF))
16221623
{
16231624
len = (int)(end - *pp);
16241625
name = deref_func_name(*pp, &len, partial, flags & TFN_NO_AUTOLOAD);
@@ -1690,7 +1691,7 @@ trans_function_name(
16901691
start);
16911692
goto theend;
16921693
}
1693-
if (!skip && !(flags & TFN_QUIET))
1694+
if (!skip && !(flags & TFN_QUIET) && !(flags & TFN_NO_DEREF))
16941695
{
16951696
char_u *cp = vim_strchr(lv.ll_name, ':');
16961697

@@ -2381,16 +2382,20 @@ translated_function_exists(char_u *name)
23812382

23822383
/*
23832384
* Return TRUE if a function "name" exists.
2385+
* If "no_defef" is TRUE, do not dereference a Funcref.
23842386
*/
23852387
int
2386-
function_exists(char_u *name)
2388+
function_exists(char_u *name, int no_deref)
23872389
{
23882390
char_u *nm = name;
23892391
char_u *p;
23902392
int n = FALSE;
2393+
int flag;
23912394

2392-
p = trans_function_name(&nm, FALSE, TFN_INT|TFN_QUIET|TFN_NO_AUTOLOAD,
2393-
NULL, NULL);
2395+
flag = TFN_INT | TFN_QUIET | TFN_NO_AUTOLOAD;
2396+
if (no_deref)
2397+
flag |= TFN_NO_DEREF;
2398+
p = trans_function_name(&nm, FALSE, flag, NULL, NULL);
23942399
nm = skipwhite(nm);
23952400

23962401
/* Only accept "funcname", "funcname ", "funcname (..." and

src/version.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -763,6 +763,8 @@ static char *(features[]) =
763763

764764
static int included_patches[] =
765765
{ /* Add new patch number below this line */
766+
/**/
767+
2134,
766768
/**/
767769
2133,
768770
/**/

src/vim.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2458,6 +2458,7 @@ int vim_main2(int argc, char **argv);
24582458
#define TFN_INT 1 /* internal function name OK */
24592459
#define TFN_QUIET 2 /* no error messages */
24602460
#define TFN_NO_AUTOLOAD 4 /* do not use script autoloading */
2461+
#define TFN_NO_DEREF 8 /* do not dereference a Funcref */
24612462

24622463
/* Values for get_lval() flags argument: */
24632464
#define GLV_QUIET TFN_QUIET /* no error messages */

0 commit comments

Comments
 (0)