]> granicus.if.org Git - vim/commitdiff
patch 8.2.2812: Vim9: still crash when using substitute expression v8.2.2812
authorBram Moolenaar <Bram@vim.org>
Mon, 26 Apr 2021 18:32:59 +0000 (20:32 +0200)
committerBram Moolenaar <Bram@vim.org>
Mon, 26 Apr 2021 18:32:59 +0000 (20:32 +0200)
Problem:    Vim9: still crash when using substitute expression.
Solution:   Put the instruction list in the stack frame. (closes #8154)

src/testdir/test_vim9_cmd.vim
src/version.c
src/vim9.h
src/vim9execute.c

index 5732e1eea47d37055ebcf16c03175ce6d931fafa..1e1a498bf69553eace039d3bd156f82c88fe5eef 100644 (file)
@@ -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()
index 35d7a59c2d16a30f57e0cfc2dbb733657d586b4e..71fa21808fa085ea1e8718ed68a9f459d274851a 100644 (file)
@@ -750,6 +750,8 @@ static char *(features[]) =
 
 static int included_patches[] =
 {   /* Add new patch number below this line */
+/**/
+    2812,
 /**/
     2811,
 /**/
index bbed384c23f06c538689219d14ba8589771d222e..5dc0a8f8da67586834644fee6eaa9e789013cbc2 100644 (file)
@@ -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
index 7f6ce5f33ae576a7d1c51d218c38a2457d30ee11..07812741e515b317a40f9dfc3f8ceffef4635e64 100644 (file)
@@ -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;