[perl #8262] //g loops infinitely on tainted data
[p5sagit/p5-mst-13.2.git] / cop.h
diff --git a/cop.h b/cop.h
index f2e4463..2444a75 100644 (file)
--- a/cop.h
+++ b/cop.h
@@ -166,7 +166,7 @@ struct cop {
 #  define CopFILESV(c)         (CopFILE(c) \
                                 ? GvSV(gv_fetchfile(CopFILE(c))) : Nullsv)
 #  define CopFILEAV(c)         (CopFILE(c) \
-                                ? GvAV(gv_fetchfile(CopFILE(c))) : Nullav)
+                                ? GvAV(gv_fetchfile(CopFILE(c))) : NULL)
 #  define CopSTASHPV(c)                ((c)->cop_stashpv)
 
 #  ifdef NETWARE
@@ -176,7 +176,7 @@ struct cop {
 #  endif
 
 #  define CopSTASH(c)          (CopSTASHPV(c) \
-                                ? gv_stashpv(CopSTASHPV(c),GV_ADD) : Nullhv)
+                                ? gv_stashpv(CopSTASHPV(c),GV_ADD) : NULL)
 #  define CopSTASH_set(c,hv)   CopSTASHPV_set(c, (hv) ? HvNAME_get(hv) : Nullch)
 #  define CopSTASH_eq(c,hv)    ((hv) && stashpv_hvname_match(c,hv))
 #  ifdef NETWARE
@@ -191,7 +191,7 @@ struct cop {
 #  define CopFILEGV_set(c,gv)  ((c)->cop_filegv = (GV*)SvREFCNT_inc(gv))
 #  define CopFILE_set(c,pv)    CopFILEGV_set((c), gv_fetchfile(pv))
 #  define CopFILESV(c)         (CopFILEGV(c) ? GvSV(CopFILEGV(c)) : Nullsv)
-#  define CopFILEAV(c)         (CopFILEGV(c) ? GvAV(CopFILEGV(c)) : Nullav)
+#  define CopFILEAV(c)         (CopFILEGV(c) ? GvAV(CopFILEGV(c)) : NULL)
 #  define CopFILE(c)           (CopFILESV(c) ? SvPVX(CopFILESV(c)) : Nullch)
 #  define CopSTASH(c)          ((c)->cop_stash)
 #  define CopSTASH_set(c,hv)   ((c)->cop_stash = (hv))
@@ -400,20 +400,35 @@ struct block_loop {
        cx->blk_loop.next_op = cLOOP->op_nextop;                        \
        cx->blk_loop.last_op = cLOOP->op_lastop;                        \
        cx->blk_loop.iterlval = Nullsv;                                 \
-       cx->blk_loop.iterary = Nullav;                                  \
+       cx->blk_loop.iterary = NULL;                                    \
        cx->blk_loop.iterix = -1;                                       \
        CX_ITERDATA_SET(cx,dat);
 
 #define POPLOOP(cx)                                                    \
        SvREFCNT_dec(cx->blk_loop.iterlval);                            \
        if (CxITERVAR(cx)) {                                            \
-           SV **s_v_p = CxITERVAR(cx);                                 \
-           sv_2mortal(*s_v_p);                                         \
-           *s_v_p = cx->blk_loop.itersave;                             \
+            if (SvPADMY(cx->blk_loop.itersave)) {                      \
+               SV **s_v_p = CxITERVAR(cx);                             \
+               sv_2mortal(*s_v_p);                                     \
+               *s_v_p = cx->blk_loop.itersave;                         \
+           }                                                           \
+           else {                                                      \
+               SvREFCNT_dec(cx->blk_loop.itersave);                    \
+           }                                                           \
        }                                                               \
        if (cx->blk_loop.iterary && cx->blk_loop.iterary != PL_curstack)\
            SvREFCNT_dec(cx->blk_loop.iterary);
 
+/* given/when context */
+struct block_givwhen {
+       OP *leave_op;
+};
+
+#define PUSHGIVEN(cx)                                                  \
+       cx->blk_givwhen.leave_op = cLOGOP->op_other;
+
+#define PUSHWHEN PUSHGIVEN
+
 /* context common to subroutines, evals and loops */
 struct block {
     I32                blku_oldsp;     /* stack pointer to copy stuff down to */
@@ -427,6 +442,7 @@ struct block {
        struct block_sub        blku_sub;
        struct block_eval       blku_eval;
        struct block_loop       blku_loop;
+       struct block_givwhen    blku_givwhen;
     } blk_u;
 };
 #define blk_oldsp      cx_u.cx_blk.blku_oldsp
@@ -438,6 +454,7 @@ struct block {
 #define blk_sub                cx_u.cx_blk.blk_u.blku_sub
 #define blk_eval       cx_u.cx_blk.blk_u.blku_eval
 #define blk_loop       cx_u.cx_blk.blk_u.blku_loop
+#define blk_givwhen    cx_u.cx_blk.blk_u.blku_givwhen
 
 /* Enter a block. */
 #define PUSHBLOCK(cx,t,sp) CXINC, cx = &cxstack[cxstack_ix],           \
@@ -540,6 +557,8 @@ struct context {
 #define CXt_SUBST      4
 #define CXt_BLOCK      5
 #define CXt_FORMAT     6
+#define CXt_GIVEN      7
+#define CXt_WHEN       8
 
 /* private flags for CXt_SUB and CXt_NULL */
 #define CXp_MULTICALL  0x00000400      /* part of a multicall (so don't
@@ -549,8 +568,10 @@ struct context {
 #define CXp_REAL       0x00000100      /* truly eval'', not a lookalike */
 #define CXp_TRYBLOCK   0x00000200      /* eval{}, not eval'' or similar */
 
-#ifdef USE_ITHREADS
 /* private flags for CXt_LOOP */
+#define CXp_FOREACH    0x00000200      /* a foreach loop */
+#define CXp_FOR_DEF    0x00000400      /* foreach using $_ */
+#ifdef USE_ITHREADS
 #  define CXp_PADVAR   0x00000100      /* itervar lives on pad, iterdata
                                           has pad offset; if not set,
                                           iterdata holds GV* */
@@ -565,6 +586,10 @@ struct context {
                         == (CXt_EVAL|CXp_REAL))
 #define CxTRYBLOCK(c)  (((c)->cx_type & (CXt_EVAL|CXp_TRYBLOCK))       \
                         == (CXt_EVAL|CXp_TRYBLOCK))
+#define CxFOREACH(c)   (((c)->cx_type & (CXt_LOOP|CXp_FOREACH))        \
+                         == (CXt_LOOP|CXp_FOREACH))
+#define CxFOREACHDEF(c)        (((c)->cx_type & (CXt_LOOP|CXp_FOREACH|CXp_FOR_DEF))\
+                        == (CXt_LOOP|CXp_FOREACH|CXp_FOR_DEF))
 
 #define CXINC (cxstack_ix < cxstack_max ? ++cxstack_ix : (cxstack_ix = cxinc()))
 
@@ -729,14 +754,16 @@ See L<perlcall/Lightweight Callbacks>.
 #define dMULTICALL \
     SV **newsp;                        /* set by POPBLOCK */                   \
     PERL_CONTEXT *cx;                                                  \
-    CV *cv;                                                            \
+    CV *multicall_cv;                                                  \
     OP *multicall_cop;                                                 \
     bool multicall_oldcatch;                                           \
     U8 hasargs = 0             /* used by PUSHSUB */
 
-#define PUSH_MULTICALL \
+#define PUSH_MULTICALL(the_cv) \
     STMT_START {                                                       \
-       AV* padlist = CvPADLIST(cv);                                    \
+       CV * const _nOnclAshIngNamE_ = the_cv;                          \
+       CV * const cv = _nOnclAshIngNamE_;                              \
+       AV * const padlist = CvPADLIST(cv);                             \
        ENTER;                                                          \
        multicall_oldcatch = CATCH_GET;                                 \
        SAVETMPS; SAVEVPTR(PL_op);                                      \
@@ -749,6 +776,7 @@ See L<perlcall/Lightweight Callbacks>.
        }                                                               \
        SAVECOMPPAD();                                                  \
        PAD_SET_CUR_NOSAVE(padlist, CvDEPTH(cv));                       \
+       multicall_cv = cv;                                              \
        multicall_cop = CvSTART(cv);                                    \
     } STMT_END
 
@@ -760,8 +788,8 @@ See L<perlcall/Lightweight Callbacks>.
 
 #define POP_MULTICALL \
     STMT_START {                                                       \
-       LEAVESUB(cv);                                                   \
-       CvDEPTH(cv)--;                                                  \
+       LEAVESUB(multicall_cv);                                         \
+       CvDEPTH(multicall_cv)--;                                        \
        POPBLOCK(cx,PL_curpm);                                          \
        CATCH_SET(multicall_oldcatch);                                  \
        LEAVE;                                                          \