0
0
mirror of https://github.com/vim/vim.git synced 2025-09-26 04:04:07 -04:00

patch 8.2.4631: crash when switching window in BufWipeout autocommand

Problem:    Crash when switching window in BufWipeout autocommand.
Solution:   Put any buffer in the window to avoid it being NULL.
            (closes #10024)
This commit is contained in:
Bram Moolenaar
2022-03-26 16:28:06 +00:00
parent bf269ed0b0
commit 347538fad0
4 changed files with 68 additions and 35 deletions

View File

@@ -708,6 +708,10 @@ aucmd_abort:
*/ */
if (wipe_buf) if (wipe_buf)
{ {
// Do not wipe out the buffer if it is used in a window.
if (buf->b_nwindows > 0)
return FALSE;
if (action == DOBUF_WIPE_REUSE) if (action == DOBUF_WIPE_REUSE)
{ {
// we can re-use this buffer number, store it // we can re-use this buffer number, store it

View File

@@ -2990,4 +2990,21 @@ func Test_closing_autocmd_window()
bwipe Xb.txt bwipe Xb.txt
endfunc endfunc
func Test_bufwipeout_changes_window()
" This should not crash, but we don't have any expectations about what
" happens, changing window in BufWipeout has unpredictable results.
tabedit
let g:window_id = win_getid()
topleft new
setlocal bufhidden=wipe
autocmd BufWipeout <buffer> call win_gotoid(g:window_id)
tabprevious
+tabclose
unlet g:window_id
au! BufWipeout
%bwipe!
endfunc
" vim: shiftwidth=2 sts=2 expandtab " vim: shiftwidth=2 sts=2 expandtab

View File

@@ -750,6 +750,8 @@ static char *(features[]) =
static int included_patches[] = static int included_patches[] =
{ /* Add new patch number below this line */ { /* Add new patch number below this line */
/**/
4631,
/**/ /**/
4630, 4630,
/**/ /**/

View File

@@ -2285,6 +2285,41 @@ entering_window(win_T *win)
} }
#endif #endif
static void
win_init_empty(win_T *wp)
{
redraw_win_later(wp, NOT_VALID);
wp->w_lines_valid = 0;
wp->w_cursor.lnum = 1;
wp->w_curswant = wp->w_cursor.col = 0;
wp->w_cursor.coladd = 0;
wp->w_pcmark.lnum = 1; // pcmark not cleared but set to line 1
wp->w_pcmark.col = 0;
wp->w_prev_pcmark.lnum = 0;
wp->w_prev_pcmark.col = 0;
wp->w_topline = 1;
#ifdef FEAT_DIFF
wp->w_topfill = 0;
#endif
wp->w_botline = 2;
#if defined(FEAT_SYN_HL) || defined(FEAT_SPELL)
wp->w_s = &wp->w_buffer->b_s;
#endif
#ifdef FEAT_TERMINAL
term_reset_wincolor(wp);
#endif
}
/*
* Init the current window "curwin".
* Called when a new file is being edited.
*/
void
curwin_init(void)
{
win_init_empty(curwin);
}
/* /*
* Close all windows for buffer "buf". * Close all windows for buffer "buf".
*/ */
@@ -2786,7 +2821,17 @@ win_close_othertab(win_T *win, int free_buf, tabpage_T *tp)
for (ptp = first_tabpage; ptp != NULL && ptp != tp; ptp = ptp->tp_next) for (ptp = first_tabpage; ptp != NULL && ptp != tp; ptp = ptp->tp_next)
; ;
if (ptp == NULL || tp == curtab) if (ptp == NULL || tp == curtab)
{
// If the buffer was removed from the window we have to give it any
// buffer.
if (win_valid_any_tab(win) && win->w_buffer == NULL)
{
win->w_buffer = firstbuf;
++firstbuf->b_nwindows;
win_init_empty(win);
}
return; return;
}
// Autocommands may have closed the window already. // Autocommands may have closed the window already.
for (wp = tp->tp_firstwin; wp != NULL && wp != win; wp = wp->w_next) for (wp = tp->tp_firstwin; wp != NULL && wp != win; wp = wp->w_next)
@@ -3685,41 +3730,6 @@ close_others(
emsg(_(e_other_window_contains_changes)); emsg(_(e_other_window_contains_changes));
} }
static void
win_init_empty(win_T *wp)
{
redraw_win_later(wp, NOT_VALID);
wp->w_lines_valid = 0;
wp->w_cursor.lnum = 1;
wp->w_curswant = wp->w_cursor.col = 0;
wp->w_cursor.coladd = 0;
wp->w_pcmark.lnum = 1; // pcmark not cleared but set to line 1
wp->w_pcmark.col = 0;
wp->w_prev_pcmark.lnum = 0;
wp->w_prev_pcmark.col = 0;
wp->w_topline = 1;
#ifdef FEAT_DIFF
wp->w_topfill = 0;
#endif
wp->w_botline = 2;
#if defined(FEAT_SYN_HL) || defined(FEAT_SPELL)
wp->w_s = &wp->w_buffer->b_s;
#endif
#ifdef FEAT_TERMINAL
term_reset_wincolor(wp);
#endif
}
/*
* Init the current window "curwin".
* Called when a new file is being edited.
*/
void
curwin_init(void)
{
win_init_empty(curwin);
}
/* /*
* Allocate the first window and put an empty buffer in it. * Allocate the first window and put an empty buffer in it.
* Called from main(). * Called from main().