develooper Front page | perl.perl5.porters | Postings from December 2014

[perl #36051] LVALUE magic should know how to assign to globs

Thread Next
From:
Father Chrysostomos via RT
Date:
December 30, 2014 05:59
Subject:
[perl #36051] LVALUE magic should know how to assign to globs
Message ID:
rt-4.0.18-17024-1419919166-1495.36051-15-0@perl.org
On Mon Dec 29 19:59:35 2014, bulk88 wrote:
> On Mon Dec 29 14:41:37 2014, sprout wrote:
> > On Mon Dec 29 13:57:37 2014, bulk88 wrote:
> > > I am currently rewriting Perl_gv_add_by_type but I see something
> > > strange
> > > in the existing code.
> > >
> > > http://perl5.git.perl.org/perl.git/commitdiff/13be902cef8b01c085a6b8b1b59fa2754a10cdfb
> > > https://rt.perl.org/Ticket/Display.html?id=77362
> > >
> > > So what is the sv_u of a PVLV? Why would a LV have a GP ptr?
> >
> > If you assign a typeglob to a deferred element or to an element of a
> > tied aggregate, then you get a PVLV that is a typeglob.
> 
> Wouldn't that cause a "Bizzare copy of" panic later, since aggregate
> slices are scalars (you can only place a RV to an aggregate in a
> aggregate slice)?

I don’t follow.

This is what I am talking about:

use Devel::Peek;
sub { $_[0] = *foo; Dump $_[0]  }->($h{nonexistent_elem});

> 
> -------------------------------------------------------------------
> C:\>perl -MDevel::Peek=Dump -E"my $s = ' '; Dump($s); $s = *ARGV::;
> Dump($s); $s
>  ='h'; Dump($s)"
> SV = PV(0x369a0c) at 0x8fbebc
>   REFCNT = 1
>   FLAGS = (POK,IsCOW,pPOK)
>   PV = 0x90667c " "\0
>   CUR = 1
>   LEN = 10
>   COW_REFCNT = 1
> SV = PVGV(0x9010a4) at 0x8fbebc
>   REFCNT = 1
>   FLAGS = (FAKE,MULTI)
>   NAME = "ARGV::"
>   NAMELEN = 6
>   GvSTASH = 0x368bbc    "main"
>   FLAGS = 0x2
>   GP = 0x9084cc
>     SV = 0x0
>     REFCNT = 2
>     IO = 0x0
>     FORM = 0x0
>     AV = 0x0
>     HV = 0x8fbe8c
>     CV = 0x0
>     CVGEN = 0x0
>     GPFLAGS = 0x0 ()
>     LINE = 1
>     FILE = "-e"
>     EGV = 0x368d5c      "ARGV::"
> SV = PVMG(0x8f453c) at 0x8fbebc
>   REFCNT = 1
>   FLAGS = (POK,IsCOW,pPOK)
>   IV = 9463952
>   NV = 0
>   PV = 0x91ad74 "h"\0
>   CUR = 1
>   LEN = 10
>   COW_REFCNT = 1
> 
> C:\>
> ---------------------------------------------------------
> 
> This is breaking the rule you can't downgrade an SV.

I have heard of that rule before, but I don’t remember the source.  I think it I read it in illguts.  But it’s actually not true, and never was.

http://perl5.git.perl.org/perl.git/blob/perl-5.000:/sv.c#l3170

> Also this doesnt SEGVs since sv_upgrade leaves the PVX buffer of a PV
> intact, sv_clear falls through from case SVt_PVGV" to the regular PV
> type, and there is no SEGV clearing the GP since this half GV fails
> isGV_with_GP(sv). I know Perl_gv_init_pvn does black magic to make
> sv_upgrade(sv, SVt_PVGV); safe.
> 
> void t3()
> PREINIT:
>     volatile SV* sv;
>     int i;
> PPCODE:
>     for(i =0; i < 40000000; i++) {
>         sv = newSVpvn("camel", 5);
>         sv_upgrade(sv, SVt_PVGV);
>         //sv_dump(GvSVn((GV*)sv)); /* crash */
>         SvREFCNT_dec_NN(sv);
>     }
> 
> But here I defeated all the logic and made a leak

This part of the core is a bit confusing.  You see, scalars with BM magic used to be of type SVt_PVGV, but were later changed to SVt_PVMG.  Some parts of the core still account for the latter, but others expect SVt_PVGV always to be a genuine GV with GP.

> void t4()
> PREINIT:
>     volatile SV* sv;
>     int i;
> PPCODE:
> 
> for(i =0; i < 400000000; i++) {
> sv = gv_fetchpv("camelpack", GV_ADD, SVt_PVAV);
> sv_setpvn(sv, "\x00\x00\x00\x00\x00\x00\x00\x00"
>          "\x00\x00\x00\x00\x00\x00\x00\x00"
>          "\x00\x00\x00\x00\x00\x00\x00\x00"
>          "\x00\x00\x00\x00\x00\x00\x00\x00"
>          "\x00\x00\x00\x00\x00\x00\x00\x00"
>          "\x00\x00\x00\x00\x00\x00\x00\x00"
>          "\x00\x00\x00\x00\x00\x00\x00\x00"
>          "\x00\x00\x00\x00\x00\x00\x00\x00"
>          "\x00\x00\x00\x00\x00\x00\x00\x00"
>          "\x00\x00\x00\x00\x00\x00\x00\x00"
>          "\x00\x00\x00\x00\x00\x00\x00\x00", sizeof(GP));
> }

Ouch.  That should probably croak or fail an assertion.

> >
> > > I thought
> > > the sv_u of a PVLV was a PV buffer.
> >
> > The sv_u of a PVLV may differ just as much as the sv_u of a PVMG.  It
> > can hold an SV pointer if you assigned a reference to a PVLV.
> >
> > Actually, it can differ more.  A PVLV can also be a REGEXP thingy
> > (with sv_u pointing to the regexp struct) even though the internal
> > type is SVt_PVLV, not SVt_REGEXP.  This is because PVLV needs to be
> > able to hold any type of scalar.
> 
> You said scalar. GV/HV/AV are aggregates.

GV is also a type of scalar.  (This goes back at least to perl 5.)  You can bind the $ sigil to any typeglob.

use Devel::Peek;
foreach (*foo) { $_ = \&bar; Dump $_ }

A typeglob created by assignment ($_ = *foo) is coercible.

Yes, this is a design flaw.

> I recently encountered "$v =
> int(${qr||});" in the test suite so I know regexps are scalars.
> 
> >
> > > I have some old XS code to
> > > de-magic/vivify a hash slice, since otherwise I need to croak.
> > >
> > > if (SvREADONLY(buffer)) {
> > >     croak(PL_no_modify);
> > > }
> > > if(SvTYPE(buffer) == SVt_PVLV && LvTYPE(buffer) == 'y'){
> > >     sv_setpv_mg(buffer, " ");
> > >     if(LvTARG(buffer)) buffer = LvTARG(buffer);
> > > }
> > > if (SvMAGICAL(buffer)) {
> > >     DumpSV(buffer);
> > >     croak("%s: magic scalar as buffer not supported.", cvname);
> > > }
> >
> > I am confused as to why that code would be affected by the sv_u field
> > of a PVLV.
> 
> Wouldn't sv_setpv_mg(buffer, " ") leak or croak panic if its done on a
> GV, AV or HV, or my "LvTYPE(buffer) == 'y'" guarantees the PVLV is a
> scalar type? I already have 1 memleak above.

That it is an SVt_PVLV guarantees it is a scalar.  When a PVLV is a GV, it should always be of the coercible type.

Hmmm.

use experimental 'refaliasing';
\$::{foo} = \substr $_, 1;
*{"foo"};

Oh no.  I don’t want to think about that.

-- 

Father Chrysostomos


---
via perlbug:  queue: perl5 status: resolved
https://rt.perl.org/Ticket/Display.html?id=36051

Thread Next


nntp.perl.org: Perl Programming lists via nntp and http.
Comments to Ask Bjørn Hansen at ask@perl.org | Group listing | About