diff options
author | Bram Moolenaar <Bram@vim.org> | 2020-12-22 20:35:40 +0100 |
---|---|---|
committer | Bram Moolenaar <Bram@vim.org> | 2020-12-22 20:35:40 +0100 |
commit | 3bdc90b7dfab314768a8f56454ea62929524f05c (patch) | |
tree | 0836d782d16f1749ae745e5a6f87972d1c0f5073 /src | |
parent | e5492609b3a153c631f1d600ecdef1af1c913bef (diff) | |
download | vim-git-3bdc90b7dfab314768a8f56454ea62929524f05c.tar.gz |
patch 8.2.2193: Vim9: can change constant in :def functionv8.2.2193
Problem: Vim9: can change constant in :def function.
Solution: Check if a variable is locked. (issue #7526)
Diffstat (limited to 'src')
-rw-r--r-- | src/evalvars.c | 24 | ||||
-rw-r--r-- | src/proto/evalvars.pro | 1 | ||||
-rw-r--r-- | src/testdir/test_vim9_func.vim | 11 | ||||
-rw-r--r-- | src/version.c | 2 | ||||
-rw-r--r-- | src/vim9execute.c | 11 |
5 files changed, 39 insertions, 10 deletions
diff --git a/src/evalvars.c b/src/evalvars.c index 572e5d556..ec3f508ed 100644 --- a/src/evalvars.c +++ b/src/evalvars.c @@ -3125,13 +3125,7 @@ set_var_const( goto failed; } - // Check in this order for backwards compatibility: - // - Whether the variable is read-only - // - Whether the variable value is locked - // - Whether the variable is locked - if (var_check_ro(di->di_flags, name, FALSE) - || value_check_lock(di->di_tv.v_lock, name, FALSE) - || var_check_lock(di->di_flags, name, FALSE)) + if (var_check_permission(di, name) == FAIL) goto failed; } else @@ -3243,6 +3237,22 @@ failed: } /* + * Check in this order for backwards compatibility: + * - Whether the variable is read-only + * - Whether the variable value is locked + * - Whether the variable is locked + */ + int +var_check_permission(dictitem_T *di, char_u *name) +{ + if (var_check_ro(di->di_flags, name, FALSE) + || value_check_lock(di->di_tv.v_lock, name, FALSE) + || var_check_lock(di->di_flags, name, FALSE)) + return FAIL; + return OK; +} + +/* * Return TRUE if di_flags "flags" indicates variable "name" is read-only. * Also give an error message. */ diff --git a/src/proto/evalvars.pro b/src/proto/evalvars.pro index 4c9d64582..c597ca372 100644 --- a/src/proto/evalvars.pro +++ b/src/proto/evalvars.pro @@ -70,6 +70,7 @@ void vars_clear_ext(hashtab_T *ht, int free_val); void delete_var(hashtab_T *ht, hashitem_T *hi); void set_var(char_u *name, typval_T *tv, int copy); void set_var_const(char_u *name, type_T *type, typval_T *tv_arg, int copy, int flags); +int var_check_permission(dictitem_T *di, char_u *name); int var_check_ro(int flags, char_u *name, int use_gettext); int var_check_lock(int flags, char_u *name, int use_gettext); int var_check_fixed(int flags, char_u *name, int use_gettext); diff --git a/src/testdir/test_vim9_func.vim b/src/testdir/test_vim9_func.vim index eadd1d1c3..bdced0257 100644 --- a/src/testdir/test_vim9_func.vim +++ b/src/testdir/test_vim9_func.vim @@ -1022,6 +1022,17 @@ def Test_vim9script_call_fail_const() writefile(lines, 'Xcall_const.vim') assert_fails('source Xcall_const.vim', 'E46:', '', 1, 'MyFunc') delete('Xcall_const.vim') + + lines =<< trim END + const g:Aconst = 77 + def Change() + # comment + g:Aconst = 99 + enddef + call Change() + unlet g:Aconst + END + CheckScriptFailure(lines, 'E741: Value is locked: Aconst', 2) enddef " Test that inside :function a Python function can be defined, :def is not diff --git a/src/version.c b/src/version.c index 7c9529b55..73a80aaf9 100644 --- a/src/version.c +++ b/src/version.c @@ -751,6 +751,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ /**/ + 2193, +/**/ 2192, /**/ 2191, diff --git a/src/vim9execute.c b/src/vim9execute.c index 9636cbffa..90b4e0ba6 100644 --- a/src/vim9execute.c +++ b/src/vim9execute.c @@ -1693,8 +1693,10 @@ call_def_function( case ISN_STOREW: case ISN_STORET: { - dictitem_T *di; - hashtab_T *ht; + dictitem_T *di; + hashtab_T *ht; + char_u *name = iptr->isn_arg.string + 2; + switch (iptr->isn_type) { case ISN_STOREG: @@ -1714,11 +1716,14 @@ call_def_function( } --ectx.ec_stack.ga_len; - di = find_var_in_ht(ht, 0, iptr->isn_arg.string + 2, TRUE); + di = find_var_in_ht(ht, 0, name, TRUE); if (di == NULL) store_var(iptr->isn_arg.string, STACK_TV_BOT(0)); else { + SOURCING_LNUM = iptr->isn_lnum; + if (var_check_permission(di, name) == FAIL) + goto on_error; clear_tv(&di->di_tv); di->di_tv = *STACK_TV_BOT(0); } |