diff options
author | Bram Moolenaar <Bram@vim.org> | 2020-01-29 22:17:16 +0100 |
---|---|---|
committer | Bram Moolenaar <Bram@vim.org> | 2020-01-29 22:17:16 +0100 |
commit | db661fb95dc41b7a9438cf3cd4e77f8410bc81c0 (patch) | |
tree | abaa599d8defc53879ca396f43f5fe816e21709e | |
parent | 5d98dc2a48156d44139b75c689bd3137ff7fe8bf (diff) | |
download | vim-git-db661fb95dc41b7a9438cf3cd4e77f8410bc81c0.tar.gz |
patch 8.2.0175: crash when removing list element in map()v8.2.0175
Problem: Crash when removing list element in map().
Solution: Lock the list. (closes #2652)
-rw-r--r-- | src/list.c | 10 | ||||
-rw-r--r-- | src/testdir/test_filter_map.vim | 10 | ||||
-rw-r--r-- | src/version.c | 2 |
3 files changed, 22 insertions, 0 deletions
diff --git a/src/list.c b/src/list.c index 855a20d07..518423b71 100644 --- a/src/list.c +++ b/src/list.c @@ -1782,6 +1782,10 @@ filter_map(typval_T *argvars, typval_T *rettv, int map) if (argvars[0].v_type == VAR_DICT) { + int prev_lock = d->dv_lock; + + if (map && d->dv_lock == 0) + d->dv_lock = VAR_LOCKED; ht = &d->dv_hashtab; hash_lock(ht); todo = (int)ht->ht_used; @@ -1813,6 +1817,7 @@ filter_map(typval_T *argvars, typval_T *rettv, int map) } } hash_unlock(ht); + d->dv_lock = prev_lock; } else if (argvars[0].v_type == VAR_BLOB) { @@ -1855,10 +1860,14 @@ filter_map(typval_T *argvars, typval_T *rettv, int map) } else // argvars[0].v_type == VAR_LIST { + int prev_lock = l->lv_lock; + // set_vim_var_nr() doesn't set the type set_vim_var_type(VV_KEY, VAR_NUMBER); range_list_materialize(l); + if (map && l->lv_lock == 0) + l->lv_lock = VAR_LOCKED; for (li = l->lv_first; li != NULL; li = nli) { if (map && var_check_lock(li->li_tv.v_lock, arg_errmsg, TRUE)) @@ -1872,6 +1881,7 @@ filter_map(typval_T *argvars, typval_T *rettv, int map) listitem_remove(l, li); ++idx; } + l->lv_lock = prev_lock; } restore_vimvar(VV_KEY, &save_key); diff --git a/src/testdir/test_filter_map.vim b/src/testdir/test_filter_map.vim index e144538de..577e0ce0b 100644 --- a/src/testdir/test_filter_map.vim +++ b/src/testdir/test_filter_map.vim @@ -93,3 +93,13 @@ func Test_map_fails() call assert_fails('call map([1], "42 +")', 'E15:') call assert_fails('call filter([1], "42 +")', 'E15:') endfunc + +func Test_map_and_modify() + let l = ["abc"] + " cannot change the list halfway a map() + call assert_fails('call map(l, "remove(l, 0)[0]")', 'E741:') + + let d = #{a: 1, b: 2, c: 3} + call assert_fails('call map(d, "remove(d, v:key)[0]")', 'E741:') + call assert_fails('echo map(d, {k,v -> remove(d, k)})', 'E741:') +endfunc diff --git a/src/version.c b/src/version.c index df1fe0d04..0306e4722 100644 --- a/src/version.c +++ b/src/version.c @@ -743,6 +743,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ /**/ + 175, +/**/ 174, /**/ 173, |