mirror of
https://github.com/neovim/neovim.git
synced 2025-12-16 11:25:33 +00:00
Merge pull request #17877 from zeertzjq/vim-8.2.4631
vim-patch:8.2.4631: crash when switching window in BufWipeout autocommand
This commit is contained in:
@@ -590,6 +590,10 @@ bool close_buffer(win_T *win, buf_T *buf, int action, bool abort_if_last)
|
|||||||
|
|
||||||
// Remove the buffer from the list.
|
// Remove the buffer from the list.
|
||||||
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 (buf->b_sfname != buf->b_ffname) {
|
if (buf->b_sfname != buf->b_ffname) {
|
||||||
XFREE_CLEAR(buf->b_sfname);
|
XFREE_CLEAR(buf->b_sfname);
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@@ -6839,7 +6839,7 @@ void tabpage_close_other(tabpage_T *tp, int forceit)
|
|||||||
|
|
||||||
// Autocommands may delete the tab page under our fingers and we may
|
// Autocommands may delete the tab page under our fingers and we may
|
||||||
// fail to close a window with a modified buffer.
|
// fail to close a window with a modified buffer.
|
||||||
if (!valid_tabpage(tp) || tp->tp_firstwin == wp) {
|
if (!valid_tabpage(tp) || tp->tp_lastwin == wp) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2611,4 +2611,21 @@ func Test_autocmd_closing_cmdwin()
|
|||||||
only
|
only
|
||||||
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
|
||||||
|
|||||||
@@ -2350,6 +2350,30 @@ void entering_window(win_T *const win)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void win_init_empty(win_T *wp)
|
||||||
|
{
|
||||||
|
redraw_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;
|
||||||
|
wp->w_topfill = 0;
|
||||||
|
wp->w_botline = 2;
|
||||||
|
wp->w_s = &wp->w_buffer->b_s;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Init the current window "curwin".
|
||||||
|
/// Called when a new file is being edited.
|
||||||
|
void curwin_init(void)
|
||||||
|
{
|
||||||
|
win_init_empty(curwin);
|
||||||
|
}
|
||||||
|
|
||||||
/// Closes all windows for buffer `buf` unless there is only one non-floating window.
|
/// Closes all windows for buffer `buf` unless there is only one non-floating window.
|
||||||
///
|
///
|
||||||
/// @param keep_curwin don't close `curwin`
|
/// @param keep_curwin don't close `curwin`
|
||||||
@@ -2867,6 +2891,13 @@ void 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;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -3793,33 +3824,6 @@ void close_others(int message, int forceit)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Init the current window "curwin".
|
|
||||||
* Called when a new file is being edited.
|
|
||||||
*/
|
|
||||||
void curwin_init(void)
|
|
||||||
{
|
|
||||||
win_init_empty(curwin);
|
|
||||||
}
|
|
||||||
|
|
||||||
void win_init_empty(win_T *wp)
|
|
||||||
{
|
|
||||||
redraw_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;
|
|
||||||
wp->w_topfill = 0;
|
|
||||||
wp->w_botline = 2;
|
|
||||||
wp->w_s = &wp->w_buffer->b_s;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* 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().
|
||||||
|
|||||||
@@ -3,8 +3,10 @@ local helpers = require('test.functional.helpers')(after_each)
|
|||||||
local clear = helpers.clear
|
local clear = helpers.clear
|
||||||
local command = helpers.command
|
local command = helpers.command
|
||||||
local eq = helpers.eq
|
local eq = helpers.eq
|
||||||
|
local neq = helpers.neq
|
||||||
local feed = helpers.feed
|
local feed = helpers.feed
|
||||||
local eval = helpers.eval
|
local eval = helpers.eval
|
||||||
|
local exec = helpers.exec
|
||||||
|
|
||||||
describe('tabpage', function()
|
describe('tabpage', function()
|
||||||
before_each(clear)
|
before_each(clear)
|
||||||
@@ -34,5 +36,20 @@ describe('tabpage', function()
|
|||||||
|
|
||||||
eq(3, eval('tabpagenr()'))
|
eq(3, eval('tabpagenr()'))
|
||||||
end)
|
end)
|
||||||
|
|
||||||
|
it('does not crash or loop 999 times if BufWipeout autocommand switches window #17868', function()
|
||||||
|
exec([[
|
||||||
|
tabedit
|
||||||
|
let s:window_id = win_getid()
|
||||||
|
botright new
|
||||||
|
setlocal bufhidden=wipe
|
||||||
|
let g:win_closed = 0
|
||||||
|
autocmd WinClosed * let g:win_closed += 1
|
||||||
|
autocmd BufWipeout <buffer> call win_gotoid(s:window_id)
|
||||||
|
tabprevious
|
||||||
|
+tabclose
|
||||||
|
]])
|
||||||
|
neq(999, eval('g:win_closed'))
|
||||||
|
end)
|
||||||
end)
|
end)
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user