Skip Menu |
Report information
Id: 77812
Status: resolved
Priority: 0/
Queue: perl5

Owner: Nobody
Requestors: sprout <sprout [at] cpan.org>
Cc:
AdminCc:

Operating System: (no value)
PatchStatus: (no value)
Severity: low
Type: unknown
Perl Version: (no value)
Fixed In: (no value)



Subject: Globs in tied scalars can be reified if STORE dies
Date: Sun, 12 Sep 2010 12:40:59 -0700
To: perlbug [...] perl.org
From: Father Chrysostomos <sprout [...] cpan.org>
Download (untitled) / with headers
text/plain 2.9k
Another regression in 5.13, this one caused by 0fe688f528. Some of these patch authors are clueless! #!perl -l sub TIESCALAR{bless[]} sub STORE{ die "No!"} sub FETCH{ *foo } tie $a, ""; () = $a; # do a fetch eval { *$a = sub{} }; # From this point on $a holds a glob without the FAKE flag. eval { $a = undef }; untie $a; $a = "bar"; print $a; In 5.12 and earlier this prints "bar". In 5.13.4 the penultimate line dies with "No!", because it’s still tied. This is because of the order of these statements in pp_sassign is wrong: /* Allow glob assignments like *$x = ..., which, when the glob has a SVf_FAKE flag, cannot be distinguished from $x = ... without looking at the op tree. */ if( SvTYPE(right) == SVt_PVGV && cBINOP->op_last->op_type == OP_RV2GV && (wasfake = SvFLAGS(right) & SVf_FAKE) ) SvFLAGS(right) &= ~SVf_FAKE; SvSetMagicSV(right, left); if(wasfake) SvFLAGS(right) |= SVf_FAKE; Turning the fake flag back on should happen before magic is called. If bug #77810 is fixed, we can simply revert the patch that caused this, and put the appropriate logic in one place. This same bug also affects a patch I wrote for #77508 (list assignment to dereferenced fake glob). Here is the example script again, with more explanatory notes: #!perl -l sub TIESCALAR{bless[]} sub STORE{ die "No you don::t!"} sub FETCH{ *foo } tie $a, ""; () = $a; # do a fetch # Now the $a scalar holds a copy of *foo; i.e., a PVGV with the FAKE flag # on, indicating that this is not really a glob, but just a scalar holding # a copy of one. eval { *$a = sub{} }; # pp_sassign (the function implementing the = operator) turns off the FAKE # flag temporarily before assignment, because of the * (rv2gv) on the # lefthand side. # Set-magic (called right after the assignment) dies (in the STORE routine # above) before the FAKE flag is turned back on. As a result, it stays off, # so what we now have looks exactly like a glob in the symbol table. eval { $a = undef }; # This is a workaround for a bug still present in blead. untie() won’t # untie a scalar if it sees a glob, whether FAKE or not. # We try to assign undef to $a, so that the $a scalar will itself hold # undef, even if STORE dies. But, since the FAKE flag is gone, we are # asigning to a ‘real’ glob. Assigning undef to a glob does nothing (except # warn). # Untie the variable. Since there is a glob, it tries to untie the IO slot, # which doesn’t exist, so nothing happens. untie $a; # We are supposedly assigning "bar" to an innocent $a variable, but in # truth we are making the glob in $a an alias to *bar. $a = "bar"; # That assignment triggers set-magic, which calls STORE, which dies. # We never get here. print $a; At this point (suppose all the above was in an eval), even if the FETCH routine starts returning undef, it will always be the glob that is returned to the calling code. This would make it rather difficult to implement read-only aliases using ties.
Download (untitled) / with headers
text/plain 364b
On Sun Sep 12 12:41:24 2010, sprout wrote: Show quoted text
> #!perl -l > sub TIESCALAR{bless[]} > sub STORE{ die "No!"} > sub FETCH{ *foo } > tie $a, ""; > () = $a; # do a fetch > eval { *$a = sub{} }; > # From this point on $a holds a glob without the FAKE flag. > eval { $a = undef }; > untie $a; > $a = "bar"; > print $a;
Fixed in 2acc3314e31a9. Tests added in 0936ef8b60a30.


This service is sponsored and maintained by Best Practical Solutions and runs on Perl.org infrastructure.

For issues related to this RT instance (aka "perlbug"), please contact perlbug-admin at perl.org