Blob Blame History Raw
diff -up vim80/src/normal.c.cve1897 vim80/src/normal.c
--- vim80/src/normal.c.cve1897	2022-06-13 14:50:22.800290132 +0200
+++ vim80/src/normal.c	2022-06-13 14:55:06.082861349 +0200
@@ -532,6 +532,22 @@ find_command(int cmdchar)
 }
 
 /*
+ * If currently editing a cmdline or text is locked: beep and give an error
+ * message, return TRUE.
+ */
+    static int
+check_text_locked(oparg_T *oap)
+{
+    if (text_locked())
+    {
+	clearopbeep(oap);
+	text_locked_msg();
+	return TRUE;
+    }
+    return FALSE;
+}
+
+/*
  * Execute a command in Normal mode.
  */
     void
@@ -792,14 +808,9 @@ getcount:
 	goto normal_end;
     }
 
-    if (text_locked() && (nv_cmds[idx].cmd_flags & NV_NCW))
-    {
-	/* This command is not allowed while editing a cmdline: beep. */
-	clearopbeep(oap);
-	text_locked_msg();
-	goto normal_end;
-    }
-    if ((nv_cmds[idx].cmd_flags & NV_NCW) && curbuf_locked())
+    if ((nv_cmds[idx].cmd_flags & NV_NCW)
+				&& (check_text_locked(oap) || curbuf_locked()))
+	// this command is not allowed now
 	goto normal_end;
 
     /*
@@ -6234,12 +6245,8 @@ nv_gotofile(cmdarg_T *cap)
     char_u	*ptr;
     linenr_T	lnum = -1;
 
-    if (text_locked())
-    {
-	clearopbeep(cap->oap);
-	text_locked_msg();
+    if (check_text_locked(cap->oap))
 	return;
-    }
     if (curbuf_locked())
     {
 	clearop(cap->oap);
@@ -8420,14 +8427,7 @@ nv_g_cmd(cmdarg_T *cap)
 
     /* "gQ": improved Ex mode */
     case 'Q':
-	if (text_locked())
-	{
-	    clearopbeep(cap->oap);
-	    text_locked_msg();
-	    break;
-	}
-
-	if (!checkclearopq(oap))
+	if (!check_text_locked(cap->oap) && !checkclearopq(oap))
 	    do_exmode(TRUE);
 	break;
 
diff -up vim80/src/testdir/test_substitute.vim.cve1897 vim80/src/testdir/test_substitute.vim
--- vim80/src/testdir/test_substitute.vim.cve1897	2022-06-13 14:50:22.849290402 +0200
+++ vim80/src/testdir/test_substitute.vim	2022-06-13 14:55:50.370111134 +0200
@@ -513,3 +513,26 @@ func Test_sub_change_window()
   bwipe!
   delfunc Repl
 endfunc
+
+" This was undoign a change in between computing the length and using it.
+func Do_Test_sub_undo_change()
+  new
+  norm o0000000000000000000000000000000000000000000000000000
+  silent! s/\%')/\=Repl()
+  bwipe!
+endfunc
+
+func Test_sub_undo_change()
+  func Repl()
+    silent! norm g-
+  endfunc
+  call Do_Test_sub_undo_change()
+
+  func! Repl()
+    silent earlier
+  endfunc
+  call Do_Test_sub_undo_change()
+
+  delfunc Repl
+endfunc
+
diff -up vim80/src/undo.c.cve1897 vim80/src/undo.c
--- vim80/src/undo.c.cve1897	2022-06-13 14:50:22.849290402 +0200
+++ vim80/src/undo.c	2022-06-13 14:56:57.916492090 +0200
@@ -2283,6 +2283,12 @@ undo_time(
     if (curbuf->b_u_synced == FALSE)
 	u_sync(TRUE);
 
+    if (text_locked())
+    {
+	text_locked_msg();
+	return;
+    }
+
     u_newcount = 0;
     u_oldcount = 0;
     if (curbuf->b_ml.ml_flags & ML_EMPTY)