]> granicus.if.org Git - vim/commitdiff
patch 8.2.0175: crash when removing list element in map() v8.2.0175
authorBram Moolenaar <Bram@vim.org>
Wed, 29 Jan 2020 21:17:16 +0000 (22:17 +0100)
committerBram Moolenaar <Bram@vim.org>
Wed, 29 Jan 2020 21:17:16 +0000 (22:17 +0100)
Problem:    Crash when removing list element in map().
Solution:   Lock the list. (closes #2652)

src/list.c
src/testdir/test_filter_map.vim
src/version.c

index 855a20d0719c2a1f13c5672b9913eac5e21a71e0..518423b7146c76ed88846b2f213ecce4594b7ced 100644 (file)
@@ -1782,6 +1782,10 @@ filter_map(typval_T *argvars, typval_T *rettv, int map)
 
        if (argvars[0].v_type == VAR_DICT)
        {
+           int     prev_lock = d->dv_lock;
+
+           if (map && d->dv_lock == 0)
+               d->dv_lock = VAR_LOCKED;
            ht = &d->dv_hashtab;
            hash_lock(ht);
            todo = (int)ht->ht_used;
@@ -1813,6 +1817,7 @@ filter_map(typval_T *argvars, typval_T *rettv, int map)
                }
            }
            hash_unlock(ht);
+           d->dv_lock = prev_lock;
        }
        else if (argvars[0].v_type == VAR_BLOB)
        {
@@ -1855,10 +1860,14 @@ filter_map(typval_T *argvars, typval_T *rettv, int map)
        }
        else // argvars[0].v_type == VAR_LIST
        {
+           int prev_lock = l->lv_lock;
+
            // set_vim_var_nr() doesn't set the type
            set_vim_var_type(VV_KEY, VAR_NUMBER);
 
            range_list_materialize(l);
+           if (map && l->lv_lock == 0)
+               l->lv_lock = VAR_LOCKED;
            for (li = l->lv_first; li != NULL; li = nli)
            {
                if (map && var_check_lock(li->li_tv.v_lock, arg_errmsg, TRUE))
@@ -1872,6 +1881,7 @@ filter_map(typval_T *argvars, typval_T *rettv, int map)
                    listitem_remove(l, li);
                ++idx;
            }
+           l->lv_lock = prev_lock;
        }
 
        restore_vimvar(VV_KEY, &save_key);
index e144538de672479b87dec1bd2316eb487434a57a..577e0ce0bd4217204df61b74b3411659f2b9793e 100644 (file)
@@ -93,3 +93,13 @@ func Test_map_fails()
   call assert_fails('call map([1], "42 +")', 'E15:')
   call assert_fails('call filter([1], "42 +")', 'E15:')
 endfunc
+
+func Test_map_and_modify()
+  let l = ["abc"]
+  " cannot change the list halfway a map()
+  call assert_fails('call map(l, "remove(l, 0)[0]")', 'E741:')
+
+  let d = #{a: 1, b: 2, c: 3}
+  call assert_fails('call map(d, "remove(d, v:key)[0]")', 'E741:')
+  call assert_fails('echo map(d, {k,v -> remove(d, k)})', 'E741:')
+endfunc
index df1fe0d045ecfcf2d8a810a681b19cf660db8d47..0306e4722395bfbba6d94abd32819cede543ff11 100644 (file)
@@ -742,6 +742,8 @@ static char *(features[]) =
 
 static int included_patches[] =
 {   /* Add new patch number below this line */
+/**/
+    175,
 /**/
     174,
 /**/