]> granicus.if.org Git - vim/commitdiff
updated for version 7.3.603 v7.3.603
authorBram Moolenaar <Bram@vim.org>
Mon, 16 Jul 2012 15:31:53 +0000 (17:31 +0200)
committerBram Moolenaar <Bram@vim.org>
Mon, 16 Jul 2012 15:31:53 +0000 (17:31 +0200)
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)

src/buffer.c
src/eval.c
src/proto/eval.pro
src/structs.h
src/testdir/test34.in
src/testdir/test34.ok
src/version.c
src/window.c

index d6d039f0e806e8bb038c199e639da8e1b32120ca..355dbc7398601c1eaf20c64d1cdf4186e53e0a36 100644 (file)
@@ -1747,7 +1747,8 @@ buflist_new(ffname, sfname, lnum, flags)
     buf->b_wininfo->wi_win = curwin;
 
 #ifdef FEAT_EVAL
-    init_var_dict(&buf->b_vars, &buf->b_bufvar);    /* init b: variables */
+    /* init b: variables */
+    init_var_dict(&buf->b_vars, &buf->b_bufvar, VAR_SCOPE);
 #endif
 #ifdef FEAT_SYN_HL
     hash_init(&buf->b_s.b_keywtab);
index 5fc32e21d094f03f6187d76eef0535d113370562..99b3bba24aec485987f6885a3bbf8562b326b2be 100644 (file)
@@ -850,8 +850,8 @@ eval_init()
     int                    i;
     struct vimvar   *p;
 
-    init_var_dict(&globvardict, &globvars_var);
-    init_var_dict(&vimvardict, &vimvars_var);
+    init_var_dict(&globvardict, &globvars_var, VAR_DEF_SCOPE);
+    init_var_dict(&vimvardict, &vimvars_var, VAR_SCOPE);
     vimvardict.dv_lock = VAR_FIXED;
     hash_init(&compat_hashtab);
     hash_init(&func_hashtab);
@@ -2725,14 +2725,26 @@ get_lval(name, rettv, lp, unlet, skip, quiet, fne_flags)
            lp->ll_dict = lp->ll_tv->vval.v_dict;
            lp->ll_di = dict_find(lp->ll_dict, key, len);
 
-           /* When assigning to g: check that a function and variable name is
-            * valid. */
-           if (rettv != NULL && lp->ll_dict == &globvardict)
+           /* When assigning to a scope dictionary check that a function and
+            * variable name is valid (only variable name unless it is l: or
+            * g: dictionary). Disallow overwriting a builtin function. */
+           if (rettv != NULL && lp->ll_dict->dv_scope != 0)
            {
-               if (rettv->v_type == VAR_FUNC
+               int prevval;
+               int wrong;
+
+               if (len != -1)
+               {
+                   prevval = key[len];
+                   key[len] = NUL;
+               }
+               wrong = (lp->ll_dict->dv_scope == VAR_DEF_SCOPE
+                              && rettv->v_type == VAR_FUNC
                               && var_check_func_name(key, lp->ll_di == NULL))
-                   return NULL;
-               if (!valid_varname(key))
+                       || !valid_varname(key);
+               if (len != -1)
+                   key[len] = prevval;
+               if (wrong)
                    return NULL;
            }
 
@@ -6951,7 +6963,7 @@ dict_alloc()
     d = (dict_T *)alloc(sizeof(dict_T));
     if (d != NULL)
     {
-       /* Add the list to the list of dicts for garbage collection. */
+       /* Add the dict to the list of dicts for garbage collection. */
        if (first_dict != NULL)
            first_dict->dv_used_prev = d;
        d->dv_used_next = first_dict;
@@ -6960,6 +6972,7 @@ dict_alloc()
 
        hash_init(&d->dv_hashtab);
        d->dv_lock = 0;
+       d->dv_scope = 0;
        d->dv_refcount = 0;
        d->dv_copyID = 0;
     }
@@ -10203,6 +10216,19 @@ f_extend(argvars, rettv)
                {
                    --todo;
                    di1 = dict_find(d1, hi2->hi_key, -1);
+                   if (d1->dv_scope != 0)
+                   {
+                       /* Disallow replacing a builtin function in l: and g:.
+                        * Check the key to be valid when adding to any
+                        * scope. */
+                       if (d1->dv_scope == VAR_DEF_SCOPE
+                               && HI2DI(hi2)->di_tv.v_type == VAR_FUNC
+                               && var_check_func_name(hi2->hi_key,
+                                                                di1 == NULL))
+                           break;
+                       if (!valid_varname(hi2->hi_key))
+                           break;
+                   }
                    if (di1 == NULL)
                    {
                        di1 = dictitem_copy(HI2DI(hi2));
@@ -20027,7 +20053,7 @@ new_script_vars(id)
        {
            sv = SCRIPT_SV(ga_scripts.ga_len + 1) =
                (scriptvar_T *)alloc_clear(sizeof(scriptvar_T));
-           init_var_dict(&sv->sv_dict, &sv->sv_var);
+           init_var_dict(&sv->sv_dict, &sv->sv_var, VAR_SCOPE);
            ++ga_scripts.ga_len;
        }
     }
@@ -20038,12 +20064,14 @@ new_script_vars(id)
  * point to it.
  */
     void
-init_var_dict(dict, dict_var)
+init_var_dict(dict, dict_var, scope)
     dict_T     *dict;
     dictitem_T *dict_var;
+    int                scope;
 {
     hash_init(&dict->dv_hashtab);
     dict->dv_lock = 0;
+    dict->dv_scope = scope;
     dict->dv_refcount = DO_NOT_FREE_CNT;
     dict->dv_copyID = 0;
     dict_var->di_tv.vval.v_dict = dict;
@@ -22304,7 +22332,7 @@ call_user_func(fp, argcount, argvars, rettv, firstline, lastline, selfdict)
     /*
      * Init l: variables.
      */
-    init_var_dict(&fc->l_vars, &fc->l_vars_var);
+    init_var_dict(&fc->l_vars, &fc->l_vars_var, VAR_DEF_SCOPE);
     if (selfdict != NULL)
     {
        /* 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)
      * Set a:0 to "argcount".
      * Set a:000 to a list with room for the "..." arguments.
      */
-    init_var_dict(&fc->l_avars, &fc->l_avars_var);
+    init_var_dict(&fc->l_avars, &fc->l_avars_var, VAR_SCOPE);
     add_nr_var(&fc->l_avars, &fc->fixvar[fixvar_idx++].var, "0",
                                (varnumber_T)(argcount - fp->uf_args.ga_len));
     /* Use "name" to avoid a warning from some compiler that checks the
index 2454f2a53fb82d60ed903e95fb77909721c063fa..63c140c5565ff2ccca23123b7ffebcf9bfb5e2bf 100644 (file)
@@ -93,7 +93,7 @@ long get_tv_number_chk __ARGS((typval_T *varp, int *denote));
 char_u *get_tv_string_chk __ARGS((typval_T *varp));
 char_u *get_var_value __ARGS((char_u *name));
 void new_script_vars __ARGS((scid_T id));
-void init_var_dict __ARGS((dict_T *dict, dictitem_T *dict_var));
+void init_var_dict __ARGS((dict_T *dict, dictitem_T *dict_var, int scope));
 void vars_clear __ARGS((hashtab_T *ht));
 void copy_tv __ARGS((typval_T *from, typval_T *to));
 void ex_echo __ARGS((exarg_T *eap));
index abcb7045d6c987c713171919b7ce9453c6f44096..36440c3c2ac341337b988354084de5da39f7bfc1 100644 (file)
@@ -1106,6 +1106,11 @@ typedef struct
 #define VAR_DICT    5  /* "v_dict" is used */
 #define VAR_FLOAT   6  /* "v_float" is used */
 
+/* Values for "dv_scope". */
+#define VAR_SCOPE     1        /* a:, v:, s:, etc. scope dictionaries */
+#define VAR_DEF_SCOPE 2        /* l:, g: scope dictionaries: here funcrefs are not
+                          allowed to mask existing functions */
+
 /* Values for "v_lock". */
 #define VAR_LOCKED  1  /* locked with lock(), can use unlock() */
 #define VAR_FIXED   2  /* locked forever */
@@ -1181,6 +1186,7 @@ struct dictvar_S
     int                dv_copyID;      /* ID used by deepcopy() */
     dict_T     *dv_copydict;   /* copied dict used by deepcopy() */
     char       dv_lock;        /* zero, VAR_LOCKED, VAR_FIXED */
+    char       dv_scope;       /* zero, VAR_SCOPE, VAR_DEF_SCOPE */
     dict_T     *dv_used_next;  /* next dict in used dicts list */
     dict_T     *dv_used_prev;  /* previous dict in used dicts list */
 };
index 28fd00c4b95ecbf393696d5ea6e9417c1deaaa7b..5abc140be0dedadd2c8e739f435c118768ddd27a 100644 (file)
@@ -1,5 +1,6 @@
 Test for user functions.
 Also test an <expr> mapping calling a function.
+Also test that a builtin function cannot be replaced.
 
 STARTTEST
 :so small.vim
@@ -58,7 +59,10 @@ XX+-XX
 ---*---
 (one
 (two
-[(one again\e:$-5,$w! test.out
+[(one again\e:call append(line('$'), max([1, 2, 3]))
+:call extend(g:, {'max': function('min')})
+:call append(line('$'), max([1, 2, 3]))
+:$-7,$w! test.out
 :delfunc Table
 :delfunc Compute
 :delfunc Expr1
index d71183dce96a9026ad0d20e54d4eec3f09700931..605381227422a161f2e088740948eb717b0c7b11 100644 (file)
@@ -4,3 +4,5 @@ XX111-XX
 1. one
 2. two
 1. one again
+3
+3
index 4e17878047a4131e99b69146fe25f6cb1c3cf7fc..6bf9708f3429d6559850b3a7b25a534b9d713e20 100644 (file)
@@ -714,6 +714,8 @@ static char *(features[]) =
 
 static int included_patches[] =
 {   /* Add new patch number below this line */
+/**/
+    603,
 /**/
     602,
 /**/
index 6460684bc38d5dec6930585d2822694205541d23..c0b7b8b91b4666a0c1dc0d83f98e80fd41a7f3ed 100644 (file)
@@ -3468,7 +3468,7 @@ alloc_tabpage()
 # endif
 #ifdef FEAT_EVAL
        /* init t: variables */
-       init_var_dict(&tp->tp_vars, &tp->tp_winvar);
+       init_var_dict(&tp->tp_vars, &tp->tp_winvar, VAR_SCOPE);
 #endif
        tp->tp_ch_used = p_ch;
     }
@@ -4410,7 +4410,7 @@ win_alloc(after, hidden)
 #endif
 #ifdef FEAT_EVAL
        /* init w: variables */
-       init_var_dict(&new_wp->w_vars, &new_wp->w_winvar);
+       init_var_dict(&new_wp->w_vars, &new_wp->w_winvar, VAR_SCOPE);
 #endif
 #ifdef FEAT_FOLDING
        foldInitWin(new_wp);