aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/nvim/ex_cmds.c15
-rw-r--r--src/nvim/regexp.c8
-rw-r--r--src/nvim/testdir/test_regexp_latin.vim11
3 files changed, 20 insertions, 14 deletions
diff --git a/src/nvim/ex_cmds.c b/src/nvim/ex_cmds.c
index 550fe1eb25..11eef0ac70 100644
--- a/src/nvim/ex_cmds.c
+++ b/src/nvim/ex_cmds.c
@@ -3644,7 +3644,6 @@ static int do_sub(exarg_T *eap, proftime_T timeout, long cmdpreview_ns, handle_T
assert(sub != NULL);
- bool sub_needs_free = false;
char *sub_copy = NULL;
// If the substitute pattern starts with "\=" then it's an expression.
@@ -3656,11 +3655,12 @@ static int do_sub(exarg_T *eap, proftime_T timeout, long cmdpreview_ns, handle_T
sub = xstrdup(sub);
sub_copy = sub;
} else {
- char *source = sub;
- sub = (char *)regtilde((char_u *)sub, p_magic, cmdpreview);
- // When previewing, the new pattern allocated by regtilde() needs to be freed
- // in this function because it will not be used or freed by regtilde() later.
- sub_needs_free = cmdpreview && sub != source;
+ char *newsub = (char *)regtilde((char_u *)sub, p_magic, cmdpreview);
+ if (newsub != sub) {
+ // newsub was allocated, free it later.
+ sub_copy = newsub;
+ sub = newsub;
+ }
}
bool cmdheight0 = p_ch < 1 && !ui_has(kUIMessages);
@@ -4459,9 +4459,6 @@ skip:
vim_regfree(regmatch.regprog);
xfree(sub_copy);
- if (sub_needs_free) {
- xfree(sub);
- }
// Restore the flag values, they can be used for ":&&".
subflags.do_all = save_do_all;
diff --git a/src/nvim/regexp.c b/src/nvim/regexp.c
index 4c49d30819..2e43e388cd 100644
--- a/src/nvim/regexp.c
+++ b/src/nvim/regexp.c
@@ -1587,12 +1587,10 @@ char_u *regtilde(char_u *source, int magic, bool preview)
// Only change reg_prev_sub when not previewing.
if (!preview) {
+ // Store a copy of newsub in reg_prev_sub. It is always allocated,
+ // because recursive calls may make the returned string invalid.
xfree(reg_prev_sub);
- if (newsub != source) { // newsub was allocated, just keep it
- reg_prev_sub = newsub;
- } else { // no ~ found, need to save newsub
- reg_prev_sub = vim_strsave(newsub);
- }
+ reg_prev_sub = vim_strsave(newsub);
}
return newsub;
diff --git a/src/nvim/testdir/test_regexp_latin.vim b/src/nvim/testdir/test_regexp_latin.vim
index 82d250e8b3..d08a980787 100644
--- a/src/nvim/testdir/test_regexp_latin.vim
+++ b/src/nvim/testdir/test_regexp_latin.vim
@@ -1027,4 +1027,15 @@ func Test_using_invalid_visual_position()
bwipe!
endfunc
+func Test_recursive_substitute_expr()
+ new
+ func Repl()
+ s
+ endfunc
+ silent! s/\%')/~\=Repl()
+
+ bwipe!
+ delfunc Repl
+endfunc
+
" vim: shiftwidth=2 sts=2 expandtab