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

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

Thread Previous | Thread Next
From:
bulk88 via RT
Date:
December 30, 2014 03:59
Subject:
[perl #36051] LVALUE magic should know how to assign to globs
Message ID:
rt-4.0.18-8578-1419911975-1909.36051-15-0@perl.org
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)?

-------------------------------------------------------------------
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. 

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

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));
    }

The reason a string doesn't work to make a leak is since S_gv_init_svtype checks the GP struct (which is a PV buffer with invalid pointers) for NULL pointer, and a string isn't going to be interpreted as a NULL pointers unless I did the above, also the type requested must be IO HV or AV. 

A different variant, I couldn't get it to SEGV.

void t4()
PREINIT:
    volatile SV* sv;
    int i;
PPCODE:
    for(i =0; i < 4; i++) {
    sv = gv_fetchpv("*main::camelpack", GV_ADD, SVt_PVAV);
    sv_setpvn(sv, "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"
             "\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));
    sv_dump(sv);
    }

C:\Documents and Settings\Owner\Desktop\cpan libs\lxs2>perl -MLocal::XS2 -MDevel
::Peek=Dump -E"Local::XS::t4(); Dump(*camelpack)"
SV = PVGV(0x963954) at 0x8fbf5c
  REFCNT = 2
  FLAGS = (POK,pPOK)
  IV = 9688024
  NV = 1.76614436923904e-317
  PV = 0x976e7c "\377\377\377\377\377\377\377\377\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\
0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"\0
  CUR = 44
  LEN = 46
SV = PVGV(0x963954) at 0x8fbf5c
  REFCNT = 2
  FLAGS = (POK,pPOK)
  IV = 9688024
  NV = 1.76614436923904e-317
  PV = 0x976e7c "\377\377\377\377\377\377\377\377\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\
0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"\0
  CUR = 44
  LEN = 46
SV = PVGV(0x963954) at 0x8fbf5c
  REFCNT = 2
  FLAGS = (POK,pPOK)
  IV = 9688024
  NV = 1.76614436923904e-317
  PV = 0x976e7c "\377\377\377\377\377\377\377\377\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\
0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"\0
  CUR = 44
  LEN = 46
SV = PVGV(0x963954) at 0x8fbf5c
  REFCNT = 2
  FLAGS = (POK,pPOK)
  IV = 9688024
  NV = 1.76614436923904e-317
  PV = 0x976e7c "\377\377\377\377\377\377\377\377\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\
0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"\0
  CUR = 44
  LEN = 46
SV = PVGV(0x9639b4) at 0x8fb70c
  REFCNT = 1
  FLAGS = ()
  NAME = "\xff\xff\xff\xff\xff\xff\xff\xff\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0
\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
  NAMELEN = 44
  GvSTASH = 0x368bbc    "main"
  FLAGS = 0x0
  GP = 0x93db94
    SV = 0x0
    REFCNT = 1
    IO = 0x0
    FORM = 0x0
    AV = 0x0
    HV = 0x0
    CV = 0x0
    CVGEN = 0x0
    GPFLAGS = 0x0 ()
    LINE = 1
    FILE = "-e"
    EGV = 0x8fb70c      "\xff\xff\xff\xff\xff\xff\xff\xff\0\0\0\0\0\0\0\0\0\0\0\
0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"

C:\Documents and Settings\Owner\Desktop\cpan libs\lxs2>

SvPV does work correctly on a GV *.

    else if (isGV_with_GP(sv)) {
	GV *const gv = MUTABLE_GV(sv);
	SV *const buffer = sv_newmortal();

	gv_efullname3(buffer, gv, "*");

	assert(SvPOK(buffer));
	if (SvUTF8(buffer))
	    SvUTF8_on(sv);
	if (lp)
	    *lp = SvCUR(buffer);
	return SvPVX(buffer);
    }


> 
> > 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. 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.

-- 
bulk88 ~ bulk88 at hotmail.com

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

Thread Previous | 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