Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

calling closure prototype SEGVs #9830

Closed
p5pRT opened this issue Aug 15, 2009 · 7 comments
Closed

calling closure prototype SEGVs #9830

p5pRT opened this issue Aug 15, 2009 · 7 comments

Comments

@p5pRT
Copy link

p5pRT commented Aug 15, 2009

Migrated from rt.perl.org#68560 (status was 'resolved')

Searchable as RT68560$

@p5pRT
Copy link
Author

p5pRT commented Aug 15, 2009

From zefram@fysh.org

Created by zefram@fysh.org

$ perl -lwe 'sub MODIFY_CODE_ATTRIBUTES { $proto = $_[1]; return (); } sub foo { my $x = $_[0]; return sub :a0 { $x } } print $proto->()'
zsh​: segmentation fault perl -lwe

Callers to foo() will be returned a clone of the "sub :a0 { $x }" code,
attached to a set of lexical variables, and this will be callable as
a function in the ordinary manner. Internally, the "sub :a0 { $x }"
code is also reified as a CV, but it's a CV that can't execute normally,
because it lacks the lexicals that it needs. Ordinary code can't get at
this prototype code, but when applying an attribute (at compile time)
the attribute handler sees the prototype CV, which is what it needs to
operate on.

So I've used the attribute mechanism as a backdoor to get a reference
to the prototype code. Obviously calling it won't work, but I expected
a clean error message. Instead it SEGVs.

Attempting to call the prototype code from inside the attribute handler
does give a clean error message, "Undefined subroutine called", because
the code hasn't been attached to the CV at that point. This is the same
effect as one gets from 'sub foo { BEGIN { foo() } }'.

Perl Info

Flags:
    category=core
    severity=low

Site configuration information for perl 5.10.0:

Configured by Debian Project at Thu Jan  1 12:43:38 UTC 2009.

Summary of my perl5 (revision 5 version 10 subversion 0) configuration:
  Platform:
    osname=linux, osvers=2.6.26-1-686, archname=i486-linux-gnu-thread-multi
    uname='linux rebekka 2.6.26-1-686 #1 smp mon dec 15 18:15:07 utc 2008 i686 gnulinux '
    config_args='-Dusethreads -Duselargefiles -Dccflags=-DDEBIAN -Dcccdlflags=-fPIC -Darchname=i486-linux-gnu -Dprefix=/usr -Dprivlib=/usr/share/perl/5.10 -Darchlib=/usr/lib/perl/5.10 -Dvendorprefix=/usr -Dvendorlib=/usr/share/perl5 -Dvendorarch=/usr/lib/perl5 -Dsiteprefix=/usr/local -Dsitelib=/usr/local/share/perl/5.10.0 -Dsitearch=/usr/local/lib/perl/5.10.0 -Dman1dir=/usr/share/man/man1 -Dman3dir=/usr/share/man/man3 -Dsiteman1dir=/usr/local/man/man1 -Dsiteman3dir=/usr/local/man/man3 -Dman1ext=1 -Dman3ext=3perl -Dpager=/usr/bin/sensible-pager -Uafs -Ud_csh -Ud_ualarm -Uusesfio -Uusenm -DDEBUGGING=-g -Doptimize=-O2 -Duseshrplib -Dlibperl=libperl.so.5.10.0 -Dd_dosuid -des'
    hint=recommended, useposix=true, d_sigaction=define
    useithreads=define, usemultiplicity=define
    useperlio=define, d_sfio=undef, uselargefiles=define, usesocks=undef
    use64bitint=undef, use64bitall=undef, uselongdouble=undef
    usemymalloc=n, bincompat5005=undef
  Compiler:
    cc='cc', ccflags ='-D_REENTRANT -D_GNU_SOURCE -DDEBIAN -fno-strict-aliasing -pipe -I/usr/local/include -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64',
    optimize='-O2 -g',
    cppflags='-D_REENTRANT -D_GNU_SOURCE -DDEBIAN -fno-strict-aliasing -pipe -I/usr/local/include'
    ccversion='', gccversion='4.3.2', gccosandvers=''
    intsize=4, longsize=4, ptrsize=4, doublesize=8, byteorder=1234
    d_longlong=define, longlongsize=8, d_longdbl=define, longdblsize=12
    ivtype='long', ivsize=4, nvtype='double', nvsize=8, Off_t='off_t', lseeksize=8
    alignbytes=4, prototype=define
  Linker and Libraries:
    ld='cc', ldflags =' -L/usr/local/lib'
    libpth=/usr/local/lib /lib /usr/lib /usr/lib64
    libs=-lgdbm -lgdbm_compat -ldb -ldl -lm -lpthread -lc -lcrypt
    perllibs=-ldl -lm -lpthread -lc -lcrypt
    libc=/lib/libc-2.7.so, so=so, useshrplib=true, libperl=libperl.so.5.10.0
    gnulibc_version='2.7'
  Dynamic Linking:
    dlsrc=dl_dlopen.xs, dlext=so, d_dlsymun=undef, ccdlflags='-Wl,-E'
    cccdlflags='-fPIC', lddlflags='-shared -O2 -g -L/usr/local/lib'

Locally applied patches:
    


@INC for perl 5.10.0:
    /etc/perl
    /usr/local/lib/perl/5.10.0
    /usr/local/share/perl/5.10.0
    /usr/lib/perl5
    /usr/share/perl5
    /usr/lib/perl/5.10
    /usr/share/perl/5.10
    /usr/local/lib/site_perl
    .


Environment for perl 5.10.0:
    HOME=/home/zefram
    LANG (unset)
    LANGUAGE (unset)
    LD_LIBRARY_PATH (unset)
    LOGDIR (unset)
    PATH=/home/zefram/pub/i686-pc-linux-gnu/bin:/home/zefram/pub/common/bin:/usr/bin:/usr/X11R6/bin:/bin:/usr/local/bin:/usr/games
    PERL_BADLANG (unset)
    SHELL=/usr/bin/zsh

@p5pRT
Copy link
Author

p5pRT commented Aug 16, 2009

From @nwc10

Thanks for the bug report and analysis

On Sat, Aug 15, 2009 at 04​:40​:16PM -0700, Zefram wrote​:

$ perl -lwe 'sub MODIFY_CODE_ATTRIBUTES { $proto = $_[1]; return (); } sub foo { my $x = $_[0]; return sub :a0 { $x } } print $proto->()'
zsh​: segmentation fault perl -lwe

Callers to foo() will be returned a clone of the "sub :a0 { $x }" code,
attached to a set of lexical variables, and this will be callable as
a function in the ordinary manner. Internally, the "sub :a0 { $x }"
code is also reified as a CV, but it's a CV that can't execute normally,
because it lacks the lexicals that it needs. Ordinary code can't get at
this prototype code, but when applying an attribute (at compile time)
the attribute handler sees the prototype CV, which is what it needs to
operate on.

So I've used the attribute mechanism as a backdoor to get a reference
to the prototype code. Obviously calling it won't work, but I expected
a clean error message. Instead it SEGVs.

Attempting to call the prototype code from inside the attribute handler
does give a clean error message, "Undefined subroutine called", because
the code hasn't been attached to the CV at that point. This is the same
effect as one gets from 'sub foo { BEGIN { foo() } }'.

The crash happens at this point in pp_entersub​:

  if (hasargs) {
  AV *const av = MUTABLE_AV(PAD_SVl(0));
  if (AvREAL(av)) {
  /* @​_ is normally not REAL--this should only ever
  * happen when DB​::sub() calls things that modify @​_ */
  av_clear(av);
  AvREAL_off(av);
  AvREIFY_on(av);
  }
  cx->blk_sub.savearray = GvAV(PL_defgv);
  GvAV(PL_defgv) = MUTABLE_AV(SvREFCNT_inc_simple(av));
  CX_CURPAD_SAVE(cx->blk_sub);
  cx->blk_sub.argarray = av;
  ++MARK;

  if (items > AvMAX(av) + 1) {

av is &PL_sv_undef, so AvMAX() is not a valid macro to apply to it.

I'm not sure if this is the right place to detect the problem. In particular,
I don't know if it's possible to use alternative syntax to take other routes
through pp_entersub and avoid that block.

I'm hoping that someone else has a better understanding of this, and can
propose a solution.

Nicholas Clark

@p5pRT
Copy link
Author

p5pRT commented Aug 16, 2009

The RT System itself - Status changed from 'new' to 'open'

@p5pRT
Copy link
Author

p5pRT commented Nov 30, 2010

From @cpansprout

On Sun Aug 16 04​:06​:42 2009, nicholas wrote​:

I'm hoping that someone else has a better understanding of this, and
can
propose a solution.

How about this? http​://perl5.git.perl.org/perl.git/commitdiff/541ed3a9

@p5pRT
Copy link
Author

p5pRT commented Nov 30, 2010

@cpansprout - Status changed from 'open' to 'resolved'

@p5pRT p5pRT closed this as completed Nov 30, 2010
@p5pRT
Copy link
Author

p5pRT commented Nov 30, 2010

From @rgarcia

On 30 November 2010 06​:54, Father Chrysostomos via RT
<perlbug-followup@​perl.org> wrote​:

On Sun Aug 16 04​:06​:42 2009, nicholas wrote​:

I'm hoping that someone else has a better understanding of this, and
can
propose a solution.

How about this? http​://perl5.git.perl.org/perl.git/commitdiff/541ed3a9

Looks fine; I see you removed already the code for which I did not
understood the necessity :)

@p5pRT
Copy link
Author

p5pRT commented Nov 30, 2010

From zefram@fysh.org

Father Chrysostomos via RT wrote​:

How about this? http​://perl5.git.perl.org/perl.git/commitdiff/541ed3a9

Looks fine, except a nit in one of the tests​:

  like $@​, qr/^Closure prototype called/,
  "Calling closure proto with no @​_ that returns a lexical";

@​_ will be interpolated there. Have another backslash.

-zefram

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

1 participant