From: Hirohito Higashi Date: Mon, 16 Mar 2026 21:41:47 +0000 (+0000) Subject: patch 9.2.0180: possible crash with winminheight=0 X-Git-Tag: v9.2.0180^0 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=a5d9654620648ea6d3f2f8dc2a3e42de219cf860;p=thirdparty%2Fvim.git 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 Signed-off-by: Christian Brabandt --- diff --git a/src/testdir/test_window_cmd.vim b/src/testdir/test_window_cmd.vim index 02e6fcbc32..1832a9790d 100644 --- a/src/testdir/test_window_cmd.vim +++ b/src/testdir/test_window_cmd.vim @@ -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\\", 'tx') + call feedkeys("ggMi" .. repeat("\", 99) .. "\", '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 diff --git a/src/version.c b/src/version.c index fe4fe69b2d..8889f69af9 100644 --- a/src/version.c +++ b/src/version.c @@ -734,6 +734,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ +/**/ + 180, /**/ 179, /**/ diff --git a/src/window.c b/src/window.c index cee40b79e6..4b6626cc31 100644 --- a/src/window.c +++ b/src/window.c @@ -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)