]> git.ipfire.org Git - thirdparty/vim.git/commitdiff
patch 9.0.0550: crash when closing a tabpage and buffer is NULL v9.0.0550
authorzeertzjq <zeertzjq@outlook.com>
Thu, 22 Sep 2022 17:08:37 +0000 (18:08 +0100)
committerBram Moolenaar <Bram@vim.org>
Thu, 22 Sep 2022 17:08:37 +0000 (18:08 +0100)
Problem:    Crash when closing a tabpage and buffer is NULL.
Solution:   Adjust how autocommands are triggered when closing a window.
            (closes #11198, closes #11197)

src/ex_docmd.c
src/testdir/test_autocmd.vim
src/version.c
src/window.c

index a786ff0cc6571007d44169676b78da2ced4b7a5f..912203917e2664722ff3b5121518783e89a56b62 100644 (file)
@@ -6304,7 +6304,6 @@ tabpage_close_other(tabpage_T *tp, int forceit)
 {
     int                done = 0;
     win_T      *wp;
-    int                h = tabline_height();
 
     // Limit to 1000 windows, autocommands may add a window while we close
     // one.  OK, so I'm paranoid...
@@ -6320,10 +6319,6 @@ tabpage_close_other(tabpage_T *tp, int forceit)
     }
 
     apply_autocmds(EVENT_TABCLOSED, NULL, NULL, FALSE, curbuf);
-
-    redraw_tabline = TRUE;
-    if (h != tabline_height())
-       shell_new_rows();
 }
 
 /*
index 17bfd1b60bb9991add0eb04c3a59d9bf8f86f1fd..3c95f87a3db867d758bf9c20cfc808c1c83f12b6 100644 (file)
@@ -515,6 +515,26 @@ func Test_WinClosed_throws_with_tabs()
   augroup! test-WinClosed
 endfunc
 
+" This used to trigger WinClosed twice for the same window, and the window's
+" buffer was NULL in the second autocommand.
+func Test_WinClosed_switch_tab()
+  edit Xa
+  split Xb
+  split Xc
+  tab split
+  new
+  augroup test-WinClosed
+    autocmd WinClosed * tabprev | bwipe!
+  augroup END
+  close
+  " Check that the tabline has been fully removed
+  call assert_equal([1, 1], win_screenpos(0))
+
+  autocmd! test-WinClosed
+  augroup! test-WinClosed
+  %bwipe!
+endfunc
+
 func s:AddAnAutocmd()
   augroup vimBarTest
     au BufReadCmd * echo 'hello'
index e3a3a0e45a0d7c3ead7b799006fc1a51556c5493..5d6951c879265836bd8a6848c24c4edf6ea8453b 100644 (file)
@@ -699,6 +699,8 @@ static char *(features[]) =
 
 static int included_patches[] =
 {   /* Add new patch number below this line */
+/**/
+    550,
 /**/
     549,
 /**/
index 3e1a3efd8619e373e5c182963cbc479730149c37..d73dfd9fd065212824d1c0a7d93752b4aac27f62 100644 (file)
@@ -2340,7 +2340,6 @@ close_windows(
 {
     win_T      *wp;
     tabpage_T   *tp, *nexttp;
-    int                h = tabline_height();
     int                count = tabpage_index(NULL);
 
     ++RedrawingDisabled;
@@ -2384,10 +2383,6 @@ close_windows(
 
     if (count != tabpage_index(NULL))
        apply_autocmds(EVENT_TABCLOSED, NULL, NULL, FALSE, curbuf);
-
-    redraw_tabline = TRUE;
-    if (h != tabline_height())
-       shell_new_rows();
 }
 
 /*
@@ -2446,18 +2441,11 @@ close_last_window_tabpage(
         * that below.
         */
        goto_tabpage_tp(alt_tabpage(), FALSE, TRUE);
-       redraw_tabline = TRUE;
 
        // Safety check: Autocommands may have closed the window when jumping
        // to the other tab page.
        if (valid_tabpage(prev_curtab) && prev_curtab->tp_firstwin == win)
-       {
-           int     h = tabline_height();
-
            win_close_othertab(win, free_buf, prev_curtab);
-           if (h != tabline_height())
-               shell_new_rows();
-       }
 #ifdef FEAT_JOB_CHANNEL
        entering_window(curwin);
 #endif
@@ -2656,7 +2644,10 @@ win_close(win_T *win, int free_buf)
                                                      && win->w_buffer == NULL)
     {
        // Need to close the window anyway, since the buffer is NULL.
+       // Don't trigger autocmds with a NULL buffer.
+       block_autocmds();
        win_close_othertab(win, FALSE, prev_curtab);
+       unblock_autocmds();
        return FAIL;
     }
 
@@ -2907,6 +2898,8 @@ win_close_othertab(win_T *win, int free_buf, tabpage_T *tp)
     // When closing the last window in a tab page remove the tab page.
     if (tp->tp_firstwin == tp->tp_lastwin)
     {
+       int     h = tabline_height();
+
        if (tp == first_tabpage)
            first_tabpage = tp->tp_next;
        else
@@ -2922,6 +2915,9 @@ win_close_othertab(win_T *win, int free_buf, tabpage_T *tp)
            ptp->tp_next = tp->tp_next;
        }
        free_tp = TRUE;
+       redraw_tabline = TRUE;
+       if (h != tabline_height())
+           shell_new_rows();
     }
 
     // Free the memory used for the window.