diff options
author | zeertzjq <zeertzjq@outlook.com> | 2023-08-17 16:58:05 +0800 |
---|---|---|
committer | zeertzjq <zeertzjq@outlook.com> | 2023-08-17 17:03:10 +0800 |
commit | 8ac9abd4fad5837c2cc7a858827efb2e53b852be (patch) | |
tree | 08cc7e0d3d47b7c5bb0e2f220021d5d44563e398 /src/nvim/eval.c | |
parent | 1ed12a2e10708f0d4ce39e5adb94d189455f4d98 (diff) | |
download | rneovim-8ac9abd4fad5837c2cc7a858827efb2e53b852be.tar.gz rneovim-8ac9abd4fad5837c2cc7a858827efb2e53b852be.tar.bz2 rneovim-8ac9abd4fad5837c2cc7a858827efb2e53b852be.zip |
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 vim/vim#12183)
https://github.com/vim/vim/commit/e6d40dcdc7227594935d2db01eca29f0e575dcee
Co-authored-by: Ernie Rael <errael@raelity.com>
Diffstat (limited to 'src/nvim/eval.c')
-rw-r--r-- | src/nvim/eval.c | 26 |
1 files changed, 17 insertions, 9 deletions
diff --git a/src/nvim/eval.c b/src/nvim/eval.c index 589bee6f84..9baf3209a2 100644 --- a/src/nvim/eval.c +++ b/src/nvim/eval.c @@ -5040,7 +5040,6 @@ static void filter_map_dict(dict_T *d, filtermap_T filtermap, const char *func_n return; } - const VarLockStatus prev_lock = d->dv_lock; dict_T *d_ret = NULL; if (filtermap == FILTERMAP_MAPNEW) { @@ -5050,7 +5049,8 @@ static void filter_map_dict(dict_T *d, filtermap_T filtermap, const char *func_n vimvars[VV_KEY].vv_type = VAR_STRING; - if (filtermap != FILTERMAP_FILTER && d->dv_lock == VAR_UNLOCKED) { + const VarLockStatus prev_lock = d->dv_lock; + if (d->dv_lock == VAR_UNLOCKED) { d->dv_lock = VAR_LOCKED; } hash_lock(&d->dv_hashtab); @@ -5060,7 +5060,6 @@ static void filter_map_dict(dict_T *d, filtermap_T filtermap, const char *func_n || var_check_ro(di->di_flags, arg_errmsg, TV_TRANSLATE))) { break; } - vimvars[VV_KEY].vv_str = xstrdup(di->di_key); typval_T newtv; bool rem; @@ -5097,14 +5096,16 @@ static void filter_map_dict(dict_T *d, filtermap_T filtermap, const char *func_n /// Implementation of map() and filter() for a Blob. static void filter_map_blob(blob_T *blob_arg, filtermap_T filtermap, typval_T *expr, - typval_T *rettv) + const char *arg_errmsg, typval_T *rettv) { if (filtermap == FILTERMAP_MAPNEW) { rettv->v_type = VAR_BLOB; rettv->vval.v_blob = NULL; } - blob_T *b; - if ((b = blob_arg) == NULL) { + blob_T *b = blob_arg; + if (b == NULL + || (filtermap == FILTERMAP_FILTER + && value_check_lock(b->bv_lock, arg_errmsg, TV_TRANSLATE))) { return; } @@ -5117,6 +5118,11 @@ static void filter_map_blob(blob_T *blob_arg, filtermap_T filtermap, typval_T *e vimvars[VV_KEY].vv_type = VAR_NUMBER; + const VarLockStatus prev_lock = b->bv_lock; + if (b->bv_lock == 0) { + b->bv_lock = VAR_LOCKED; + } + for (int i = 0, idx = 0; i < b->bv_ga.ga_len; i++) { const varnumber_T val = tv_blob_get(b, i); typval_T tv = { @@ -5148,6 +5154,8 @@ static void filter_map_blob(blob_T *blob_arg, filtermap_T filtermap, typval_T *e } idx++; } + + b->bv_lock = prev_lock; } /// Implementation of map() and filter() for a String. @@ -5215,7 +5223,6 @@ static void filter_map_list(list_T *l, filtermap_T filtermap, const char *func_n return; } - const VarLockStatus prev_lock = tv_list_locked(l); list_T *l_ret = NULL; if (filtermap == FILTERMAP_MAPNEW) { @@ -5225,7 +5232,8 @@ static void filter_map_list(list_T *l, filtermap_T filtermap, const char *func_n vimvars[VV_KEY].vv_type = VAR_NUMBER; - if (filtermap != FILTERMAP_FILTER && tv_list_locked(l) == VAR_UNLOCKED) { + const VarLockStatus prev_lock = tv_list_locked(l); + if (tv_list_locked(l) == VAR_UNLOCKED) { tv_list_set_lock(l, VAR_LOCKED); } @@ -5311,7 +5319,7 @@ static void filter_map(typval_T *argvars, typval_T *rettv, filtermap_T filtermap filter_map_dict(argvars[0].vval.v_dict, filtermap, func_name, arg_errmsg, expr, rettv); } else if (argvars[0].v_type == VAR_BLOB) { - filter_map_blob(argvars[0].vval.v_blob, filtermap, expr, rettv); + filter_map_blob(argvars[0].vval.v_blob, filtermap, expr, arg_errmsg, rettv); } else if (argvars[0].v_type == VAR_STRING) { filter_map_string(tv_get_string(&argvars[0]), filtermap, expr, rettv); } else { |