patch 9.1.0413: smoothscroll may cause infinite loop Commit: https://github.com/vim/vim/commit/eff20eb35d2dba413c6d115291dd9ddea705e802 Author: Christian Brabandt <c...@256bit.org> Date: Wed May 15 21:35:36 2024 +0200
patch 9.1.0413: smoothscroll may cause infinite loop Problem: smoothscroll may cause infinite loop, with very narrow windows (Jaehwang Jung, after v9.1.0280) Solution: Check for width1 being negative, verify that win_linetabsize does not overflow fixes: #14750 closes: #14772 Co-authored-by: zeertzjq <zeert...@outlook.com> Signed-off-by: Christian Brabandt <c...@256bit.org> diff --git a/src/charset.c b/src/charset.c index 470698f0e..9aa402ac5 100644 --- a/src/charset.c +++ b/src/charset.c @@ -765,10 +765,22 @@ linetabsize_str(char_u *s) linetabsize_col(int startcol, char_u *s) { chartabsize_T cts; + vimlong_T vcol; init_chartabsize_arg(&cts, curwin, 0, startcol, s, s); + vcol = cts.cts_vcol; + while (*cts.cts_ptr != NUL) - cts.cts_vcol += lbr_chartabsize_adv(&cts); + { + vcol += lbr_chartabsize_adv(&cts); + if (vcol > MAXCOL) + { + cts.cts_vcol = MAXCOL; + break; + } + else + cts.cts_vcol = (int)vcol; + } clear_chartabsize_arg(&cts); return (int)cts.cts_vcol; } @@ -840,22 +852,33 @@ linetabsize_no_outer(win_T *wp, linenr_T lnum) void win_linetabsize_cts(chartabsize_T *cts, colnr_T len) { + vimlong_T vcol = cts->cts_vcol; #ifdef FEAT_PROP_POPUP cts->cts_with_trailing = len == MAXCOL; #endif for ( ; *cts->cts_ptr != NUL && (len == MAXCOL || cts->cts_ptr < cts->cts_line + len); MB_PTR_ADV(cts->cts_ptr)) - cts->cts_vcol += win_lbr_chartabsize(cts, NULL); + { + vcol += win_lbr_chartabsize(cts, NULL); + if (vcol > MAXCOL) + { + cts->cts_vcol = MAXCOL; + break; + } + else + cts->cts_vcol = (int)vcol; + } #ifdef FEAT_PROP_POPUP // check for a virtual text at the end of a line or on an empty line if (len == MAXCOL && cts->cts_has_prop_with_text && *cts->cts_ptr == NUL) { (void)win_lbr_chartabsize(cts, NULL); - cts->cts_vcol += cts->cts_cur_text_width; + vcol += cts->cts_cur_text_width; // when properties are above or below the empty line must also be // counted if (cts->cts_ptr == cts->cts_line && cts->cts_prop_lines > 0) - ++cts->cts_vcol; + ++vcol; + cts->cts_vcol = vcol > MAXCOL ? MAXCOL : (int)vcol; } #endif } diff --git a/src/move.c b/src/move.c index 3e589caae..dd232686e 100644 --- a/src/move.c +++ b/src/move.c @@ -1630,6 +1630,7 @@ static void cursor_correct_sms(void) int width2 = width1 + curwin_col_off2(); int so_cols = so == 0 ? 0 : width1 + (so - 1) * width2; int space_cols = (curwin->w_height - 1) * width2; + int overlap, top, bot; int size = so == 0 ? 0 : win_linetabsize(curwin, curwin->w_topline, ml_get(curwin->w_topline), (colnr_T)MAXCOL); @@ -1639,16 +1640,16 @@ static void cursor_correct_sms(void) so_cols = space_cols / 2; // Not enough room: put cursor in the middle. // Not enough screen lines in topline: ignore 'scrolloff'. - while (so_cols > size && so_cols - width2 >= width1) + while (so_cols > size && so_cols - width2 >= width1 && width1 > 0) so_cols -= width2; if (so_cols >= width1 && so_cols > size) so_cols -= width1; // If there is no marker or we have non-zero scrolloff, just ignore it. - int overlap = (curwin->w_skipcol == 0 || so_cols != 0) ? 0 + overlap = (curwin->w_skipcol == 0 || so_cols != 0) ? 0 : sms_marker_overlap(curwin, -1); - int top = curwin->w_skipcol + overlap + so_cols; - int bot = curwin->w_skipcol + width1 + (curwin->w_height - 1) * width2 + top = curwin->w_skipcol + overlap + so_cols; + bot = curwin->w_skipcol + width1 + (curwin->w_height - 1) * width2 - so_cols; validate_virtcol(); colnr_T col = curwin->w_virtcol; diff --git a/src/testdir/test_normal.vim b/src/testdir/test_normal.vim index 5cbf681ea..09ae42c16 100644 --- a/src/testdir/test_normal.vim +++ b/src/testdir/test_normal.vim @@ -4268,4 +4268,14 @@ func Test_halfpage_longline() call assert_equal(2, line('.')) bwipe! endfunc + +" Test for Ctrl-E with long line and very narrow window, +" used to cause an inifite loop +func Test_scroll_longline_no_loop() + 4vnew + setl smoothscroll number showbreak=> scrolloff=2 + call setline(1, repeat(['Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.'], 3)) + exe "normal! \<C-E>" + bwipe! +endfunc " vim: shiftwidth=2 sts=2 expandtab nofoldenable diff --git a/src/version.c b/src/version.c index 834954af7..b79693c6a 100644 --- a/src/version.c +++ b/src/version.c @@ -704,6 +704,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ +/**/ + 413, /**/ 412, /**/ -- -- 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 vim_dev+unsubscr...@googlegroups.com. To view this discussion on the web visit https://groups.google.com/d/msgid/vim_dev/E1s7KYj-003vsL-23%40256bit.org.