mirror of
https://github.com/neovim/neovim.git
synced 2025-09-14 23:38:17 +00:00
vim-patch:8.1.0736: code for Blob not sufficiently tested
Problem: Code for Blob not sufficiently tested.
Solution: Add more tests. Fix uncovered crash. Add test_null_blob().
c0f5a78c15
eval0 and ex_echo's emsg-specific changes have already been ported.
These tests uncover another crash that was fixed in v8.1.0738.
This commit is contained in:
@@ -242,6 +242,7 @@ static struct vimvar {
|
||||
VV(VV__NULL_STRING, "_null_string", VAR_STRING, VV_RO),
|
||||
VV(VV__NULL_LIST, "_null_list", VAR_LIST, VV_RO),
|
||||
VV(VV__NULL_DICT, "_null_dict", VAR_DICT, VV_RO),
|
||||
VV(VV__NULL_BLOB, "_null_blob", VAR_BLOB, VV_RO),
|
||||
VV(VV_LUA, "lua", VAR_PARTIAL, VV_RO),
|
||||
};
|
||||
#undef VV
|
||||
@@ -2125,8 +2126,8 @@ char_u *get_lval(char_u *const name, typval_T *const rettv,
|
||||
return NULL;
|
||||
}
|
||||
if (rettv != NULL
|
||||
&& !(rettv->v_type == VAR_LIST || rettv->vval.v_list != NULL)
|
||||
&& !(rettv->v_type == VAR_BLOB || rettv->vval.v_blob != NULL)) {
|
||||
&& !(rettv->v_type == VAR_LIST && rettv->vval.v_list != NULL)
|
||||
&& !(rettv->v_type == VAR_BLOB && rettv->vval.v_blob != NULL)) {
|
||||
if (!quiet) {
|
||||
EMSG(_("E709: [:] requires a List or Blob value"));
|
||||
}
|
||||
@@ -2252,15 +2253,24 @@ char_u *get_lval(char_u *const name, typval_T *const rettv,
|
||||
}
|
||||
tv_clear(&var1);
|
||||
|
||||
if (lp->ll_n1 < 0 || lp->ll_n1 > tv_blob_len(lp->ll_tv->vval.v_blob)) {
|
||||
const int bloblen = tv_blob_len(lp->ll_tv->vval.v_blob);
|
||||
if (lp->ll_n1 < 0 || lp->ll_n1 > bloblen
|
||||
|| (lp->ll_range && lp->ll_n1 == bloblen)) {
|
||||
if (!quiet) {
|
||||
EMSGN(_(e_listidx), lp->ll_n1);
|
||||
EMSGN(_(e_blobidx), lp->ll_n1);
|
||||
}
|
||||
tv_clear(&var2);
|
||||
return NULL;
|
||||
}
|
||||
if (lp->ll_range && !lp->ll_empty2) {
|
||||
lp->ll_n2 = (long)tv_get_number(&var2);
|
||||
tv_clear(&var2);
|
||||
if (lp->ll_n2 < 0 || lp->ll_n2 >= bloblen || lp->ll_n2 < lp->ll_n1) {
|
||||
if (!quiet) {
|
||||
EMSGN(_(e_blobidx), lp->ll_n2);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
lp->ll_blob = lp->ll_tv->vval.v_blob;
|
||||
lp->ll_tv = NULL;
|
||||
@@ -2364,13 +2374,20 @@ static void set_var_lval(lval_T *lp, char_u *endp, typval_T *rettv,
|
||||
}
|
||||
|
||||
if (lp->ll_range && rettv->v_type == VAR_BLOB) {
|
||||
if (tv_blob_len(rettv->vval.v_blob) != tv_blob_len(lp->ll_blob)) {
|
||||
EMSG(_("E972: Blob value has more items than target"));
|
||||
return;
|
||||
if (lp->ll_empty2) {
|
||||
lp->ll_n2 = tv_blob_len(lp->ll_blob) - 1;
|
||||
}
|
||||
|
||||
for (int i = lp->ll_n1; i <= lp->ll_n2; i++) {
|
||||
tv_blob_set(lp->ll_blob, i, tv_blob_get(rettv->vval.v_blob, i));
|
||||
if (lp->ll_n2 - lp->ll_n1 + 1 != tv_blob_len(rettv->vval.v_blob)) {
|
||||
EMSG(_("E972: Blob value does not have the right number of bytes"));
|
||||
return;
|
||||
}
|
||||
if (lp->ll_empty2) {
|
||||
lp->ll_n2 = tv_blob_len(lp->ll_blob);
|
||||
}
|
||||
|
||||
for (int il = lp->ll_n1, ir = 0; il <= lp->ll_n2; il++) {
|
||||
tv_blob_set(lp->ll_blob, il, tv_blob_get(rettv->vval.v_blob, ir++));
|
||||
}
|
||||
} else {
|
||||
bool error = false;
|
||||
@@ -2386,9 +2403,8 @@ static void set_var_lval(lval_T *lp, char_u *endp, typval_T *rettv,
|
||||
if (lp->ll_n1 == gap->ga_len) {
|
||||
gap->ga_len++;
|
||||
}
|
||||
} else {
|
||||
EMSG(_(e_invrange));
|
||||
}
|
||||
// error for invalid range was already given in get_lval()
|
||||
}
|
||||
}
|
||||
} else if (op != NULL && *op != '=') {
|
||||
@@ -4591,7 +4607,7 @@ eval_index(
|
||||
case VAR_BLOB: {
|
||||
len = tv_blob_len(rettv->vval.v_blob);
|
||||
if (range) {
|
||||
// The resulting variable is a substring. If the indexes
|
||||
// The resulting variable is a sub-blob. If the indexes
|
||||
// are out of range the result is empty.
|
||||
if (n1 < 0) {
|
||||
n1 = len + n1;
|
||||
|
@@ -167,6 +167,7 @@ typedef enum {
|
||||
VV__NULL_STRING, // String with NULL value. For test purposes only.
|
||||
VV__NULL_LIST, // List with NULL value. For test purposes only.
|
||||
VV__NULL_DICT, // Dictionary with NULL value. For test purposes only.
|
||||
VV__NULL_BLOB, // Blob with NULL value. For test purposes only.
|
||||
VV_LUA,
|
||||
} VimVarIndex;
|
||||
|
||||
|
@@ -2174,13 +2174,17 @@ void tv_blob_unref(blob_T *const b)
|
||||
bool tv_blob_equal(const blob_T *const b1, const blob_T *const b2)
|
||||
FUNC_ATTR_WARN_UNUSED_RESULT
|
||||
{
|
||||
if (b1 == NULL || b2 == NULL) {
|
||||
return false;
|
||||
const int len1 = tv_blob_len(b1);
|
||||
const int len2 = tv_blob_len(b2);
|
||||
|
||||
// empty and NULL are considered the same
|
||||
if (len1 == 0 && len2 == 0) {
|
||||
return true;
|
||||
}
|
||||
if (b1 == b2) {
|
||||
return true;
|
||||
}
|
||||
if (tv_blob_len(b1) != tv_blob_len(b2)) {
|
||||
if (len1 != len2) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@@ -21,6 +21,12 @@ func Test_blob_create()
|
||||
call assert_equal(0xDE, get(b, 0))
|
||||
call assert_equal(0xEF, get(b, 3))
|
||||
call assert_fails('let x = get(b, 4)')
|
||||
|
||||
call assert_fails('let b = 0z1', 'E973:')
|
||||
call assert_fails('let b = 0z1x', 'E973:')
|
||||
call assert_fails('let b = 0z12345', 'E973:')
|
||||
|
||||
call assert_equal(0z, v:_null_blob)
|
||||
endfunc
|
||||
|
||||
" assignment to a blob
|
||||
@@ -32,6 +38,45 @@ func Test_blob_assign()
|
||||
let bcopy = b[:]
|
||||
call assert_equal(b, bcopy)
|
||||
call assert_false(b is bcopy)
|
||||
|
||||
let b = 0zDEADBEEF
|
||||
let b2 = b
|
||||
call assert_true(b is b2)
|
||||
let b[:] = 0z11223344
|
||||
call assert_equal(0z11223344, b)
|
||||
call assert_equal(0z11223344, b2)
|
||||
call assert_true(b is b2)
|
||||
|
||||
let b = 0zDEADBEEF
|
||||
let b[3:] = 0z66
|
||||
call assert_equal(0zDEADBE66, b)
|
||||
let b[:1] = 0z8899
|
||||
call assert_equal(0z8899BE66, b)
|
||||
|
||||
call assert_fails('let b[2:3] = 0z112233', 'E972:')
|
||||
call assert_fails('let b[2:3] = 0z11', 'E972:')
|
||||
call assert_fails('let b[3:2] = 0z', 'E979:')
|
||||
|
||||
let b = 0zDEADBEEF
|
||||
let b += 0z99
|
||||
call assert_equal(0zDEADBEEF99, b)
|
||||
|
||||
call assert_fails('let b .= 0z33', 'E734:')
|
||||
call assert_fails('let b .= "xx"', 'E734:')
|
||||
call assert_fails('let b += "xx"', 'E734:')
|
||||
call assert_fails('let b[1:1] .= 0z55', 'E734:')
|
||||
endfunc
|
||||
|
||||
func Test_blob_get_range()
|
||||
let b = 0z0011223344
|
||||
call assert_equal(0z2233, b[2:3])
|
||||
call assert_equal(0z223344, b[2:-1])
|
||||
call assert_equal(0z00, b[0:-5])
|
||||
call assert_equal(0z, b[0:-11])
|
||||
call assert_equal(0z44, b[-1:])
|
||||
call assert_equal(0z0011223344, b[:])
|
||||
call assert_equal(0z0011223344, b[:-1])
|
||||
call assert_equal(0z, b[5:6])
|
||||
endfunc
|
||||
|
||||
func Test_blob_to_string()
|
||||
@@ -44,8 +89,12 @@ endfunc
|
||||
func Test_blob_compare()
|
||||
let b1 = 0z0011
|
||||
let b2 = 0z1100
|
||||
let b3 = 0z001122
|
||||
call assert_true(b1 == b1)
|
||||
call assert_false(b1 == b2)
|
||||
call assert_false(b1 == b3)
|
||||
call assert_true(b1 != b2)
|
||||
call assert_true(b1 != b3)
|
||||
call assert_true(b1 == 0z0011)
|
||||
|
||||
call assert_false(b1 is b2)
|
||||
@@ -65,7 +114,7 @@ func Test_blob_range_assign()
|
||||
let b[1] = 0x11
|
||||
let b[2] = 0x22
|
||||
call assert_equal(0z001122, b)
|
||||
call assert_fails('let b[4] = 0x33')
|
||||
call assert_fails('let b[4] = 0x33', 'E979:')
|
||||
endfunc
|
||||
|
||||
func Test_blob_for_loop()
|
||||
@@ -173,4 +222,16 @@ func Test_blob_reverse()
|
||||
call assert_equal(0zDE, reverse(0zDE))
|
||||
endfunc
|
||||
|
||||
func Test_blob_lock()
|
||||
let b = 0z112233
|
||||
lockvar b
|
||||
call assert_fails('let b = 0z44', 'E741:')
|
||||
unlockvar b
|
||||
let b = 0z44
|
||||
endfunc
|
||||
|
||||
func Test_blob_sort()
|
||||
call assert_fails('call sort([1.0, 0z11], "f")', 'E975:')
|
||||
endfunc
|
||||
|
||||
" vim: shiftwidth=2 sts=2 expandtab
|
||||
|
Reference in New Issue
Block a user