From 80d7395dcfe96158428da6bb3d28a6eee1244e28 Mon Sep 17 00:00:00 2001 From: Sean Dewar Date: Wed, 4 Aug 2021 19:25:54 +0200 Subject: [PATCH] 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) --- src/blob.c | 7 ++-- src/errors.h | 3 +- src/eval.c | 2 +- src/list.c | 60 ++++++++++++++++++--------------- src/proto/blob.pro | 2 +- src/testdir/test_blob.vim | 33 ++++++++++++++++++ src/testdir/test_eval_stuff.vim | 6 ++-- src/version.c | 2 ++ 8 files changed, 79 insertions(+), 36 deletions(-) diff --git a/src/blob.c b/src/blob.c index 57fe58b05..2138ac074 100644 --- a/src/blob.c +++ b/src/blob.c @@ -412,16 +412,19 @@ blob_set_range(blob_T *dest, long n1, long n2, typval_T *src) * "remove({blob})" function */ void -blob_remove(typval_T *argvars, typval_T *rettv) +blob_remove(typval_T *argvars, typval_T *rettv, char_u *arg_errmsg) { + blob_T *b = argvars[0].vval.v_blob; int error = FALSE; long idx; long end; + if (b != NULL && value_check_lock(b->bv_lock, arg_errmsg, TRUE)) + return; + idx = (long)tv_get_number_chk(&argvars[1], &error); if (!error) { - blob_T *b = argvars[0].vval.v_blob; int len = blob_len(b); char_u *p; diff --git a/src/errors.h b/src/errors.h index 44b2828f6..942cf658b 100644 --- a/src/errors.h +++ b/src/errors.h @@ -366,7 +366,8 @@ EXTERN char e_returning_value_in_function_without_return_type[] INIT(= N_("E1096: Returning a value in a function without a return type")); EXTERN char e_line_incomplete[] INIT(= N_("E1097: Line incomplete")); -// E1098 unused +EXTERN char e_string_list_or_blob_required[] + INIT(= N_("E1098: String, List or Blob required")); EXTERN char e_unknown_error_while_executing_str[] INIT(= N_("E1099: Unknown error while executing %s")); EXTERN char e_cannot_declare_script_variable_in_function[] diff --git a/src/eval.c b/src/eval.c index 3688176ab..550fe8e2b 100644 --- a/src/eval.c +++ b/src/eval.c @@ -1749,7 +1749,7 @@ eval_for_line( } else { - emsg(_(e_listreq)); + emsg(_(e_string_list_or_blob_required)); clear_tv(&tv); } } diff --git a/src/list.c b/src/list.c index c65c8df6f..bf24cee22 100644 --- a/src/list.c +++ b/src/list.c @@ -2817,45 +2817,49 @@ f_insert(typval_T *argvars, typval_T *rettv) if (argvars[0].v_type == VAR_BLOB) { - int val, len; - char_u *p; + blob_T *b = argvars[0].vval.v_blob; - if (argvars[0].vval.v_blob == NULL) + if (b == NULL) { if (in_vim9script()) emsg(_(e_cannot_add_to_null_blob)); - return; } - - len = blob_len(argvars[0].vval.v_blob); - if (argvars[2].v_type != VAR_UNKNOWN) + else if (!value_check_lock(b->bv_lock, + (char_u *)N_("insert() argument"), TRUE)) { - before = (long)tv_get_number_chk(&argvars[2], &error); + int val, len; + char_u *p; + + len = blob_len(b); + if (argvars[2].v_type != VAR_UNKNOWN) + { + before = (long)tv_get_number_chk(&argvars[2], &error); + if (error) + return; // type error; errmsg already given + if (before < 0 || before > len) + { + semsg(_(e_invarg2), tv_get_string(&argvars[2])); + return; + } + } + val = tv_get_number_chk(&argvars[1], &error); if (error) - return; // type error; errmsg already given - if (before < 0 || before > len) + return; + if (val < 0 || val > 255) { - semsg(_(e_invarg2), tv_get_string(&argvars[2])); + semsg(_(e_invarg2), tv_get_string(&argvars[1])); return; } - } - val = tv_get_number_chk(&argvars[1], &error); - if (error) - return; - if (val < 0 || val > 255) - { - semsg(_(e_invarg2), tv_get_string(&argvars[1])); - return; - } - if (ga_grow(&argvars[0].vval.v_blob->bv_ga, 1) == FAIL) - return; - p = (char_u *)argvars[0].vval.v_blob->bv_ga.ga_data; - mch_memmove(p + before + 1, p + before, (size_t)len - before); - *(p + before) = val; - ++argvars[0].vval.v_blob->bv_ga.ga_len; + if (ga_grow(&b->bv_ga, 1) == FAIL) + return; + p = (char_u *)b->bv_ga.ga_data; + mch_memmove(p + before + 1, p + before, (size_t)len - before); + *(p + before) = val; + ++b->bv_ga.ga_len; - copy_tv(&argvars[0], rettv); + copy_tv(&argvars[0], rettv); + } } else if (argvars[0].v_type != VAR_LIST) semsg(_(e_listblobarg), "insert()"); @@ -2917,7 +2921,7 @@ f_remove(typval_T *argvars, typval_T *rettv) if (argvars[0].v_type == VAR_DICT) dict_remove(argvars, rettv, arg_errmsg); else if (argvars[0].v_type == VAR_BLOB) - blob_remove(argvars, rettv); + blob_remove(argvars, rettv, arg_errmsg); else if (argvars[0].v_type == VAR_LIST) list_remove(argvars, rettv, arg_errmsg); else diff --git a/src/proto/blob.pro b/src/proto/blob.pro index 157f15bbc..5d80463e3 100644 --- a/src/proto/blob.pro +++ b/src/proto/blob.pro @@ -18,5 +18,5 @@ int blob_slice_or_index(blob_T *blob, int is_range, varnumber_T n1, varnumber_T int check_blob_index(long bloblen, varnumber_T n1, int quiet); int check_blob_range(long bloblen, varnumber_T n1, varnumber_T n2, int quiet); int blob_set_range(blob_T *dest, long n1, long n2, typval_T *src); -void blob_remove(typval_T *argvars, typval_T *rettv); +void blob_remove(typval_T *argvars, typval_T *rettv, char_u *arg_errmsg); /* vim: set ft=c : */ diff --git a/src/testdir/test_blob.vim b/src/testdir/test_blob.vim index b41ca78f3..d56c4f748 100644 --- a/src/testdir/test_blob.vim +++ b/src/testdir/test_blob.vim @@ -428,6 +428,23 @@ func Test_blob_func_remove() call remove(test_null_blob(), 1, 2) END call CheckLegacyAndVim9Failure(lines, 'E979:') + + let lines =<< trim END + let b = 0zDEADBEEF + lockvar b + call remove(b, 0) + unlockvar b + END + call CheckScriptFailure(lines, 'E741:') + + " can only check at script level, not in a :def function + let lines =<< trim END + vim9script + var b = 0zDEADBEEF + lockvar b + remove(b, 0) + END + call CheckScriptFailure(lines, 'E741:') endfunc func Test_blob_read_write() @@ -543,6 +560,22 @@ func Test_blob_insert() insert(test_null_blob(), 0x33) END call CheckDefExecAndScriptFailure(lines, 'E1131:') + + let lines =<< trim END + let b = 0zDEADBEEF + lockvar b + call insert(b, 3) + unlockvar b + END + call CheckScriptFailure(lines, 'E741:') + + let lines =<< trim END + vim9script + var b = 0zDEADBEEF + lockvar b + insert(b, 3) + END + call CheckScriptFailure(lines, 'E741:') endfunc func Test_blob_reverse() diff --git a/src/testdir/test_eval_stuff.vim b/src/testdir/test_eval_stuff.vim index 1fbb74bc4..ac9589d24 100644 --- a/src/testdir/test_eval_stuff.vim +++ b/src/testdir/test_eval_stuff.vim @@ -65,9 +65,9 @@ func Test_E963() endfunc func Test_for_invalid() - call assert_fails("for x in 99", 'E714:') - call assert_fails("for x in function('winnr')", 'E714:') - call assert_fails("for x in {'a': 9}", 'E714:') + call assert_fails("for x in 99", 'E1098:') + call assert_fails("for x in function('winnr')", 'E1098:') + call assert_fails("for x in {'a': 9}", 'E1098:') if 0 /1/5/2/s/\n diff --git a/src/version.c b/src/version.c index 35bb3910a..1b1f7a605 100644 --- a/src/version.c +++ b/src/version.c @@ -755,6 +755,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ +/**/ + 3284, /**/ 3283, /**/ -- 2.40.0