Skip to content

Commit 35a89ce

Browse files
paul-ollischrisbra
authored andcommitted
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]>
1 parent 377339d commit 35a89ce

File tree

3 files changed

+24
-3
lines changed

3 files changed

+24
-3
lines changed

src/change.c

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -297,7 +297,6 @@ may_record_change(
297297
if (curbuf->b_recorded_changes == NULL) // out of memory
298298
return;
299299
++curbuf->b_recorded_changes->lv_refcount;
300-
curbuf->b_recorded_changes->lv_lock = VAR_FIXED;
301300
}
302301

303302
dict = dict_alloc();
@@ -489,6 +488,7 @@ invoke_listener_set(
489488
listener_T *lnr;
490489
typval_T rettv;
491490
typval_T argv[6];
491+
typval_T val;
492492

493493
argv[0].v_type = VAR_NUMBER;
494494
argv[0].vval.v_number = buf->b_fnum; // a:bufnr
@@ -501,6 +501,13 @@ invoke_listener_set(
501501
argv[4].v_type = VAR_LIST;
502502
argv[4].vval.v_list = recorded_changes;
503503

504+
// Ensure the list of changes is locked to prevent any modifications by
505+
// callback code..
506+
val.v_type = VAR_LIST;
507+
val.v_lock = 0;
508+
val.vval.v_list = recorded_changes;
509+
item_lock(&val, -1, TRUE, FALSE);
510+
504511
// Protect against recursive callbacks, lock the buffer against changes and
505512
// set the updating_screen flag to prevent channel input processing, which
506513
// might also try to update the buffer.
@@ -547,7 +554,6 @@ invoke_sync_listeners(
547554
return;
548555

549556
++recorded_changes->lv_refcount;
550-
recorded_changes->lv_lock = VAR_FIXED;
551557

552558
dict = dict_alloc();
553559
if (dict == NULL)

src/testdir/test_listener.vim

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,8 +21,21 @@ func s:AnotherStoreList(l)
2121
endfunc
2222

2323
func s:EvilStoreList(l)
24+
func! Modify_dict_in_list(the_list, key)
25+
let a:the_list[0][a:key] = a:the_list[0][a:key] + 1
26+
endfunc
27+
func! Modify_list_entry(the_list)
28+
let a:the_list[0] = 42
29+
endfunc
30+
2431
let s:list3 = a:l
25-
call assert_fails("call add(a:l, 'myitem')", "E742:")
32+
call assert_fails("call add(a:l, 'myitem')", "E741:")
33+
call assert_fails("call remove(a:l, 1)", "E741:")
34+
call assert_fails("call Modify_dict_in_list(a:l, 'lnum')", "E741:")
35+
call assert_fails("call Modify_dict_in_list(a:l, 'end')", "E741:")
36+
call assert_fails("call Modify_dict_in_list(a:l, 'col')", "E741:")
37+
call assert_fails("call Modify_dict_in_list(a:l, 'added')", "E741:")
38+
call assert_fails("call Modify_list_entry(a:l)", "E741:")
2639
endfunc
2740

2841
func Test_listening()

src/version.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -729,6 +729,8 @@ static char *(features[]) =
729729

730730
static int included_patches[] =
731731
{ /* Add new patch number below this line */
732+
/**/
733+
1792,
732734
/**/
733735
1791,
734736
/**/

0 commit comments

Comments
 (0)