From 9e38c4a79fe0351e9e18bc57cf48b960e8d31e88 Mon Sep 17 00:00:00 2001 From: Sean Dewar Date: Sat, 31 Jul 2021 00:20:20 +0100 Subject: vim-patch:8.2.1473: items in a list given to :const can still be modified Problem: Items in a list given to :const can still be modified. Solution: Work like ":lockvar! name" but don't lock referenced items. Make locking a blob work. https://github.com/vim/vim/commit/021bda56710d98c09a6b35610a476ab2dd8c58ad --- src/nvim/eval/typval.c | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) (limited to 'src/nvim/eval') diff --git a/src/nvim/eval/typval.c b/src/nvim/eval/typval.c index d983ce14b5..b08fe274f0 100644 --- a/src/nvim/eval/typval.c +++ b/src/nvim/eval/typval.c @@ -2659,7 +2659,10 @@ void tv_copy(const typval_T *const from, typval_T *const to) /// @param[out] tv Item to (un)lock. /// @param[in] deep Levels to (un)lock, -1 to (un)lock everything. /// @param[in] lock True if it is needed to lock an item, false to unlock. -void tv_item_lock(typval_T *const tv, const int deep, const bool lock) +/// @param[in] check_refcount If true, do not lock a list or dict with a +/// reference count larger than 1. +void tv_item_lock(typval_T *const tv, const int deep, const bool lock, + const bool check_refcount) FUNC_ATTR_NONNULL_ALL { // TODO(ZyX-I): Make this not recursive @@ -2688,19 +2691,19 @@ void tv_item_lock(typval_T *const tv, const int deep, const bool lock) switch (tv->v_type) { case VAR_BLOB: { blob_T *const b = tv->vval.v_blob; - if (b != NULL) { + if (b != NULL && !(check_refcount && b->bv_refcount > 1)) { CHANGE_LOCK(lock, b->bv_lock); } break; } case VAR_LIST: { list_T *const l = tv->vval.v_list; - if (l != NULL) { + if (l != NULL && !(check_refcount && l->lv_refcount > 1)) { CHANGE_LOCK(lock, l->lv_lock); if (deep < 0 || deep > 1) { // Recursive: lock/unlock the items the List contains. TV_LIST_ITER(l, li, { - tv_item_lock(TV_LIST_ITEM_TV(li), deep - 1, lock); + tv_item_lock(TV_LIST_ITEM_TV(li), deep - 1, lock, check_refcount); }); } } @@ -2708,12 +2711,12 @@ void tv_item_lock(typval_T *const tv, const int deep, const bool lock) } case VAR_DICT: { dict_T *const d = tv->vval.v_dict; - if (d != NULL) { + if (d != NULL && !(check_refcount && d->dv_refcount > 1)) { CHANGE_LOCK(lock, d->dv_lock); if (deep < 0 || deep > 1) { // recursive: lock/unlock the items the List contains TV_DICT_ITER(d, di, { - tv_item_lock(&di->di_tv, deep - 1, lock); + tv_item_lock(&di->di_tv, deep - 1, lock, check_refcount); }); } } -- cgit