Patch 7.3.146
Problem:    It's possible to assign to a read-only member of a dict.
            It's possible to create a global variable "0". (ZyX)
            It's possible to add a v: variable with ":let v:.name = 1".
Solution:   Add check for dict item being read-only.
            Check the name of g: variables.
            Disallow adding v: variables.
Files:      src/eval.c


*** ../vim-7.3.145/src/eval.c   2011-02-01 13:48:47.000000000 +0100
--- src/eval.c  2011-03-27 15:56:44.000000000 +0200
***************
*** 789,794 ****
--- 789,796 ----
  static void set_var __ARGS((char_u *name, typval_T *varp, int copy));
  static int var_check_ro __ARGS((int flags, char_u *name));
  static int var_check_fixed __ARGS((int flags, char_u *name));
+ static int var_check_func_name __ARGS((char_u *name, int new_var));
+ static int valid_varname __ARGS((char_u *varname));
  static int tv_check_lock __ARGS((int lock, char_u *name));
  static int item_copy __ARGS((typval_T *from, typval_T *to, int deep, int 
copyID));
  static char_u *find_option_end __ARGS((char_u **arg, int *opt_flags));
***************
*** 2716,2723 ****
--- 2718,2744 ----
            lp->ll_list = NULL;
            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)
+           {
+               if (rettv->v_type == VAR_FUNC
+                              && var_check_func_name(key, lp->ll_di == NULL))
+                   return NULL;
+               if (!valid_varname(key))
+                   return NULL;
+           }
+ 
            if (lp->ll_di == NULL)
            {
+               /* Can't add "v:" variable. */
+               if (lp->ll_dict == &vimvardict)
+               {
+                   EMSG2(_(e_illvar), name);
+                   return NULL;
+               }
+ 
                /* Key does not exist in dict: may need to add it. */
                if (*p == '[' || *p == '.' || unlet)
                {
***************
*** 2737,2742 ****
--- 2758,2767 ----
                    p = NULL;
                break;
            }
+           /* existing variable, need to check if it can be changed */
+           else if (var_check_ro(lp->ll_di->di_flags, name))
+               return NULL;
+ 
            if (len == -1)
                clear_tv(&var1);
            lp->ll_tv = &lp->ll_di->di_tv;
***************
*** 19786,19792 ****
      dictitem_T        *v;
      char_u    *varname;
      hashtab_T *ht;
-     char_u    *p;
  
      ht = find_var_ht(name, &varname);
      if (ht == NULL || *varname == NUL)
--- 19811,19816 ----
***************
*** 19796,19820 ****
      }
      v = find_var_in_ht(ht, varname, TRUE);
  
!     if (tv->v_type == VAR_FUNC)
!     {
!       if (!(vim_strchr((char_u *)"wbs", name[0]) != NULL && name[1] == ':')
!               && !ASCII_ISUPPER((name[0] != NUL && name[1] == ':')
!                                                        ? name[2] : name[0]))
!       {
!           EMSG2(_("E704: Funcref variable name must start with a capital: 
%s"), name);
!           return;
!       }
!       /* Don't allow hiding a function.  When "v" is not NULL we might be
!        * assigning another function to the same var, the type is checked
!        * below. */
!       if (v == NULL && function_exists(name))
!       {
!           EMSG2(_("E705: Variable name conflicts with existing function: %s"),
!                                                                       name);
!           return;
!       }
!     }
  
      if (v != NULL)
      {
--- 19820,19827 ----
      }
      v = find_var_in_ht(ht, varname, TRUE);
  
!     if (tv->v_type == VAR_FUNC && var_check_func_name(name, v == NULL))
!       return;
  
      if (v != NULL)
      {
***************
*** 19880,19892 ****
        }
  
        /* Make sure the variable name is valid. */
!       for (p = varname; *p != NUL; ++p)
!           if (!eval_isnamec1(*p) && (p == varname || !VIM_ISDIGIT(*p))
!                                                      && *p != AUTOLOAD_CHAR)
!           {
!               EMSG2(_(e_illvar), varname);
!               return;
!           }
  
        v = (dictitem_T *)alloc((unsigned)(sizeof(dictitem_T)
                                                          + STRLEN(varname)));
--- 19887,19894 ----
        }
  
        /* Make sure the variable name is valid. */
!       if (!valid_varname(varname))
!           return;
  
        v = (dictitem_T *)alloc((unsigned)(sizeof(dictitem_T)
                                                          + STRLEN(varname)));
***************
*** 19951,19956 ****
--- 19953,20007 ----
  }
  
  /*
+  * Check if a funcref is assigned to a valid variable name.
+  * Return TRUE and give an error if not.
+  */
+     static int
+ var_check_func_name(name, new_var)
+     char_u *name;    /* points to start of variable name */
+     int    new_var;  /* TRUE when creating the variable */
+ {
+     if (!(vim_strchr((char_u *)"wbs", name[0]) != NULL && name[1] == ':')
+           && !ASCII_ISUPPER((name[0] != NUL && name[1] == ':')
+                                                    ? name[2] : name[0]))
+     {
+       EMSG2(_("E704: Funcref variable name must start with a capital: %s"),
+                                                                       name);
+       return TRUE;
+     }
+     /* Don't allow hiding a function.  When "v" is not NULL we might be
+      * assigning another function to the same var, the type is checked
+      * below. */
+     if (new_var && function_exists(name))
+     {
+       EMSG2(_("E705: Variable name conflicts with existing function: %s"),
+                                                                   name);
+       return TRUE;
+     }
+     return FALSE;
+ }
+ 
+ /*
+  * Check if a variable name is valid.
+  * Return FALSE and give an error if not.
+  */
+     static int
+ valid_varname(varname)
+     char_u *varname;
+ {
+     char_u *p;
+ 
+     for (p = varname; *p != NUL; ++p)
+       if (!eval_isnamec1(*p) && (p == varname || !VIM_ISDIGIT(*p))
+                                                  && *p != AUTOLOAD_CHAR)
+       {
+           EMSG2(_(e_illvar), varname);
+           return FALSE;
+       }
+     return TRUE;
+ }
+ 
+ /*
   * Return TRUE if typeval "tv" is set to be locked (immutable).
   * Also give an error message, using "name".
   */
*** ../vim-7.3.145/src/version.c        2011-03-26 18:32:00.000000000 +0100
--- src/version.c       2011-03-27 16:01:03.000000000 +0200
***************
*** 716,717 ****
--- 716,719 ----
  {   /* Add new patch number below this line */
+ /**/
+     146,
  /**/

-- 
ARTHUR: It is I, Arthur, son of Uther Pendragon, from the castle of Camelot.
        King of all Britons, defeator of the Saxons, sovereign of all England!
   [Pause]
SOLDIER: Get away!
                 "Monty Python and the Holy Grail" PYTHON (MONTY) PICTURES LTD

 /// Bram Moolenaar -- [email protected] -- http://www.Moolenaar.net   \\\
///        sponsor Vim, vote for features -- http://www.Vim.org/sponsor/ \\\
\\\  an exciting new programming language -- http://www.Zimbu.org        ///
 \\\            help me help AIDS victims -- http://ICCF-Holland.org    ///

-- 
You received this message from the "vim_dev" maillist.
Do not top-post! Type your reply below the text you are replying to.
For more information, visit http://www.vim.org/maillist.php

Raspunde prin e-mail lui