From 338f1fc0ee3ca929387448fe464579d6113fa76a Mon Sep 17 00:00:00 2001 From: Bram Moolenaar Date: Thu, 26 May 2022 15:56:23 +0100 Subject: [PATCH] patch 8.2.5023: substitute overwrites allocated buffer Problem: Substitute overwrites allocated buffer. Solution: Disallow undo when in a substitute command. --- src/normal.c | 42 ++++++++++++++++----------------- src/testdir/test_substitute.vim | 22 +++++++++++++++++ src/undo.c | 6 +++++ src/version.c | 2 ++ 4 files changed, 51 insertions(+), 21 deletions(-) diff --git a/src/normal.c b/src/normal.c index bc3e29e1abaa..53c50dc8b368 100644 --- a/src/normal.c +++ b/src/normal.c @@ -514,6 +514,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; +} + /* * Execute a command in Normal mode. */ @@ -775,14 +791,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; /* @@ -6164,12 +6175,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); @@ -8330,14 +8337,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 --git a/src/testdir/test_substitute.vim b/src/testdir/test_substitute.vim index a1c324ed8d20..c8df09f4ec1e 100644 --- a/src/testdir/test_substitute.vim +++ b/src/testdir/test_substitute.vim @@ -530,3 +530,25 @@ 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 + diff --git a/src/undo.c b/src/undo.c index cac09f0f58df..81cc28e8b801 100644 --- a/src/undo.c +++ b/src/undo.c @@ -2278,6 +2278,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); diff --git a/src/version.c b/src/version.c index 9751865c7adf..cd6c33162204 100644 --- a/src/version.c +++ b/src/version.c @@ -795,6 +795,8 @@ static char *(features[]) = 805, /**/ 5024, +/**/ + 5023, /**/ 4977, /**/