140 lines
3.4 KiB
Diff
140 lines
3.4 KiB
Diff
From 338f1fc0ee3ca929387448fe464579d6113fa76a Mon Sep 17 00:00:00 2001
|
|
From: Bram Moolenaar <Bram@vim.org>
|
|
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 | 23 ++++++++++++++++++++++
|
|
src/undo.c | 6 ++++++
|
|
3 files changed, 50 insertions(+), 21 deletions(-)
|
|
|
|
diff --git a/src/normal.c b/src/normal.c
|
|
index f122627..d33a56a 100644
|
|
--- a/src/normal.c
|
|
+++ b/src/normal.c
|
|
@@ -161,6 +161,22 @@ typedef void (*nv_func_T)(cmdarg_T *cap);
|
|
*/
|
|
|
|
/*
|
|
+ * 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;
|
|
+}
|
|
+
|
|
+/*
|
|
* This table contains one entry for every Normal or Visual mode command.
|
|
* The order doesn't matter, init_normal_cmds() will create a sorted index.
|
|
* It is faster when all keys from zero to '~' are present.
|
|
@@ -738,14 +754,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;
|
|
|
|
/*
|
|
@@ -4155,12 +4166,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);
|
|
@@ -6288,14 +6295,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 2404b32..be7aaa8 100644
|
|
--- a/src/testdir/test_substitute.vim
|
|
+++ b/src/testdir/test_substitute.vim
|
|
@@ -800,3 +800,26 @@ func Test_sub_open_cmdline_win()
|
|
call delete('Xscript')
|
|
call delete('Xresult')
|
|
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 3dcf277..b3a91b5 100644
|
|
--- a/src/undo.c
|
|
+++ b/src/undo.c
|
|
@@ -2283,6 +2283,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);
|
|
--
|
|
1.8.3.1
|
|
|