summaryrefslogtreecommitdiff
path: root/cop.h
diff options
context:
space:
mode:
authorDavid Mitchell <davem@iabyn.com>2010-09-08 16:53:10 +0100
committerDavid Mitchell <davem@iabyn.com>2010-09-08 16:53:10 +0100
commitf83b46a0147ba6f476add85d17f61a7e7fb00f21 (patch)
tree0dcc25c8bf4f78496319fc13634d851282f3a960 /cop.h
parentaafca5257dfefe4cf2a531c79cadea21a566f9c3 (diff)
downloadperl-f83b46a0147ba6f476add85d17f61a7e7fb00f21.tar.gz
bad things happened with for $x (...) { *x = *y }
fix for [perl #21469]: since the GP may be pulled from under us and freed, coredumps and strange things can happen. Fix this by storing a pointer to the GV in the loop block, rather than a pointer to the GvSV slot. The ITHREADS variant already stores GV rather than than &GvSV; extend this to non-threaded builds too. Also, for both threaded and non-threaded, it used to push &GvSV on the save stack. Fix this by introducing a new save type, SAVEt_GVSV. This behaves similarly to SAVEt_SV, but without magic get/set. This means that for $package_var (...) is now close in behaviour to local $package_var = ... (except for the magic bit).
Diffstat (limited to 'cop.h')
-rw-r--r--cop.h14
1 files changed, 9 insertions, 5 deletions
diff --git a/cop.h b/cop.h
index c91e9a4a09..86a67d001e 100644
--- a/cop.h
+++ b/cop.h
@@ -469,15 +469,19 @@ struct block_loop {
};
#ifdef USE_ITHREADS
-# define CxITERVAR(c) \
+# define CxITERVAR_PADSV(c) \
+ &CX_CURPAD_SV( (c)->blk_loop.itervar_u, (c)->blk_loop.my_op->op_targ)
+#else
+# define CxITERVAR_PADSV(c) ((c)->blk_loop.itervar_u.svp)
+#endif
+
+#define CxITERVAR(c) \
((c)->blk_loop.itervar_u.oldcomppad \
? (CxPADLOOP(c) \
- ? &CX_CURPAD_SV( (c)->blk_loop.itervar_u, (c)->blk_loop.my_op->op_targ) \
+ ? CxITERVAR_PADSV(c) \
: &GvSV((c)->blk_loop.itervar_u.gv)) \
: (SV**)NULL)
-#else
-# define CxITERVAR(c) ((c)->blk_loop.itervar_u.svp)
-#endif
+
#define CxLABEL(c) (0 + CopLABEL((c)->blk_oldcop))
#define CxHASARGS(c) (((c)->cx_type & CXp_HASARGS) == CXp_HASARGS)
#define CxLVAL(c) (0 + (c)->blk_u16)