Skip to content

Commit 34ba06b

Browse files
committed
patch 8.1.2197: ExitPre autocommand may cause accessing freed memory
Problem: ExitPre autocommand may cause accessing freed memory. Solution: Check the window pointer is still valid. (closes #5093)
1 parent d53ebfc commit 34ba06b

3 files changed

Lines changed: 31 additions & 6 deletions

File tree

src/ex_docmd.c

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -4817,9 +4817,9 @@ before_quit_autocmds(win_T *wp, int quit_all, int forceit)
48174817
{
48184818
apply_autocmds(EVENT_QUITPRE, NULL, NULL, FALSE, wp->w_buffer);
48194819

4820-
/* Bail out when autocommands closed the window.
4821-
* Refuse to quit when the buffer in the last window is being closed (can
4822-
* only happen in autocommands). */
4820+
// Bail out when autocommands closed the window.
4821+
// Refuse to quit when the buffer in the last window is being closed (can
4822+
// only happen in autocommands).
48234823
if (!win_valid(wp)
48244824
|| curbuf_locked()
48254825
|| (wp->w_buffer->b_nwindows == 1 && wp->w_buffer->b_locked > 0))
@@ -4828,9 +4828,10 @@ before_quit_autocmds(win_T *wp, int quit_all, int forceit)
48284828
if (quit_all || (check_more(FALSE, forceit) == OK && only_one_window()))
48294829
{
48304830
apply_autocmds(EVENT_EXITPRE, NULL, NULL, FALSE, curbuf);
4831-
/* Refuse to quit when locked or when the buffer in the last window is
4832-
* being closed (can only happen in autocommands). */
4833-
if (curbuf_locked()
4831+
// Refuse to quit when locked or when the window was closed or the
4832+
// buffer in the last window is being closed (can only happen in
4833+
// autocommands).
4834+
if (!win_valid(wp) || curbuf_locked()
48344835
|| (curbuf->b_nwindows == 1 && curbuf->b_locked > 0))
48354836
return TRUE;
48364837
}

src/testdir/test_exit.vim

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ func Test_exiting()
4040
endif
4141
call delete('Xtestout')
4242

43+
" ExitPre autocommand splits the window, so that it's no longer the last one.
4344
let after =<< trim [CODE]
4445
au QuitPre * call writefile(["QuitPre"], "Xtestout", "a")
4546
au ExitPre * call writefile(["ExitPre"], "Xtestout", "a")
@@ -58,4 +59,25 @@ func Test_exiting()
5859
\ readfile('Xtestout'))
5960
endif
6061
call delete('Xtestout')
62+
63+
" ExitPre autocommand splits and closes the window, so that there is still
64+
" one window but it's a different one.
65+
let after =<< trim [CODE]
66+
au QuitPre * call writefile(["QuitPre"], "Xtestout", "a")
67+
au ExitPre * call writefile(["ExitPre"], "Xtestout", "a")
68+
augroup nasty
69+
au ExitPre * split | only
70+
augroup END
71+
quit
72+
augroup nasty
73+
au! ExitPre
74+
augroup END
75+
quit
76+
[CODE]
77+
78+
if RunVim([], after, '')
79+
call assert_equal(['QuitPre', 'ExitPre', 'QuitPre', 'ExitPre'],
80+
\ readfile('Xtestout'))
81+
endif
82+
call delete('Xtestout')
6183
endfunc

src/version.c

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

742742
static int included_patches[] =
743743
{ /* Add new patch number below this line */
744+
/**/
745+
2197,
744746
/**/
745747
2196,
746748
/**/

0 commit comments

Comments
 (0)