patch 9.2.0180: possible crash with winminheight=0
Commit:
https://github.com/vim/vim/commit/a5d9654620648ea6d3f2f8dc2a3e42de219cf860
Author: Hirohito Higashi <[email protected]>
Date: Mon Mar 16 21:41:47 2026 +0000
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 <[email protected]>
Signed-off-by: Christian Brabandt <[email protected]>
diff --git a/src/testdir/test_window_cmd.vim b/src/testdir/test_window_cmd.vim
index 02e6fcbc3..1832a9790 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\<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
diff --git a/src/version.c b/src/version.c
index fe4fe69b2..8889f69af 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 cee40b79e..4b6626cc3 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)
--
--
You received this message from the "vim_dev" maillist.
Do not top-post! Type your reply below the text you are replying to.
For more information, visit http://www.vim.org/maillist.php
---
You received this message because you are subscribed to the Google Groups
"vim_dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email
to [email protected].
To view this discussion visit
https://groups.google.com/d/msgid/vim_dev/E1w2FkH-008vGH-Es%40256bit.org.