patch 9.2.0180: possible crash with winminheight=0

Problem:  possible crash with winminheight=0
          (Emilien Breton)
Solution: Use <= instead of < when checking reserved room in
          frame_setheight() to correctly handle the zero-height
          boundary case (Hirohito Higashi).

In frame_setheight(), when shrinking the current window and the only
other window has 'winfixheight' with 'winminheight'=0, room_reserved
was not cleared because the condition used '<' instead of '<='.
The freed rows were discarded, leaving fr_height sum less than
topframe fr_height.  Subsequent resize operations then computed a
wrong room_cmdline that expanded topframe beyond the screen, causing
a crash.

fixes:  #19706
closes: #19712

Signed-off-by: Hirohito Higashi <h.east.727@gmail.com>
Signed-off-by: Christian Brabandt <cb@256bit.org>
This commit is contained in:
Hirohito Higashi
2026-03-16 21:41:47 +00:00
committed by Christian Brabandt
parent e06d084735
commit a5d9654620
3 changed files with 67 additions and 1 deletions
+64
View File
@@ -2374,4 +2374,68 @@ func Test_resize_from_another_tabpage()
call StopVimInTerminal(buf)
endfunc
" When shrinking a window and the only other window has 'winfixheight'
" with 'winminheight'=0, freed rows must go to the wfh window.
func Test_winfixheight_resize_wmh_zero()
set winminheight=0 laststatus=0
let id1 = win_getid()
copen
let id2 = win_getid()
wincmd w
wincmd _
let wi1 = getwininfo(id1)[0]
let wi2 = getwininfo(id2)[0]
let exp = &lines - wi1.status_height - wi2.height - wi2.status_height - &ch
call assert_equal([exp, 1], [wi1.height, wi1.status_height])
call assert_equal([0, 0], [wi2.height, wi2.status_height])
wincmd w " enter qf (height 0 -> 1)
let wi1 = getwininfo(id1)[0]
let wi2 = getwininfo(id2)[0]
let exp = &lines - wi1.status_height - wi2.height - wi2.status_height - &ch
call assert_equal(exp, wi1.height)
call assert_equal(1, wi2.height)
wincmd w
" Freed rows must go to qf (wfh, only other window).
" Before the fix, the rows were lost (fr_height sum < topframe fr_height),
" resulting in wrong window heights in subsequent operations.
1wincmd _
let wi1 = getwininfo(id1)[0]
let wi2 = getwininfo(id2)[0]
call assert_equal(1, wi1.height)
let exp = &lines - wi1.height - wi1.status_height - &ch
call assert_equal(exp, wi2.height)
wincmd w
99wincmd +
let wi1 = getwininfo(id1)[0]
let wi2 = getwininfo(id2)[0]
call assert_equal(0, wi1.height)
let exp = &lines - wi1.height - wi1.status_height - &ch
call assert_equal(exp, wi2.height)
99wincmd -
let wi1 = getwininfo(id1)[0]
let wi2 = getwininfo(id2)[0]
let exp = &lines - wi1.status_height - wi2.height - &ch
call assert_equal(exp, wi1.height)
call assert_equal(1, wi2.height)
" The original bug caused a crash here, but could not be reproduced in the
" test. Kept as-is, though it has no particular significance.
wincmd w
call feedkeys("999i\<CR>\<Esc>", 'tx')
call feedkeys("ggMi" .. repeat("\<CR>", 99) .. "\<Esc>", 'tx')
let wi1 = getwininfo(id1)[0]
let wi2 = getwininfo(id2)[0]
let exp = &lines - wi1.status_height - wi2.height - &ch
call assert_equal(exp, wi1.height)
call assert_equal(1, wi2.height)
cclose
set winminheight& laststatus&
endfunc
" vim: shiftwidth=2 sts=2 expandtab
+2
View File
@@ -734,6 +734,8 @@ static char *(features[]) =
static int included_patches[] =
{ /* Add new patch number below this line */
/**/
180,
/**/
179,
/**/
+1 -1
View File
@@ -6650,7 +6650,7 @@ frame_setheight(frame_T *curfrp, int height)
room_reserved = room + room_cmdline - height;
// If there is only a 'winfixheight' window and making the
// window smaller, need to make the other window taller.
if (take < 0 && room - curfrp->fr_height < room_reserved)
if (take < 0 && room - curfrp->fr_height <= room_reserved)
room_reserved = 0;
if (take > 0 && room_cmdline > 0)