develooper Front page | perl.perl5.porters | Postings from August 2010

[PATCH] Re: [perl #77362] Assigning glob to lvalue causes stringification

Thread Next
Father Chrysostomos
August 29, 2010 12:49
[PATCH] Re: [perl #77362] Assigning glob to lvalue causes stringification
Message ID:
On, Wed, 25 Aug 2010 17:27:18 +0100, Dave Mitchell wrote:
> On Sun, Aug 22, 2010 at 12:24:36PM -0700, Father Chrysostomos wrote:
> > Take this bit, for instance:
> >     case SVt_PVGV:
> > 	if (isGV_with_GP(sstr) && dtype <= SVt_PVGV) {
> > 	    glob_assign_glob(dstr, sstr, dtype);
> > 	    return;
> > 	}
> > 
> > Should that SVt_PVGV be changed to SVt_PVLV, or would that have strange
> > side-effects? (This same logic occurs in several other places in the
> > same function.)
> Answer: yes, it should probably be changed. Try it and see if anything
> breaks!

One test fails, and dozens of other things break without any tests failing, because so many parts of the perl source code don’t take globs-as-PVLVs into account. So, in trying to fix one little niggling bug, I’ve set off a chain reaction. :-) I’ve fixed all of those I know about. I tried to avoid a megapatch, but the problems turned out to be so intertwined that I couldn’t help it. 

> > Why would an SVt_PVLV require the LHS to be SVt_PVNV and not something else?
> I think that was a mistake. I think the original intent of the change
> (ded42b9f771444bf991e51e9d91e40238f0181e2) was to stop upgrading the
> destination to an LV just because the src was an LV. I suspect just
> skipping an upgrade in the LV case would be ok.

But wouldn’t that cause problems if the RHS is an lvalue holding a number and the LHS is undef?

After learning this code more throughly than I had intended, I believe this can be left as it is.

> > Near the bottom:
> > 	if (isGV_with_GP(sstr)) {
> > 	    /* This stringification rule for globs is spread in 3 places.
> > 	       This feels bad. FIXME.  */
> > 	    const U32 wasfake = sflags & SVf_FAKE;
> > 
> > 	    /* FAKE globs can get coerced, so need to turn this off
> > 	       temporarily if it is on.  */
> > 	    SvFAKE_off(sstr);
> > 	    gv_efullname3(dstr, MUTABLE_GV(sstr), "*");
> > 	    SvFLAGS(sstr) |= wasfake;
> > 	}
> > 
> > When is a glob ever supposed to be stringified when assigned to something? If I’m reading the code correctly, this is only reached when a glob is assigned to an SVt_PVLV (which causes this bug) or an SVt_PVIO (how can that ever happen?). Is this code really supposed to be reached?> 
> Well I put in an assert(dtype == SVt_PVLV) there and no tests failed, so
> it looks like your conclusion is probably correct, and that this code
> chunk should removed once the LV is handled earlier.

Out of paranoia, I’ve left that code unchanged, in case some XS code is assigning a glob to an IO thingy and expecting the latter to morph into a scalar. I think any such code would be buggy, so it probably can be removed; but I leave it to you.

Here is some text for perldelta. The various PVLV fixups throughout the source are not deserving of mention, since they fix bugs that couldn’t have occurred before the changes to sv_setsv_flags.

(Under Selected Bug Fixes:)

=item *

Assigning a glob to a PVLV used to convert it to a plain string. Now it
works correctly, and a PVLV can hold a glob. This would happen when a
nonexistent hash or array element was passed to a subroutine:

  sub { $_[0] = *foo }->($hash{key});
  # $_[0] would have been the string "*main::foo"

It also happened when a glob was assigned to, or returned from, an element
of a tied array or hash.

Thread Next Perl Programming lists via nntp and http.
Comments to Ask Bjørn Hansen at | Group listing | About