changeset 35159:531c6b18dd0f v9.1.0406

patch 9.1.0406: Divide by zero with getmousepos() and 'smoothscroll' Commit: https://github.com/vim/vim/commit/031a745608d615d56f9d79bb0f76e2a74b2eaf14 Author: zeertzjq <zeertzjq@outlook.com> Date: Sat May 11 11:23:37 2024 +0200 patch 9.1.0406: Divide by zero with getmousepos() and 'smoothscroll' Problem: Divide by zero with getmousepos() and 'smoothscroll'. Solution: Don't compute skip_lines when width1 is zero. (zeertzjq) closes: #14747 Signed-off-by: zeertzjq <zeertzjq@outlook.com> Signed-off-by: Christian Brabandt <cb@256bit.org>
author Christian Brabandt <cb@256bit.org>
date Sat, 11 May 2024 11:30:13 +0200
parents 7191ebc28df2
children ee6031d181da
files src/mouse.c src/move.c src/testdir/test_functions.vim src/version.c
diffstat 4 files changed, 87 insertions(+), 10 deletions(-) [+]
line wrap: on
line diff
--- a/src/mouse.c
+++ b/src/mouse.c
@@ -3029,16 +3029,22 @@ mouse_comp_pos(
 
 	if (win->w_skipcol > 0 && lnum == win->w_topline)
 	{
-	    // Adjust for 'smoothscroll' clipping the top screen lines.
-	    // A similar formula is used in curs_columns().
 	    int width1 = win->w_width - win_col_off(win);
-	    int skip_lines = 0;
-	    if (win->w_skipcol > width1)
-		skip_lines = (win->w_skipcol - width1)
+
+	    if (width1 > 0)
+	    {
+		int skip_lines = 0;
+
+		// Adjust for 'smoothscroll' clipping the top screen lines.
+		// A similar formula is used in curs_columns().
+		if (win->w_skipcol > width1)
+		    skip_lines = (win->w_skipcol - width1)
 					    / (width1 + win_col_off2(win)) + 1;
-	    else if (win->w_skipcol > 0)
-		skip_lines = 1;
-	    count -= skip_lines;
+		else if (win->w_skipcol > 0)
+		    skip_lines = 1;
+
+		count -= skip_lines;
+	    }
 	}
 
 	if (count > row)
--- a/src/move.c
+++ b/src/move.c
@@ -2617,12 +2617,14 @@ scroll_cursor_bot(int min_scroll, int se
 			    plines_win
 #endif
 					(curwin, curwin->w_topline, FALSE);
-	    int skip_lines = 0;
 	    int width1 = curwin->w_width - curwin_col_off();
+
 	    if (width1 > 0)
 	    {
 		int width2 = width1 + curwin_col_off2();
-		// similar formula is used in curs_columns()
+		int skip_lines = 0;
+
+		// A similar formula is used in curs_columns().
 		if (curwin->w_skipcol > width1)
 		    skip_lines += (curwin->w_skipcol - width1) / width2 + 1;
 		else if (curwin->w_skipcol > 0)
--- a/src/testdir/test_functions.vim
+++ b/src/testdir/test_functions.vim
@@ -3697,6 +3697,73 @@ func Test_getmousepos()
         \ column: 8,
         \ coladd: 21,
         \ }, getmousepos())
+
+  30vnew
+  setlocal smoothscroll number
+  call setline(1, join(range(100)))
+  exe "normal! \<C-E>"
+  call test_setmouse(1, 5)
+  call assert_equal(#{
+        \ screenrow: 1,
+        \ screencol: 5,
+        \ winid: win_getid(),
+        \ winrow: 1,
+        \ wincol: 5,
+        \ line: 1,
+        \ column: 27,
+        \ coladd: 0,
+        \ }, getmousepos())
+  call test_setmouse(2, 5)
+  call assert_equal(#{
+        \ screenrow: 2,
+        \ screencol: 5,
+        \ winid: win_getid(),
+        \ winrow: 2,
+        \ wincol: 5,
+        \ line: 1,
+        \ column: 53,
+        \ coladd: 0,
+        \ }, getmousepos())
+
+  exe "normal! \<C-E>"
+  call test_setmouse(1, 5)
+  call assert_equal(#{
+        \ screenrow: 1,
+        \ screencol: 5,
+        \ winid: win_getid(),
+        \ winrow: 1,
+        \ wincol: 5,
+        \ line: 1,
+        \ column: 53,
+        \ coladd: 0,
+        \ }, getmousepos())
+  call test_setmouse(2, 5)
+  call assert_equal(#{
+        \ screenrow: 2,
+        \ screencol: 5,
+        \ winid: win_getid(),
+        \ winrow: 2,
+        \ wincol: 5,
+        \ line: 1,
+        \ column: 79,
+        \ coladd: 0,
+        \ }, getmousepos())
+
+  vert resize 4
+  call test_setmouse(2, 2)
+  " This used to crash Vim
+  call assert_equal(#{
+        \ screenrow: 2,
+        \ screencol: 2,
+        \ winid: win_getid(),
+        \ winrow: 2,
+        \ wincol: 2,
+        \ line: 1,
+        \ column: 53,
+        \ coladd: 0,
+        \ }, getmousepos())
+
+  bwipe!
   bwipe!
 endfunc
 
--- 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 */
 /**/
+    406,
+/**/
     405,
 /**/
     404,