neovim

Neovim text editor
git clone https://git.dasho.dev/neovim.git
Log | Files | Refs | README

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:
Msrc/nvim/eval.c | 15+++++++--------
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);