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:
@@ -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
|
||||||
|
@@ -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
|
||||||
|
@@ -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,
|
||||||
/**/
|
/**/
|
||||||
|
80
src/window.c
80
src/window.c
@@ -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().
|
||||||
|
Reference in New Issue
Block a user