changeset 30974:013f8436b0d5 v9.0.0822

patch 9.0.0822: crash when dragging the statusline with a mapping Commit: https://github.com/vim/vim/commit/8ab9ca93eea32b318235384720200771863ecaee Author: Bram Moolenaar <Bram@vim.org> Date: Mon Oct 31 13:06:26 2022 +0000 patch 9.0.0822: crash when dragging the statusline with a mapping Problem: Crash when dragging the statusline with a mapping. Solution: Check for valid window pointer. (issue https://github.com/vim/vim/issues/11427)
author Bram Moolenaar <Bram@vim.org>
date Wed, 02 Nov 2022 11:18:52 +0100
parents 4d6024463de7
children 91804e81772e
files src/mouse.c src/proto/mouse.pro src/testdir/test_mapping.vim src/version.c src/window.c
diffstat 5 files changed, 44 insertions(+), 10 deletions(-) [+]
line wrap: on
line diff
--- a/src/mouse.c
+++ b/src/mouse.c
@@ -179,6 +179,18 @@ get_fpos_of_mouse(pos_T *mpos)
 }
 #endif
 
+static int	mouse_got_click = FALSE;	// got a click some time back
+
+/*
+ * Reset the flag that a mouse click was seen.  To be called when switching tab
+ * page.
+ */
+    void
+reset_mouse_got_click(void)
+{
+    mouse_got_click = FALSE;
+}
+
 /*
  * Do the appropriate action for the current mouse click in the current mode.
  * Not used for Command-line mode.
@@ -224,7 +236,6 @@ do_mouse(
     int		fixindent)	// PUT_FIXINDENT if fixing indent necessary
 {
     static int	do_always = FALSE;	// ignore 'mouse' setting next time
-    static int	got_click = FALSE;	// got a click some time back
 
     int		which_button;	// MOUSE_LEFT, _MIDDLE or _RIGHT
     int		is_click = FALSE; // If FALSE it's a drag or release event
@@ -336,14 +347,14 @@ do_mouse(
 
     // Ignore drag and release events if we didn't get a click.
     if (is_click)
-	got_click = TRUE;
+	mouse_got_click = TRUE;
     else
     {
-	if (!got_click)			// didn't get click, ignore
+	if (!mouse_got_click)			// didn't get click, ignore
 	    return FALSE;
-	if (!is_drag)			// release, reset got_click
+	if (!is_drag)			// release, reset mouse_got_click
 	{
-	    got_click = FALSE;
+	    mouse_got_click = FALSE;
 	    if (in_tab_line)
 	    {
 		in_tab_line = FALSE;
@@ -360,7 +371,7 @@ do_mouse(
 	if (count > 1)
 	    stuffnumReadbuff(count);
 	stuffcharReadbuff(Ctrl_T);
-	got_click = FALSE;		// ignore drag&release now
+	mouse_got_click = FALSE;		// ignore drag&release now
 	return FALSE;
     }
 
@@ -641,7 +652,7 @@ do_mouse(
 	    }
 # ifdef FEAT_MENU
 	    show_popupmenu();
-	    got_click = FALSE;	// ignore release events
+	    mouse_got_click = FALSE;	// ignore release events
 # endif
 	    return (jump_flags & CURSOR_MOVED) != 0;
 #else
@@ -698,7 +709,7 @@ do_mouse(
     // next mouse click.
     if (!is_drag && oap != NULL && oap->op_type != OP_NOP)
     {
-	got_click = FALSE;
+	mouse_got_click = FALSE;
 	oap->motion_type = MCHAR;
     }
 
@@ -897,7 +908,7 @@ do_mouse(
 	    do_cmdline_cmd((char_u *)".cc");
 	else					// location list window
 	    do_cmdline_cmd((char_u *)".ll");
-	got_click = FALSE;		// ignore drag&release now
+	mouse_got_click = FALSE;		// ignore drag&release now
     }
 #endif
 
@@ -909,7 +920,7 @@ do_mouse(
 	if (State & MODE_INSERT)
 	    stuffcharReadbuff(Ctrl_O);
 	stuffcharReadbuff(Ctrl_RSB);
-	got_click = FALSE;		// ignore drag&release now
+	mouse_got_click = FALSE;		// ignore drag&release now
     }
 
     // Shift-Mouse click searches for the next occurrence of the word under
--- a/src/proto/mouse.pro
+++ b/src/proto/mouse.pro
@@ -1,6 +1,7 @@
 /* mouse.c */
 void mouse_set_vert_scroll_step(long step);
 void mouse_set_hor_scroll_step(long step);
+void reset_mouse_got_click(void);
 int do_mouse(oparg_T *oap, int c, int dir, long count, int fixindent);
 void ins_mouse(int c);
 void ins_mousescroll(int dir);
--- a/src/testdir/test_mapping.vim
+++ b/src/testdir/test_mapping.vim
@@ -1648,6 +1648,24 @@ func Test_mouse_drag_mapped_start_select
   set mouse&
 endfunc
 
+func Test_mouse_drag_statusline()
+  set laststatus=2
+  set mouse=a
+  func ClickExpr()
+      call test_setmouse(&lines - 1, 1)
+        return "\<LeftMouse>"
+  endfunc
+  func DragExpr()
+      call test_setmouse(&lines - 2, 1)
+        return "\<LeftDrag>"
+  endfunc
+  nnoremap <expr> <F2> ClickExpr()
+  nnoremap <expr> <F3> DragExpr()
+
+  " this was causing a crash in win_drag_status_line()
+  call feedkeys("\<F2>:tabnew\<CR>\<F3>", 'tx')
+endfunc
+
 " Test for mapping <LeftDrag> in Insert mode
 func Test_mouse_drag_insert_map()
   set mouse=a
--- a/src/version.c
+++ b/src/version.c
@@ -696,6 +696,8 @@ static char *(features[]) =
 static int included_patches[] =
 {   /* Add new patch number below this line */
 /**/
+    822,
+/**/
     821,
 /**/
     820,
--- a/src/window.c
+++ b/src/window.c
@@ -4249,6 +4249,7 @@ leave_tabpage(
 {
     tabpage_T	*tp = curtab;
 
+    reset_mouse_got_click();
 #ifdef FEAT_JOB_CHANNEL
     leaving_window(curwin);
 #endif
@@ -4464,6 +4465,7 @@ goto_tabpage_tp(
     // Don't repeat a message in another tab page.
     set_keep_msg(NULL, 0);
 
+    reset_mouse_got_click();
     skip_win_fix_scroll = TRUE;
     if (tp != curtab && leave_tabpage(tp->tp_curwin->w_buffer,
 					trigger_leave_autocmds) == OK)