Mercurial > vim
comparison src/eval.c @ 2739:2bd574a2ef1c v7.3.146
updated for version 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.
author | Bram Moolenaar <bram@vim.org> |
---|---|
date | Sun, 27 Mar 2011 16:03:15 +0200 |
parents | 3ea3dcbf2cd6 |
children | 6146c9859f65 |
comparison
equal
deleted
inserted
replaced
2738:01b806a03556 | 2739:2bd574a2ef1c |
---|---|
787 static void list_one_var __ARGS((dictitem_T *v, char_u *prefix, int *first)); | 787 static void list_one_var __ARGS((dictitem_T *v, char_u *prefix, int *first)); |
788 static void list_one_var_a __ARGS((char_u *prefix, char_u *name, int type, char_u *string, int *first)); | 788 static void list_one_var_a __ARGS((char_u *prefix, char_u *name, int type, char_u *string, int *first)); |
789 static void set_var __ARGS((char_u *name, typval_T *varp, int copy)); | 789 static void set_var __ARGS((char_u *name, typval_T *varp, int copy)); |
790 static int var_check_ro __ARGS((int flags, char_u *name)); | 790 static int var_check_ro __ARGS((int flags, char_u *name)); |
791 static int var_check_fixed __ARGS((int flags, char_u *name)); | 791 static int var_check_fixed __ARGS((int flags, char_u *name)); |
792 static int var_check_func_name __ARGS((char_u *name, int new_var)); | |
793 static int valid_varname __ARGS((char_u *varname)); | |
792 static int tv_check_lock __ARGS((int lock, char_u *name)); | 794 static int tv_check_lock __ARGS((int lock, char_u *name)); |
793 static int item_copy __ARGS((typval_T *from, typval_T *to, int deep, int copyID)); | 795 static int item_copy __ARGS((typval_T *from, typval_T *to, int deep, int copyID)); |
794 static char_u *find_option_end __ARGS((char_u **arg, int *opt_flags)); | 796 static char_u *find_option_end __ARGS((char_u **arg, int *opt_flags)); |
795 static char_u *trans_function_name __ARGS((char_u **pp, int skip, int flags, funcdict_T *fd)); | 797 static char_u *trans_function_name __ARGS((char_u **pp, int skip, int flags, funcdict_T *fd)); |
796 static int eval_fname_script __ARGS((char_u *p)); | 798 static int eval_fname_script __ARGS((char_u *p)); |
2714 } | 2716 } |
2715 } | 2717 } |
2716 lp->ll_list = NULL; | 2718 lp->ll_list = NULL; |
2717 lp->ll_dict = lp->ll_tv->vval.v_dict; | 2719 lp->ll_dict = lp->ll_tv->vval.v_dict; |
2718 lp->ll_di = dict_find(lp->ll_dict, key, len); | 2720 lp->ll_di = dict_find(lp->ll_dict, key, len); |
2721 | |
2722 /* When assigning to g: check that a function and variable name is | |
2723 * valid. */ | |
2724 if (rettv != NULL && lp->ll_dict == &globvardict) | |
2725 { | |
2726 if (rettv->v_type == VAR_FUNC | |
2727 && var_check_func_name(key, lp->ll_di == NULL)) | |
2728 return NULL; | |
2729 if (!valid_varname(key)) | |
2730 return NULL; | |
2731 } | |
2732 | |
2719 if (lp->ll_di == NULL) | 2733 if (lp->ll_di == NULL) |
2720 { | 2734 { |
2735 /* Can't add "v:" variable. */ | |
2736 if (lp->ll_dict == &vimvardict) | |
2737 { | |
2738 EMSG2(_(e_illvar), name); | |
2739 return NULL; | |
2740 } | |
2741 | |
2721 /* Key does not exist in dict: may need to add it. */ | 2742 /* Key does not exist in dict: may need to add it. */ |
2722 if (*p == '[' || *p == '.' || unlet) | 2743 if (*p == '[' || *p == '.' || unlet) |
2723 { | 2744 { |
2724 if (!quiet) | 2745 if (!quiet) |
2725 EMSG2(_(e_dictkey), key); | 2746 EMSG2(_(e_dictkey), key); |
2735 clear_tv(&var1); | 2756 clear_tv(&var1); |
2736 if (lp->ll_newkey == NULL) | 2757 if (lp->ll_newkey == NULL) |
2737 p = NULL; | 2758 p = NULL; |
2738 break; | 2759 break; |
2739 } | 2760 } |
2761 /* existing variable, need to check if it can be changed */ | |
2762 else if (var_check_ro(lp->ll_di->di_flags, name)) | |
2763 return NULL; | |
2764 | |
2740 if (len == -1) | 2765 if (len == -1) |
2741 clear_tv(&var1); | 2766 clear_tv(&var1); |
2742 lp->ll_tv = &lp->ll_di->di_tv; | 2767 lp->ll_tv = &lp->ll_di->di_tv; |
2743 } | 2768 } |
2744 else | 2769 else |
19784 int copy; /* make copy of value in "tv" */ | 19809 int copy; /* make copy of value in "tv" */ |
19785 { | 19810 { |
19786 dictitem_T *v; | 19811 dictitem_T *v; |
19787 char_u *varname; | 19812 char_u *varname; |
19788 hashtab_T *ht; | 19813 hashtab_T *ht; |
19789 char_u *p; | |
19790 | 19814 |
19791 ht = find_var_ht(name, &varname); | 19815 ht = find_var_ht(name, &varname); |
19792 if (ht == NULL || *varname == NUL) | 19816 if (ht == NULL || *varname == NUL) |
19793 { | 19817 { |
19794 EMSG2(_(e_illvar), name); | 19818 EMSG2(_(e_illvar), name); |
19795 return; | 19819 return; |
19796 } | 19820 } |
19797 v = find_var_in_ht(ht, varname, TRUE); | 19821 v = find_var_in_ht(ht, varname, TRUE); |
19798 | 19822 |
19799 if (tv->v_type == VAR_FUNC) | 19823 if (tv->v_type == VAR_FUNC && var_check_func_name(name, v == NULL)) |
19800 { | 19824 return; |
19801 if (!(vim_strchr((char_u *)"wbs", name[0]) != NULL && name[1] == ':') | |
19802 && !ASCII_ISUPPER((name[0] != NUL && name[1] == ':') | |
19803 ? name[2] : name[0])) | |
19804 { | |
19805 EMSG2(_("E704: Funcref variable name must start with a capital: %s"), name); | |
19806 return; | |
19807 } | |
19808 /* Don't allow hiding a function. When "v" is not NULL we might be | |
19809 * assigning another function to the same var, the type is checked | |
19810 * below. */ | |
19811 if (v == NULL && function_exists(name)) | |
19812 { | |
19813 EMSG2(_("E705: Variable name conflicts with existing function: %s"), | |
19814 name); | |
19815 return; | |
19816 } | |
19817 } | |
19818 | 19825 |
19819 if (v != NULL) | 19826 if (v != NULL) |
19820 { | 19827 { |
19821 /* existing variable, need to clear the value */ | 19828 /* existing variable, need to clear the value */ |
19822 if (var_check_ro(v->di_flags, name) | 19829 if (var_check_ro(v->di_flags, name) |
19878 EMSG2(_(e_illvar), name); | 19885 EMSG2(_(e_illvar), name); |
19879 return; | 19886 return; |
19880 } | 19887 } |
19881 | 19888 |
19882 /* Make sure the variable name is valid. */ | 19889 /* Make sure the variable name is valid. */ |
19883 for (p = varname; *p != NUL; ++p) | 19890 if (!valid_varname(varname)) |
19884 if (!eval_isnamec1(*p) && (p == varname || !VIM_ISDIGIT(*p)) | 19891 return; |
19885 && *p != AUTOLOAD_CHAR) | |
19886 { | |
19887 EMSG2(_(e_illvar), varname); | |
19888 return; | |
19889 } | |
19890 | 19892 |
19891 v = (dictitem_T *)alloc((unsigned)(sizeof(dictitem_T) | 19893 v = (dictitem_T *)alloc((unsigned)(sizeof(dictitem_T) |
19892 + STRLEN(varname))); | 19894 + STRLEN(varname))); |
19893 if (v == NULL) | 19895 if (v == NULL) |
19894 return; | 19896 return; |
19946 { | 19948 { |
19947 EMSG2(_("E795: Cannot delete variable %s"), name); | 19949 EMSG2(_("E795: Cannot delete variable %s"), name); |
19948 return TRUE; | 19950 return TRUE; |
19949 } | 19951 } |
19950 return FALSE; | 19952 return FALSE; |
19953 } | |
19954 | |
19955 /* | |
19956 * Check if a funcref is assigned to a valid variable name. | |
19957 * Return TRUE and give an error if not. | |
19958 */ | |
19959 static int | |
19960 var_check_func_name(name, new_var) | |
19961 char_u *name; /* points to start of variable name */ | |
19962 int new_var; /* TRUE when creating the variable */ | |
19963 { | |
19964 if (!(vim_strchr((char_u *)"wbs", name[0]) != NULL && name[1] == ':') | |
19965 && !ASCII_ISUPPER((name[0] != NUL && name[1] == ':') | |
19966 ? name[2] : name[0])) | |
19967 { | |
19968 EMSG2(_("E704: Funcref variable name must start with a capital: %s"), | |
19969 name); | |
19970 return TRUE; | |
19971 } | |
19972 /* Don't allow hiding a function. When "v" is not NULL we might be | |
19973 * assigning another function to the same var, the type is checked | |
19974 * below. */ | |
19975 if (new_var && function_exists(name)) | |
19976 { | |
19977 EMSG2(_("E705: Variable name conflicts with existing function: %s"), | |
19978 name); | |
19979 return TRUE; | |
19980 } | |
19981 return FALSE; | |
19982 } | |
19983 | |
19984 /* | |
19985 * Check if a variable name is valid. | |
19986 * Return FALSE and give an error if not. | |
19987 */ | |
19988 static int | |
19989 valid_varname(varname) | |
19990 char_u *varname; | |
19991 { | |
19992 char_u *p; | |
19993 | |
19994 for (p = varname; *p != NUL; ++p) | |
19995 if (!eval_isnamec1(*p) && (p == varname || !VIM_ISDIGIT(*p)) | |
19996 && *p != AUTOLOAD_CHAR) | |
19997 { | |
19998 EMSG2(_(e_illvar), varname); | |
19999 return FALSE; | |
20000 } | |
20001 return TRUE; | |
19951 } | 20002 } |
19952 | 20003 |
19953 /* | 20004 /* |
19954 * Return TRUE if typeval "tv" is set to be locked (immutable). | 20005 * Return TRUE if typeval "tv" is set to be locked (immutable). |
19955 * Also give an error message, using "name". | 20006 * Also give an error message, using "name". |