vim-patch:9.1.0121: Infinite loop or signed overflow with 'smoothscroll'

Problem:  infinite loop in win_update with 'smoothscroll' set when
          window width is equal to textoff, or signed integer overflow
          if smaller.
Solution: don't revalidate wp->w_skipcol in that case, as no buffer text
          is being shown. (Sean Dewar)

02fcae02a9

Test_window_split_no_room changes were already cherry-picked earlier.
This commit is contained in:
Sean Dewar 2024-02-25 01:15:30 +00:00
parent 01b27410a3
commit b2245307f2
No known key found for this signature in database
GPG Key ID: 08CC2C83AD41B581
3 changed files with 43 additions and 18 deletions

View File

@ -1513,7 +1513,7 @@ static void win_update(win_T *wp)
// Make sure skipcol is valid, it depends on various options and the window
// width.
if (wp->w_skipcol > 0) {
if (wp->w_skipcol > 0 && wp->w_width_inner > win_col_off(wp)) {
int w = 0;
int width1 = wp->w_width_inner - win_col_off(wp);
int width2 = width1 + win_col_off2(wp);

View File

@ -963,4 +963,42 @@ func Test_smoothscroll_insert_bottom()
call StopVimInTerminal(buf)
endfunc
func Test_smoothscroll_in_zero_width_window()
set cpo+=n number smoothscroll
set winwidth=99999 winminwidth=0
vsplit
call assert_equal(0, winwidth(winnr('#')))
call win_execute(win_getid(winnr('#')), "norm! \<C-Y>")
only!
set winwidth& winminwidth&
set cpo-=n nonumber nosmoothscroll
endfunc
func Test_smoothscroll_textoff_small_winwidth()
set smoothscroll number
call setline(1, 'llanfairpwllgwyngyllgogerychwyrndrobwllllantysiliogogogoch')
vsplit
let textoff = getwininfo(win_getid())[0].textoff
execute 'vertical resize' textoff + 1
redraw
call assert_equal(0, winsaveview().skipcol)
execute "normal! 0\<C-E>"
redraw
call assert_equal(1, winsaveview().skipcol)
execute 'vertical resize' textoff - 1
" This caused a signed integer overflow.
redraw
call assert_equal(1, winsaveview().skipcol)
execute 'vertical resize' textoff
" This caused an infinite loop.
redraw
call assert_equal(1, winsaveview().skipcol)
%bw!
set smoothscroll& number&
endfunc
" vim: shiftwidth=2 sts=2 expandtab

View File

@ -2105,19 +2105,6 @@ func Test_new_help_window_on_error()
call assert_equal(expand("<cword>"), "'mod'")
endfunc
func Test_smoothscroll_in_zero_width_window()
set cpo+=n number smoothscroll
set winwidth=99999 winminwidth=0
vsplit
call assert_equal(0, winwidth(winnr('#')))
call win_execute(win_getid(winnr('#')), "norm! \<C-Y>")
only!
set winwidth& winminwidth&
set cpo-=n nonumber nosmoothscroll
endfunc
func Test_splitmove_flatten_frame()
split
vsplit
@ -2131,7 +2118,7 @@ func Test_splitmove_flatten_frame()
only!
endfunc
func Test_splitmove_autocmd_window_no_room()
func Test_autocmd_window_force_room()
" Open as many windows as possible
while v:true
try
@ -2158,7 +2145,7 @@ func Test_splitmove_autocmd_window_no_room()
edit unload me
enew
bunload! unload\ me
augroup SplitMoveAucmdWin
augroup AucmdWinForceRoom
au!
au BufEnter * ++once let s:triggered = v:true
\| call assert_equal('autocmd', win_gettype())
@ -2172,8 +2159,8 @@ func Test_splitmove_autocmd_window_no_room()
call assert_equal(winrestcmd(), restcmd)
unlet! s:triggered
au! SplitMoveAucmdWin
augroup! SplitMoveAucmdWin
au! AucmdWinForceRoom
augroup! AucmdWinForceRoom
%bw!
endfunc