vim-patch:8.2.2472: crash when using command line window in an autocommand

Problem:    Crash when using command line window in an autocommand.
            (houyunsong)
Solution:   Save and restore au_new_curbuf.
aad5f9d79a

Nvim has removed :open, so use :edit in the test instead.
This commit is contained in:
zeertzjq 2022-04-20 09:18:39 +08:00
parent 9b10b4cc64
commit fa15f2f938
2 changed files with 25 additions and 4 deletions

View File

@ -2497,16 +2497,19 @@ int do_ecmd(int fnum, char_u *ffname, char_u *sfname, exarg_T *eap, linenr_T new
if (buf->b_fname != NULL) { if (buf->b_fname != NULL) {
new_name = vim_strsave(buf->b_fname); new_name = vim_strsave(buf->b_fname);
} }
const bufref_T save_au_new_curbuf = au_new_curbuf;
set_bufref(&au_new_curbuf, buf); set_bufref(&au_new_curbuf, buf);
apply_autocmds(EVENT_BUFLEAVE, NULL, NULL, false, curbuf); apply_autocmds(EVENT_BUFLEAVE, NULL, NULL, false, curbuf);
cmdwin_type = save_cmdwin_type; cmdwin_type = save_cmdwin_type;
if (!bufref_valid(&au_new_curbuf)) { if (!bufref_valid(&au_new_curbuf)) {
// New buffer has been deleted. // New buffer has been deleted.
delbuf_msg(new_name); // Frees new_name. delbuf_msg(new_name); // Frees new_name.
au_new_curbuf = save_au_new_curbuf;
goto theend; goto theend;
} }
if (aborting()) { // autocmds may abort script processing if (aborting()) { // autocmds may abort script processing
xfree(new_name); xfree(new_name);
au_new_curbuf = save_au_new_curbuf;
goto theend; goto theend;
} }
if (buf == curbuf) { // already in new buffer if (buf == curbuf) { // already in new buffer
@ -2540,12 +2543,14 @@ int do_ecmd(int fnum, char_u *ffname, char_u *sfname, exarg_T *eap, linenr_T new
// autocmds may abort script processing // autocmds may abort script processing
if (aborting() && curwin->w_buffer != NULL) { if (aborting() && curwin->w_buffer != NULL) {
xfree(new_name); xfree(new_name);
au_new_curbuf = save_au_new_curbuf;
goto theend; goto theend;
} }
// Be careful again, like above. // Be careful again, like above.
if (!bufref_valid(&au_new_curbuf)) { if (!bufref_valid(&au_new_curbuf)) {
// New buffer has been deleted. // New buffer has been deleted.
delbuf_msg(new_name); // Frees new_name. delbuf_msg(new_name); // Frees new_name.
au_new_curbuf = save_au_new_curbuf;
goto theend; goto theend;
} }
if (buf == curbuf) { // already in new buffer if (buf == curbuf) { // already in new buffer
@ -2585,8 +2590,7 @@ int do_ecmd(int fnum, char_u *ffname, char_u *sfname, exarg_T *eap, linenr_T new
did_get_winopts = true; did_get_winopts = true;
} }
xfree(new_name); xfree(new_name);
au_new_curbuf.br_buf = NULL; au_new_curbuf = save_au_new_curbuf;
au_new_curbuf.br_buf_free_count = 0;
} }
curwin->w_pcmark.lnum = 1; curwin->w_pcmark.lnum = 1;

View File

@ -2695,9 +2695,9 @@ func Test_autocmd_closes_window()
au BufNew,BufWinLeave * e %e au BufNew,BufWinLeave * e %e
file yyy file yyy
au BufNew,BufWinLeave * ball au BufNew,BufWinLeave * ball
call assert_fails('n xxx', 'E143:') n xxx
bwipe % %bwipe
au! BufNew au! BufNew
au! BufWinLeave au! BufWinLeave
endfunc endfunc
@ -2715,6 +2715,23 @@ func Test_autocmd_quit_psearch()
augroup END augroup END
endfunc endfunc
" Fuzzer found some strange combination that caused a crash.
func Test_autocmd_normal_mess()
augroup aucmd_normal_test
au BufLeave,BufWinLeave,BufHidden,BufUnload,BufDelete,BufWipeout * norm 7q/qc
augroup END
" Nvim has removed :open
" o4
e4
silent! H
e xx
normal G
augroup aucmd_normal_test
au!
augroup END
endfunc
func Test_autocmd_closing_cmdwin() func Test_autocmd_closing_cmdwin()
au BufWinLeave * nested q au BufWinLeave * nested q
call assert_fails("norm 7q?\n", 'E855:') call assert_fails("norm 7q?\n", 'E855:')