mirror of
https://github.com/neovim/neovim.git
synced 2024-12-24 21:25:04 -07:00
vim-patch:8.2.2476: using freed memory when splitting window while closing buffer
Problem: Using freed memory when using an autocommand to split a window
while a buffer is being closed.
Solution: Disallow splitting when the buffer has b_locked_split set.
983d83ff1c
Put the error message in window.c.
Cherry-pick a memory leak fix from Vim patch 8.2.0399.
Test still fails.
This commit is contained in:
parent
407be5975d
commit
1664e3d4bc
@ -466,6 +466,7 @@ bool close_buffer(win_T *win, buf_T *buf, int action, bool abort_if_last, bool i
|
|||||||
// When the buffer is no longer in a window, trigger BufWinLeave
|
// When the buffer is no longer in a window, trigger BufWinLeave
|
||||||
if (buf->b_nwindows == 1) {
|
if (buf->b_nwindows == 1) {
|
||||||
buf->b_locked++;
|
buf->b_locked++;
|
||||||
|
buf->b_locked_split++;
|
||||||
if (apply_autocmds(EVENT_BUFWINLEAVE, buf->b_fname, buf->b_fname, false,
|
if (apply_autocmds(EVENT_BUFWINLEAVE, buf->b_fname, buf->b_fname, false,
|
||||||
buf) && !bufref_valid(&bufref)) {
|
buf) && !bufref_valid(&bufref)) {
|
||||||
// Autocommands deleted the buffer.
|
// Autocommands deleted the buffer.
|
||||||
@ -473,6 +474,7 @@ bool close_buffer(win_T *win, buf_T *buf, int action, bool abort_if_last, bool i
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
buf->b_locked--;
|
buf->b_locked--;
|
||||||
|
buf->b_locked_split--;
|
||||||
if (abort_if_last && last_nonfloat(win)) {
|
if (abort_if_last && last_nonfloat(win)) {
|
||||||
// Autocommands made this the only window.
|
// Autocommands made this the only window.
|
||||||
emsg(_(e_auabort));
|
emsg(_(e_auabort));
|
||||||
@ -483,6 +485,7 @@ bool close_buffer(win_T *win, buf_T *buf, int action, bool abort_if_last, bool i
|
|||||||
// BufHidden
|
// BufHidden
|
||||||
if (!unload_buf) {
|
if (!unload_buf) {
|
||||||
buf->b_locked++;
|
buf->b_locked++;
|
||||||
|
buf->b_locked_split++;
|
||||||
if (apply_autocmds(EVENT_BUFHIDDEN, buf->b_fname, buf->b_fname, false,
|
if (apply_autocmds(EVENT_BUFHIDDEN, buf->b_fname, buf->b_fname, false,
|
||||||
buf) && !bufref_valid(&bufref)) {
|
buf) && !bufref_valid(&bufref)) {
|
||||||
// Autocommands deleted the buffer.
|
// Autocommands deleted the buffer.
|
||||||
@ -490,6 +493,7 @@ bool close_buffer(win_T *win, buf_T *buf, int action, bool abort_if_last, bool i
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
buf->b_locked--;
|
buf->b_locked--;
|
||||||
|
buf->b_locked_split--;
|
||||||
if (abort_if_last && last_nonfloat(win)) {
|
if (abort_if_last && last_nonfloat(win)) {
|
||||||
// Autocommands made this the only window.
|
// Autocommands made this the only window.
|
||||||
emsg(_(e_auabort));
|
emsg(_(e_auabort));
|
||||||
@ -678,6 +682,7 @@ void buf_freeall(buf_T *buf, int flags)
|
|||||||
|
|
||||||
// Make sure the buffer isn't closed by autocommands.
|
// Make sure the buffer isn't closed by autocommands.
|
||||||
buf->b_locked++;
|
buf->b_locked++;
|
||||||
|
buf->b_locked_split++;
|
||||||
|
|
||||||
bufref_T bufref;
|
bufref_T bufref;
|
||||||
set_bufref(&bufref, buf);
|
set_bufref(&bufref, buf);
|
||||||
@ -703,6 +708,7 @@ void buf_freeall(buf_T *buf, int flags)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
buf->b_locked--;
|
buf->b_locked--;
|
||||||
|
buf->b_locked_split--;
|
||||||
|
|
||||||
// If the buffer was in curwin and the window has changed, go back to that
|
// If the buffer was in curwin and the window has changed, go back to that
|
||||||
// window, if it still exists. This avoids that ":edit x" triggering a
|
// window, if it still exists. This avoids that ":edit x" triggering a
|
||||||
@ -1466,8 +1472,8 @@ void set_curbuf(buf_T *buf, int action)
|
|||||||
set_bufref(&prevbufref, prevbuf);
|
set_bufref(&prevbufref, prevbuf);
|
||||||
set_bufref(&newbufref, buf);
|
set_bufref(&newbufref, buf);
|
||||||
|
|
||||||
// Autocommands may delete the current buffer and/or the buffer we want to go
|
// Autocommands may delete the current buffer and/or the buffer we want to
|
||||||
// to. In those cases don't close the buffer.
|
// go to. In those cases don't close the buffer.
|
||||||
if (!apply_autocmds(EVENT_BUFLEAVE, NULL, NULL, false, curbuf)
|
if (!apply_autocmds(EVENT_BUFLEAVE, NULL, NULL, false, curbuf)
|
||||||
|| (bufref_valid(&prevbufref) && bufref_valid(&newbufref)
|
|| (bufref_valid(&prevbufref) && bufref_valid(&newbufref)
|
||||||
&& !aborting())) {
|
&& !aborting())) {
|
||||||
|
@ -532,6 +532,8 @@ struct file_buffer {
|
|||||||
int b_flags; // various BF_ flags
|
int b_flags; // various BF_ flags
|
||||||
int b_locked; // Buffer is being closed or referenced, don't
|
int b_locked; // Buffer is being closed or referenced, don't
|
||||||
// let autocommands wipe it out.
|
// let autocommands wipe it out.
|
||||||
|
int b_locked_split; // Buffer is being closed, don't allow opening
|
||||||
|
// a new window with it.
|
||||||
int b_ro_locked; // Non-zero when the buffer can't be changed.
|
int b_ro_locked; // Non-zero when the buffer can't be changed.
|
||||||
// Used for FileChangedRO
|
// Used for FileChangedRO
|
||||||
|
|
||||||
|
@ -6376,6 +6376,7 @@ static int open_cmdwin(void)
|
|||||||
// Create a window for the command-line buffer.
|
// Create a window for the command-line buffer.
|
||||||
if (win_split((int)p_cwh, WSP_BOT) == FAIL) {
|
if (win_split((int)p_cwh, WSP_BOT) == FAIL) {
|
||||||
beep_flush();
|
beep_flush();
|
||||||
|
ga_clear(&winsizes);
|
||||||
return K_IGNORE;
|
return K_IGNORE;
|
||||||
}
|
}
|
||||||
cmdwin_type = get_cmdline_type();
|
cmdwin_type = get_cmdline_type();
|
||||||
|
@ -2717,17 +2717,14 @@ endfunc
|
|||||||
|
|
||||||
" Fuzzer found some strange combination that caused a crash.
|
" Fuzzer found some strange combination that caused a crash.
|
||||||
func Test_autocmd_normal_mess()
|
func Test_autocmd_normal_mess()
|
||||||
" TODO: why does this hang on Windows?
|
|
||||||
CheckNotMSWindows
|
|
||||||
|
|
||||||
augroup aucmd_normal_test
|
augroup aucmd_normal_test
|
||||||
au BufLeave,BufWinLeave,BufHidden,BufUnload,BufDelete,BufWipeout * norm 7q/qc
|
au BufLeave,BufWinLeave,BufHidden,BufUnload,BufDelete,BufWipeout * norm 7q/qc
|
||||||
augroup END
|
augroup END
|
||||||
" Nvim has removed :open
|
" Nvim has removed :open
|
||||||
" o4
|
" call assert_fails('o4', 'E1159')
|
||||||
e4
|
call assert_fails('e4', 'E1159')
|
||||||
silent! H
|
silent! H
|
||||||
e xx
|
call assert_fails('e xx', 'E1159')
|
||||||
normal G
|
normal G
|
||||||
|
|
||||||
augroup aucmd_normal_test
|
augroup aucmd_normal_test
|
||||||
@ -2749,7 +2746,7 @@ func Test_autocmd_vimgrep()
|
|||||||
au QuickfixCmdPre,BufNew,BufDelete,BufReadCmd * sb
|
au QuickfixCmdPre,BufNew,BufDelete,BufReadCmd * sb
|
||||||
au QuickfixCmdPre,BufNew,BufDelete,BufReadCmd * q9 |