Skip Menu |

Date: Sun, 4 Jan 2015 12:44:02 -0600
From: Brian Carpenter <brian.carpenter [...] gmail.com>
To: perlbug [...] perl.org
Subject: Segmentation fault in Perl5 while fuzzing Perl binary (possible stack overflow?)
Download (untitled) / with headers
text/plain 8.9k
Download (untitled) / with headers
text/html 12.1k
I'm still fuzzing a Perl binary that I built from git source on 01/02/2015 using the afl-gcc compiler:

CC=/path/to/afl-gcc ./Configure
AFL_HARDEN=1 make

This is perl 5, version 21, subversion 8 (v5.21.8 (v5.21.7-209-g4e27940)) built for x86_64-linux

Besides the above information, this version of Perl was compiled using all defaults (enter was pressed for every question).

While fuzzing the perl binary, I found another testcase which causes a segfault (and possible stack overflow). I've attached the testcase and the resulting core dump to this email. 

geeknik@deb7fuzz:~/findings/perl/fuzzer02/crashes$ /home/geeknik/perl5/perl id\:000023\,sig\:11\,src\:004555+020002\,op\:splice\,rep\:16 

String found where operator expected at id:000023,sig:11,src:004555+020002,op:splice,rep:16 line 8, near "print3"Hello World.\n""
Backslash found where operator expected at id:000023,sig:11,src:004555+020002,op:splice,rep:16 line 11, near "is\"
String found where operator expected at id:000023,sig:11,src:004555+020002,op:splice,rep:16 line 11, near "Mnt ""
(Missing semicolon on previous line?)
Array found where operator expected at id:000023,sig:11,src:004555+020002,op:splice,rep:16 line 11, at end of line
(Missing operator before ?)
Bareword found where operator expected at id:000023,sig:11,src:004555+020002,op:splice,rep:16 line 11, near "<P>Note"
(Missing operator before Note?)
Bareword found where operator expected at id:000023,sig:11,src:004555+020002,op:splice,rep:16 line 11, near "]g"
(Missing operator before g?)
String found where operator expected at id:000023,sig:11,src:004555+020002,op:splice,rep:16 line 11, near "print ""
(Missing semicolon on previous line?)
Bareword found where operator expected at id:000023,sig:11,src:004555+020002,op:splice,rep:16 line 12, near "print "into"
  (Might be a runaway multi-line "" string starting on line 11)
(Do you need to predeclare print?)
String found where operator expected at id:000023,sig:11,src:004555+020002,op:splice,rep:16 line 15, near "n"
   }
print ""
Segmentation fault (core dumped)


geeknik@deb7fuzz:~/findings/perl/fuzzer02/crashes$ valgrind -q /home/geeknik/perl5/perl id\:000023\,sig\:11\,src\:004555+020002\,op\:splice\,rep\:16 

String found where operator expected at id:000023,sig:11,src:004555+020002,op:splice,rep:16 line 8, near "print3"Hello World.\n""
Backslash found where operator expected at id:000023,sig:11,src:004555+020002,op:splice,rep:16 line 11, near "is\"
String found where operator expected at id:000023,sig:11,src:004555+020002,op:splice,rep:16 line 11, near "Mnt ""
(Missing semicolon on previous line?)
Array found where operator expected at id:000023,sig:11,src:004555+020002,op:splice,rep:16 line 11, at end of line
(Missing operator before ?)
Bareword found where operator expected at id:000023,sig:11,src:004555+020002,op:splice,rep:16 line 11, near "<P>Note"
(Missing operator before Note?)
Bareword found where operator expected at id:000023,sig:11,src:004555+020002,op:splice,rep:16 line 11, near "]g"
(Missing operator before g?)
String found where operator expected at id:000023,sig:11,src:004555+020002,op:splice,rep:16 line 11, near "print ""
(Missing semicolon on previous line?)
Bareword found where operator expected at id:000023,sig:11,src:004555+020002,op:splice,rep:16 line 12, near "print "into"
  (Might be a runaway multi-line "" string starting on line 11)
(Do you need to predeclare print?)
String found where operator expected at id:000023,sig:11,src:004555+020002,op:splice,rep:16 line 15, near "n"
   }
print ""
==55834== Invalid read of size 8
==55834==    at 0x4C0100: Perl_pmruntime (op.c:5481)
==55834==    by 0x5CBEBC: Perl_yyparse (perly.y:1000)
==55834==    by 0x4F3114: perl_parse (perl.c:2273)
==55834==    by 0x42A92B: main (perlmain.c:114)
==55834==  Address 0x8 is not stack'd, malloc'd or (recently) free'd
==55834== 
==55834== 
==55834== Process terminating with default action of signal 11 (SIGSEGV): dumping core
==55834==  Access not within mapped region at address 0x8
==55834==    at 0x4C0100: Perl_pmruntime (op.c:5481)
==55834==    by 0x5CBEBC: Perl_yyparse (perly.y:1000)
==55834==    by 0x4F3114: perl_parse (perl.c:2273)
==55834==    by 0x42A92B: main (perlmain.c:114)
==55834==  If you believe this happened as a result of a stack
==55834==  overflow in your program's main thread (unlikely but
==55834==  possible), you can try to increase the size of the
==55834==  main thread stack using the --main-stacksize= flag.
==55834==  The main thread stack size used in this run was 8388608.
Segmentation fault


geeknik@deb7fuzz:~/findings/perl/fuzzer02/crashes$ gdb /home/geeknik/perl5/perl core

GNU gdb (GDB) 7.4.1-debian
Copyright (C) 2012 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 "x86_64-linux-gnu".
For bug reporting instructions, please see:
Reading symbols from /home/geeknik/perl5/perl...done.
[New LWP 46515]

warning: Can't read pathname for load map: Input/output error.
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/lib/x86_64-linux-gnu/libthread_db.so.1".
Core was generated by `/home/geeknik/perl5/perl id:000023,sig:11,src:004555+020002,op:splice,rep:16'.
Program terminated with signal 11, Segmentation fault.
#0  Perl_pmruntime (o=0x2c6b550, expr=0x2c6b290, isreg=true, floor=0) at op.c:5481
5481        while (OpSIBLING(kid) != repl)
(gdb) bt
#0  Perl_pmruntime (o=0x2c6b550, expr=0x2c6b290, isreg=true, floor=0) at op.c:5481
#1  0x00000000005cbebd in Perl_yyparse (gramtype=<optimized out>) at perly.y:1000
#2  0x00000000004f3115 in S_parse_body (xsinit=0x42ad20 <xs_init>, env=0x0) at perl.c:2273
#3  perl_parse (my_perl=<optimized out>, xsinit=0x42ad20 <xs_init>, argc=<optimized out>, argv=<optimized out>, env=0x0) at perl.c:1607
#4  0x000000000042a92c in main (argc=2, argv=0x7fff492c7348, env=0x7fff492c7360) at perlmain.c:114
#5  0x00007fc0bf96dead in __libc_start_main (main=<optimized out>, argc=<optimized out>, ubp_av=<optimized out>, init=<optimized out>, 
    fini=<optimized out>, rtld_fini=<optimized out>, stack_end=0x7fff492c7338) at libc-start.c:244
#6  0x000000000042ac45 in _start ()
(gdb) 


./perlbug -d
---
Flags:
    category=core
    severity=low
---
This perlbug was built using Perl 5.21.8 - Fri Jan  2 19:02:59 CST 2015
It is being executed now by  Perl 5.21.7 - Thu Dec 18 14:34:01 CST 2014.

Site configuration information for perl 5.21.7:

Configured by geeknik at Thu Dec 18 14:34:01 CST 2014.

Summary of my perl5 (revision 5 version 21 subversion 7) configuration:
  Commit id: e9d2bd8a490981edfc4ddabb5889ca0e86f29e29
  Platform:
    osname=linux, osvers=3.2.0-4-amd64, archname=x86_64-linux
    uname='linux deb7fuzz 3.2.0-4-amd64 #1 smp debian 3.2.63-2+deb7u2 x86_64 gnulinux '
    config_args=''
    hint=recommended, useposix=true, d_sigaction=define
    useithreads=undef, usemultiplicity=undef
    use64bitint=define, use64bitall=define, uselongdouble=undef
    usemymalloc=n, bincompat5005=undef
  Compiler:
    cc='/home/geeknik/afl/afl-gcc', ccflags ='-fwrapv -fno-strict-aliasing -pipe -fstack-protector -I/usr/local/include -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64 -D_FORTIFY_SOURCE=2',
    optimize='-O2',
    cppflags='-fwrapv -fno-strict-aliasing -pipe -fstack-protector -I/usr/local/include'
    ccversion='', gccversion='4.7.2', 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='double', nvsize=8, Off_t='off_t', lseeksize=8
    alignbytes=8, prototype=define
  Linker and Libraries:
    ld='/home/geeknik/afl/afl-gcc', ldflags =' -fstack-protector -L/usr/local/lib'
    libpth=/usr/local/lib /usr/lib/gcc/x86_64-linux-gnu/4.7/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=-lnsl -ldl -lm -lcrypt -lutil -lc -lpthread
    perllibs=-lnsl -ldl -lm -lcrypt -lutil -lc -lpthread
    libc=libc-2.13.so, so=so, useshrplib=false, libperl=libperl.a
    gnulibc_version='2.13'
  Dynamic Linking:
    dlsrc=dl_dlopen.xs, dlext=so, d_dlsymun=undef, ccdlflags='-Wl,-E'
    cccdlflags='-fPIC', lddlflags='-shared -O2 -L/usr/local/lib -fstack-protector'


---
@INC for perl 5.21.7:
    /usr/local/lib/perl5/site_perl/5.21.7/x86_64-linux
    /usr/local/lib/perl5/site_perl/5.21.7
    /usr/local/lib/perl5/5.21.7/x86_64-linux
    /usr/local/lib/perl5/5.21.7
    .

---
Environment for perl 5.21.7:
    HOME=/home/geeknik
    LANG=en_US.UTF-8
    LANGUAGE (unset)
    LD_LIBRARY_PATH (unset)
    LOGDIR (unset)
    PATH=/usr/local/bin:/usr/bin:/bin:/usr/local/games:/usr/games
    PERL_BADLANG (unset)
    SHELL=/bin/bash

Details on AFL can be found here: http://lcamtuf.coredump.cx/afl/

Download core.gz
application/x-gzip 62.8k

Message body not shown because it is not plain text.

Download crash.gz
application/x-gzip 573b

Message body not shown because it is not plain text.

RT-Send-CC: perl5-porters [...] perl.org
Download (untitled) / with headers
text/plain 1.6k
The patch provided by khw in RT #123539 to address a different segfault reported by the same tester does not address the problem in *this* ticket. So this is a different problem. ##### $ git branch * 123539-segfault ##### $ ./perl -Ilib -c ~/learn/perl/p5p/noshebang-123542-crash String found where operator expected at /home/jkeenan/learn/perl/p5p/noshebang-123542-crash line 8, near "print3"Hello World.\n"" Backslash found where operator expected at /home/jkeenan/learn/perl/p5p/noshebang-123542-crash line 11, near "is\" String found where operator expected at /home/jkeenan/learn/perl/p5p/noshebang-123542-crash line 11, near "Mnt "" (Missing semicolon on previous line?) Array found where operator expected at /home/jkeenan/learn/perl/p5p/noshebang-123542-crash line 11, at end of line (Missing operator before ?) Bareword found where operator expected at /home/jkeenan/learn/perl/p5p/noshebang-123542-crash line 11, near "<P>Note" (Missing operator before Note?) Bareword found where operator expected at /home/jkeenan/learn/perl/p5p/noshebang-123542-crash line 11, near "]g" (Missing operator before g?) String found where operator expected at /home/jkeenan/learn/perl/p5p/noshebang-123542-crash line 11, near "print "" (Missing semicolon on previous line?) Bareword found where operator expected at /home/jkeenan/learn/perl/p5p/noshebang-123542-crash line 12, near "print "into" (Might be a runaway multi-line "" string starting on line 11) (Do you need to predeclare print?) String found where operator expected at /home/jkeenan/learn/perl/p5p/noshebang-123542-crash line 15, near "n" } print "" Segmentation fault (core dumped) ##### -- James E Keenan (jkeenan@cpan.org)
RT-Send-CC: perl5-porters [...] perl.org
Download (untitled) / with headers
text/plain 612b
On Sun Jan 04 16:23:21 2015, jkeenan wrote: Show quoted text
> The patch provided by khw in RT #123539 to address a different > segfault reported by the same tester does not address the problem in > *this* ticket. So this is a different problem.
Right, this is a problem with the construction of the op-tree. The loop: while (OpSIBLING(kid) != repl) kid = OpSIBLING(kid); op_sibling_splice(expr, kid, 1, NULL); attempts to deref a NULL kid because it can't find repl in the op's children. Adding NULL checks here crashes in op_free() instead. I'm working on producing a smaller test-case. Tony
RT-Send-CC: perl5-porters [...] perl.org
Download (untitled) / with headers
text/plain 129b
On Sun Jan 04 18:21:03 2015, tonyc wrote: Show quoted text
> I'm working on producing a smaller test-case.
Attached a smaller test case. Tony
Subject: 123542-fuzz-crash-mod.pl
@pairs = s "y" } " y($);); my($pair); @pairs = s ý${air<BR>\n" } print "<P>Note t read(STDIN,$buffer,$ENV{'CONTENT_LENGTH'});\n"; rMnt "necessary); @xairs = s "y$pair<BR>\n" } print "into spaces and get rid y(z$buffer); read(STDINˆ"; print ",$buffer,$ENV{'CONTENT_LENGTH'}); @pairs = s%ý$pair<BR>\n" } print "$ENV{'CONTENT_LENGTH'});hat further parsing is\n = s "$p"; is\n"; rMnt "necessFry); readHSTDIN,$buffer,$ENV{'CONTENT_LENGTH'}); @pairs print "n"; pri~t "n" "n"; print " y($bufH; @pairs = s "x$pair<BR>\n" } rMnt "necessary); read(STDI.,$buffer,$ENV{'CONTENT_LENGTH'}); @pairs = s d get rid of some\d"; print "other webýencoding.\n";
RT-Send-CC: perl5-porters [...] perl.org
Download (untitled) / with headers
text/plain 953b
On Sun Jan 04 18:21:03 2015, tonyc wrote: Show quoted text
> On Sun Jan 04 16:23:21 2015, jkeenan wrote:
> > The patch provided by khw in RT #123539 to address a different > > segfault reported by the same tester does not address the problem in > > *this* ticket. So this is a different problem.
> > Right, this is a problem with the construction of the op-tree. > > The loop: > > while (OpSIBLING(kid) != repl) > kid = OpSIBLING(kid); > op_sibling_splice(expr, kid, 1, NULL); > > attempts to deref a NULL kid because it can't find repl in the op's > children. > > Adding NULL checks here crashes in op_free() instead. > > I'm working on producing a smaller test-case.
I cannot reproduce this on a Mac. I do get a crash on dromedary, but no debugging symbols, which makes it a little hard to debug. :-( This has to be some sort of memory corruption if op_last points to something not found in the op_first->op_sibling->... chain. -- Father Chrysostomos
RT-Send-CC: perl5-porters [...] perl.org
Download (untitled) / with headers
text/plain 1.2k
On Sun Jan 04 23:41:14 2015, sprout wrote: Show quoted text
> On Sun Jan 04 18:21:03 2015, tonyc wrote:
> > On Sun Jan 04 16:23:21 2015, jkeenan wrote:
> > > The patch provided by khw in RT #123539 to address a different > > > segfault reported by the same tester does not address the problem > > > in > > > *this* ticket. So this is a different problem.
> > > > Right, this is a problem with the construction of the op-tree. > > > > The loop: > > > > while (OpSIBLING(kid) != repl) > > kid = OpSIBLING(kid); > > op_sibling_splice(expr, kid, 1, NULL); > > > > attempts to deref a NULL kid because it can't find repl in the op's > > children. > > > > Adding NULL checks here crashes in op_free() instead. > > > > I'm working on producing a smaller test-case.
> > I cannot reproduce this on a Mac. I do get a crash on dromedary, but > no debugging symbols, which makes it a little hard to debug. :-( > > This has to be some sort of memory corruption if op_last points to > something not found in the op_first->op_sibling->... chain.
A bisect blames it on me: 8be227ab5eaa23f2d21fd15f70190e494496dcbe is the first bad commit commit 8be227ab5eaa23f2d21fd15f70190e494496dcbe Author: Father Chrysostomos <sprout@cpan.org> Date: Sat Jun 23 09:54:31 2012 -0700 CV-based slab allocation for ops -- Father Chrysostomos
Date: Mon, 05 Jan 2015 21:31:24 +0100
To: "Father Chrysostomos via RT" <perlbug-followup [...] perl.org>
From: Andreas Koenig <andreas.koenig.7os6VVqR [...] franz.ak.mind.de>
Subject: Re: [perl #123542] Segmentation fault in Perl5 while fuzzing Perl binary (possible stack overflow?)
Download (untitled) / with headers
text/plain 1.5k
In case you still need a stacktrace, I have produced one with v5.17.1-224-g8be227a: Program terminated with signal SIGABRT, Aborted. #0 0x00007ff4faf42107 in __GI_raise (sig=sig@entry=6) at ../nptl/sysdeps/unix/sysv/linux/raise.c:56 56 ../nptl/sysdeps/unix/sysv/linux/raise.c: No such file or directory. (gdb) bt #0 0x00007ff4faf42107 in __GI_raise (sig=sig@entry=6) at ../nptl/sysdeps/unix/sysv/linux/raise.c:56 #1 0x00007ff4faf434e8 in __GI_abort () at abort.c:89 #2 0x00007ff4faf80044 in __libc_message (do_abort=do_abort@entry=1, fmt=fmt@entry=0x7ff4fb072c60 "*** Error in `%s': %s: 0x%s ***\n") at ../sysdeps/posix/libc_fatal.c:175 #3 0x00007ff4faf8581e in malloc_printerr (action=1, str=0x7ff4fb06ed1e "free(): invalid pointer", ptr=<optimized out>) at malloc.c:4996 #4 0x00007ff4faf86526 in _int_free (av=<optimized out>, p=<optimized out>, have_lock=0) at malloc.c:3840 #5 0x000000000041e589 in Perl_opslab_force_free ( my_perl=my_perl@entry=0x187c010, slab=0x18a5cd0) at op.c:482 #6 0x000000000045f075 in Perl_cv_undef (my_perl=0x187c010, cv=0x187fbe0) at pad.c:372 #7 0x00000000004ae342 in Perl_sv_clear (my_perl=0x187c010, orig_sv=0x3836, orig_sv@entry=0x187fbe0) at sv.c:6106 #8 0x00000000004ae794 in Perl_sv_free2 (my_perl=my_perl@entry=0x187c010, sv=0x187fbe0) at sv.c:6524 #9 0x00000000004379c1 in perl_destruct (my_perl=0x187c010) at perl.c:758 #10 0x000000000041bd03 in main (argc=2, argv=0x7fffa166ef08, env=0x7fffa166ef20) at perlmain.c:131 -- andreas
RT-Send-CC: perl5-porters [...] perl.org
Download (untitled) / with headers
text/plain 1.6k
On Sun Jan 04 18:21:03 2015, tonyc wrote: Show quoted text
> On Sun Jan 04 16:23:21 2015, jkeenan wrote:
> > The patch provided by khw in RT #123539 to address a different > > segfault reported by the same tester does not address the problem in > > *this* ticket. So this is a different problem.
> > Right, this is a problem with the construction of the op-tree. > > The loop: > > while (OpSIBLING(kid) != repl) > kid = OpSIBLING(kid); > op_sibling_splice(expr, kid, 1, NULL); > > attempts to deref a NULL kid because it can't find repl in the op's > children.
In this case kid and repl are the op_first and op_last, respectively, of expr. But expr is an unop with no op_last field. So cLISTOPx(...)->op_last reads past the end of the op struct into the next op slot, and repl ends up holding an opslot pointer. That can’t be found in the kids (there is only one kid), so we crash when doing OpSIBLING(NULL), as you observed. Show quoted text
> > Adding NULL checks here crashes in op_free() instead.
Because substrepl is pointing to something that is not an op. Show quoted text
> I'm working on producing a smaller test-case.
I got it down to s/${<>{})//. On Mon Jan 05 06:05:53 2015, sprout wrote: Show quoted text
> A bisect blames it on me: > > 8be227ab5eaa23f2d21fd15f70190e494496dcbe is the first bad commit > commit 8be227ab5eaa23f2d21fd15f70190e494496dcbe > Author: Father Chrysostomos <sprout@cpan.org> > Date: Sat Jun 23 09:54:31 2012 -0700 > > CV-based slab allocation for ops
It started failing then because previously ops were allocated via calloc, so cLISTOPx(unop)->op_last would produce a null pointer. So kid->op_sibling == repl was true on the very first kid (the only kid), and the loop would end. I fixed this in 08b999a9. -- Father Chrysostomos
RT-Send-CC: perl5-porters [...] perl.org
Download (untitled) / with headers
text/plain 752b
On Thu Jan 08 18:12:29 2015, sprout wrote: Show quoted text
> I got it down to s/${<>{})//. > > On Mon Jan 05 06:05:53 2015, sprout wrote:
> > A bisect blames it on me: > > > > 8be227ab5eaa23f2d21fd15f70190e494496dcbe is the first bad commit > > commit 8be227ab5eaa23f2d21fd15f70190e494496dcbe > > Author: Father Chrysostomos <sprout@cpan.org> > > Date: Sat Jun 23 09:54:31 2012 -0700 > > > > CV-based slab allocation for ops
> > It started failing then because previously ops were allocated via > calloc, so cLISTOPx(unop)->op_last would produce a null pointer. So > kid->op_sibling == repl was true on the very first kid (the only kid), > and the loop would end.
Actually, my reduced case *does* crash in 5.10-14, but not in 5.8[789]. -- Father Chrysostomos
Subject: Your ticket against Perl 5 has been resolved
Download (untitled) / with headers
text/plain 263b
Thanks for submitting this ticket The issue should be resolved with the release today of Perl v5.22, available at http://www.perl.org/get.html If you find that the problem persists, feel free to reopen this ticket -- Karl Williamson for the Perl 5 porters team


This service is sponsored and maintained by Best Practical Solutions and runs on Perl.org infrastructure.

For issues related to this RT instance (aka "perlbug"), please contact perlbug-admin at perl.org