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)