]> git.ipfire.org Git - thirdparty/vim.git/commitdiff
patch 9.2.0284: tabpanel: crash when tabpanel expression returns variable line count v9.2.0284
authorChristian Brabandt <cb@256bit.org>
Thu, 2 Apr 2026 17:37:58 +0000 (17:37 +0000)
committerChristian Brabandt <cb@256bit.org>
Thu, 2 Apr 2026 17:37:58 +0000 (17:37 +0000)
Problem:  When a tabpanel expression returns a different number of lines on
          successive evaluations, the computed row offset can become negative,
          causing screen_fill() to receive an invalid start_row and crash
          (after v9.1.1391).
Solution: Clamp the row argument in screen_fill_tailing_area() to zero,
          add a safety check in screen_fill() for negative start_row
          (Michał Majchrowicz)

Supported by AI

Co-authored-by: Michał Majchrowicz <mmajchrowicz@afine.com>
Signed-off-by: Christian Brabandt <cb@256bit.org>
src/screen.c
src/tabpanel.c
src/testdir/test_tabpanel.vim
src/version.c

index eeee319bfe5e0dfbd025c7c118794d36c68e710a..3e6fd3f4c07b0e220043f2579cfc655eeb43cbf7 100644 (file)
@@ -2498,6 +2498,7 @@ screen_fill(
     if (end_col > screen_Columns)      // safety check
        end_col = screen_Columns;
     if (ScreenLines == NULL
+           || start_row < 0            // should not happen
            || start_row >= end_row
            || start_col >= end_col)    // nothing to do
        return;
index 9db957dda5a3f40bfbfa0f292000aeb652e654c9..2a6dbe83187d5a0a80ac1ff17da1a4f031b8b28f 100644 (file)
@@ -544,7 +544,7 @@ do_by_tplmode(
     }
 
     // fill the area of TabPanelFill.
-    screen_fill_tailing_area(tplmode, row - args.offsetrow, args.maxrow,
+    screen_fill_tailing_area(tplmode, MAX(row - args.offsetrow, 0), args.maxrow,
            args.col_start, args.col_end, attr_tplf);
 }
 
index 0329dd7a4cbd2440a585ad01cbc8b6a8a8560f68..f983e2b37df7fd14a93c25754efc4d25e4829e41 100644 (file)
@@ -892,4 +892,35 @@ func Test_tabpanel_large_columns()
   call assert_fails(':set tabpanelopt=columns:-1', 'E474:')
 endfunc
 
+func Test_tabpanel_variable_height()
+  CheckFeature tabpanel
+
+  let save_lines = &lines
+  let save_showtabpanel = &showtabpanel
+  let save_tabpanel = &tabpanel
+
+  set lines=10
+  tabnew | tabnew | tabnew | tabnew | tabnew
+
+  let g:tpl_n = 0
+  func! GetTpl() abort
+    let g:tpl_n += 1
+    return g:tpl_n <= 5 ? "x\nx" : "x"
+  endfunc
+
+  set showtabpanel=2
+  let &tabpanel = "%!GetTpl()"
+
+  " Should not crash
+  redraw!
+
+  " Cleanup
+  let &tabpanel = save_tabpanel
+  let &showtabpanel = save_showtabpanel
+  let &lines = save_lines
+  delfunc GetTpl
+  unlet g:tpl_n
+  %bwipeout!
+endfunc
+
 " vim: shiftwidth=2 sts=2 expandtab
index 964ce05f717b215ddbe4b46b78b4b835140ff9fd..ebb4732943e9d658da1a4ba1e68314d8b9ae4800 100644 (file)
@@ -734,6 +734,8 @@ static char *(features[]) =
 
 static int included_patches[] =
 {   /* Add new patch number below this line */
+/**/
+    284,
 /**/
     283,
 /**/