]> git.ipfire.org Git - thirdparty/vim.git/commitdiff
patch 9.2.0180: possible crash with winminheight=0 v9.2.0180
authorHirohito Higashi <h.east.727@gmail.com>
Mon, 16 Mar 2026 21:41:47 +0000 (21:41 +0000)
committerChristian Brabandt <cb@256bit.org>
Mon, 16 Mar 2026 21:44:17 +0000 (21:44 +0000)
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>
src/testdir/test_window_cmd.vim
src/version.c
src/window.c

index 02e6fcbc32452d780f1dbb1eac5f88732a3e081c..1832a9790dd109ffedf31b1c86e42c82f085ca4c 100644 (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
index fe4fe69b2d7ca5e181ef2ae9395ed13c6efd782a..8889f69af9c31a8313fd2c723a5c75c7e8cd31d9 100644 (file)
@@ -734,6 +734,8 @@ static char *(features[]) =
 
 static int included_patches[] =
 {   /* Add new patch number below this line */
+/**/
+    180,
 /**/
     179,
 /**/
index cee40b79e6518bc2e1f26aff0fbda3c382a0dab0..4b6626cc31bc444ed36543d92441f55a2f2d3585 100644 (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)