mirror of
https://github.com/vim/vim.git
synced 2025-07-26 11:04:33 -04:00
patch 8.2.0175: crash when removing list element in map()
Problem: Crash when removing list element in map(). Solution: Lock the list. (closes #2652)
This commit is contained in:
parent
5d98dc2a48
commit
db661fb95d
10
src/list.c
10
src/list.c
@ -1782,6 +1782,10 @@ filter_map(typval_T *argvars, typval_T *rettv, int map)
|
|||||||
|
|
||||||
if (argvars[0].v_type == VAR_DICT)
|
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;
|
ht = &d->dv_hashtab;
|
||||||
hash_lock(ht);
|
hash_lock(ht);
|
||||||
todo = (int)ht->ht_used;
|
todo = (int)ht->ht_used;
|
||||||
@ -1813,6 +1817,7 @@ filter_map(typval_T *argvars, typval_T *rettv, int map)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
hash_unlock(ht);
|
hash_unlock(ht);
|
||||||
|
d->dv_lock = prev_lock;
|
||||||
}
|
}
|
||||||
else if (argvars[0].v_type == VAR_BLOB)
|
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
|
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_nr() doesn't set the type
|
||||||
set_vim_var_type(VV_KEY, VAR_NUMBER);
|
set_vim_var_type(VV_KEY, VAR_NUMBER);
|
||||||
|
|
||||||
range_list_materialize(l);
|
range_list_materialize(l);
|
||||||
|
if (map && l->lv_lock == 0)
|
||||||
|
l->lv_lock = VAR_LOCKED;
|
||||||
for (li = l->lv_first; li != NULL; li = nli)
|
for (li = l->lv_first; li != NULL; li = nli)
|
||||||
{
|
{
|
||||||
if (map && var_check_lock(li->li_tv.v_lock, arg_errmsg, TRUE))
|
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);
|
listitem_remove(l, li);
|
||||||
++idx;
|
++idx;
|
||||||
}
|
}
|
||||||
|
l->lv_lock = prev_lock;
|
||||||
}
|
}
|
||||||
|
|
||||||
restore_vimvar(VV_KEY, &save_key);
|
restore_vimvar(VV_KEY, &save_key);
|
||||||
|
@ -93,3 +93,13 @@ func Test_map_fails()
|
|||||||
call assert_fails('call map([1], "42 +")', 'E15:')
|
call assert_fails('call map([1], "42 +")', 'E15:')
|
||||||
call assert_fails('call filter([1], "42 +")', 'E15:')
|
call assert_fails('call filter([1], "42 +")', 'E15:')
|
||||||
endfunc
|
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
|
||||||
|
@ -742,6 +742,8 @@ static char *(features[]) =
|
|||||||
|
|
||||||
static int included_patches[] =
|
static int included_patches[] =
|
||||||
{ /* Add new patch number below this line */
|
{ /* Add new patch number below this line */
|
||||||
|
/**/
|
||||||
|
175,
|
||||||
/**/
|
/**/
|
||||||
174,
|
174,
|
||||||
/**/
|
/**/
|
||||||
|
Loading…
x
Reference in New Issue
Block a user