Merge pull request #37431 from zeertzjq/vim-9.1.2087

vim-patch:9.1.{2087,2090}
This commit is contained in:
zeertzjq
2026-01-17 19:01:09 +08:00
committed by GitHub
3 changed files with 54 additions and 3 deletions

View File

@@ -718,13 +718,21 @@ 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 (unless when inside free_all_mem() where all
// buffers need to be freed and autocommands are blocked).
if (wipe_buf && buf->b_nwindows <= 0 && (buf->b_prev != NULL || buf->b_next != NULL
#if defined(EXITFREE)
|| entered_free_all_mem
#endif
)) {
if (clear_w_buf) {
win->w_buffer = NULL;
}

View File

@@ -2765,6 +2765,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.

View File

@@ -862,6 +862,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'