| To: vim_dev@googlegroups.com |
| Subject: Patch 7.3.146 |
| Fcc: outbox |
| From: Bram Moolenaar <Bram@moolenaar.net> |
| Mime-Version: 1.0 |
| Content-Type: text/plain; charset=UTF-8 |
| Content-Transfer-Encoding: 8bit |
| |
| |
| 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 |
| |
| |
| |
| |
| |
| *** 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". |
| */ |
| |
| |
| |
| *** 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 -- Bram@Moolenaar.net -- 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 /// |