summaryrefslogtreecommitdiff
path: root/pp_ctl.c
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 /pp_ctl.c
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 'pp_ctl.c')
-rw-r--r--pp_ctl.c7
1 files changed, 2 insertions, 5 deletions
diff --git a/pp_ctl.c b/pp_ctl.c
index b2c68d360a..155313e295 100644
--- a/pp_ctl.c
+++ b/pp_ctl.c
@@ -1967,13 +1967,10 @@ PP(pp_enteriter)
}
else { /* symbol table variable */
GV * const gv = MUTABLE_GV(POPs);
- SV** svp = &GvSV(gv); SAVEGENERICSV(*svp);
+ SV** svp = &GvSV(gv);
+ save_pushptrptr(gv, SvREFCNT_inc(*svp), SAVEt_GVSV);
*svp = newSV(0);
-#ifdef USE_ITHREADS
itervar = (void *)gv;
-#else
- itervar = (void *)svp;
-#endif
}
if (PL_op->op_private & OPpITER_DEF)