Skip to content

Commit 80d7395

Browse files
seandewarbrammool
authored andcommitted
patch 8.2.3284: no error for insert() or remove() changing a locked blob
Problem: No error for insert() or remove() changing a locked blob. Solution: Check a blob is not locked before changing it. (Sean Dewar, closes #8696)
1 parent 0eec851 commit 80d7395

8 files changed

Lines changed: 79 additions & 36 deletions

File tree

src/blob.c

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -412,16 +412,19 @@ blob_set_range(blob_T *dest, long n1, long n2, typval_T *src)
412412
* "remove({blob})" function
413413
*/
414414
void
415-
blob_remove(typval_T *argvars, typval_T *rettv)
415+
blob_remove(typval_T *argvars, typval_T *rettv, char_u *arg_errmsg)
416416
{
417+
blob_T *b = argvars[0].vval.v_blob;
417418
int error = FALSE;
418419
long idx;
419420
long end;
420421

422+
if (b != NULL && value_check_lock(b->bv_lock, arg_errmsg, TRUE))
423+
return;
424+
421425
idx = (long)tv_get_number_chk(&argvars[1], &error);
422426
if (!error)
423427
{
424-
blob_T *b = argvars[0].vval.v_blob;
425428
int len = blob_len(b);
426429
char_u *p;
427430

src/errors.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -366,7 +366,8 @@ EXTERN char e_returning_value_in_function_without_return_type[]
366366
INIT(= N_("E1096: Returning a value in a function without a return type"));
367367
EXTERN char e_line_incomplete[]
368368
INIT(= N_("E1097: Line incomplete"));
369-
// E1098 unused
369+
EXTERN char e_string_list_or_blob_required[]
370+
INIT(= N_("E1098: String, List or Blob required"));
370371
EXTERN char e_unknown_error_while_executing_str[]
371372
INIT(= N_("E1099: Unknown error while executing %s"));
372373
EXTERN char e_cannot_declare_script_variable_in_function[]

src/eval.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1749,7 +1749,7 @@ eval_for_line(
17491749
}
17501750
else
17511751
{
1752-
emsg(_(e_listreq));
1752+
emsg(_(e_string_list_or_blob_required));
17531753
clear_tv(&tv);
17541754
}
17551755
}

src/list.c

Lines changed: 32 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -2817,45 +2817,49 @@ f_insert(typval_T *argvars, typval_T *rettv)
28172817

28182818
if (argvars[0].v_type == VAR_BLOB)
28192819
{
2820-
int val, len;
2821-
char_u *p;
2820+
blob_T *b = argvars[0].vval.v_blob;
28222821

2823-
if (argvars[0].vval.v_blob == NULL)
2822+
if (b == NULL)
28242823
{
28252824
if (in_vim9script())
28262825
emsg(_(e_cannot_add_to_null_blob));
2827-
return;
28282826
}
2829-
2830-
len = blob_len(argvars[0].vval.v_blob);
2831-
if (argvars[2].v_type != VAR_UNKNOWN)
2827+
else if (!value_check_lock(b->bv_lock,
2828+
(char_u *)N_("insert() argument"), TRUE))
28322829
{
2833-
before = (long)tv_get_number_chk(&argvars[2], &error);
2830+
int val, len;
2831+
char_u *p;
2832+
2833+
len = blob_len(b);
2834+
if (argvars[2].v_type != VAR_UNKNOWN)
2835+
{
2836+
before = (long)tv_get_number_chk(&argvars[2], &error);
2837+
if (error)
2838+
return; // type error; errmsg already given
2839+
if (before < 0 || before > len)
2840+
{
2841+
semsg(_(e_invarg2), tv_get_string(&argvars[2]));
2842+
return;
2843+
}
2844+
}
2845+
val = tv_get_number_chk(&argvars[1], &error);
28342846
if (error)
2835-
return; // type error; errmsg already given
2836-
if (before < 0 || before > len)
2847+
return;
2848+
if (val < 0 || val > 255)
28372849
{
2838-
semsg(_(e_invarg2), tv_get_string(&argvars[2]));
2850+
semsg(_(e_invarg2), tv_get_string(&argvars[1]));
28392851
return;
28402852
}
2841-
}
2842-
val = tv_get_number_chk(&argvars[1], &error);
2843-
if (error)
2844-
return;
2845-
if (val < 0 || val > 255)
2846-
{
2847-
semsg(_(e_invarg2), tv_get_string(&argvars[1]));
2848-
return;
2849-
}
28502853

2851-
if (ga_grow(&argvars[0].vval.v_blob->bv_ga, 1) == FAIL)
2852-
return;
2853-
p = (char_u *)argvars[0].vval.v_blob->bv_ga.ga_data;
2854-
mch_memmove(p + before + 1, p + before, (size_t)len - before);
2855-
*(p + before) = val;
2856-
++argvars[0].vval.v_blob->bv_ga.ga_len;
2854+
if (ga_grow(&b->bv_ga, 1) == FAIL)
2855+
return;
2856+
p = (char_u *)b->bv_ga.ga_data;
2857+
mch_memmove(p + before + 1, p + before, (size_t)len - before);
2858+
*(p + before) = val;
2859+
++b->bv_ga.ga_len;
28572860

2858-
copy_tv(&argvars[0], rettv);
2861+
copy_tv(&argvars[0], rettv);
2862+
}
28592863
}
28602864
else if (argvars[0].v_type != VAR_LIST)
28612865
semsg(_(e_listblobarg), "insert()");
@@ -2917,7 +2921,7 @@ f_remove(typval_T *argvars, typval_T *rettv)
29172921
if (argvars[0].v_type == VAR_DICT)
29182922
dict_remove(argvars, rettv, arg_errmsg);
29192923
else if (argvars[0].v_type == VAR_BLOB)
2920-
blob_remove(argvars, rettv);
2924+
blob_remove(argvars, rettv, arg_errmsg);
29212925
else if (argvars[0].v_type == VAR_LIST)
29222926
list_remove(argvars, rettv, arg_errmsg);
29232927
else

src/proto/blob.pro

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,5 +18,5 @@ int blob_slice_or_index(blob_T *blob, int is_range, varnumber_T n1, varnumber_T
1818
int check_blob_index(long bloblen, varnumber_T n1, int quiet);
1919
int check_blob_range(long bloblen, varnumber_T n1, varnumber_T n2, int quiet);
2020
int blob_set_range(blob_T *dest, long n1, long n2, typval_T *src);
21-
void blob_remove(typval_T *argvars, typval_T *rettv);
21+
void blob_remove(typval_T *argvars, typval_T *rettv, char_u *arg_errmsg);
2222
/* vim: set ft=c : */

src/testdir/test_blob.vim

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -428,6 +428,23 @@ func Test_blob_func_remove()
428428
call remove(test_null_blob(), 1, 2)
429429
END
430430
call CheckLegacyAndVim9Failure(lines, 'E979:')
431+
432+
let lines =<< trim END
433+
let b = 0zDEADBEEF
434+
lockvar b
435+
call remove(b, 0)
436+
unlockvar b
437+
END
438+
call CheckScriptFailure(lines, 'E741:')
439+
440+
" can only check at script level, not in a :def function
441+
let lines =<< trim END
442+
vim9script
443+
var b = 0zDEADBEEF
444+
lockvar b
445+
remove(b, 0)
446+
END
447+
call CheckScriptFailure(lines, 'E741:')
431448
endfunc
432449

433450
func Test_blob_read_write()
@@ -543,6 +560,22 @@ func Test_blob_insert()
543560
insert(test_null_blob(), 0x33)
544561
END
545562
call CheckDefExecAndScriptFailure(lines, 'E1131:')
563+
564+
let lines =<< trim END
565+
let b = 0zDEADBEEF
566+
lockvar b
567+
call insert(b, 3)
568+
unlockvar b
569+
END
570+
call CheckScriptFailure(lines, 'E741:')
571+
572+
let lines =<< trim END
573+
vim9script
574+
var b = 0zDEADBEEF
575+
lockvar b
576+
insert(b, 3)
577+
END
578+
call CheckScriptFailure(lines, 'E741:')
546579
endfunc
547580

548581
func Test_blob_reverse()

src/testdir/test_eval_stuff.vim

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -65,9 +65,9 @@ func Test_E963()
6565
endfunc
6666

6767
func Test_for_invalid()
68-
call assert_fails("for x in 99", 'E714:')
69-
call assert_fails("for x in function('winnr')", 'E714:')
70-
call assert_fails("for x in {'a': 9}", 'E714:')
68+
call assert_fails("for x in 99", 'E1098:')
69+
call assert_fails("for x in function('winnr')", 'E1098:')
70+
call assert_fails("for x in {'a': 9}", 'E1098:')
7171

7272
if 0
7373
/1/5/2/s/\n

src/version.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -755,6 +755,8 @@ static char *(features[]) =
755755

756756
static int included_patches[] =
757757
{ /* Add new patch number below this line */
758+
/**/
759+
3284,
758760
/**/
759761
3283,
760762
/**/

0 commit comments

Comments
 (0)