This is a live mirror of the Perl 5 development currently hosted at https://github.com/perl/perl5
pp_return: avoid potential CX stack realloc prob
[perl5.git] / cop.h
diff --git a/cop.h b/cop.h
index c0cfab2..525f546 100644 (file)
--- a/cop.h
+++ b/cop.h
@@ -574,6 +574,19 @@ struct block_format {
 
 #define CX_LEAVE_SCOPE(cx) LEAVE_SCOPE(cx->cx_old_savestack_ix)
 
+#ifdef DEBUGGING
+/* on debugging builds, poison cx afterwards so we know no code
+ * uses it - because after doing cxstack_ix--, any ties, exceptions etc
+ * may overwrite the current stack frame */
+#  define CX_POP(cx)                                                   \
+        assert(&cxstack[cxstack_ix] == cx);                            \
+        cxstack_ix--;                                                  \
+        cx = NULL;
+#else
+#  define CX_POP(cx) cxstack_ix--;
+#endif
+
+
 /* base for the next two macros. Don't use directly.
  * The context frame holds a reference to the CV so that it can't be
  * freed while we're executing it */
@@ -655,6 +668,23 @@ struct block_format {
     CvDEPTH((const CV*)cx->blk_sub.cv) = cx->blk_sub.olddepth;          \
     SvREFCNT_dec_NN(cx->blk_sub.cv);
 
+/* handle the @_ part of leaving a sub */
+
+#define POPSUB_ARGS(cx) \
+    STMT_START {                                                       \
+        AV *av;                                                         \
+        assert(AvARRAY(MUTABLE_AV(                                      \
+            PadlistARRAY(CvPADLIST(cx->blk_sub.cv))[                    \
+                    CvDEPTH(cx->blk_sub.cv)])) == PL_curpad);           \
+        POP_SAVEARRAY();                                               \
+        /* abandon @_ if it got reified */                             \
+        av = MUTABLE_AV(PAD_SVl(0));                                    \
+        if (UNLIKELY(AvREAL(av)))                                      \
+            clear_defarray(av, 0);                                      \
+        else {                                                         \
+            CLEAR_ARGARRAY(av);                                                \
+        }                                                              \
+    } STMT_END
 
 #define POPSUB(cx)                                                     \
     STMT_START {                                                       \
@@ -668,18 +698,7 @@ struct block_format {
                CopSTASHPV((COP*)CvSTART((const CV*)cx->blk_sub.cv)));  \
                                                                        \
        if (CxHASARGS(cx)) {                                            \
-            AV *av;                                                     \
-            assert(AvARRAY(MUTABLE_AV(                                  \
-                PadlistARRAY(CvPADLIST(cx->blk_sub.cv))[                \
-                        CvDEPTH(cx->blk_sub.cv)])) == PL_curpad);       \
-           POP_SAVEARRAY();                                            \
-           /* abandon @_ if it got reified */                          \
-            av = MUTABLE_AV(PAD_SVl(0));                                \
-           if (UNLIKELY(AvREAL(av)))                                   \
-                clear_defarray(av, 0);                                  \
-           else {                                                      \
-               CLEAR_ARGARRAY(av);                                     \
-           }                                                           \
+            POPSUB_ARGS(cx);                                            \
        }                                                               \
         }                                                               \
         POPSUB_COMMON(cx);                                              \
@@ -734,7 +753,6 @@ struct block_eval {
 #define POPEVAL(cx)                                                    \
     STMT_START {                                                       \
        PL_in_eval = CxOLD_IN_EVAL(cx);                                 \
-       optype = CxOLD_OP_TYPE(cx);                                     \
        PL_eval_root = cx->blk_eval.old_eval_root;                      \
        if (cx->blk_eval.cur_text && SvSCREAM(cx->blk_eval.cur_text))   \
            SvREFCNT_dec_NN(cx->blk_eval.cur_text);                     \
@@ -1292,12 +1310,12 @@ See L<perlcall/LIGHTWEIGHT CALLBACKS>.
        cx = &cxstack[cxstack_ix];                                      \
        CX_LEAVE_SCOPE(cx);                                             \
         POPSUB_COMMON(cx);                                              \
-       POPBLOCK(cx);                                                   \
         newsp = PL_stack_base + cx->blk_oldsp;                          \
         gimme = cx->blk_gimme;                                          \
         PERL_UNUSED_VAR(newsp); /* for API */                           \
         PERL_UNUSED_VAR(gimme); /* for API */                           \
-       cxstack_ix--;                                                   \
+       POPBLOCK(cx);                                                   \
+       CX_POP(cx);                                                     \
        POPSTACK;                                                       \
        CATCH_SET(multicall_oldcatch);                                  \
        SPAGAIN;                                                        \
@@ -1313,16 +1331,9 @@ See L<perlcall/LIGHTWEIGHT CALLBACKS>.
        PADLIST * const padlist = CvPADLIST(cv);                        \
        cx = &cxstack[cxstack_ix];                                      \
        assert(CxMULTICALL(cx));                                        \
-       CvDEPTH(multicall_cv) = cx->blk_sub.olddepth;                   \
-        SvREFCNT_dec_NN(multicall_cv);                                  \
+        POPSUB_COMMON(cx);                                              \
        cx->cx_type = (CXt_SUB|CXp_MULTICALL|flags);                    \
-        {                                                               \
-            /* save a few things that we don't want PUSHSUB to zap */   \
-            PAD * const prevcomppad = cx->blk_sub.prevcomppad;          \
-           PUSHSUB(cx);                                                \
-            /* undo the stuff that PUSHSUB zapped */                    \
-            cx->blk_sub.prevcomppad = prevcomppad ;                     \
-        }                                                               \
+        PUSHSUB(cx);                                                   \
         if (!(flags & CXp_SUB_RE_FAKE))                                 \
             CvDEPTH(cv)++;                                             \
        if (CvDEPTH(cv) >= 2) {                                         \