]> granicus.if.org Git - vim/commitdiff
patch 8.2.1083: crash when using reduce() on a NULL list v8.2.1083
authorBram Moolenaar <Bram@vim.org>
Mon, 29 Jun 2020 18:09:36 +0000 (20:09 +0200)
committerBram Moolenaar <Bram@vim.org>
Mon, 29 Jun 2020 18:09:36 +0000 (20:09 +0200)
Problem:    Crash when using reduce() on a NULL list.
Solution:   Only access the list when not NULL.

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

index 56ed5fcdb69a9f61976955d18b909ba9cce30a64..ffcffa9f0c5cbafb4d80ed88139ea82d2ec88826 100644 (file)
@@ -2475,10 +2475,10 @@ f_reduce(typval_T *argvars, typval_T *rettv)
        list_T      *l = argvars[0].vval.v_list;
        listitem_T  *li = NULL;
        int         r;
-       int         prev_locked = l->lv_lock;
        int         called_emsg_start = called_emsg;
 
-       CHECK_LIST_MATERIALIZE(l);
+       if (l != NULL)
+           CHECK_LIST_MATERIALIZE(l);
        if (argvars[2].v_type == VAR_UNKNOWN)
        {
            if (l == NULL || l->lv_first == NULL)
@@ -2495,20 +2495,25 @@ f_reduce(typval_T *argvars, typval_T *rettv)
            if (l != NULL)
                li = l->lv_first;
        }
-
-       l->lv_lock = VAR_FIXED;  // disallow the list changing here
        copy_tv(&initial, rettv);
-       for ( ; li != NULL; li = li->li_next)
+
+       if (l != NULL)
        {
-           argv[0] = *rettv;
-           argv[1] = li->li_tv;
-           rettv->v_type = VAR_UNKNOWN;
-           r = call_func(func_name, -1, rettv, 2, argv, &funcexe);
-           clear_tv(&argv[0]);
-           if (r == FAIL || called_emsg != called_emsg_start)
-               break;
+           int     prev_locked = l->lv_lock;
+
+           l->lv_lock = VAR_FIXED;  // disallow the list changing here
+           for ( ; li != NULL; li = li->li_next)
+           {
+               argv[0] = *rettv;
+               argv[1] = li->li_tv;
+               rettv->v_type = VAR_UNKNOWN;
+               r = call_func(func_name, -1, rettv, 2, argv, &funcexe);
+               clear_tv(&argv[0]);
+               if (r == FAIL || called_emsg != called_emsg_start)
+                   break;
+           }
+           l->lv_lock = prev_locked;
        }
-       l->lv_lock = prev_locked;
     }
     else
     {
index 26b0e91e0336683ae0e183c15548dc9eec609d09..8a8d35328990009bac12b4ace220ee3774decac7 100644 (file)
@@ -718,6 +718,9 @@ func Test_reduce()
   call assert_fails("call reduce(g:lut, { acc, val -> EvilRemove() }, 1)", 'E742:')
   unlet g:lut
   delfunc EvilRemove
+
+  call assert_equal(42, reduce(test_null_list(), function('add'), 42))
+  call assert_equal(42, reduce(test_null_blob(), function('add'), 42))
 endfunc
 
 " splitting a string to a List using split()
index 9806b91f6a56319a98d5a3e6a70d9d027a544de2..2ffa1114798f3102638882b88e9b86dc50188394 100644 (file)
@@ -754,6 +754,8 @@ static char *(features[]) =
 
 static int included_patches[] =
 {   /* Add new patch number below this line */
+/**/
+    1083,
 /**/
     1082,
 /**/