mirror of
https://github.com/neovim/neovim.git
synced 2026-05-04 04:55:16 +00:00
vim-patch:9.2.0180: possible crash with winminheight=0 (#38335)
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: vim/vim#19706
closes: vim/vim#19712
a5d9654620
Co-authored-by: Hirohito Higashi <h.east.727@gmail.com>
This commit is contained in:
@@ -6311,7 +6311,7 @@ static void frame_setheight(frame_T *curfrp, int height)
|
|||||||
}
|
}
|
||||||
// If there is only a 'winfixheight' window and making the
|
// If there is only a 'winfixheight' window and making the
|
||||||
// window smaller, need to make the other window taller.
|
// 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;
|
room_reserved = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -2326,4 +2326,68 @@ func Test_resize_from_another_tabpage()
|
|||||||
call StopVimInTerminal(buf)
|
call StopVimInTerminal(buf)
|
||||||
endfunc
|
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
|
" vim: shiftwidth=2 sts=2 expandtab
|
||||||
|
|||||||
Reference in New Issue
Block a user