forked from aniani/vim
patch 9.0.1416: crash when collection is modified when using filter()
Problem: Crash when collection is modified when using filter(). Solution: Lock the list/dict/blob. (Ernie Rael, closes #12183)
This commit is contained in:
committed by
Bram Moolenaar
parent
7c4516fe93
commit
e6d40dcdc7
11
src/blob.c
11
src/blob.c
@@ -592,9 +592,10 @@ blob_filter_map(
|
|||||||
blob_T *blob_arg,
|
blob_T *blob_arg,
|
||||||
filtermap_T filtermap,
|
filtermap_T filtermap,
|
||||||
typval_T *expr,
|
typval_T *expr,
|
||||||
|
char_u *arg_errmsg,
|
||||||
typval_T *rettv)
|
typval_T *rettv)
|
||||||
{
|
{
|
||||||
blob_T *b;
|
blob_T *b = blob_arg;
|
||||||
int i;
|
int i;
|
||||||
typval_T tv;
|
typval_T tv;
|
||||||
varnumber_T val;
|
varnumber_T val;
|
||||||
@@ -609,7 +610,8 @@ blob_filter_map(
|
|||||||
rettv->v_type = VAR_BLOB;
|
rettv->v_type = VAR_BLOB;
|
||||||
rettv->vval.v_blob = NULL;
|
rettv->vval.v_blob = NULL;
|
||||||
}
|
}
|
||||||
if ((b = blob_arg) == NULL)
|
if (b == NULL || (filtermap == FILTERMAP_FILTER
|
||||||
|
&& value_check_lock(b->bv_lock, arg_errmsg, TRUE)))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
b_ret = b;
|
b_ret = b;
|
||||||
@@ -623,6 +625,10 @@ blob_filter_map(
|
|||||||
// 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);
|
||||||
|
|
||||||
|
int prev_lock = b->bv_lock;
|
||||||
|
if (b->bv_lock == 0)
|
||||||
|
b->bv_lock = VAR_LOCKED;
|
||||||
|
|
||||||
// Create one funccal_T for all eval_expr_typval() calls.
|
// Create one funccal_T for all eval_expr_typval() calls.
|
||||||
fc = eval_expr_get_funccal(expr, &newtv);
|
fc = eval_expr_get_funccal(expr, &newtv);
|
||||||
|
|
||||||
@@ -658,6 +664,7 @@ blob_filter_map(
|
|||||||
++idx;
|
++idx;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
b->bv_lock = prev_lock;
|
||||||
if (fc != NULL)
|
if (fc != NULL)
|
||||||
remove_funccal();
|
remove_funccal();
|
||||||
}
|
}
|
||||||
|
@@ -1305,7 +1305,7 @@ dict_extend_func(
|
|||||||
action = (char_u *)"force";
|
action = (char_u *)"force";
|
||||||
|
|
||||||
if (type != NULL && check_typval_arg_type(type, &argvars[1],
|
if (type != NULL && check_typval_arg_type(type, &argvars[1],
|
||||||
func_name, 2) == FAIL)
|
func_name, 2) == FAIL)
|
||||||
return;
|
return;
|
||||||
dict_extend(d1, d2, action, func_name);
|
dict_extend(d1, d2, action, func_name);
|
||||||
|
|
||||||
@@ -1333,7 +1333,6 @@ dict_filter_map(
|
|||||||
typval_T *expr,
|
typval_T *expr,
|
||||||
typval_T *rettv)
|
typval_T *rettv)
|
||||||
{
|
{
|
||||||
int prev_lock;
|
|
||||||
dict_T *d_ret = NULL;
|
dict_T *d_ret = NULL;
|
||||||
hashtab_T *ht;
|
hashtab_T *ht;
|
||||||
hashitem_T *hi;
|
hashitem_T *hi;
|
||||||
@@ -1353,8 +1352,6 @@ dict_filter_map(
|
|||||||
&& value_check_lock(d->dv_lock, arg_errmsg, TRUE)))
|
&& value_check_lock(d->dv_lock, arg_errmsg, TRUE)))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
prev_lock = d->dv_lock;
|
|
||||||
|
|
||||||
if (filtermap == FILTERMAP_MAPNEW)
|
if (filtermap == FILTERMAP_MAPNEW)
|
||||||
{
|
{
|
||||||
if (rettv_dict_alloc(rettv) == FAIL)
|
if (rettv_dict_alloc(rettv) == FAIL)
|
||||||
@@ -1365,7 +1362,8 @@ dict_filter_map(
|
|||||||
// Create one funccal_T for all eval_expr_typval() calls.
|
// Create one funccal_T for all eval_expr_typval() calls.
|
||||||
fc = eval_expr_get_funccal(expr, &newtv);
|
fc = eval_expr_get_funccal(expr, &newtv);
|
||||||
|
|
||||||
if (filtermap != FILTERMAP_FILTER && d->dv_lock == 0)
|
int prev_lock = d->dv_lock;
|
||||||
|
if (d->dv_lock == 0)
|
||||||
d->dv_lock = VAR_LOCKED;
|
d->dv_lock = VAR_LOCKED;
|
||||||
ht = &d->dv_hashtab;
|
ht = &d->dv_hashtab;
|
||||||
hash_lock(ht);
|
hash_lock(ht);
|
||||||
|
12
src/list.c
12
src/list.c
@@ -2398,7 +2398,7 @@ list_filter_map(
|
|||||||
// 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);
|
||||||
|
|
||||||
if (filtermap != FILTERMAP_FILTER && l->lv_lock == 0)
|
if (l->lv_lock == 0)
|
||||||
l->lv_lock = VAR_LOCKED;
|
l->lv_lock = VAR_LOCKED;
|
||||||
|
|
||||||
// Create one funccal_T for all eval_expr_typval() calls.
|
// Create one funccal_T for all eval_expr_typval() calls.
|
||||||
@@ -2576,15 +2576,15 @@ filter_map(typval_T *argvars, typval_T *rettv, filtermap_T filtermap)
|
|||||||
|
|
||||||
if (argvars[0].v_type == VAR_DICT)
|
if (argvars[0].v_type == VAR_DICT)
|
||||||
dict_filter_map(argvars[0].vval.v_dict, filtermap, type, func_name,
|
dict_filter_map(argvars[0].vval.v_dict, filtermap, type, func_name,
|
||||||
arg_errmsg, expr, rettv);
|
arg_errmsg, expr, rettv);
|
||||||
else if (argvars[0].v_type == VAR_BLOB)
|
else if (argvars[0].v_type == VAR_BLOB)
|
||||||
blob_filter_map(argvars[0].vval.v_blob, filtermap, expr, rettv);
|
blob_filter_map(argvars[0].vval.v_blob, filtermap, expr,
|
||||||
|
arg_errmsg, rettv);
|
||||||
else if (argvars[0].v_type == VAR_STRING)
|
else if (argvars[0].v_type == VAR_STRING)
|
||||||
string_filter_map(tv_get_string(&argvars[0]), filtermap, expr,
|
string_filter_map(tv_get_string(&argvars[0]), filtermap, expr, rettv);
|
||||||
rettv);
|
|
||||||
else // argvars[0].v_type == VAR_LIST
|
else // argvars[0].v_type == VAR_LIST
|
||||||
list_filter_map(argvars[0].vval.v_list, filtermap, type, func_name,
|
list_filter_map(argvars[0].vval.v_list, filtermap, type, func_name,
|
||||||
arg_errmsg, expr, rettv);
|
arg_errmsg, expr, rettv);
|
||||||
|
|
||||||
restore_vimvar(VV_KEY, &save_key);
|
restore_vimvar(VV_KEY, &save_key);
|
||||||
restore_vimvar(VV_VAL, &save_val);
|
restore_vimvar(VV_VAL, &save_val);
|
||||||
|
@@ -20,7 +20,7 @@ int check_blob_range(long bloblen, varnumber_T n1, varnumber_T n2, int quiet);
|
|||||||
int blob_set_range(blob_T *dest, long n1, long n2, typval_T *src);
|
int blob_set_range(blob_T *dest, long n1, long n2, typval_T *src);
|
||||||
void blob_add(typval_T *argvars, typval_T *rettv);
|
void blob_add(typval_T *argvars, typval_T *rettv);
|
||||||
void blob_remove(typval_T *argvars, typval_T *rettv, char_u *arg_errmsg);
|
void blob_remove(typval_T *argvars, typval_T *rettv, char_u *arg_errmsg);
|
||||||
void blob_filter_map(blob_T *blob_arg, filtermap_T filtermap, typval_T *expr, typval_T *rettv);
|
void blob_filter_map(blob_T *blob_arg, filtermap_T filtermap, typval_T *expr, char_u *arg_errmsg, typval_T *rettv);
|
||||||
void blob_insert_func(typval_T *argvars, typval_T *rettv);
|
void blob_insert_func(typval_T *argvars, typval_T *rettv);
|
||||||
void blob_reduce(typval_T *argvars, typval_T *expr, typval_T *rettv);
|
void blob_reduce(typval_T *argvars, typval_T *expr, typval_T *rettv);
|
||||||
void blob_reverse(blob_T *b, typval_T *rettv);
|
void blob_reverse(blob_T *b, typval_T *rettv);
|
||||||
|
@@ -116,6 +116,21 @@ func Test_map_and_modify()
|
|||||||
let d = #{a: 1, b: 2, c: 3}
|
let d = #{a: 1, b: 2, c: 3}
|
||||||
call assert_fails('call map(d, "remove(d, v:key)[0]")', 'E741:')
|
call assert_fails('call map(d, "remove(d, v:key)[0]")', 'E741:')
|
||||||
call assert_fails('echo map(d, {k,v -> remove(d, k)})', 'E741:')
|
call assert_fails('echo map(d, {k,v -> remove(d, k)})', 'E741:')
|
||||||
|
|
||||||
|
let b = 0z1234
|
||||||
|
call assert_fails('call filter(b, "remove(b, 0)")', 'E741:')
|
||||||
|
endfunc
|
||||||
|
|
||||||
|
func Test_filter_and_modify()
|
||||||
|
let l = [0]
|
||||||
|
" cannot change the list halfway a map()
|
||||||
|
call assert_fails('call filter(l, "remove(l, 0)")', 'E741:')
|
||||||
|
|
||||||
|
let d = #{a: 0, b: 0, c: 0}
|
||||||
|
call assert_fails('call filter(d, "remove(d, v:key)")', 'E741:')
|
||||||
|
|
||||||
|
let b = 0z1234
|
||||||
|
call assert_fails('call filter(b, "remove(b, 0)")', 'E741:')
|
||||||
endfunc
|
endfunc
|
||||||
|
|
||||||
func Test_mapnew_dict()
|
func Test_mapnew_dict()
|
||||||
|
@@ -695,6 +695,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 */
|
||||||
|
/**/
|
||||||
|
1416,
|
||||||
/**/
|
/**/
|
||||||
1415,
|
1415,
|
||||||
/**/
|
/**/
|
||||||
|
Reference in New Issue
Block a user