Mercurial > vim
changeset 24545:fe29b220eece v8.2.2812
patch 8.2.2812: Vim9: still crash when using substitute expression
Commit: https://github.com/vim/vim/commit/5930ddcd25c3c31a323cdb1b74c228958e124527
Author: Bram Moolenaar <Bram@vim.org>
Date: Mon Apr 26 20:32:59 2021 +0200
patch 8.2.2812: Vim9: still crash when using substitute expression
Problem: Vim9: still crash when using substitute expression.
Solution: Put the instruction list in the stack frame. (closes https://github.com/vim/vim/issues/8154)
author | Bram Moolenaar <Bram@vim.org> |
---|---|
date | Mon, 26 Apr 2021 20:45:04 +0200 |
parents | ed8d91abc6eb |
children | eb6c05ae77f9 |
files | src/testdir/test_vim9_cmd.vim src/version.c src/vim9.h src/vim9execute.c |
diffstat | 4 files changed, 15 insertions(+), 11 deletions(-) [+] |
line wrap: on
line diff
--- a/src/testdir/test_vim9_cmd.vim +++ b/src/testdir/test_vim9_cmd.vim @@ -1208,15 +1208,18 @@ def Test_substitute_expr() CheckDefFailure(['s/from/\="x"/9'], 'E488:') # When calling a function the right instruction list needs to be restored. + g:cond = true var lines =<< trim END vim9script def Foo() Bar([]) enddef def Bar(l: list<number>) + if g:cond s/^/\=Rep()/ for n in l[:] endfor + endif enddef def Rep(): string return 'rep' @@ -1227,6 +1230,7 @@ def Test_substitute_expr() bwipe! END CheckScriptSuccess(lines) + unlet g:cond enddef def Test_redir_to_var()
--- 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 */ /**/ + 2812, +/**/ 2811, /**/ 2810,
--- a/src/vim9.h +++ b/src/vim9.h @@ -427,15 +427,17 @@ struct dfunc_S { // Number of entries used by stack frame for a function call. // - ec_dfunc_idx: function index // - ec_iidx: instruction index +// - ec_instr: instruction list pointer // - ec_outer: stack used for closures // - funclocal: function-local data // - ec_frame_idx: previous frame index #define STACK_FRAME_FUNC_OFF 0 #define STACK_FRAME_IIDX_OFF 1 -#define STACK_FRAME_OUTER_OFF 2 -#define STACK_FRAME_FUNCLOCAL_OFF 3 -#define STACK_FRAME_IDX_OFF 4 -#define STACK_FRAME_SIZE 5 +#define STACK_FRAME_INSTR_OFF 2 +#define STACK_FRAME_OUTER_OFF 3 +#define STACK_FRAME_FUNCLOCAL_OFF 4 +#define STACK_FRAME_IDX_OFF 5 +#define STACK_FRAME_SIZE 6 #ifdef DEFINE_VIM9_GLOBALS
--- a/src/vim9execute.c +++ b/src/vim9execute.c @@ -279,6 +279,7 @@ call_dfunc( // Store current execution state in stack frame for ISN_RETURN. STACK_TV_BOT(STACK_FRAME_FUNC_OFF)->vval.v_number = ectx->ec_dfunc_idx; STACK_TV_BOT(STACK_FRAME_IIDX_OFF)->vval.v_number = ectx->ec_iidx; + STACK_TV_BOT(STACK_FRAME_INSTR_OFF)->vval.v_string = (void *)ectx->ec_instr; STACK_TV_BOT(STACK_FRAME_OUTER_OFF)->vval.v_string = (void *)ectx->ec_outer; STACK_TV_BOT(STACK_FRAME_FUNCLOCAL_OFF)->vval.v_string = (void *)floc; STACK_TV_BOT(STACK_FRAME_IDX_OFF)->vval.v_number = ectx->ec_frame_idx; @@ -592,6 +593,8 @@ func_return(ectx_T *ectx) ectx->ec_dfunc_idx = prev_dfunc_idx; ectx->ec_iidx = STACK_TV(ectx->ec_frame_idx + STACK_FRAME_IIDX_OFF)->vval.v_number; + ectx->ec_instr = (void *)STACK_TV(ectx->ec_frame_idx + + STACK_FRAME_INSTR_OFF)->vval.v_string; ectx->ec_outer = (void *)STACK_TV(ectx->ec_frame_idx + STACK_FRAME_OUTER_OFF)->vval.v_string; floc = (void *)STACK_TV(ectx->ec_frame_idx @@ -599,13 +602,6 @@ func_return(ectx_T *ectx) // restoring ec_frame_idx must be last ectx->ec_frame_idx = STACK_TV(ectx->ec_frame_idx + 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;