diff options
author | Sean Dewar <seandewar@users.noreply.github.com> | 2022-01-18 12:22:54 +0000 |
---|---|---|
committer | Sean Dewar <seandewar@users.noreply.github.com> | 2022-01-18 12:49:30 +0000 |
commit | 1ae73e2d1c328a6181f4ebaebfc273e1d1c8d59d (patch) | |
tree | acacb77f0f9a62fd140ef2d9a685ee57f3e5160e | |
parent | fcf5dd34fdfde3a6632b96a88f66c1053cba08d1 (diff) | |
download | rneovim-1ae73e2d1c328a6181f4ebaebfc273e1d1c8d59d.tar.gz rneovim-1ae73e2d1c328a6181f4ebaebfc273e1d1c8d59d.tar.bz2 rneovim-1ae73e2d1c328a6181f4ebaebfc273e1d1c8d59d.zip |
vim-patch:8.2.0175: crash when removing list element in map()
Problem: Crash when removing list element in map().
Solution: Lock the list. (closes vim/vim#2652)
https://github.com/vim/vim/commit/db661fb95dc41b7a9438cf3cd4e77f8410bc81c0
-rw-r--r-- | src/nvim/eval.c | 10 | ||||
-rw-r--r-- | src/nvim/testdir/test_filter_map.vim | 10 |
2 files changed, 20 insertions, 0 deletions
diff --git a/src/nvim/eval.c b/src/nvim/eval.c index 6dbdc09c3b..d25903c12a 100644 --- a/src/nvim/eval.c +++ b/src/nvim/eval.c @@ -6468,6 +6468,10 @@ void filter_map(typval_T *argvars, typval_T *rettv, int map) if (argvars[0].v_type == VAR_DICT) { vimvars[VV_KEY].vv_type = VAR_STRING; + const VarLockStatus prev_lock = d->dv_lock; + if (map && d->dv_lock == VAR_UNLOCKED) { + d->dv_lock = VAR_LOCKED; + } ht = &d->dv_hashtab; hash_lock(ht); todo = (int)ht->ht_used; @@ -6498,6 +6502,7 @@ void 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) { vimvars[VV_KEY].vv_type = VAR_NUMBER; @@ -6530,6 +6535,10 @@ void filter_map(typval_T *argvars, typval_T *rettv, int map) assert(argvars[0].v_type == VAR_LIST); vimvars[VV_KEY].vv_type = VAR_NUMBER; + const VarLockStatus prev_lock = tv_list_locked(l); + if (map && tv_list_locked(l) == VAR_UNLOCKED) { + tv_list_set_lock(l, VAR_LOCKED); + } for (listitem_T *li = tv_list_first(l); li != NULL;) { if (map && var_check_lock(TV_LIST_ITEM_TV(li)->v_lock, arg_errmsg, @@ -6548,6 +6557,7 @@ void filter_map(typval_T *argvars, typval_T *rettv, int map) } idx++; } + tv_list_set_lock(l, prev_lock); } restore_vimvar(VV_KEY, &save_key); diff --git a/src/nvim/testdir/test_filter_map.vim b/src/nvim/testdir/test_filter_map.vim index a52a66ac2f..1cd3a2287b 100644 --- a/src/nvim/testdir/test_filter_map.vim +++ b/src/nvim/testdir/test_filter_map.vim @@ -88,4 +88,14 @@ func Test_map_filter_fails() call assert_fails("let l = filter('abc', '\"> \" . v:val')", 'E896:') 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 + " vim: shiftwidth=2 sts=2 expandtab |