From c36350bca3eed8ef97061e28c38b5b89cae1f13e Mon Sep 17 00:00:00 2001 From: Bram Moolenaar Date: Mon, 2 Sep 2019 20:44:07 +0200 Subject: [PATCH] patch 8.1.1964: crash when using nested map() and filter() Problem: Crash when using nested map() and filter(). Solution: Do not set the v:key type to string without clearing the pointer. --- src/eval.c | 21 +++++++++++---------- src/testdir/test_filter_map.vim | 6 ++++++ src/version.c | 2 ++ 3 files changed, 19 insertions(+), 10 deletions(-) diff --git a/src/eval.c b/src/eval.c index e75624345..8da8205d5 100644 --- a/src/eval.c +++ b/src/eval.c @@ -7185,8 +7185,6 @@ filter_map(typval_T *argvars, typval_T *rettv, int map) hashtab_T *ht; hashitem_T *hi; dict_T *d = NULL; - typval_T save_val; - typval_T save_key; blob_T *b = NULL; int rem; int todo; @@ -7225,18 +7223,19 @@ filter_map(typval_T *argvars, typval_T *rettv, int map) * was not passed as argument. */ if (expr->v_type != VAR_UNKNOWN) { + 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. */ + // We reset "did_emsg" to be able to detect whether an error + // occurred during evaluation of the expression. save_did_emsg = did_emsg; did_emsg = FALSE; - prepare_vimvar(VV_KEY, &save_key); if (argvars[0].v_type == VAR_DICT) { - set_vim_var_type(VV_KEY, VAR_STRING); - ht = &d->dv_hashtab; hash_lock(ht); todo = (int)ht->ht_used; @@ -7274,7 +7273,9 @@ filter_map(typval_T *argvars, typval_T *rettv, int map) int i; typval_T tv; + // set_vim_var_nr() doesn't set the type set_vim_var_type(VV_KEY, VAR_NUMBER); + for (i = 0; i < b->bv_ga.ga_len; i++) { tv.v_type = VAR_NUMBER; @@ -7285,7 +7286,7 @@ filter_map(typval_T *argvars, typval_T *rettv, int map) if (tv.v_type != VAR_NUMBER) { emsg(_(e_invalblob)); - return; + break; } tv.v_type = VAR_NUMBER; blob_set(b, i, tv.vval.v_number); @@ -7300,9 +7301,9 @@ filter_map(typval_T *argvars, typval_T *rettv, int map) } } } - else + else // argvars[0].v_type == VAR_LIST { - // argvars[0].v_type == VAR_LIST + // set_vim_var_nr() doesn't set the type set_vim_var_type(VV_KEY, VAR_NUMBER); for (li = l->lv_first; li != NULL; li = nli) diff --git a/src/testdir/test_filter_map.vim b/src/testdir/test_filter_map.vim index 1dd3a5b29..72a8d841e 100644 --- a/src/testdir/test_filter_map.vim +++ b/src/testdir/test_filter_map.vim @@ -53,6 +53,12 @@ func Test_filter_map_list_expr_funcref() call assert_equal([0, 2, 4, 6], map([1, 2, 3, 4], function('s:filter4'))) endfunc +func Test_filter_map_nested() + let x = {"x":10} + let r = map(range(2), 'filter(copy(x), "1")') + call assert_equal([x, x], r) +endfunc + " dict with funcref func Test_filter_map_dict_expr_funcref() let dict = {"foo": 1, "bar": 2, "baz": 3} diff --git a/src/version.c b/src/version.c index fe8b34ae6..c159705f3 100644 --- a/src/version.c +++ b/src/version.c @@ -761,6 +761,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ +/**/ + 1964, /**/ 1963, /**/ -- 2.40.0