mirror of
https://github.com/vim/vim.git
synced 2026-05-28 00:21:37 +02:00
patch 9.1.2087: Crash when using :tabonly in BufUnload
Problem: Crash when using :tabonly in BufUnload.
Solution: Set curbuf when setting curwin->w_buffer. Don't wipe out a
buffer if there are no other buffers. Don't decrement
b_nwindows if it was 0 before buf_freeall() (zeertzjq).
fixes: #19088#issuecomment-3710172769
closes: #19186
Signed-off-by: zeertzjq <zeertzjq@outlook.com>
Signed-off-by: Christian Brabandt <cb@256bit.org>
This commit is contained in:
committed by
Christian Brabandt
parent
a1895b67b7
commit
fa64f92f6a
+7
-3
@@ -776,14 +776,18 @@ aucmd_abort:
|
||||
|
||||
// Autocommands may have opened or closed windows for this buffer.
|
||||
// Decrement the count for the close we do here.
|
||||
if (buf->b_nwindows > 0)
|
||||
// Don't decrement b_nwindows if the buffer wasn't displayed in any window
|
||||
// before calling buf_freeall(),
|
||||
if (nwindows > 0 && buf->b_nwindows > 0)
|
||||
--buf->b_nwindows;
|
||||
|
||||
/*
|
||||
* Remove the buffer from the list.
|
||||
* Do not wipe out the buffer if it is used in a window.
|
||||
* Do not wipe out the buffer if it is used in a window, or if autocommands
|
||||
* wiped out all other buffers.
|
||||
*/
|
||||
if (wipe_buf && buf->b_nwindows <= 0)
|
||||
if (wipe_buf && buf->b_nwindows <= 0
|
||||
&& (buf->b_prev != NULL || buf->b_next != NULL))
|
||||
{
|
||||
tabpage_T *tp;
|
||||
win_T *wp;
|
||||
|
||||
@@ -861,6 +861,46 @@ func Test_BufUnload_close_other()
|
||||
call Run_test_BufUnload_close_other('setlocal bufhidden=wipe')
|
||||
endfunc
|
||||
|
||||
func Run_test_BufUnload_tabonly(first_cmd)
|
||||
exe a:first_cmd
|
||||
tabnew Xa
|
||||
setlocal bufhidden=wipe
|
||||
tabprevious
|
||||
autocmd BufWinLeave Xa ++once tabnext
|
||||
autocmd BufUnload Xa ++once tabonly
|
||||
tabonly
|
||||
|
||||
%bwipe!
|
||||
endfunc
|
||||
|
||||
func Test_BufUnload_tabonly()
|
||||
" This used to dereference a NULL curbuf.
|
||||
call Run_test_BufUnload_tabonly('setlocal bufhidden=hide')
|
||||
" This used to dereference a NULL firstbuf.
|
||||
call Run_test_BufUnload_tabonly('setlocal bufhidden=wipe')
|
||||
endfunc
|
||||
|
||||
func Run_test_BufUnload_tabonly_nested(second_autocmd)
|
||||
file Xa
|
||||
tabnew Xb
|
||||
setlocal bufhidden=wipe
|
||||
tabnew Xc
|
||||
setlocal bufhidden=wipe
|
||||
autocmd BufUnload Xb ++once ++nested bwipe! Xa
|
||||
exe $'autocmd BufUnload Xa ++once ++nested {a:second_autocmd}'
|
||||
autocmd BufWinLeave Xc ++once tabnext
|
||||
tabfirst
|
||||
2tabclose
|
||||
|
||||
%bwipe!
|
||||
endfunc
|
||||
|
||||
func Test_BufUnload_tabonly_nested()
|
||||
" These used to cause heap-use-after-free.
|
||||
call Run_test_BufUnload_tabonly_nested('tabonly')
|
||||
call Run_test_BufUnload_tabonly_nested('tabonly | tabprevious')
|
||||
endfunc
|
||||
|
||||
func s:AddAnAutocmd()
|
||||
augroup vimBarTest
|
||||
au BufReadCmd * echo 'hello'
|
||||
|
||||
@@ -734,6 +734,8 @@ static char *(features[]) =
|
||||
|
||||
static int included_patches[] =
|
||||
{ /* Add new patch number below this line */
|
||||
/**/
|
||||
2087,
|
||||
/**/
|
||||
2086,
|
||||
/**/
|
||||
|
||||
@@ -3462,6 +3462,8 @@ win_close_othertab(win_T *win, int free_buf, tabpage_T *tp)
|
||||
{
|
||||
win->w_buffer = firstbuf;
|
||||
++firstbuf->b_nwindows;
|
||||
if (win == curwin)
|
||||
curbuf = curwin->w_buffer;
|
||||
win_init_empty(win);
|
||||
}
|
||||
return;
|
||||
|
||||
Reference in New Issue
Block a user