vim-patch:8.1.0897: can modify a:000 when using a reference (#14902)

Problem:    Can modify a:000 when using a reference.
Solution:   Make check for locked variable stricter. (Ozaki Kiichi,
            closes vim/vim#3930)
05c00c038b
This commit is contained in:
Jan Edmund Lazo
2021-06-26 10:19:09 -04:00
committed by GitHub
parent ad9c2c069a
commit 20dc3f1989
6 changed files with 85 additions and 54 deletions

View File

@@ -1994,7 +1994,7 @@ void tv_dict_extend(dict_T *const d1, dict_T *const d2,
} else if (*action == 'f' && di2 != di1) {
typval_T oldtv;
if (tv_check_lock(di1->di_tv.v_lock, arg_errmsg, arg_errmsg_len)
if (var_check_lock(di1->di_tv.v_lock, arg_errmsg, arg_errmsg_len)
|| var_check_ro(di1->di_flags, arg_errmsg, arg_errmsg_len)) {
break;
}
@@ -2625,7 +2625,7 @@ bool tv_islocked(const typval_T *const tv)
///
/// Also gives an error message when typval is locked.
///
/// @param[in] lock Lock status.
/// @param[in] tv Typval.
/// @param[in] name Variable name, used in the error message.
/// @param[in] name_len Variable name length. Use #TV_TRANSLATE to translate
/// variable name and compute the length. Use #TV_CSTRING
@@ -2639,9 +2639,36 @@ bool tv_islocked(const typval_T *const tv)
/// gettext.
///
/// @return true if variable is locked, false otherwise.
bool tv_check_lock(const VarLockStatus lock, const char *name,
bool tv_check_lock(const typval_T *tv, const char *name,
size_t name_len)
FUNC_ATTR_WARN_UNUSED_RESULT
{
VarLockStatus lock = VAR_UNLOCKED;
switch (tv->v_type) {
// case VAR_BLOB:
// if (tv->vval.v_blob != NULL)
// lock = tv->vval.v_blob->bv_lock;
// break;
case VAR_LIST:
if (tv->vval.v_list != NULL) {
lock = tv->vval.v_list->lv_lock;
}
break;
case VAR_DICT:
if (tv->vval.v_dict != NULL) {
lock = tv->vval.v_dict->dv_lock;
}
break;
default:
break;
}
return var_check_lock(tv->v_lock, name, name_len)
|| (lock != VAR_UNLOCKED && var_check_lock(lock, name, name_len));
}
/// @return true if variable "name" is locked (immutable)
bool var_check_lock(VarLockStatus lock, const char *name, size_t name_len)
{
const char *error_message = NULL;
switch (lock) {