To: vim_dev@googlegroups.com Subject: Patch 8.2.2476 Fcc: outbox From: Bram Moolenaar Mime-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ------------ Patch 8.2.2476 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. Files: src/buffer.c, src/window.c, src/errors.h, src/structs.h, src/popupwin.c, src/testdir/test_autocmd.vim *** ../vim-8.2.2475/src/buffer.c 2021-01-23 15:14:57.308269451 +0100 --- src/buffer.c 2021-02-06 23:21:35.680739843 +0100 *************** *** 595,600 **** --- 595,601 ---- if (buf->b_nwindows == 1) { ++buf->b_locked; + ++buf->b_locked_split; if (apply_autocmds(EVENT_BUFWINLEAVE, buf->b_fname, buf->b_fname, FALSE, buf) && !bufref_valid(&bufref)) *************** *** 605,610 **** --- 606,612 ---- return FALSE; } --buf->b_locked; + --buf->b_locked_split; if (abort_if_last && one_window()) // Autocommands made this the only window. goto aucmd_abort; *************** *** 614,625 **** --- 616,629 ---- if (!unload_buf) { ++buf->b_locked; + ++buf->b_locked_split; if (apply_autocmds(EVENT_BUFHIDDEN, buf->b_fname, buf->b_fname, FALSE, buf) && !bufref_valid(&bufref)) // Autocommands deleted the buffer. goto aucmd_abort; --buf->b_locked; + --buf->b_locked_split; if (abort_if_last && one_window()) // Autocommands made this the only window. goto aucmd_abort; *************** *** 800,805 **** --- 804,810 ---- // Make sure the buffer isn't closed by autocommands. ++buf->b_locked; + ++buf->b_locked_split; set_bufref(&bufref, buf); if (buf->b_ml.ml_mfp != NULL) { *************** *** 826,831 **** --- 831,837 ---- return; } --buf->b_locked; + --buf->b_locked_split; // 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 *************** *** 1718,1725 **** set_bufref(&prevbufref, prevbuf); set_bufref(&newbufref, buf); ! // Autocommands may delete the current buffer and/or the buffer we want to go ! // to. In those cases don't close the buffer. if (!apply_autocmds(EVENT_BUFLEAVE, NULL, NULL, FALSE, curbuf) || (bufref_valid(&prevbufref) && bufref_valid(&newbufref) --- 1724,1731 ---- set_bufref(&prevbufref, prevbuf); set_bufref(&newbufref, buf); ! // Autocommands may delete the current buffer and/or the buffer we want to ! // go to. In those cases don't close the buffer. if (!apply_autocmds(EVENT_BUFLEAVE, NULL, NULL, FALSE, curbuf) || (bufref_valid(&prevbufref) && bufref_valid(&newbufref) *** ../vim-8.2.2475/src/window.c 2020-12-29 12:46:47.662457054 +0100 --- src/window.c 2021-02-06 23:23:10.616459822 +0100 *************** *** 769,774 **** --- 769,779 ---- emsg(_("E242: Can't split a window while closing another")); return FAIL; } + if (curwin->w_buffer->b_locked_split) + { + emsg(_(e_cannot_split_window_when_closing_buffer)); + return FAIL; + } return OK; } *************** *** 793,798 **** --- 798,806 ---- if (ERROR_IF_ANY_POPUP_WINDOW) return FAIL; + if (check_split_disallowed() == FAIL) + return FAIL; + // When the ":tab" modifier was used open a new tab page instead. if (may_open_tabpage() == OK) return OK; *************** *** 804,811 **** emsg(_("E442: Can't split topleft and botright at the same time")); return FAIL; } - if (check_split_disallowed() == FAIL) - return FAIL; // When creating the help window make a snapshot of the window layout. // Otherwise clear the snapshot, it's now invalid. --- 812,817 ---- *** ../vim-8.2.2475/src/errors.h 2021-02-01 20:14:44.566705066 +0100 --- src/errors.h 2021-02-06 22:41:30.771750526 +0100 *************** *** 353,355 **** --- 353,357 ---- INIT(= N_("E1157: Missing return type")); EXTERN char e_cannot_use_flatten_in_vim9_script[] INIT(= N_("E1158: Cannot use flatten() in Vim9 script")); + EXTERN char e_cannot_split_window_when_closing_buffer[] + INIT(= N_("E1159: Cannot split a window when closing the buffer")); *** ../vim-8.2.2475/src/structs.h 2021-01-31 14:45:56.925141860 +0100 --- src/structs.h 2021-02-06 23:19:56.601032025 +0100 *************** *** 2633,2638 **** --- 2633,2640 ---- int b_flags; // various BF_ flags int b_locked; // Buffer is being closed or referenced, don't // let autocommands wipe it out. + int b_locked_split; // Buffer is being closed, don't allow opening + // a new window with it. /* * b_ffname has the full path of the file (NULL for no name). *** ../vim-8.2.2475/src/popupwin.c 2021-02-06 14:59:21.126120022 +0100 --- src/popupwin.c 2021-02-06 23:22:18.660613080 +0100 *************** *** 1941,1947 **** buf->b_p_ul = -1; // no undo buf->b_p_swf = FALSE; // no swap file buf->b_p_bl = FALSE; // unlisted buffer ! buf->b_locked = TRUE; // Avoid that 'buftype' is reset when this buffer is entered. buf->b_p_initialized = TRUE; --- 1941,1947 ---- buf->b_p_ul = -1; // no undo buf->b_p_swf = FALSE; // no swap file buf->b_p_bl = FALSE; // unlisted buffer ! buf->b_locked = TRUE; // prevent deleting the buffer // Avoid that 'buftype' is reset when this buffer is entered. buf->b_p_initialized = TRUE; *** ../vim-8.2.2475/src/testdir/test_autocmd.vim 2021-02-06 19:28:42.108044822 +0100 --- src/testdir/test_autocmd.vim 2021-02-07 12:12:09.845326444 +0100 *************** *** 2761,2775 **** " Fuzzer found some strange combination that caused a crash. func Test_autocmd_normal_mess() - " TODO: why does this hang on Windows? - CheckNotMSWindows - augroup aucmd_normal_test au BufLeave,BufWinLeave,BufHidden,BufUnload,BufDelete,BufWipeout * norm 7q/qc augroup END ! o4 silent! H ! e xx normal G augroup aucmd_normal_test --- 2761,2772 ---- " Fuzzer found some strange combination that caused a crash. func Test_autocmd_normal_mess() augroup aucmd_normal_test au BufLeave,BufWinLeave,BufHidden,BufUnload,BufDelete,BufWipeout * norm 7q/qc augroup END ! call assert_fails('o4', 'E1159') silent! H ! call assert_fails('e xx', 'E1159') normal G augroup aucmd_normal_test *************** *** 2791,2797 **** au QuickfixCmdPre,BufNew,BufDelete,BufReadCmd * sb au QuickfixCmdPre,BufNew,BufDelete,BufReadCmd * q9 augroup END ! " TODO: if this is executed directly valgrind reports errors call assert_fails('lv?a?', 'E926:') augroup aucmd_vimgrep --- 2788,2794 ---- au QuickfixCmdPre,BufNew,BufDelete,BufReadCmd * sb au QuickfixCmdPre,BufNew,BufDelete,BufReadCmd * q9 augroup END ! %bwipe! call assert_fails('lv?a?', 'E926:') augroup aucmd_vimgrep *** ../vim-8.2.2475/src/version.c 2021-02-06 19:28:42.108044822 +0100 --- src/version.c 2021-02-06 22:39:49.472030634 +0100 *************** *** 752,753 **** --- 752,755 ---- { /* Add new patch number below this line */ + /**/ + 2476, /**/ -- Veni, Vidi, Video -- I came, I saw, I taped what I saw. /// Bram Moolenaar -- Bram@Moolenaar.net -- http://www.Moolenaar.net \\\ /// sponsor Vim, vote for features -- http://www.Vim.org/sponsor/ \\\ \\\ an exciting new programming language -- http://www.Zimbu.org /// \\\ help me help AIDS victims -- http://ICCF-Holland.org ///