summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorChristian Brabandt <cb@256bit.org>2024-05-15 21:35:36 +0200
committerChristian Brabandt <cb@256bit.org>2024-05-15 21:35:36 +0200
commiteff20eb35d2dba413c6d115291dd9ddea705e802 (patch)
treed3d42ccb48d254a6261ec6c40c7920ef6953dea7
parentfed01960d2b0280339bba29183b1c3859366e805 (diff)
patch 9.1.0413: smoothscroll may cause infinite loopv9.1.0413
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 <zeertzjq@outlook.com> Signed-off-by: Christian Brabandt <cb@256bit.org>
-rw-r--r--src/charset.c31
-rw-r--r--src/move.c9
-rw-r--r--src/testdir/test_normal.vim10
-rw-r--r--src/version.c2
4 files changed, 44 insertions, 8 deletions
diff --git a/src/charset.c b/src/charset.c
index 470698f0e0..9aa402ac5e 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 3e589caae0..dd232686e9 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 5cbf681ea1..09ae42c167 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 834954af71..b79693c6a8 100644
--- a/src/version.c
+++ b/src/version.c
@@ -705,6 +705,8 @@ static char *(features[]) =
static int included_patches[] =
{ /* Add new patch number below this line */
/**/
+ 413,
+/**/
412,
/**/
411,