Skip to content

Commit 7cb43f2

Browse files
seandewarchrisbra
authored andcommitted
patch 9.2.0254: w_locked can be bypassed when setting recursively
Problem: w_locked can be bypassed when recursively set if not restored to its prior value. Solution: Rather than save/restore everywhere, just make it a count, like other locks (Sean Dewar) Requires the previous commit, otherwise b_nwindows will be wrong in tests, which causes a bunch of weird failures. closes: #19728 Signed-off-by: Sean Dewar <6256228+seandewar@users.noreply.github.com> Signed-off-by: Christian Brabandt <cb@256bit.org>
1 parent bf21df1 commit 7cb43f2

7 files changed

Lines changed: 45 additions & 19 deletions

File tree

src/arglist.c

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -200,7 +200,7 @@ alist_add(
200200
if (check_arglist_locked() == FAIL)
201201
return;
202202
arglist_locked = TRUE;
203-
wp->w_locked = TRUE;
203+
++wp->w_locked;
204204

205205
#ifdef BACKSLASH_IN_FILENAME
206206
slash_adjust(fname);
@@ -212,7 +212,7 @@ alist_add(
212212
++al->al_ga.ga_len;
213213

214214
arglist_locked = FALSE;
215-
wp->w_locked = FALSE;
215+
--wp->w_locked;
216216
}
217217

218218
#if defined(BACKSLASH_IN_FILENAME)
@@ -373,7 +373,7 @@ alist_add_list(
373373
mch_memmove(&(ARGLIST[after + count]), &(ARGLIST[after]),
374374
(ARGCOUNT - after) * sizeof(aentry_T));
375375
arglist_locked = TRUE;
376-
wp->w_locked = TRUE;
376+
++wp->w_locked;
377377
for (i = 0; i < count; ++i)
378378
{
379379
int flags = BLN_LISTED | (will_edit ? BLN_CURBUF : 0);
@@ -382,7 +382,7 @@ alist_add_list(
382382
ARGLIST[after + i].ae_fnum = buflist_add(files[i], flags);
383383
}
384384
arglist_locked = FALSE;
385-
wp->w_locked = FALSE;
385+
--wp->w_locked;
386386
ALIST(wp)->al_ga.ga_len += count;
387387
if (old_argcount > 0 && wp->w_arg_idx >= after)
388388
wp->w_arg_idx += count;

src/buffer.c

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -80,15 +80,14 @@ static garray_T buf_reuse = GA_EMPTY; // file numbers to recycle
8080
static void
8181
trigger_undo_ftplugin(buf_T *buf, win_T *win)
8282
{
83-
int win_was_locked = win->w_locked;
8483
window_layout_lock();
85-
buf->b_locked++;
86-
win->w_locked = TRUE;
84+
++buf->b_locked;
85+
++win->w_locked;
8786
// b:undo_ftplugin may be set, undo it
8887
do_cmdline_cmd((char_u*)"if exists('b:undo_ftplugin') | :legacy :exe \
8988
b:undo_ftplugin | endif");
90-
buf->b_locked--;
91-
win->w_locked = win_was_locked;
89+
--buf->b_locked;
90+
--win->w_locked;
9291
window_layout_unlock();
9392
}
9493

src/ex_cmds.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3082,7 +3082,7 @@ do_ecmd(
30823082

30833083
// Set the w_locked flag to avoid that autocommands close the
30843084
// window. And set b_locked for the same reason.
3085-
the_curwin->w_locked = TRUE;
3085+
++the_curwin->w_locked;
30863086
++buf->b_locked;
30873087

30883088
if (curbuf == old_curbuf.br_buf)
@@ -3097,7 +3097,7 @@ do_ecmd(
30973097

30983098
// Autocommands may have closed the window.
30993099
if (win_valid(the_curwin))
3100-
the_curwin->w_locked = FALSE;
3100+
--the_curwin->w_locked;
31013101
--buf->b_locked;
31023102

31033103
#ifdef FEAT_EVAL

src/terminal.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3736,10 +3736,10 @@ term_after_channel_closed(term_T *term)
37363736
if (is_aucmd_win(wp))
37373737
do_set_w_locked = TRUE;
37383738
if (do_set_w_locked)
3739-
wp->w_locked = TRUE;
3739+
++wp->w_locked;
37403740
do_bufdel(DOBUF_WIPE, (char_u *)"", 1, fnum, fnum, FALSE);
37413741
if (do_set_w_locked)
3742-
wp->w_locked = FALSE;
3742+
--wp->w_locked;
37433743
aucmd_restbuf(&aco);
37443744
}
37453745
#ifdef FEAT_PROP_POPUP

src/testdir/test_window_cmd.vim

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2496,4 +2496,29 @@ func Test_laststatus_vsplit_row_height_mixed_stlo_reversed()
24962496
call StopVimInTerminal(buf)
24972497
endfunc
24982498

2499+
func Test_window_w_locked_bypass()
2500+
split Xfoo
2501+
let s:win = win_getid()
2502+
2503+
augroup TestBypass
2504+
" :quit fired this with w_locked set. Shouldn't be able to unset w_locked
2505+
" and close s:win if we do other stuff that also sets it.
2506+
au WinLeave * ++once call assert_equal(s:win, win_getid())
2507+
\| quit | call assert_notequal(0, win_id2win(s:win))
2508+
\| args Xbar
2509+
\| argadd Xbaz
2510+
\| edit Xbaz-but-cooler
2511+
\| quit | call assert_notequal(0, win_id2win(s:win))
2512+
augroup END
2513+
quit
2514+
call assert_equal(1, bufexists('Xbaz-but-cooler')) " check WinLeave ran
2515+
2516+
unlet! s:win
2517+
augroup TestBypass
2518+
au!
2519+
augroup END
2520+
%argd!
2521+
%bw!
2522+
endfunc
2523+
24992524
" vim: shiftwidth=2 sts=2 expandtab

src/version.c

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

735735
static int included_patches[] =
736736
{ /* Add new patch number below this line */
737+
/**/
738+
254,
737739
/**/
738740
253,
739741
/**/

src/window.c

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2717,10 +2717,10 @@ win_close_buffer(win_T *win, int action, int abort_if_last)
27172717
bufref_T bufref;
27182718

27192719
set_bufref(&bufref, curbuf);
2720-
win->w_locked = TRUE;
2720+
++win->w_locked;
27212721
close_buffer(win, win->w_buffer, action, abort_if_last, TRUE, TRUE);
27222722
if (win_valid_any_tab(win))
2723-
win->w_locked = FALSE;
2723+
--win->w_locked;
27242724
// Make sure curbuf is valid. It can become invalid if 'bufhidden' is
27252725
// "wipe".
27262726
if (!bufref_valid(&bufref))
@@ -2823,19 +2823,19 @@ win_close(win_T *win, int free_buf)
28232823
other_buffer = TRUE;
28242824
if (!win_valid(win))
28252825
return FAIL;
2826-
win->w_locked = TRUE;
2826+
++win->w_locked;
28272827
apply_autocmds(EVENT_BUFLEAVE, NULL, NULL, FALSE, curbuf);
28282828
if (!win_valid(win))
28292829
return FAIL;
2830-
win->w_locked = FALSE;
2830+
--win->w_locked;
28312831
if (last_window())
28322832
return FAIL;
28332833
}
2834-
win->w_locked = TRUE;
2834+
++win->w_locked;
28352835
apply_autocmds(EVENT_WINLEAVE, NULL, NULL, FALSE, curbuf);
28362836
if (!win_valid(win))
28372837
return FAIL;
2838-
win->w_locked = FALSE;
2838+
--win->w_locked;
28392839
if (last_window())
28402840
return FAIL;
28412841
#ifdef FEAT_EVAL

0 commit comments

Comments
 (0)