Perl / perl5

🐪 The Perl programming language
https://dev.perl.org/perl5/
Other
1.96k stars 555 forks source link

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

Open p5pRT opened 8 years ago

p5pRT commented 8 years ago

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

Searchable as RT128258$

p5pRT commented 8 years ago

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​: c29dfc6a6c45f86648c51f961304254cc3c449b9   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 commented 8 years ago

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 commented 8 years ago

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

p5pRT commented 8 years ago

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.