]> granicus.if.org Git - vim/commitdiff
patch 8.1.1964: crash when using nested map() and filter() v8.1.1964
authorBram Moolenaar <Bram@vim.org>
Mon, 2 Sep 2019 18:44:07 +0000 (20:44 +0200)
committerBram Moolenaar <Bram@vim.org>
Mon, 2 Sep 2019 18:44:07 +0000 (20:44 +0200)
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
src/testdir/test_filter_map.vim
src/version.c

index e75624345a1d1181fb269923035f47b4863d9c64..8da8205d5064d6b19657cd61405c84c5f2970126 100644 (file)
@@ -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)
index 1dd3a5b29f481fb790b2c9e242fb7e1406b0ba47..72a8d841e95a5f146ed3036f3de8b63d3c2ce872 100644 (file)
@@ -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}
index fe8b34ae651a42d09db6fe4bbdb6b95b66c8469c..c159705f3e3eec7106c46b231b84cd3c67ca1674 100644 (file)
@@ -761,6 +761,8 @@ static char *(features[]) =
 
 static int included_patches[] =
 {   /* Add new patch number below this line */
+/**/
+    1964,
 /**/
     1963,
 /**/