diff options
author | Bram Moolenaar <Bram@vim.org> | 2022-04-01 15:26:58 +0100 |
---|---|---|
committer | Bram Moolenaar <Bram@vim.org> | 2022-04-01 15:26:58 +0100 |
commit | 22ebd172e48ba060c8a7bae3dbf6480b7596d937 (patch) | |
tree | ff1a418ba71300eaf1ddd85e37e682b16ade4958 /src | |
parent | ffe6e646dc6aede3bce062e40256ce0edc64bc08 (diff) |
patch 8.2.4662: no error for using out of range list indexv8.2.4662
Problem: No error for using out of range list index.
Solution: Check list index at script level like in compiled function.
(closes #10051)
Diffstat (limited to 'src')
-rw-r--r-- | src/eval.c | 3 | ||||
-rw-r--r-- | src/evalvars.c | 8 | ||||
-rw-r--r-- | src/list.c | 12 | ||||
-rw-r--r-- | src/proto/list.pro | 2 | ||||
-rw-r--r-- | src/testdir/test_vim9_assign.vim | 6 | ||||
-rw-r--r-- | src/version.c | 2 | ||||
-rw-r--r-- | src/vim.h | 2 | ||||
-rw-r--r-- | src/vim9execute.c | 2 |
8 files changed, 26 insertions, 11 deletions
diff --git a/src/eval.c b/src/eval.c index 0d24f76888..2cde642161 100644 --- a/src/eval.c +++ b/src/eval.c @@ -1311,7 +1311,8 @@ get_lval( lp->ll_dict = NULL; lp->ll_list = lp->ll_tv->vval.v_list; - lp->ll_li = check_range_index_one(lp->ll_list, &lp->ll_n1, quiet); + lp->ll_li = check_range_index_one(lp->ll_list, &lp->ll_n1, + (flags & GLV_ASSIGN_WITH_OP) == 0, quiet); if (lp->ll_li == NULL) { clear_tv(&var2); diff --git a/src/evalvars.c b/src/evalvars.c index 202ada1914..dd70427d32 100644 --- a/src/evalvars.c +++ b/src/evalvars.c @@ -1647,13 +1647,15 @@ ex_let_one( { lval_T lv; char_u *p; + int lval_flags = (flags & (ASSIGN_NO_DECL | ASSIGN_DECL)) + ? GLV_NO_DECL : 0; + if (op != NULL && *op != '=') + lval_flags |= GLV_ASSIGN_WITH_OP; // ":let var = expr": Set internal variable. // ":let var: type = expr": Set internal variable with type. // ":let {expr} = expr": Idem, name made with curly braces - p = get_lval(arg, tv, &lv, FALSE, FALSE, - (flags & (ASSIGN_NO_DECL | ASSIGN_DECL)) - ? GLV_NO_DECL : 0, FNE_CHECK_START); + p = get_lval(arg, tv, &lv, FALSE, FALSE, lval_flags, FNE_CHECK_START); if (p != NULL && lv.ll_name != NULL) { if (endchars != NULL && vim_strchr(endchars, diff --git a/src/list.c b/src/list.c index 666fb5ad61..50bf3afc0f 100644 --- a/src/list.c +++ b/src/list.c @@ -760,18 +760,20 @@ list_insert(list_T *l, listitem_T *ni, listitem_T *item) /* * Get the list item in "l" with index "n1". "n1" is adjusted if needed. - * In Vim9, it is at the end of the list, add an item. + * In Vim9, it is at the end of the list, add an item if "can_append" is TRUE. * Return NULL if there is no such item. */ listitem_T * -check_range_index_one(list_T *l, long *n1, int quiet) +check_range_index_one(list_T *l, long *n1, int can_append, int quiet) { - listitem_T *li = list_find_index(l, n1); + long orig_n1 = *n1; + listitem_T *li = list_find_index(l, n1); if (li == NULL) { // Vim9: Allow for adding an item at the end. - if (in_vim9script() && *n1 == l->lv_len && l->lv_lock == 0) + if (can_append && in_vim9script() + && *n1 == l->lv_len && l->lv_lock == 0) { list_append_number(l, 0); li = list_find_index(l, n1); @@ -779,7 +781,7 @@ check_range_index_one(list_T *l, long *n1, int quiet) if (li == NULL) { if (!quiet) - semsg(_(e_list_index_out_of_range_nr), *n1); + semsg(_(e_list_index_out_of_range_nr), orig_n1); return NULL; } } diff --git a/src/proto/list.pro b/src/proto/list.pro index 468775e59a..3f77f04d15 100644 --- a/src/proto/list.pro +++ b/src/proto/list.pro @@ -30,7 +30,7 @@ int list_append_string(list_T *l, char_u *str, int len); int list_append_number(list_T *l, varnumber_T n); int list_insert_tv(list_T *l, typval_T *tv, listitem_T *item); void list_insert(list_T *l, listitem_T *ni, listitem_T *item); -listitem_T *check_range_index_one(list_T *l, long *n1, int quiet); +listitem_T *check_range_index_one(list_T *l, long *n1, int can_append, int quiet); int check_range_index_two(list_T *l, long *n1, listitem_T *li1, long *n2, int quiet); int list_assign_range(list_T *dest, list_T *src, long idx1_arg, long idx2, int empty_idx2, char_u *op, char_u *varname); void f_flatten(typval_T *argvars, typval_T *rettv); diff --git a/src/testdir/test_vim9_assign.vim b/src/testdir/test_vim9_assign.vim index 0a25ca4a7e..57d205ceef 100644 --- a/src/testdir/test_vim9_assign.vim +++ b/src/testdir/test_vim9_assign.vim @@ -288,6 +288,12 @@ def Test_assign_concat() s ..= {a: 2} END v9.CheckDefAndScriptFailure(lines, ['E1105: Cannot convert dict to string', 'E734: Wrong variable type for .='], 2) + + lines =<< trim END + var ls: list<string> = [] + ls[-1] ..= 'foo' + END + v9.CheckDefExecAndScriptFailure(lines, 'E684: list index out of range: -1', 2) enddef def Test_assign_register() diff --git a/src/version.c b/src/version.c index 95a0f0e0cf..d3be7a8536 100644 --- a/src/version.c +++ b/src/version.c @@ -751,6 +751,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ /**/ + 4662, +/**/ 4661, /**/ 4660, @@ -2632,6 +2632,7 @@ typedef enum { #define TFN_NO_DECL 0x20 // only used for GLV_NO_DECL #define TFN_COMPILING 0x40 // only used for GLV_COMPILING #define TFN_NEW_FUNC 0x80 // defining a new function +#define TFN_ASSIGN_WITH_OP 0x100 // only for GLV_ASSIGN_WITH_OP // Values for get_lval() flags argument: #define GLV_QUIET TFN_QUIET // no error messages @@ -2639,6 +2640,7 @@ typedef enum { #define GLV_READ_ONLY TFN_READ_ONLY // will not change the var #define GLV_NO_DECL TFN_NO_DECL // assignment without :var or :let #define GLV_COMPILING TFN_COMPILING // variable may be defined later +#define GLV_ASSIGN_WITH_OP TFN_ASSIGN_WITH_OP // assignment with operator #define DO_NOT_FREE_CNT 99999 // refcount for dict or list that should not // be freed. diff --git a/src/vim9execute.c b/src/vim9execute.c index a1710407a8..a6789b5999 100644 --- a/src/vim9execute.c +++ b/src/vim9execute.c @@ -1988,7 +1988,7 @@ execute_storerange(isn_T *iptr, ectx_T *ectx) else n2 = (long)tv_get_number_chk(tv_idx2, NULL); - li1 = check_range_index_one(tv_dest->vval.v_list, &n1, FALSE); + li1 = check_range_index_one(tv_dest->vval.v_list, &n1, TRUE, FALSE); if (li1 == NULL) status = FAIL; else |