Skip to content

Commit 4adf7a7

Browse files
committed
updated for version 7.3.603
Problem: It is possible to add replace builtin functions by calling extend() on g:. Solution: Add a flag to a dict to indicate it is a scope. Check for existing functions. (ZyX)
1 parent d0ab901 commit 4adf7a7

File tree

8 files changed

+61
-18
lines changed

8 files changed

+61
-18
lines changed

src/buffer.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1747,7 +1747,8 @@ buflist_new(ffname, sfname, lnum, flags)
17471747
buf->b_wininfo->wi_win = curwin;
17481748

17491749
#ifdef FEAT_EVAL
1750-
init_var_dict(&buf->b_vars, &buf->b_bufvar); /* init b: variables */
1750+
/* init b: variables */
1751+
init_var_dict(&buf->b_vars, &buf->b_bufvar, VAR_SCOPE);
17511752
#endif
17521753
#ifdef FEAT_SYN_HL
17531754
hash_init(&buf->b_s.b_keywtab);

src/eval.c

Lines changed: 41 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -850,8 +850,8 @@ eval_init()
850850
int i;
851851
struct vimvar *p;
852852

853-
init_var_dict(&globvardict, &globvars_var);
854-
init_var_dict(&vimvardict, &vimvars_var);
853+
init_var_dict(&globvardict, &globvars_var, VAR_DEF_SCOPE);
854+
init_var_dict(&vimvardict, &vimvars_var, VAR_SCOPE);
855855
vimvardict.dv_lock = VAR_FIXED;
856856
hash_init(&compat_hashtab);
857857
hash_init(&func_hashtab);
@@ -2725,14 +2725,26 @@ get_lval(name, rettv, lp, unlet, skip, quiet, fne_flags)
27252725
lp->ll_dict = lp->ll_tv->vval.v_dict;
27262726
lp->ll_di = dict_find(lp->ll_dict, key, len);
27272727

2728-
/* When assigning to g: check that a function and variable name is
2729-
* valid. */
2730-
if (rettv != NULL && lp->ll_dict == &globvardict)
2728+
/* When assigning to a scope dictionary check that a function and
2729+
* variable name is valid (only variable name unless it is l: or
2730+
* g: dictionary). Disallow overwriting a builtin function. */
2731+
if (rettv != NULL && lp->ll_dict->dv_scope != 0)
27312732
{
2732-
if (rettv->v_type == VAR_FUNC
2733+
int prevval;
2734+
int wrong;
2735+
2736+
if (len != -1)
2737+
{
2738+
prevval = key[len];
2739+
key[len] = NUL;
2740+
}
2741+
wrong = (lp->ll_dict->dv_scope == VAR_DEF_SCOPE
2742+
&& rettv->v_type == VAR_FUNC
27332743
&& var_check_func_name(key, lp->ll_di == NULL))
2734-
return NULL;
2735-
if (!valid_varname(key))
2744+
|| !valid_varname(key);
2745+
if (len != -1)
2746+
key[len] = prevval;
2747+
if (wrong)
27362748
return NULL;
27372749
}
27382750

@@ -6951,7 +6963,7 @@ dict_alloc()
69516963
d = (dict_T *)alloc(sizeof(dict_T));
69526964
if (d != NULL)
69536965
{
6954-
/* Add the list to the list of dicts for garbage collection. */
6966+
/* Add the dict to the list of dicts for garbage collection. */
69556967
if (first_dict != NULL)
69566968
first_dict->dv_used_prev = d;
69576969
d->dv_used_next = first_dict;
@@ -6960,6 +6972,7 @@ dict_alloc()
69606972

69616973
hash_init(&d->dv_hashtab);
69626974
d->dv_lock = 0;
6975+
d->dv_scope = 0;
69636976
d->dv_refcount = 0;
69646977
d->dv_copyID = 0;
69656978
}
@@ -10203,6 +10216,19 @@ f_extend(argvars, rettv)
1020310216
{
1020410217
--todo;
1020510218
di1 = dict_find(d1, hi2->hi_key, -1);
10219+
if (d1->dv_scope != 0)
10220+
{
10221+
/* Disallow replacing a builtin function in l: and g:.
10222+
* Check the key to be valid when adding to any
10223+
* scope. */
10224+
if (d1->dv_scope == VAR_DEF_SCOPE
10225+
&& HI2DI(hi2)->di_tv.v_type == VAR_FUNC
10226+
&& var_check_func_name(hi2->hi_key,
10227+
di1 == NULL))
10228+
break;
10229+
if (!valid_varname(hi2->hi_key))
10230+
break;
10231+
}
1020610232
if (di1 == NULL)
1020710233
{
1020810234
di1 = dictitem_copy(HI2DI(hi2));
@@ -20027,7 +20053,7 @@ new_script_vars(id)
2002720053
{
2002820054
sv = SCRIPT_SV(ga_scripts.ga_len + 1) =
2002920055
(scriptvar_T *)alloc_clear(sizeof(scriptvar_T));
20030-
init_var_dict(&sv->sv_dict, &sv->sv_var);
20056+
init_var_dict(&sv->sv_dict, &sv->sv_var, VAR_SCOPE);
2003120057
++ga_scripts.ga_len;
2003220058
}
2003320059
}
@@ -20038,12 +20064,14 @@ new_script_vars(id)
2003820064
* point to it.
2003920065
*/
2004020066
void
20041-
init_var_dict(dict, dict_var)
20067+
init_var_dict(dict, dict_var, scope)
2004220068
dict_T *dict;
2004320069
dictitem_T *dict_var;
20070+
int scope;
2004420071
{
2004520072
hash_init(&dict->dv_hashtab);
2004620073
dict->dv_lock = 0;
20074+
dict->dv_scope = scope;
2004720075
dict->dv_refcount = DO_NOT_FREE_CNT;
2004820076
dict->dv_copyID = 0;
2004920077
dict_var->di_tv.vval.v_dict = dict;
@@ -22304,7 +22332,7 @@ call_user_func(fp, argcount, argvars, rettv, firstline, lastline, selfdict)
2230422332
/*
2230522333
* Init l: variables.
2230622334
*/
22307-
init_var_dict(&fc->l_vars, &fc->l_vars_var);
22335+
init_var_dict(&fc->l_vars, &fc->l_vars_var, VAR_DEF_SCOPE);
2230822336
if (selfdict != NULL)
2230922337
{
2231022338
/* Set l:self to "selfdict". Use "name" to avoid a warning from
@@ -22325,7 +22353,7 @@ call_user_func(fp, argcount, argvars, rettv, firstline, lastline, selfdict)
2232522353
* Set a:0 to "argcount".
2232622354
* Set a:000 to a list with room for the "..." arguments.
2232722355
*/
22328-
init_var_dict(&fc->l_avars, &fc->l_avars_var);
22356+
init_var_dict(&fc->l_avars, &fc->l_avars_var, VAR_SCOPE);
2232922357
add_nr_var(&fc->l_avars, &fc->fixvar[fixvar_idx++].var, "0",
2233022358
(varnumber_T)(argcount - fp->uf_args.ga_len));
2233122359
/* Use "name" to avoid a warning from some compiler that checks the

src/proto/eval.pro

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -93,7 +93,7 @@ long get_tv_number_chk __ARGS((typval_T *varp, int *denote));
9393
char_u *get_tv_string_chk __ARGS((typval_T *varp));
9494
char_u *get_var_value __ARGS((char_u *name));
9595
void new_script_vars __ARGS((scid_T id));
96-
void init_var_dict __ARGS((dict_T *dict, dictitem_T *dict_var));
96+
void init_var_dict __ARGS((dict_T *dict, dictitem_T *dict_var, int scope));
9797
void vars_clear __ARGS((hashtab_T *ht));
9898
void copy_tv __ARGS((typval_T *from, typval_T *to));
9999
void ex_echo __ARGS((exarg_T *eap));

src/structs.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1106,6 +1106,11 @@ typedef struct
11061106
#define VAR_DICT 5 /* "v_dict" is used */
11071107
#define VAR_FLOAT 6 /* "v_float" is used */
11081108

1109+
/* Values for "dv_scope". */
1110+
#define VAR_SCOPE 1 /* a:, v:, s:, etc. scope dictionaries */
1111+
#define VAR_DEF_SCOPE 2 /* l:, g: scope dictionaries: here funcrefs are not
1112+
allowed to mask existing functions */
1113+
11091114
/* Values for "v_lock". */
11101115
#define VAR_LOCKED 1 /* locked with lock(), can use unlock() */
11111116
#define VAR_FIXED 2 /* locked forever */
@@ -1181,6 +1186,7 @@ struct dictvar_S
11811186
int dv_copyID; /* ID used by deepcopy() */
11821187
dict_T *dv_copydict; /* copied dict used by deepcopy() */
11831188
char dv_lock; /* zero, VAR_LOCKED, VAR_FIXED */
1189+
char dv_scope; /* zero, VAR_SCOPE, VAR_DEF_SCOPE */
11841190
dict_T *dv_used_next; /* next dict in used dicts list */
11851191
dict_T *dv_used_prev; /* previous dict in used dicts list */
11861192
};

src/testdir/test34.in

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
Test for user functions.
22
Also test an <expr> mapping calling a function.
3+
Also test that a builtin function cannot be replaced.
34

45
STARTTEST
56
:so small.vim
@@ -58,7 +59,10 @@ XX+-XX
5859
---*---
5960
(one
6061
(two
61-
[(one again:$-5,$w! test.out
62+
[(one again:call append(line('$'), max([1, 2, 3]))
63+
:call extend(g:, {'max': function('min')})
64+
:call append(line('$'), max([1, 2, 3]))
65+
:$-7,$w! test.out
6266
:delfunc Table
6367
:delfunc Compute
6468
:delfunc Expr1

src/testdir/test34.ok

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,3 +4,5 @@ XX111-XX
44
1. one
55
2. two
66
1. one again
7+
3
8+
3

src/version.c

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

715715
static int included_patches[] =
716716
{ /* Add new patch number below this line */
717+
/**/
718+
603,
717719
/**/
718720
602,
719721
/**/

src/window.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3468,7 +3468,7 @@ alloc_tabpage()
34683468
# endif
34693469
#ifdef FEAT_EVAL
34703470
/* init t: variables */
3471-
init_var_dict(&tp->tp_vars, &tp->tp_winvar);
3471+
init_var_dict(&tp->tp_vars, &tp->tp_winvar, VAR_SCOPE);
34723472
#endif
34733473
tp->tp_ch_used = p_ch;
34743474
}
@@ -4410,7 +4410,7 @@ win_alloc(after, hidden)
44104410
#endif
44114411
#ifdef FEAT_EVAL
44124412
/* init w: variables */
4413-
init_var_dict(&new_wp->w_vars, &new_wp->w_winvar);
4413+
init_var_dict(&new_wp->w_vars, &new_wp->w_winvar, VAR_SCOPE);
44144414
#endif
44154415
#ifdef FEAT_FOLDING
44164416
foldInitWin(new_wp);

0 commit comments

Comments
 (0)