Karsten Hopp c97417
To: vim_dev@googlegroups.com
Karsten Hopp c97417
Subject: Patch 7.3.146
Karsten Hopp c97417
Fcc: outbox
Karsten Hopp c97417
From: Bram Moolenaar <Bram@moolenaar.net>
Karsten Hopp c97417
Mime-Version: 1.0
Karsten Hopp c97417
Content-Type: text/plain; charset=UTF-8
Karsten Hopp c97417
Content-Transfer-Encoding: 8bit
Karsten Hopp c97417
------------
Karsten Hopp c97417
Karsten Hopp c97417
Patch 7.3.146
Karsten Hopp c97417
Problem:    It's possible to assign to a read-only member of a dict.
Karsten Hopp c97417
	    It's possible to create a global variable "0". (ZyX)
Karsten Hopp c97417
            It's possible to add a v: variable with ":let v:.name = 1".
Karsten Hopp c97417
Solution:   Add check for dict item being read-only.
Karsten Hopp c97417
	    Check the name of g: variables.
Karsten Hopp c97417
	    Disallow adding v: variables.
Karsten Hopp c97417
Files:	    src/eval.c
Karsten Hopp c97417
Karsten Hopp c97417
Karsten Hopp c97417
*** ../vim-7.3.145/src/eval.c	2011-02-01 13:48:47.000000000 +0100
Karsten Hopp c97417
--- src/eval.c	2011-03-27 15:56:44.000000000 +0200
Karsten Hopp c97417
***************
Karsten Hopp c97417
*** 789,794 ****
Karsten Hopp c97417
--- 789,796 ----
Karsten Hopp c97417
  static void set_var __ARGS((char_u *name, typval_T *varp, int copy));
Karsten Hopp c97417
  static int var_check_ro __ARGS((int flags, char_u *name));
Karsten Hopp c97417
  static int var_check_fixed __ARGS((int flags, char_u *name));
Karsten Hopp c97417
+ static int var_check_func_name __ARGS((char_u *name, int new_var));
Karsten Hopp c97417
+ static int valid_varname __ARGS((char_u *varname));
Karsten Hopp c97417
  static int tv_check_lock __ARGS((int lock, char_u *name));
Karsten Hopp c97417
  static int item_copy __ARGS((typval_T *from, typval_T *to, int deep, int copyID));
Karsten Hopp c97417
  static char_u *find_option_end __ARGS((char_u **arg, int *opt_flags));
Karsten Hopp c97417
***************
Karsten Hopp c97417
*** 2716,2723 ****
Karsten Hopp c97417
--- 2718,2744 ----
Karsten Hopp c97417
  	    lp->ll_list = NULL;
Karsten Hopp c97417
  	    lp->ll_dict = lp->ll_tv->vval.v_dict;
Karsten Hopp c97417
  	    lp->ll_di = dict_find(lp->ll_dict, key, len);
Karsten Hopp c97417
+ 
Karsten Hopp c97417
+ 	    /* When assigning to g: check that a function and variable name is
Karsten Hopp c97417
+ 	     * valid. */
Karsten Hopp c97417
+ 	    if (rettv != NULL && lp->ll_dict == &globvardict)
Karsten Hopp c97417
+ 	    {
Karsten Hopp c97417
+ 		if (rettv->v_type == VAR_FUNC
Karsten Hopp c97417
+ 			       && var_check_func_name(key, lp->ll_di == NULL))
Karsten Hopp c97417
+ 		    return NULL;
Karsten Hopp c97417
+ 		if (!valid_varname(key))
Karsten Hopp c97417
+ 		    return NULL;
Karsten Hopp c97417
+ 	    }
Karsten Hopp c97417
+ 
Karsten Hopp c97417
  	    if (lp->ll_di == NULL)
Karsten Hopp c97417
  	    {
Karsten Hopp c97417
+ 		/* Can't add "v:" variable. */
Karsten Hopp c97417
+ 		if (lp->ll_dict == &vimvardict)
Karsten Hopp c97417
+ 		{
Karsten Hopp c97417
+ 		    EMSG2(_(e_illvar), name);
Karsten Hopp c97417
+ 		    return NULL;
Karsten Hopp c97417
+ 		}
Karsten Hopp c97417
+ 
Karsten Hopp c97417
  		/* Key does not exist in dict: may need to add it. */
Karsten Hopp c97417
  		if (*p == '[' || *p == '.' || unlet)
Karsten Hopp c97417
  		{
Karsten Hopp c97417
***************
Karsten Hopp c97417
*** 2737,2742 ****
Karsten Hopp c97417
--- 2758,2767 ----
Karsten Hopp c97417
  		    p = NULL;
Karsten Hopp c97417
  		break;
Karsten Hopp c97417
  	    }
Karsten Hopp c97417
+ 	    /* existing variable, need to check if it can be changed */
Karsten Hopp c97417
+ 	    else if (var_check_ro(lp->ll_di->di_flags, name))
Karsten Hopp c97417
+ 		return NULL;
Karsten Hopp c97417
+ 
Karsten Hopp c97417
  	    if (len == -1)
Karsten Hopp c97417
  		clear_tv(&var1;;
Karsten Hopp c97417
  	    lp->ll_tv = &lp->ll_di->di_tv;
Karsten Hopp c97417
***************
Karsten Hopp c97417
*** 19786,19792 ****
Karsten Hopp c97417
      dictitem_T	*v;
Karsten Hopp c97417
      char_u	*varname;
Karsten Hopp c97417
      hashtab_T	*ht;
Karsten Hopp c97417
-     char_u	*p;
Karsten Hopp c97417
  
Karsten Hopp c97417
      ht = find_var_ht(name, &varname);
Karsten Hopp c97417
      if (ht == NULL || *varname == NUL)
Karsten Hopp c97417
--- 19811,19816 ----
Karsten Hopp c97417
***************
Karsten Hopp c97417
*** 19796,19820 ****
Karsten Hopp c97417
      }
Karsten Hopp c97417
      v = find_var_in_ht(ht, varname, TRUE);
Karsten Hopp c97417
  
Karsten Hopp c97417
!     if (tv->v_type == VAR_FUNC)
Karsten Hopp c97417
!     {
Karsten Hopp c97417
! 	if (!(vim_strchr((char_u *)"wbs", name[0]) != NULL && name[1] == ':')
Karsten Hopp c97417
! 		&& !ASCII_ISUPPER((name[0] != NUL && name[1] == ':')
Karsten Hopp c97417
! 							 ? name[2] : name[0]))
Karsten Hopp c97417
! 	{
Karsten Hopp c97417
! 	    EMSG2(_("E704: Funcref variable name must start with a capital: %s"), name);
Karsten Hopp c97417
! 	    return;
Karsten Hopp c97417
! 	}
Karsten Hopp c97417
! 	/* Don't allow hiding a function.  When "v" is not NULL we might be
Karsten Hopp c97417
! 	 * assigning another function to the same var, the type is checked
Karsten Hopp c97417
! 	 * below. */
Karsten Hopp c97417
! 	if (v == NULL && function_exists(name))
Karsten Hopp c97417
! 	{
Karsten Hopp c97417
! 	    EMSG2(_("E705: Variable name conflicts with existing function: %s"),
Karsten Hopp c97417
! 									name);
Karsten Hopp c97417
! 	    return;
Karsten Hopp c97417
! 	}
Karsten Hopp c97417
!     }
Karsten Hopp c97417
  
Karsten Hopp c97417
      if (v != NULL)
Karsten Hopp c97417
      {
Karsten Hopp c97417
--- 19820,19827 ----
Karsten Hopp c97417
      }
Karsten Hopp c97417
      v = find_var_in_ht(ht, varname, TRUE);
Karsten Hopp c97417
  
Karsten Hopp c97417
!     if (tv->v_type == VAR_FUNC && var_check_func_name(name, v == NULL))
Karsten Hopp c97417
! 	return;
Karsten Hopp c97417
  
Karsten Hopp c97417
      if (v != NULL)
Karsten Hopp c97417
      {
Karsten Hopp c97417
***************
Karsten Hopp c97417
*** 19880,19892 ****
Karsten Hopp c97417
  	}
Karsten Hopp c97417
  
Karsten Hopp c97417
  	/* Make sure the variable name is valid. */
Karsten Hopp c97417
! 	for (p = varname; *p != NUL; ++p)
Karsten Hopp c97417
! 	    if (!eval_isnamec1(*p) && (p == varname || !VIM_ISDIGIT(*p))
Karsten Hopp c97417
! 						       && *p != AUTOLOAD_CHAR)
Karsten Hopp c97417
! 	    {
Karsten Hopp c97417
! 		EMSG2(_(e_illvar), varname);
Karsten Hopp c97417
! 		return;
Karsten Hopp c97417
! 	    }
Karsten Hopp c97417
  
Karsten Hopp c97417
  	v = (dictitem_T *)alloc((unsigned)(sizeof(dictitem_T)
Karsten Hopp c97417
  							  + STRLEN(varname)));
Karsten Hopp c97417
--- 19887,19894 ----
Karsten Hopp c97417
  	}
Karsten Hopp c97417
  
Karsten Hopp c97417
  	/* Make sure the variable name is valid. */
Karsten Hopp c97417
! 	if (!valid_varname(varname))
Karsten Hopp c97417
! 	    return;
Karsten Hopp c97417
  
Karsten Hopp c97417
  	v = (dictitem_T *)alloc((unsigned)(sizeof(dictitem_T)
Karsten Hopp c97417
  							  + STRLEN(varname)));
Karsten Hopp c97417
***************
Karsten Hopp c97417
*** 19951,19956 ****
Karsten Hopp c97417
--- 19953,20007 ----
Karsten Hopp c97417
  }
Karsten Hopp c97417
  
Karsten Hopp c97417
  /*
Karsten Hopp c97417
+  * Check if a funcref is assigned to a valid variable name.
Karsten Hopp c97417
+  * Return TRUE and give an error if not.
Karsten Hopp c97417
+  */
Karsten Hopp c97417
+     static int
Karsten Hopp c97417
+ var_check_func_name(name, new_var)
Karsten Hopp c97417
+     char_u *name;    /* points to start of variable name */
Karsten Hopp c97417
+     int    new_var;  /* TRUE when creating the variable */
Karsten Hopp c97417
+ {
Karsten Hopp c97417
+     if (!(vim_strchr((char_u *)"wbs", name[0]) != NULL && name[1] == ':')
Karsten Hopp c97417
+ 	    && !ASCII_ISUPPER((name[0] != NUL && name[1] == ':')
Karsten Hopp c97417
+ 						     ? name[2] : name[0]))
Karsten Hopp c97417
+     {
Karsten Hopp c97417
+ 	EMSG2(_("E704: Funcref variable name must start with a capital: %s"),
Karsten Hopp c97417
+ 									name);
Karsten Hopp c97417
+ 	return TRUE;
Karsten Hopp c97417
+     }
Karsten Hopp c97417
+     /* Don't allow hiding a function.  When "v" is not NULL we might be
Karsten Hopp c97417
+      * assigning another function to the same var, the type is checked
Karsten Hopp c97417
+      * below. */
Karsten Hopp c97417
+     if (new_var && function_exists(name))
Karsten Hopp c97417
+     {
Karsten Hopp c97417
+ 	EMSG2(_("E705: Variable name conflicts with existing function: %s"),
Karsten Hopp c97417
+ 								    name);
Karsten Hopp c97417
+ 	return TRUE;
Karsten Hopp c97417
+     }
Karsten Hopp c97417
+     return FALSE;
Karsten Hopp c97417
+ }
Karsten Hopp c97417
+ 
Karsten Hopp c97417
+ /*
Karsten Hopp c97417
+  * Check if a variable name is valid.
Karsten Hopp c97417
+  * Return FALSE and give an error if not.
Karsten Hopp c97417
+  */
Karsten Hopp c97417
+     static int
Karsten Hopp c97417
+ valid_varname(varname)
Karsten Hopp c97417
+     char_u *varname;
Karsten Hopp c97417
+ {
Karsten Hopp c97417
+     char_u *p;
Karsten Hopp c97417
+ 
Karsten Hopp c97417
+     for (p = varname; *p != NUL; ++p)
Karsten Hopp c97417
+ 	if (!eval_isnamec1(*p) && (p == varname || !VIM_ISDIGIT(*p))
Karsten Hopp c97417
+ 						   && *p != AUTOLOAD_CHAR)
Karsten Hopp c97417
+ 	{
Karsten Hopp c97417
+ 	    EMSG2(_(e_illvar), varname);
Karsten Hopp c97417
+ 	    return FALSE;
Karsten Hopp c97417
+ 	}
Karsten Hopp c97417
+     return TRUE;
Karsten Hopp c97417
+ }
Karsten Hopp c97417
+ 
Karsten Hopp c97417
+ /*
Karsten Hopp c97417
   * Return TRUE if typeval "tv" is set to be locked (immutable).
Karsten Hopp c97417
   * Also give an error message, using "name".
Karsten Hopp c97417
   */
Karsten Hopp c97417
*** ../vim-7.3.145/src/version.c	2011-03-26 18:32:00.000000000 +0100
Karsten Hopp c97417
--- src/version.c	2011-03-27 16:01:03.000000000 +0200
Karsten Hopp c97417
***************
Karsten Hopp c97417
*** 716,717 ****
Karsten Hopp c97417
--- 716,719 ----
Karsten Hopp c97417
  {   /* Add new patch number below this line */
Karsten Hopp c97417
+ /**/
Karsten Hopp c97417
+     146,
Karsten Hopp c97417
  /**/
Karsten Hopp c97417
Karsten Hopp c97417
-- 
Karsten Hopp c97417
ARTHUR: It is I, Arthur, son of Uther Pendragon, from the castle of Camelot.
Karsten Hopp c97417
        King of all Britons, defeator of the Saxons, sovereign of all England!
Karsten Hopp c97417
   [Pause]
Karsten Hopp c97417
SOLDIER: Get away!
Karsten Hopp c97417
                 "Monty Python and the Holy Grail" PYTHON (MONTY) PICTURES LTD
Karsten Hopp c97417
Karsten Hopp c97417
 /// Bram Moolenaar -- Bram@Moolenaar.net -- http://www.Moolenaar.net   \\\
Karsten Hopp c97417
///        sponsor Vim, vote for features -- http://www.Vim.org/sponsor/ \\\
Karsten Hopp c97417
\\\  an exciting new programming language -- http://www.Zimbu.org        ///
Karsten Hopp c97417
 \\\            help me help AIDS victims -- http://ICCF-Holland.org    ///