diff options
author | David Mitchell <davem@iabyn.com> | 2010-09-08 16:53:10 +0100 |
---|---|---|
committer | David Mitchell <davem@iabyn.com> | 2010-09-08 16:53:10 +0100 |
commit | f83b46a0147ba6f476add85d17f61a7e7fb00f21 (patch) | |
tree | 0dcc25c8bf4f78496319fc13634d851282f3a960 /scope.c | |
parent | aafca5257dfefe4cf2a531c79cadea21a566f9c3 (diff) | |
download | perl-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.c | 6 |
1 files changed, 6 insertions, 0 deletions
@@ -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); |