summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBram Moolenaar <Bram@vim.org>2021-04-25 14:48:49 +0200
committerBram Moolenaar <Bram@vim.org>2021-04-25 14:48:49 +0200
commitd386e923c751f389b2ac038ff2cb7b40035f8cc6 (patch)
treee30c10509be00a9d1570172cc16316e2725740fc
parentdc4c2309f2af347068edd60548269018f476dab9 (diff)
patch 8.2.2810: Vim9: crash when calling a function in a substitute expressionv8.2.2810
Problem: Vim9: crash when calling a function in a substitute expression. Solution: Set the instructions back to the substitute expression instrunctions. (closes #8148)
-rw-r--r--src/testdir/test_vim9_cmd.vim23
-rw-r--r--src/version.c2
-rw-r--r--src/vim9execute.c6
3 files changed, 30 insertions, 1 deletions
diff --git a/src/testdir/test_vim9_cmd.vim b/src/testdir/test_vim9_cmd.vim
index ab2ad6788a..401cc0f4cc 100644
--- a/src/testdir/test_vim9_cmd.vim
+++ b/src/testdir/test_vim9_cmd.vim
@@ -1194,10 +1194,31 @@ def Test_substitute_expr()
endfor
assert_equal('yes no abc', getline(1))
+ bwipe!
+
CheckDefFailure(['s/from/\="x")/'], 'E488:')
CheckDefFailure(['s/from/\="x"/9'], 'E488:')
- bwipe!
+ # When calling a function the right instruction list needs to be restored.
+ var lines =<< trim END
+ vim9script
+ def Foo()
+ Bar([])
+ enddef
+ def Bar(l: list<number>)
+ s/^/\=Rep()/
+ for n in l[:]
+ endfor
+ enddef
+ def Rep(): string
+ return 'rep'
+ enddef
+ new
+ Foo()
+ assert_equal('rep', getline(1))
+ bwipe!
+ END
+ CheckScriptSuccess(lines)
enddef
def Test_redir_to_var()
diff --git a/src/version.c b/src/version.c
index d235e94ebb..53735b27ff 100644
--- a/src/version.c
+++ b/src/version.c
@@ -751,6 +751,8 @@ static char *(features[]) =
static int included_patches[] =
{ /* Add new patch number below this line */
/**/
+ 2810,
+/**/
2809,
/**/
2808,
diff --git a/src/vim9execute.c b/src/vim9execute.c
index c90fb65b67..7f6ce5f33a 100644
--- a/src/vim9execute.c
+++ b/src/vim9execute.c
@@ -601,6 +601,12 @@ func_return(ectx_T *ectx)
+ STACK_FRAME_IDX_OFF)->vval.v_number;
ectx->ec_instr = INSTRUCTIONS(prev_dfunc);
+ // If the call was inside an ISN_SUBSTITUTE instruction need to use its
+ // list of instructions.
+ if (ectx->ec_instr[ectx->ec_iidx - 1].isn_type == ISN_SUBSTITUTE)
+ ectx->ec_instr = ectx->ec_instr[ectx->ec_iidx - 1]
+ .isn_arg.subs.subs_instr;
+
if (floc == NULL)
ectx->ec_funclocal.floc_restore_cmdmod = FALSE;
else