0
0
mirror of https://github.com/vim/vim.git synced 2025-09-25 03:54:15 -04:00

patch 8.2.2781: add() silently skips when adding to null list or blob

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.
This commit is contained in:
Bram Moolenaar
2021-04-18 14:12:31 +02:00
parent d551d6c268
commit b7c21afef1
6 changed files with 101 additions and 20 deletions

View File

@@ -2662,6 +2662,12 @@ eval_variable(
if (tv->vval.v_list != NULL) if (tv->vval.v_list != NULL)
++tv->vval.v_list->lv_refcount; ++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); copy_tv(tv, rettv);
} }
} }

View File

@@ -2412,22 +2412,33 @@ f_mapnew(typval_T *argvars, typval_T *rettv)
void void
f_add(typval_T *argvars, typval_T *rettv) f_add(typval_T *argvars, typval_T *rettv)
{ {
list_T *l;
blob_T *b;
rettv->vval.v_number = 1; // Default: Failed rettv->vval.v_number = 1; // Default: Failed
if (argvars[0].v_type == VAR_LIST) if (argvars[0].v_type == VAR_LIST)
{ {
if ((l = argvars[0].vval.v_list) != NULL list_T *l = argvars[0].vval.v_list;
&& !value_check_lock(l->lv_lock,
(char_u *)N_("add() argument"), TRUE) 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) && list_append_tv(l, &argvars[1]) == OK)
{
copy_tv(&argvars[0], rettv); copy_tv(&argvars[0], rettv);
}
} }
else if (argvars[0].v_type == VAR_BLOB) else if (argvars[0].v_type == VAR_BLOB)
{ {
if ((b = argvars[0].vval.v_blob) != NULL blob_T *b = argvars[0].vval.v_blob;
&& !value_check_lock(b->bv_lock,
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)) (char_u *)N_("add() argument"), TRUE))
{ {
int error = FALSE; int error = FALSE;

View File

@@ -316,27 +316,59 @@ func Test_blob_for_loop()
endfunc endfunc
func Test_blob_concatenate() func Test_blob_concatenate()
let b = 0z0011 let lines =<< trim END
let b += 0z2233 VAR b = 0z0011
call assert_equal(0z00112233, b) LET b += 0z2233
call assert_equal(0z00112233, b)
call assert_fails('let b += "a"') LET b = 0zDEAD + 0zBEEF
call assert_fails('let b += 88') call assert_equal(0zDEADBEEF, b)
END
call CheckLegacyAndVim9Success(lines)
let b = 0zDEAD + 0zBEEF let lines =<< trim END
call assert_equal(0zDEADBEEF, b) VAR b = 0z0011
LET b += "a"
END
call CheckLegacyAndVim9Failure(lines, ['E734:', 'E1012:', 'E734:'])
let lines =<< trim END
VAR b = 0z0011
LET b += 88
END
call CheckLegacyAndVim9Failure(lines, ['E734:', 'E1012:', 'E734:'])
endfunc endfunc
func Test_blob_add() 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 let b = 0z0011
call add(b, 0x22)
call assert_equal(0z001122, b)
call add(b, '51') 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_equal(1, add(test_null_blob(), 0x22))
call assert_fails('call add(b, [9])', 'E745:') let lines =<< trim END
call assert_fails('call add("", 0x01)', 'E897:') 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 endfunc
func Test_blob_empty() func Test_blob_empty()

View File

@@ -86,11 +86,24 @@ def Test_add_list()
END END
CheckDefFailure(lines, 'E1012:', 2) CheckDefFailure(lines, 'E1012:', 2)
lines =<< trim END
add(test_null_list(), 123)
END
CheckDefExecAndScriptFailure(lines, 'E1130:', 1)
lines =<< trim END lines =<< trim END
var l: list<number> = test_null_list() var l: list<number> = test_null_list()
add(l, 123) add(l, 123)
END END
CheckDefExecFailure(lines, 'E1130:', 2) 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 enddef
def Test_add_blob() def Test_add_blob()
@@ -108,11 +121,24 @@ def Test_add_blob()
END END
CheckDefFailure(lines, 'E1012:', 2) CheckDefFailure(lines, 'E1012:', 2)
lines =<< trim END
add(test_null_blob(), 123)
END
CheckDefExecAndScriptFailure(lines, 'E1131:', 1)
lines =<< trim END lines =<< trim END
var b: blob = test_null_blob() var b: blob = test_null_blob()
add(b, 123) add(b, 123)
END END
CheckDefExecFailure(lines, 'E1131:', 2) 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 enddef
def Test_append() def Test_append()

View File

@@ -750,6 +750,8 @@ static char *(features[]) =
static int included_patches[] = static int included_patches[] =
{ /* Add new patch number below this line */ { /* Add new patch number below this line */
/**/
2781,
/**/ /**/
2780, 2780,
/**/ /**/

View File

@@ -1020,6 +1020,10 @@ allocate_if_null(typval_T *tv)
if (tv->vval.v_dict == NULL) if (tv->vval.v_dict == NULL)
(void)rettv_dict_alloc(tv); (void)rettv_dict_alloc(tv);
break; break;
case VAR_BLOB:
if (tv->vval.v_blob == NULL)
(void)rettv_blob_alloc(tv);
break;
default: default:
break; break;
} }