Closed p5pRT closed 6 years ago
Greetings Porters\,
I have compiled bleadperl with the afl-gcc compiler using:
./Configure -Dusedevel -Dprefix='/usr/local/perl-afl' -Dcc=afl-gcc -Duselongdouble -Duse64bitint -Doptimize=-g -Uversiononly -Uman1dir -Uman3dir -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 filtering out testcases that are merely iterations of "#!perl -u"\, I have located the following testcase that triggers a segmentation fault in the perl interpreter. The testcase is the 15-byte file:
&{0==0}*&{0==0}
Several other variations of this failed\, but this is the simplest example. All have either two calls to "&{0==0}" or nested calls of that type "&{0==&{0==0}}". This looks vaguely similar to the bugs arising from the stack not being refcounted (c.f. 125840\, 123710\, 123804\, 123997\, but the failure point is different. Unfortunately\, no valgrind is available\, as I haven't yet had a chance to upgrade to a version of valgrind that's aware of dwarf 4 and I'm off to work. If you for whatever reason are unable to repro this\, I'll try to add updated information early this week.
**GDB**
GNU gdb (GDB) 7.10 Copyright (C) 2015 Free Software Foundation\, Inc. License GPLv3+: GNU GPL version 3 or later \<http://gnu.org/licenses/gpl.html> This is free software: you are free to change and redistribute it. There is NO WARRANTY\, to the extent permitted by law. Type "show copying" and "show warranty" for details. This GDB was configured as "i686-pc-linux-gnu". Type "show configuration" for configuration details. For bug reporting instructions\, please see: \<http://www.gnu.org/software/gdb/bugs/>. Find the GDB manual and other documentation resources online at: \<http://www.gnu.org/software/gdb/documentation/>. For help\, type "help". Type "apropos word" to search for commands related to "word"... Reading symbols from ../bin/perl...done. (gdb) run Starting program: /usr/local/perl-afl/bin/perl f4i000000 [Thread debugging using libthread_db enabled] Using host libthread_db library "/lib/libthread_db.so.1".
Program received signal SIGSEGV\, Segmentation fault. 0x083ff152 in Perl_pp_multiply () at pp.c:1275 1275 tryAMAGICbin_MG(mult_amg\, AMGf_assign|AMGf_numeric); (gdb) bt #0 0x083ff152 in Perl_pp_multiply () at pp.c:1275 #1 0x083506fb in Perl_runops_standard () at run.c:41 #2 0x08116c47 in S_run_body (oldscope=1) at perl.c:2456 #3 perl_run (my_perl=0x87d8008) at perl.c:2379 #4 0x08068762 in main (argc=2\, argv=0xbffff7e4\, env=0xbffff7f0) at perlmain.c:116
**PERL -V** Summary of my perl5 (revision 5 version 23 subversion 3) configuration: Commit id: 718ac8a2e5fd26fa68078f057e7c332594ebebf6 Platform: osname=linux\, osvers=2.6.32-5-686\, archname=i686-linux-64int-ld uname='linux nagios 2.6.32-5-686 #1 smp tue may 13 16:33:32 utc 2014 i686 gnulinux ' config_args='-Dusedevel -Dprefix=/usr/local/perl-afl -Dcc=afl-gcc -Duselongdouble -Duse64bitint -Doptimize=-g -Uversiononly -Uman1dir -Uman3dir -des' hint=recommended\, useposix=true\, d_sigaction=define useithreads=undef\, usemultiplicity=undef use64bitint=define\, use64bitall=undef\, uselongdouble=define usemymalloc=n\, bincompat5005=undef Compiler: cc='afl-gcc'\, ccflags ='-fwrapv -fno-strict-aliasing -pipe -fstack-protector-strong -I/usr/local/include -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64'\, optimize='-g'\, cppflags='-fwrapv -fno-strict-aliasing -pipe -fstack-protector-strong -I/usr/local/include' ccversion=''\, gccversion='5.2.0'\, gccosandvers='' intsize=4\, longsize=4\, ptrsize=4\, doublesize=8\, byteorder=12345678\, doublekind=3 d_longlong=define\, longlongsize=8\, d_longdbl=define\, longdblsize=12\, longdblkind=3 ivtype='long long'\, ivsize=8\, nvtype='long double'\, nvsize=12\, Off_t='off_t'\, lseeksize=8 alignbytes=4\, prototype=define Linker and Libraries: ld='afl-gcc'\, ldflags =' -fstack-protector-strong -L/usr/local/lib' libpth=/usr/local/lib /usr/local/lib/gcc/i686-pc-linux-gnu/5.2.0/include-fixed /usr/lib /lib/../lib /usr/lib/../lib /lib /usr/lib/i486-linux-gnu /usr/lib64 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: HAS_TIMES PERLIO_LAYERS PERL_COPY_ON_WRITE PERL_DONT_CREATE_GVSV PERL_HASH_FUNC_ONE_AT_A_TIME_HARD PERL_MALLOC_WRAP PERL_PRESERVE_IVUV PERL_USE_DEVEL 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 Sep 8 2015 22:24:21 @INC: /usr/local/perl-afl/lib/site_perl/5.23.3/i686-linux-64int-ld /usr/local/perl-afl/lib/site_perl/5.23.3 /usr/local/perl-afl/lib/5.23.3/i686-linux-64int-ld /usr/local/perl-afl/lib/5.23.3 /usr/local/perl-afl/lib/site_perl/5.23.2 /usr/local/perl-afl/lib/site_perl .
%% VALGRIND OUTPUT FOR CANONICAL TESTCASE ABOVE %%
==6140== Memcheck\, a memory error detector ==6140== Copyright (C) 2002-2013\, and GNU GPL'd\, by Julian Seward et al. ==6140== Using Valgrind-3.10.1 and LibVEX; rerun with -h for copyright info ==6140== Command: ../bin/perl f4i000000 ==6140== ==6140== Invalid read of size 4 ==6140== at 0x83FF4D9: Perl_pp_multiply (pp.c:1274) ==6140== by 0x83506FA: Perl_runops_standard (run.c:41) ==6140== by 0x8116C46: S_run_body (perl.c:2456) ==6140== by 0x8116C46: perl_run (perl.c:2379) ==6140== by 0x8068761: main (perlmain.c:116) ==6140== Address 0x42bffd4 is 4 bytes before a block of size 512 alloc'd ==6140== at 0x402A0DE: malloc (vg_replace_malloc.c:296) ==6140== by 0x82B3593: Perl_safesysmalloc (util.c:153) ==6140== by 0x83435E7: Perl_av_extend_guts (av.c:182) ==6140== by 0x834375F: Perl_av_extend (av.c:80) ==6140== by 0x845C97D: Perl_new_stackinfo (scope.c:56) ==6140== by 0x80FF36D: Perl_init_stacks (perl.c:4063) ==6140== by 0x80FF84D: perl_construct (perl.c:249) ==6140== by 0x80684B8: main (perlmain.c:110) ==6140== ==6140== Invalid read of size 4 ==6140== at 0x83FF152: Perl_pp_multiply (pp.c:1275) ==6140== by 0x83506FA: Perl_runops_standard (run.c:41) ==6140== by 0x8116C46: S_run_body (perl.c:2456) ==6140== by 0x8116C46: perl_run (perl.c:2379) ==6140== by 0x8068761: main (perlmain.c:116) ==6140== Address 0x8 is not stack'd\, malloc'd or (recently) free'd ==6140== ==6140== ==6140== Process terminating with default action of signal 11 (SIGSEGV) ==6140== Access not within mapped region at address 0x8 ==6140== at 0x83FF152: Perl_pp_multiply (pp.c:1275) ==6140== by 0x83506FA: Perl_runops_standard (run.c:41) ==6140== by 0x8116C46: S_run_body (perl.c:2456) ==6140== by 0x8116C46: perl_run (perl.c:2379) ==6140== by 0x8068761: main (perlmain.c:116) ==6140== If you believe this happened as a result of a stack ==6140== overflow in your program's main thread (unlikely but ==6140== possible)\, you can try to increase the size of the ==6140== main thread stack using the --main-stacksize= flag. ==6140== The main thread stack size used in this run was 8388608. ==6140== ==6140== HEAP SUMMARY: ==6140== in use at exit: 87\,294 bytes in 520 blocks ==6140== total heap usage: 618 allocs\, 98 frees\, 104\,737 bytes allocated ==6140== ==6140== LEAK SUMMARY: ==6140== definitely lost: 80 bytes in 1 blocks ==6140== indirectly lost: 1\,821 bytes in 18 blocks ==6140== possibly lost: 0 bytes in 0 blocks ==6140== still reachable: 85\,393 bytes in 501 blocks ==6140== suppressed: 0 bytes in 0 blocks ==6140== Rerun with --leak-check=full to see details of leaked memory ==6140== ==6140== For counts of detected and suppressed errors\, rerun with: -v ==6140== ERROR SUMMARY: 2 errors from 2 contexts (suppressed: 0 from 0) Segmentation fault
For fun\, some other examples of failing testcases after afl-tmin:
&{0==&{0==0}}.0 &{0==0}/&{0==0}&0 &{0*&{0==0}==0}/0 &{0==0}*&{0==0}
On Sat Sep 12 05:36:20 2015\, dcollinsn@gmail.com wrote:
&{0==0}*&{0==0}
Several other variations of this failed\, but this is the simplest example. All have either two calls to "&{0==0}" or nested calls of that type "&{0==&{0==0}}". This looks vaguely similar to the bugs arising from the stack not being refcounted (c.f. 125840\, 123710\, 123804\, 123997\, but the failure point is different.
No\, it’s more like stack corruption (perl getting confused about where it’s stack pointer should be):
$ ./miniperl -Ilib -le 'print 1\, 2\, 3\,&{0==0}*&{0==0}\, 4\, 5\, 6' 16456
--
Father Chrysostomos
The RT System itself - Status changed from 'new' to 'open'
On Sun Sep 20 15:22:29 2015\, sprout wrote:
On Sat Sep 12 05:36:20 2015\, dcollinsn@gmail.com wrote:
&{0==0}*&{0==0}
Several other variations of this failed\, but this is the simplest example. All have either two calls to "&{0==0}" or nested calls of that type "&{0==&{0==0}}". This looks vaguely similar to the bugs arising from the stack not being refcounted (c.f. 125840\, 123710\, 123804\, 123997\, but the failure point is different.
No\, it’s more like stack corruption (perl getting confused about where it’s stack pointer should be):
$ ./miniperl -Ilib -le 'print 1\, 2\, 3\,&{0==0}*&{0==0}\, 4\, 5\, 6' 16456
Specifically\, it is related to the fact that PL_sv_yes->() silently does nothing\, but its doing nothing is badly implemented.
This whole PL_sv_yes call thing is wart resulting from implementation details. I wonder if we can just remove it from perl space. Surely nobody is relying on it! (Famous last words.)
--
Father Chrysostomos
Father Chrysostomos via RT wrote:
This whole PL_sv_yes call thing is wart resulting from implementation details. I wonder if we can just remove it from perl space.
We certainly should\, because its exposure per se produces visible bugs:
$ perl -lwe '*1 = sub { print @_; }; &1(2); &{!!1}(3)' 2
Even if its do-nothing behaviour were implemented correctly\, it's wrong for it to behave differently from an ordinary 1 as a subroutine ref.
-zefram
On Sat Sep 12 05:36:20 2015\, dcollinsn@gmail.com wrote:
After reducing testcases using `afl-tmin` and filtering out testcases that are merely iterations of "#!perl -u"\, I have located the following testcase that triggers a segmentation fault in the perl interpreter. The testcase is the 15-byte file:
&{0==0}*&{0==0}
The attached fixes the handling of calls to &PL_sv_yes.
I'm not sure how to approach eliminating the wart.
Tony
On Tue Nov 03 16:17:43 2015\, tonyc wrote:
The attached fixes the handling of calls to &PL_sv_yes.
I'm not sure how to approach eliminating the wart.
Tony
That fix looks like it doesn't fix the problem. It needs to be fixed in the optree at compile tile\, that multiply operator takes 1 argument\, not empty list. There might be other ways to get rh and lh operands of multiply to be empty list and cause the same crash again without calling empty sub references (PL_sv_yes in this case).
-- bulk88 ~ bulk88 at hotmail.com
bulk88 via RT wrote:
There might be other ways to get rh and lh operands of multiply to be empty list and cause the same crash again
Any such way would be another bug. The operands of the multiply op are put into scalar context\, and it is intended that every optree scalar-context optree will yield exactly one value on the stack. The magic subroutine behind &PL_sv_yes was erroneous in not obeying scalar context.
-zefram
On Tue Nov 03 16:17:43 2015\, tonyc wrote:
On Sat Sep 12 05:36:20 2015\, dcollinsn@gmail.com wrote:
After reducing testcases using `afl-tmin` and filtering out testcases that are merely iterations of "#!perl -u"\, I have located the following testcase that triggers a segmentation fault in the perl interpreter. The testcase is the 15-byte file:
&{0==0}*&{0==0}
The attached fixes the handling of calls to &PL_sv_yes.
Applied as 0cd52e23ae641a766983833dc8b37b743474be9e.
I'm not sure how to approach eliminating the wart.
Leaving the ticket open in case someone figures that out.
Tony
On Wed\, Jan 06\, 2016 at 09:28:17PM -0800\, Tony Cook via RT wrote:
I'm not sure how to approach eliminating the wart.
Leaving the ticket open in case someone figures that out.
Maybe make the method-locating code return a stub XS CV rather than PL_sv_yes when it fails to find "import"?\, This XS sub would do whatever pp_entersub used to do when it encountered PL_sv_yes.
-- "Procrastination grows to fill the available time" -- Mitchell's corollary to Parkinson's Law
Dave Mitchell wrote:
Maybe make the method-locating code return a stub XS CV rather than PL_sv_yes when it fails to find "import"?
Done in commit 0740a29d60ebd4ff72090340b0140ec2210e90c7. That resolves this ticket.
-zefram
@iabyn - Status changed from 'open' to 'pending release'
Thank you for filing this report. You have helped make Perl better.
With the release yesterday of Perl 5.28.0\, this and 185 other issues have been resolved.
Perl 5.28.0 may be downloaded via: https://metacpan.org/release/XSAWYERX/perl-5.28.0
If you find that the problem persists\, feel free to reopen this ticket.
@khwilliamson - Status changed from 'pending release' to 'resolved'
Migrated from rt.perl.org#126042 (status was 'resolved')
Searchable as RT126042$