]> granicus.if.org Git - vim/commitdiff
patch 8.2.2781: add() silently skips when adding to null list or blob v8.2.2781
authorBram Moolenaar <Bram@vim.org>
Sun, 18 Apr 2021 12:12:31 +0000 (14:12 +0200)
committerBram Moolenaar <Bram@vim.org>
Sun, 18 Apr 2021 12:12:31 +0000 (14:12 +0200)
Problem:    Add() silently skips when adding to null list or blob.
Solution:   Give an error in Vim9 script.  Allocate blob when it is NULL like
            with list and dict.

src/evalvars.c
src/list.c
src/testdir/test_blob.vim
src/testdir/test_vim9_builtin.vim
src/version.c
src/vim9execute.c

index ebfc42b187b9dffc75cd2bf68576a50f87c65093..9952ffcadfe9b0e392e054957d8a9cb37604147a 100644 (file)
@@ -2662,6 +2662,12 @@ eval_variable(
                if (tv->vval.v_list != NULL)
                    ++tv->vval.v_list->lv_refcount;
            }
+           else if (tv->v_type == VAR_BLOB && tv->vval.v_blob == NULL)
+           {
+               tv->vval.v_blob = blob_alloc();
+               if (tv->vval.v_blob != NULL)
+                   ++tv->vval.v_blob->bv_refcount;
+           }
            copy_tv(tv, rettv);
        }
     }
index 56b2188ff4d64b36f3037bb9eab9ed2fd67f1b9e..988b2d982c4bca43bad88e8f5670eb14f32f9ea8 100644 (file)
@@ -2412,22 +2412,33 @@ f_mapnew(typval_T *argvars, typval_T *rettv)
     void
 f_add(typval_T *argvars, typval_T *rettv)
 {
-    list_T     *l;
-    blob_T     *b;
-
     rettv->vval.v_number = 1; // Default: Failed
     if (argvars[0].v_type == VAR_LIST)
     {
-       if ((l = argvars[0].vval.v_list) != NULL
-               && !value_check_lock(l->lv_lock,
-                                        (char_u *)N_("add() argument"), TRUE)
+       list_T  *l = argvars[0].vval.v_list;
+
+       if (l == NULL)
+       {
+           if (in_vim9script())
+               emsg(_(e_cannot_add_to_null_list));
+       }
+       else if (!value_check_lock(l->lv_lock,
+                                         (char_u *)N_("add() argument"), TRUE)
                && list_append_tv(l, &argvars[1]) == OK)
+       {
            copy_tv(&argvars[0], rettv);
+       }
     }
     else if (argvars[0].v_type == VAR_BLOB)
     {
-       if ((b = argvars[0].vval.v_blob) != NULL
-               && !value_check_lock(b->bv_lock,
+       blob_T  *b = argvars[0].vval.v_blob;
+
+       if (b == NULL)
+       {
+           if (in_vim9script())
+               emsg(_(e_cannot_add_to_null_blob));
+       }
+       else if (!value_check_lock(b->bv_lock,
                                         (char_u *)N_("add() argument"), TRUE))
        {
            int         error = FALSE;
index fa482b432fb95aeaefa61dbb3b64df28ee56bd31..f54d7733f206cd37322486523890be54d723cba0 100644 (file)
@@ -316,27 +316,59 @@ func Test_blob_for_loop()
 endfunc
 
 func Test_blob_concatenate()
-  let b = 0z0011
-  let b += 0z2233
-  call assert_equal(0z00112233, b)
+  let lines =<< trim END
+      VAR b = 0z0011
+      LET b += 0z2233
+      call assert_equal(0z00112233, b)
+
+      LET b = 0zDEAD + 0zBEEF
+      call assert_equal(0zDEADBEEF, b)
+  END
+  call CheckLegacyAndVim9Success(lines)
 
-  call assert_fails('let b += "a"')
-  call assert_fails('let b += 88')
+  let lines =<< trim END
+      VAR b = 0z0011
+      LET b += "a"
+  END
+  call CheckLegacyAndVim9Failure(lines, ['E734:', 'E1012:', 'E734:'])
 
-  let b = 0zDEAD + 0zBEEF
-  call assert_equal(0zDEADBEEF, b)
+  let lines =<< trim END
+      VAR b = 0z0011
+      LET b += 88
+  END
+  call CheckLegacyAndVim9Failure(lines, ['E734:', 'E1012:', 'E734:'])
 endfunc
 
 func Test_blob_add()
+  let lines =<< trim END
+      VAR b = 0z0011
+      call add(b, 0x22)
+      call assert_equal(0z001122, b)
+  END
+  call CheckLegacyAndVim9Success(lines)
+
+  " Only works in legacy script
   let b = 0z0011
-  call add(b, 0x22)
-  call assert_equal(0z001122, b)
   call add(b, '51')
-  call assert_equal(0z00112233, b)
+  call assert_equal(0z001133, b)
   call assert_equal(1, add(test_null_blob(), 0x22))
 
-  call assert_fails('call add(b, [9])', 'E745:')
-  call assert_fails('call add("", 0x01)', 'E897:')
+  let lines =<< trim END
+      VAR b = 0z0011
+      call add(b, [9])
+  END
+  call CheckLegacyAndVim9Failure(lines, ['E745:', 'E1012:', 'E745:'])
+
+  let lines =<< trim END
+      VAR b = 0z0011
+      call add("", 0x01)
+  END
+  call CheckLegacyAndVim9Failure(lines, 'E897:')
+
+  let lines =<< trim END
+      add(test_null_blob(), 0x22)
+  END
+  call CheckDefExecAndScriptFailure(lines, 'E1131:')
 endfunc
 
 func Test_blob_empty()
index 5c13d512775264f14704e5ea0399b68c5b00fd46..bf15a415951092961eef6ef2d320dc6861099f87 100644 (file)
@@ -86,11 +86,24 @@ def Test_add_list()
   END
   CheckDefFailure(lines, 'E1012:', 2)
 
+  lines =<< trim END
+      add(test_null_list(), 123)
+  END
+  CheckDefExecAndScriptFailure(lines, 'E1130:', 1)
+
   lines =<< trim END
       var l: list<number> = test_null_list()
       add(l, 123)
   END
   CheckDefExecFailure(lines, 'E1130:', 2)
+
+  # Getting variable with NULL list allocates a new list at script level
+  lines =<< trim END
+      vim9script
+      var l: list<number> = test_null_list()
+      add(l, 123)
+  END
+  CheckScriptSuccess(lines)
 enddef
 
 def Test_add_blob()
@@ -108,11 +121,24 @@ def Test_add_blob()
   END
   CheckDefFailure(lines, 'E1012:', 2)
 
+  lines =<< trim END
+      add(test_null_blob(), 123)
+  END
+  CheckDefExecAndScriptFailure(lines, 'E1131:', 1)
+
   lines =<< trim END
       var b: blob = test_null_blob()
       add(b, 123)
   END
   CheckDefExecFailure(lines, 'E1131:', 2)
+
+  # Getting variable with NULL blob allocates a new blob at script level
+  lines =<< trim END
+      vim9script
+      var b: blob = test_null_blob()
+      add(b, 123)
+  END
+  CheckScriptSuccess(lines)
 enddef
 
 def Test_append()
index c3e2ea852752dfeceeeb88a44e174b9049f75c89..6216faff7b7ab8c6c60e19f5752b151729a7eeba 100644 (file)
@@ -750,6 +750,8 @@ static char *(features[]) =
 
 static int included_patches[] =
 {   /* Add new patch number below this line */
+/**/
+    2781,
 /**/
     2780,
 /**/
index 4e1af4e583d2f97ce05025e05526764efe680cd4..60b58f98a3674f35413a4bd3bb263dc563db058a 100644 (file)
@@ -1020,6 +1020,10 @@ allocate_if_null(typval_T *tv)
            if (tv->vval.v_dict == NULL)
                (void)rettv_dict_alloc(tv);
            break;
+       case VAR_BLOB:
+           if (tv->vval.v_blob == NULL)
+               (void)rettv_blob_alloc(tv);
+           break;
        default:
            break;
     }