patch 9.1.1792: List of changes not protected from changes
Commit:
https://github.com/vim/vim/commit/35a89ce9db8748c68ed4584eaa46875a5c1e09ef
Author: Paul Ollis <[email protected]>
Date: Thu Sep 25 20:11:34 2025 +0000
patch 9.1.1792: List of changes not protected from changes
Problem: List of changes not protected from changes when processing
listeners (after v9.1.1782)
Solution: Fully lock changes list for listener callbacks (Paul Ollis)
closes: #18385
Signed-off-by: Paul Ollis <[email protected]>
Signed-off-by: Christian Brabandt <[email protected]>
diff --git a/src/change.c b/src/change.c
index fe2a732c3..527d2cc8c 100644
--- a/src/change.c
+++ b/src/change.c
@@ -297,7 +297,6 @@ may_record_change(
if (curbuf->b_recorded_changes == NULL) // out of memory
return;
++curbuf->b_recorded_changes->lv_refcount;
- curbuf->b_recorded_changes->lv_lock = VAR_FIXED;
}
dict = dict_alloc();
@@ -489,6 +488,7 @@ invoke_listener_set(
listener_T *lnr;
typval_T rettv;
typval_T argv[6];
+ typval_T val;
argv[0].v_type = VAR_NUMBER;
argv[0].vval.v_number = buf->b_fnum; // a:bufnr
@@ -501,6 +501,13 @@ invoke_listener_set(
argv[4].v_type = VAR_LIST;
argv[4].vval.v_list = recorded_changes;
+ // Ensure the list of changes is locked to prevent any modifications by
+ // callback code..
+ val.v_type = VAR_LIST;
+ val.v_lock = 0;
+ val.vval.v_list = recorded_changes;
+ item_lock(&val, -1, TRUE, FALSE);
+
// Protect against recursive callbacks, lock the buffer against changes and
// set the updating_screen flag to prevent channel input processing, which
// might also try to update the buffer.
@@ -547,7 +554,6 @@ invoke_sync_listeners(
return;
++recorded_changes->lv_refcount;
- recorded_changes->lv_lock = VAR_FIXED;
dict = dict_alloc();
if (dict == NULL)
diff --git a/src/testdir/test_listener.vim b/src/testdir/test_listener.vim
index 88e4a3f78..7fc985ec9 100644
--- a/src/testdir/test_listener.vim
+++ b/src/testdir/test_listener.vim
@@ -21,8 +21,21 @@ func s:AnotherStoreList(l)
endfunc
func s:EvilStoreList(l)
+ func! Modify_dict_in_list(the_list, key)
+ let a:the_list[0][a:key] = a:the_list[0][a:key] + 1
+ endfunc
+ func! Modify_list_entry(the_list)
+ let a:the_list[0] = 42
+ endfunc
+
let s:list3 = a:l
- call assert_fails("call add(a:l, 'myitem')", "E742:")
+ call assert_fails("call add(a:l, 'myitem')", "E741:")
+ call assert_fails("call remove(a:l, 1)", "E741:")
+ call assert_fails("call Modify_dict_in_list(a:l, 'lnum')", "E741:")
+ call assert_fails("call Modify_dict_in_list(a:l, 'end')", "E741:")
+ call assert_fails("call Modify_dict_in_list(a:l, 'col')", "E741:")
+ call assert_fails("call Modify_dict_in_list(a:l, 'added')", "E741:")
+ call assert_fails("call Modify_list_entry(a:l)", "E741:")
endfunc
func Test_listening()
diff --git a/src/version.c b/src/version.c
index f48b3d79e..80071eab6 100644
--- a/src/version.c
+++ b/src/version.c
@@ -729,6 +729,8 @@ static char *(features[]) =
static int included_patches[] =
{ /* Add new patch number below this line */
+/**/
+ 1792,
/**/
1791,
/**/
--
--
You received this message from the "vim_dev" maillist.
Do not top-post! Type your reply below the text you are replying to.
For more information, visit http://www.vim.org/maillist.php
---
You received this message because you are subscribed to the Google Groups
"vim_dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email
to [email protected].
To view this discussion visit
https://groups.google.com/d/msgid/vim_dev/E1v1sbL-00BNiK-N5%40256bit.org.