patch 8.2.5023: substitute overwrites allocated buffer v8.2.5023
authorBram Moolenaar <Bram@vim.org>
Thu, 26 May 2022 14:56:23 +0000 (15:56 +0100)
committerBram Moolenaar <Bram@vim.org>
Thu, 26 May 2022 14:56:23 +0000 (15:56 +0100)
Problem:    Substitute overwrites allocated buffer.
Solution:   Disallow undo when in a substitute command.

src/normal.c
src/testdir/test_substitute.vim
src/undo.c
src/version.c

index bc3e29e1abaa13a179f5344c0faf6b702412058a..53c50dc8b368c54d2ee15694201ca64b184dc2d2 100644 (file)
@@ -183,6 +183,22 @@ find_command(int cmdchar)
     return idx;
 }
 
+/*
+ * 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;
+}
+
 /*
  * Handle the count before a normal command and set cap->count0.
  */
@@ -802,14 +818,9 @@ normal_cmd(
        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;
 
     // In Visual/Select mode, a few keys are handled in a special way.
@@ -4049,12 +4060,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);
@@ -6182,14 +6189,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;
 
index a1c324ed8d208bccec9cf7182a30a50ebf36285f..c8df09f4ec1ebeb67e8792e734d247b2edcf0ca7 100644 (file)
@@ -1013,6 +1013,28 @@ func Test_sub_change_window()
   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
+
 " Test for the 2-letter and 3-letter :substitute commands
 func Test_substitute_short_cmd()
   new
index cac09f0f58df8e7ca1921345af7e4462496eefd9..81cc28e8b80183b0973a8005e6c12de4498eab3e 100644 (file)
@@ -2327,6 +2327,12 @@ undo_time(
     int                    above = FALSE;
     int                    did_undo = TRUE;
 
+    if (text_locked())
+    {
+       text_locked_msg();
+       return;
+    }
+
     // First make sure the current undoable change is synced.
     if (curbuf->b_u_synced == FALSE)
        u_sync(TRUE);
index 9751865c7adfe1e2d7a2b69aa6c7b64eb36cd26d..cd6c33162204e712a746b389f6adaa51a5a764f0 100644 (file)
@@ -734,6 +734,8 @@ static char *(features[]) =
 
 static int included_patches[] =
 {   /* Add new patch number below this line */
+/**/
+    5023,
 /**/
     5022,
 /**/