summaryrefslogtreecommitdiff
path: root/scope.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 /scope.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 'scope.c')
-rw-r--r--scope.c6
1 files changed, 6 insertions, 0 deletions
diff --git a/scope.c b/scope.c
index 93ef4b3fc9..046b3387d5 100644
--- a/scope.c
+++ b/scope.c
@@ -778,9 +778,15 @@ Perl_leave_scope(pTHX_ I32 base)
*(char**)ptr = str;
}
break;
+ case SAVEt_GVSV: /* scalar slot in GV */
+ value = MUTABLE_SV(SSPOPPTR);
+ gv = MUTABLE_GV(SSPOPPTR);
+ ptr = &GvSV(gv);
+ goto restore_svp;
case SAVEt_GENERIC_SVREF: /* generic sv */
value = MUTABLE_SV(SSPOPPTR);
ptr = SSPOPPTR;
+ restore_svp:
sv = *(SV**)ptr;
*(SV**)ptr = value;
SvREFCNT_dec(sv);