Skip to content

Segfault due to stack overflow: 'sub UNIVERSAL::DESTROY{$e=bless[]}' #15369

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

Open
p5pRT opened this issue May 27, 2016 · 4 comments
Open

Segfault due to stack overflow: 'sub UNIVERSAL::DESTROY{$e=bless[]}' #15369

p5pRT opened this issue May 27, 2016 · 4 comments

Comments

@p5pRT
Copy link

p5pRT commented May 27, 2016

Migrated from rt.perl.org#128258 (status was 'open')

Searchable as RT128258$

@p5pRT
Copy link
Author

p5pRT commented May 27, 2016

From @dcollinsn

Greetings Porters,

I have compiled bleadperl with the afl-gcc compiler using​:

./Configure -Dusedevel -Dprefix='/usr/local/perl-afl' -Dcc='ccache afl-gcc' -Uuselongdouble -Duse64bitall -Doptimize=-g -Uversiononly -Uman1dir -Uman3dir -Dusequadmath -des
AFL_HARDEN=1 make && make test

And then fuzzed the resulting binary using​:

AFL_NO_VAR_CHECK=1 afl-fuzz -i in -o out bin/perl @​@​

After reducing testcases using `afl-tmin` and performing additional minimization by hand, I have located the following testcase that triggers a segfault in the perl interpreter. The testcase is the file below. On normal builds and debug builds, this segfaults.

dcollins@​nightshade64​:~/perl$ ./miniperl -Ilib -e 'sub UNIVERSAL​::DESTROY{$e=bless[]}'
Segmentation fault

This is a stack overflow issue due to infinite recursion. Here is the looping series of stack frames​:

#943 0x000000000053c07b in Perl_free_tmps () at scope.c​:207
#944 0x000000000043017d in Perl_call_sv (sv=0x8539a0, flags=45) at perl.c​:2887
#945 0x000000000050dba4 in S_curse (sv=0x19b8550, check_refcnt=true) at sv.c​:6853
#946 0x000000000050c574 in Perl_sv_clear (orig_sv=0x19b8598) at sv.c​:6457
#947 0x000000000050df22 in Perl_sv_free2 (sv=0x19b8598, rc=1) at sv.c​:6954
#948 0x000000000053b8aa in S_SvREFCNT_dec_NN (sv=0x19b8598) at inline.h​:177

Valgrind concurs​:

==7488== Stack overflow in thread #1​: can't grow stack to 0xffe801000
==7488==
==7488== Process terminating with default action of signal 11 (SIGSEGV)
==7488== Access not within mapped region at address 0xFFE801F6C
==7488== Stack overflow in thread #1​: can't grow stack to 0xffe801000
==7488== at 0x53DA15​: Perl_leave_scope (scope.c​:801)
==7488== If you believe this happened as a result of a stack
==7488== overflow in your program's main thread (unlikely but
==7488== possible), you can try to increase the size of the
==7488== main thread stack using the --main-stacksize= flag.
==7488== The main thread stack size used in this run was 8388608.
==7488== Stack overflow in thread #1​: can't grow stack to 0xffe801000

A bisect was attempted but this behavior has persisted since 5.12.0 at least.

**PERL -V**

dcollins@​nightshade64​:~/perldebug$ ./perl -Ilib -V
Summary of my perl5 (revision 5 version 25 subversion 2) configuration​:
  Commit id​: c29dfc6
  Platform​:
  osname=linux, osvers=4.5.0-2-amd64, archname=x86_64-linux-ld
  uname='linux nightshade64 4.5.0-2-amd64 #1 smp debian 4.5.3-2 (2016-05-08) x86_64 gnulinux '
  config_args='-Dusedevel -Dprefix=/usr/local/perl-afl -Dcc=ccache gcc-6.1 -Duselongdouble -Duse64bitall -Doptimize=-g -Uversiononly -Uman1dir -Uman3dir -DDEBUGGING -DPERL_POISON -des'
  hint=recommended, useposix=true, d_sigaction=define
  useithreads=undef, usemultiplicity=undef
  use64bitint=define, use64bitall=define, uselongdouble=define
  usemymalloc=n, bincompat5005=undef
  Compiler​:
  cc='ccache gcc-6.1', ccflags ='-fwrapv -DDEBUGGING -fno-strict-aliasing -pipe -fstack-protector-strong -I/usr/local/include -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64',
  optimize='-g',
  cppflags='-fwrapv -DDEBUGGING -fno-strict-aliasing -pipe -fstack-protector-strong -I/usr/local/include'
  ccversion='', gccversion='6.1.0', gccosandvers=''
  intsize=4, longsize=8, ptrsize=8, doublesize=8, byteorder=12345678, doublekind=3
  d_longlong=define, longlongsize=8, d_longdbl=define, longdblsize=16, longdblkind=3
  ivtype='long', ivsize=8, nvtype='long double', nvsize=16, Off_t='off_t', lseeksize=8
  alignbytes=16, prototype=define
  Linker and Libraries​:
  ld='ccache gcc-6.1', ldflags =' -fstack-protector-strong -L/usr/local/lib'
  libpth=/usr/local/lib /usr/local/lib/gcc/x86_64-pc-linux-gnu/6.1.0/include-fixed /usr/include/x86_64-linux-gnu /usr/lib /lib/x86_64-linux-gnu /lib/../lib /usr/lib/x86_64-linux-gnu /usr/lib/../lib /lib
  libs=-lpthread -lnsl -ldl -lm -lcrypt -lutil -lc
  perllibs=-lpthread -lnsl -ldl -lm -lcrypt -lutil -lc
  libc=libc-2.22.so, so=so, useshrplib=false, libperl=libperl.a
  gnulibc_version='2.22'
  Dynamic Linking​:
  dlsrc=dl_dlopen.xs, dlext=so, d_dlsymun=undef, ccdlflags='-Wl,-E'
  cccdlflags='-fPIC', lddlflags='-shared -g -L/usr/local/lib -fstack-protector-strong'

Characteristics of this binary (from libperl)​:
  Compile-time options​: DEBUGGING HAS_TIMES PERLIO_LAYERS PERL_COPY_ON_WRITE
  PERL_DONT_CREATE_GVSV
  PERL_HASH_FUNC_ONE_AT_A_TIME_HARD PERL_MALLOC_WRAP
  PERL_OP_PARENT PERL_PRESERVE_IVUV PERL_USE_DEVEL
  USE_64_BIT_ALL USE_64_BIT_INT USE_LARGE_FILES
  USE_LOCALE USE_LOCALE_COLLATE USE_LOCALE_CTYPE
  USE_LOCALE_NUMERIC USE_LOCALE_TIME USE_LONG_DOUBLE
  USE_PERLIO USE_PERL_ATOF
  Built under linux
  Compiled at May 26 2016 17​:57​:37
  @​INC​:
  lib
  /usr/local/perl-afl/lib/site_perl/5.25.2/x86_64-linux-ld
  /usr/local/perl-afl/lib/site_perl/5.25.2
  /usr/local/perl-afl/lib/5.25.2/x86_64-linux-ld
  /usr/local/perl-afl/lib/5.25.2
  /usr/local/perl-afl/lib/site_perl/5.25.1
  /usr/local/perl-afl/lib/site_perl/5.24.0
  /usr/local/perl-afl/lib/site_perl
  .

@p5pRT
Copy link
Author

p5pRT commented Jul 7, 2016

From @iabyn

On Thu, May 26, 2016 at 06​:33​:34PM -0700, Dan Collins wrote​:

dcollins@​nightshade64​:~/perl$ ./miniperl -Ilib -e 'sub UNIVERSAL​::DESTROY{$e=bless[]}'
Segmentation fault

This is a stack overflow issue due to infinite recursion. Here is the looping series of stack frames​:

I've added it to the #111358​: [META] C stack recursion ticket.
There isn't any obvious way that I can think of of avoiding this, apart
from maybe refusing to call a destructor if its current depth is over some
arbitrary limit; and even then, croaking with "too deep in DESTROY" might
trigger destructors which create a new recursion cycle.

--
You never really learn to swear until you learn to drive.

@p5pRT
Copy link
Author

p5pRT commented Jul 7, 2016

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

@p5pRT
Copy link
Author

p5pRT commented Jul 7, 2016

From @demerphq

One possibility is to forbid universal destroy hooks. Or to forbid use of
bless while executing universal destroy hooks.

This is a delightfully evil bug btw. I laughed with joy and dread when I
first saw it.
On 7 Jul 2016 12​:23, "Dave Mitchell" <davem@​iabyn.com> wrote​:

On Thu, May 26, 2016 at 06​:33​:34PM -0700, Dan Collins wrote​:

dcollins@​nightshade64​:~/perl$ ./miniperl -Ilib -e 'sub
UNIVERSAL​::DESTROY{$e=bless[]}'
Segmentation fault

This is a stack overflow issue due to infinite recursion. Here is the
looping series of stack frames​:

I've added it to the #111358​: [META] C stack recursion ticket.
There isn't any obvious way that I can think of of avoiding this, apart
from maybe refusing to call a destructor if its current depth is over some
arbitrary limit; and even then, croaking with "too deep in DESTROY" might
trigger destructors which create a new recursion cycle.

--
You never really learn to swear until you learn to drive.

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

No branches or pull requests

2 participants