commit f89e1eb036f1028f41b439a58e6a44dff3bf7e5c
parent 4c2b7ddcddce5322226a05aa03c9d1a0ec5aa6b2
Author: Jan Edmund Lazo <jan.lazo@mail.utoronto.ca>
Date: Sat, 13 Sep 2025 01:31:29 -0400
vim-patch:8.1.1964: crash when using nested map() and filter() (#35715)
Problem: Crash when using nested map() and filter().
Solution: Do not set the v:key type to string without clearing the pointer.
https://github.com/vim/vim/commit/c36350bca3eed8ef97061e28c38b5b89cae1f13e
Port filter_map() changes from patch 8.1.1939.
Note: v8.1.1964 reverts a redundant change for `filter_map()` (now
within `filter_map_dict()`) from v8.1.1957.
Co-authored-by: Bram Moolenaar <Bram@vim.org>
Diffstat:
1 file changed, 7 insertions(+), 8 deletions(-)
diff --git a/src/nvim/eval.c b/src/nvim/eval.c
@@ -5412,8 +5412,6 @@ static void filter_map_dict(dict_T *d, filtermap_T filtermap, const char *func_n
d_ret = rettv->vval.v_dict;
}
- vimvars[VV_KEY].vv_type = VAR_STRING;
-
const VarLockStatus prev_lock = d->dv_lock;
if (d->dv_lock == VAR_UNLOCKED) {
d->dv_lock = VAR_LOCKED;
@@ -5425,11 +5423,11 @@ 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);
+ set_vim_var_string(VV_KEY, di->di_key, -1);
typval_T newtv;
bool rem;
int r = filter_map_one(&di->di_tv, expr, filtermap, &newtv, &rem);
- tv_clear(&vimvars[VV_KEY].vv_tv);
+ tv_clear(get_vim_var_tv(VV_KEY));
if (r == FAIL || did_emsg) {
tv_clear(&newtv);
break;
@@ -5496,7 +5494,7 @@ static void filter_map_blob(blob_T *blob_arg, filtermap_T filtermap, typval_T *e
.v_lock = VAR_UNLOCKED,
.vval.v_number = val,
};
- vimvars[VV_KEY].vv_nr = idx;
+ set_vim_var_nr(VV_KEY, idx);
typval_T newtv;
bool rem;
if (filter_map_one(&tv, expr, filtermap, &newtv, &rem) == FAIL
@@ -5614,7 +5612,7 @@ static void filter_map_list(list_T *l, filtermap_T filtermap, const char *func_n
&& value_check_lock(TV_LIST_ITEM_TV(li)->v_lock, arg_errmsg, TV_TRANSLATE)) {
break;
}
- vimvars[VV_KEY].vv_nr = idx;
+ set_vim_var_nr(VV_KEY, idx);
typval_T newtv;
bool rem;
if (filter_map_one(TV_LIST_ITEM_TV(li), expr, filtermap, &newtv, &rem) == FAIL) {
@@ -5684,15 +5682,16 @@ static void filter_map(typval_T *argvars, typval_T *rettv, filtermap_T filtermap
}
typval_T save_val;
+ typval_T save_key;
+
prepare_vimvar(VV_VAL, &save_val);
+ prepare_vimvar(VV_KEY, &save_key);
// We reset "did_emsg" to be able to detect whether an error
// occurred during evaluation of the expression.
int save_did_emsg = did_emsg;
did_emsg = false;
- typval_T save_key;
- prepare_vimvar(VV_KEY, &save_key);
if (argvars[0].v_type == VAR_DICT) {
filter_map_dict(argvars[0].vval.v_dict, filtermap, func_name,
arg_errmsg, expr, rettv);