mirror of
https://github.com/neovim/neovim.git
synced 2026-02-21 09:50:19 +10:00
vim-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: vim/vim#19088#issuecomment-3710172769
closes: vim/vim#19186
fa64f92f6a
(cherry picked from commit eb5a7cc0dd)
This commit is contained in:
committed by
github-actions[bot]
parent
1e001b5c8d
commit
0cc15be15d
@@ -693,13 +693,16 @@ bool close_buffer(win_T *win, buf_T *buf, int action, bool abort_if_last, bool i
|
||||
|
||||
// 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.
|
||||
if (wipe_buf && buf->b_nwindows <= 0) {
|
||||
// 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 && (buf->b_prev != NULL || buf->b_next != NULL)) {
|
||||
if (clear_w_buf) {
|
||||
win->w_buffer = NULL;
|
||||
}
|
||||
|
||||
@@ -2699,6 +2699,9 @@ static void win_unclose_buffer(win_T *win, bufref_T *bufref, bool did_decrement)
|
||||
// If the buffer was removed from the window we have to give it any buffer.
|
||||
win->w_buffer = firstbuf;
|
||||
firstbuf->b_nwindows++;
|
||||
if (win == curwin) {
|
||||
curbuf = curwin->w_buffer;
|
||||
}
|
||||
win_init_empty(win);
|
||||
} else if (did_decrement && win->w_buffer == bufref->br_buf && bufref_valid(bufref)) {
|
||||
// close_buffer() decremented the window count, but we're keeping the window.
|
||||
|
||||
@@ -789,6 +789,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'
|
||||
|
||||
Reference in New Issue
Block a user