Skip to content

Commit b2fbb7c

Browse files
patch 9.2.0284: tabpanel: crash when tabpanel expression returns variable line count
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 <[email protected]> Signed-off-by: Christian Brabandt <[email protected]>
1 parent 12f6f20 commit b2fbb7c

4 files changed

Lines changed: 35 additions & 1 deletion

File tree

src/screen.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2498,6 +2498,7 @@ screen_fill(
24982498
if (end_col > screen_Columns) // safety check
24992499
end_col = screen_Columns;
25002500
if (ScreenLines == NULL
2501+
|| start_row < 0 // should not happen
25012502
|| start_row >= end_row
25022503
|| start_col >= end_col) // nothing to do
25032504
return;

src/tabpanel.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -544,7 +544,7 @@ do_by_tplmode(
544544
}
545545

546546
// fill the area of TabPanelFill.
547-
screen_fill_tailing_area(tplmode, row - args.offsetrow, args.maxrow,
547+
screen_fill_tailing_area(tplmode, MAX(row - args.offsetrow, 0), args.maxrow,
548548
args.col_start, args.col_end, attr_tplf);
549549
}
550550

src/testdir/test_tabpanel.vim

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -892,4 +892,35 @@ func Test_tabpanel_large_columns()
892892
call assert_fails(':set tabpanelopt=columns:-1', 'E474:')
893893
endfunc
894894

895+
func Test_tabpanel_variable_height()
896+
CheckFeature tabpanel
897+
898+
let save_lines = &lines
899+
let save_showtabpanel = &showtabpanel
900+
let save_tabpanel = &tabpanel
901+
902+
set lines=10
903+
tabnew | tabnew | tabnew | tabnew | tabnew
904+
905+
let g:tpl_n = 0
906+
func! GetTpl() abort
907+
let g:tpl_n += 1
908+
return g:tpl_n <= 5 ? "x\nx" : "x"
909+
endfunc
910+
911+
set showtabpanel=2
912+
let &tabpanel = "%!GetTpl()"
913+
914+
" Should not crash
915+
redraw!
916+
917+
" Cleanup
918+
let &tabpanel = save_tabpanel
919+
let &showtabpanel = save_showtabpanel
920+
let &lines = save_lines
921+
delfunc GetTpl
922+
unlet g:tpl_n
923+
%bwipeout!
924+
endfunc
925+
895926
" vim: shiftwidth=2 sts=2 expandtab

src/version.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -734,6 +734,8 @@ static char *(features[]) =
734734

735735
static int included_patches[] =
736736
{ /* Add new patch number below this line */
737+
/**/
738+
284,
737739
/**/
738740
283,
739741
/**/

0 commit comments

Comments
 (0)