diff options
author | Bram Moolenaar <Bram@vim.org> | 2021-11-22 20:10:18 +0000 |
---|---|---|
committer | Bram Moolenaar <Bram@vim.org> | 2021-11-22 20:10:18 +0000 |
commit | 3b3755fe19e9ded2a1c45f14b2c6fa065bcaf2c6 (patch) | |
tree | 92ed5f9e604bc7f42fcf6ddf0fd2499f46accb85 /src | |
parent | 7a53f29c031f54ab67a803e5e3f8cb44e4edc4bc (diff) |
patch 8.2.3650: Vim9: for loop variable can be a list memberv8.2.3650
Problem: Vim9: for loop variable can be a list member.
Solution: Check for valid variable name. (closes #9179)
Diffstat (limited to 'src')
-rw-r--r-- | src/dict.c | 2 | ||||
-rw-r--r-- | src/eval.c | 2 | ||||
-rw-r--r-- | src/evalvars.c | 7 | ||||
-rw-r--r-- | src/proto/evalvars.pro | 2 | ||||
-rw-r--r-- | src/testdir/test_vim9_script.vim | 26 | ||||
-rw-r--r-- | src/version.c | 2 | ||||
-rw-r--r-- | src/vim9compile.c | 6 |
7 files changed, 38 insertions, 9 deletions
diff --git a/src/dict.c b/src/dict.c index aa3c611372..032c1b5a81 100644 --- a/src/dict.c +++ b/src/dict.c @@ -1102,7 +1102,7 @@ dict_extend(dict_T *d1, dict_T *d2, char_u *action, char *func_name) && HI2DI(hi2)->di_tv.v_type == VAR_FUNC && var_wrong_func_name(hi2->hi_key, di1 == NULL)) break; - if (!valid_varname(hi2->hi_key, TRUE)) + if (!valid_varname(hi2->hi_key, -1, TRUE)) break; } diff --git a/src/eval.c b/src/eval.c index 41291a2441..0e8b6a6776 100644 --- a/src/eval.c +++ b/src/eval.c @@ -1128,7 +1128,7 @@ get_lval( wrong = (lp->ll_dict->dv_scope == VAR_DEF_SCOPE && rettv->v_type == VAR_FUNC && var_wrong_func_name(key, lp->ll_di == NULL)) - || !valid_varname(key, TRUE); + || !valid_varname(key, -1, TRUE); if (len != -1) key[len] = prevval; if (wrong) diff --git a/src/evalvars.c b/src/evalvars.c index afbab79ff4..b56073453b 100644 --- a/src/evalvars.c +++ b/src/evalvars.c @@ -3431,7 +3431,7 @@ set_var_const( // Make sure the variable name is valid. In Vim9 script an autoload // variable must be prefixed with "g:". - if (!valid_varname(varname, !vim9script + if (!valid_varname(varname, -1, !vim9script || STRNCMP(name, "g:", 2) == 0)) goto failed; @@ -3631,14 +3631,15 @@ value_check_lock(int lock, char_u *name, int use_gettext) /* * Check if a variable name is valid. When "autoload" is true "#" is allowed. + * If "len" is -1 use all of "varname", otherwise up to "varname[len]". * Return FALSE and give an error if not. */ int -valid_varname(char_u *varname, int autoload) +valid_varname(char_u *varname, int len, int autoload) { char_u *p; - for (p = varname; *p != NUL; ++p) + for (p = varname; len < 0 ? *p != NUL : p < varname + len; ++p) if (!eval_isnamec1(*p) && (p == varname || !VIM_ISDIGIT(*p)) && !(autoload && *p == AUTOLOAD_CHAR)) { diff --git a/src/proto/evalvars.pro b/src/proto/evalvars.pro index 58c1222956..778506f88d 100644 --- a/src/proto/evalvars.pro +++ b/src/proto/evalvars.pro @@ -78,7 +78,7 @@ int var_check_lock(int flags, char_u *name, int use_gettext); int var_check_fixed(int flags, char_u *name, int use_gettext); int var_wrong_func_name(char_u *name, int new_var); int value_check_lock(int lock, char_u *name, int use_gettext); -int valid_varname(char_u *varname, int autoload); +int valid_varname(char_u *varname, int len, int autoload); void reset_v_option_vars(void); void assert_error(garray_T *gap); int var_exists(char_u *var); diff --git a/src/testdir/test_vim9_script.vim b/src/testdir/test_vim9_script.vim index ca5d7beb08..989627f95f 100644 --- a/src/testdir/test_vim9_script.vim +++ b/src/testdir/test_vim9_script.vim @@ -2865,11 +2865,35 @@ def Test_for_loop_fails() endfor END CheckDefExecAndScriptFailure(lines, 'E1012: Type mismatch; expected job but got string', 2) + + lines =<< trim END + var i = 0 + for i in [1, 2, 3] + echo i + endfor + END + CheckDefExecAndScriptFailure2(lines, 'E1017:', 'E1041:') + + lines =<< trim END + var l = [0] + for l[0] in [1, 2, 3] + echo l[0] + endfor + END + CheckDefExecAndScriptFailure2(lines, 'E461:', 'E1017:') + + lines =<< trim END + var d = {x: 0} + for d.x in [1, 2, 3] + echo d.x + endfor + END + CheckDefExecAndScriptFailure2(lines, 'E461:', 'E1017:') enddef def Test_for_loop_script_var() # cannot use s:var in a :def function - CheckDefFailure(['for s:var in range(3)', 'echo 3'], 'E1101:') + CheckDefFailure(['for s:var in range(3)', 'echo 3'], 'E461:') # can use s:var in Vim9 script, with or without s: var lines =<< trim END diff --git a/src/version.c b/src/version.c index 3851e8043f..121ce6eae9 100644 --- a/src/version.c +++ b/src/version.c @@ -758,6 +758,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ /**/ + 3650, +/**/ 3649, /**/ 3648, diff --git a/src/vim9compile.c b/src/vim9compile.c index 303b1e3127..934f41b47a 100644 --- a/src/vim9compile.c +++ b/src/vim9compile.c @@ -8220,8 +8220,8 @@ compile_for(char_u *arg_start, cctx_T *cctx) for (idx = 0; idx < var_count; ++idx) { assign_dest_T dest = dest_local; - int opt_flags = 0; - int vimvaridx = -1; + int opt_flags = 0; + int vimvaridx = -1; type_T *type = &t_any; type_T *lhs_type = &t_any; where_T where = WHERE_INIT; @@ -8255,6 +8255,8 @@ compile_for(char_u *arg_start, cctx_T *cctx) } else { + if (!valid_varname(arg, varlen, FALSE)) + goto failed; if (lookup_local(arg, varlen, NULL, cctx) == OK) { semsg(_(e_variable_already_declared), arg); |