@@ -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
0 commit comments