]> git.ipfire.org Git - thirdparty/vim.git/commitdiff
patch 9.1.1792: List of changes not protected from changes v9.1.1792
authorPaul Ollis <paul@cleversheep.org>
Thu, 25 Sep 2025 20:11:34 +0000 (20:11 +0000)
committerChristian Brabandt <cb@256bit.org>
Thu, 25 Sep 2025 20:11:34 +0000 (20:11 +0000)
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 <paul@cleversheep.org>
Signed-off-by: Christian Brabandt <cb@256bit.org>
src/change.c
src/testdir/test_listener.vim
src/version.c

index fe2a732c38394f7834874c1687535e500cba550d..527d2cc8c04d79104f290aa1d27d5847ad0851ea 100644 (file)
@@ -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)
index 88e4a3f785814d115f105a0cef5517c997fd2000..7fc985ec980469e2105f7b810d382c44ef7d1f8f 100644 (file)
@@ -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()
index f48b3d79e6aff7a215023313de382346f9f7ee00..80071eab6324771cd4eead705884d4d029da6853 100644 (file)
@@ -729,6 +729,8 @@ static char *(features[]) =
 
 static int included_patches[] =
 {   /* Add new patch number below this line */
+/**/
+    1792,
 /**/
     1791,
 /**/