Skip Menu |
Report information
Id: 123677
Status: resolved
Priority: 0/
Queue: perl5

Owner: Nobody
Requestors: brian.carpenter [at] gmail.com
Cc:
AdminCc:

Operating System: (no value)
PatchStatus: (no value)
Severity: low
Type: unknown
Perl Version: (no value)
Fixed In: 5.22.0



Date: Mon, 26 Jan 2015 05:39:36 -0600
From: Brian Carpenter <brian.carpenter [...] gmail.com>
To: perlbug [...] perl.org
Subject: 31 byte one liner crashes Perl5.21.9
Download (untitled) / with headers
text/plain 3.8k
Good morning. The fuzzing attack against Perl continues with an interesting (at least to me) test case. I built Perl 5.21.9 from Git source this morning.

/home/geeknik/perl5/perl -v
This is perl 5, version 21, subversion 9 (v5.21.9 (v5.21.8-57-gd28cce6)) built for x86_64-linux


Using the american fuzzy lop (http://http://lcamtuf.coredump.cx/afl/) compiler in this fashion, I built the executable:

CC=/path/to/afl-gcc ./Configure (defaulted through all of the options)
ran make without using AFL_HARDEN=1

Test case and core dump are attached.

valgrind -q /home/geeknik/perl5/perl final-crasher4
Bareword found where operator expected at final-crasher4 line 1, near "0h"
(Missing operator before h?)
==37418== Invalid read of size 2
==37418==    at 0x464C79: Perl_newSVREF (op.c:9387)
==37418==    by 0x5BA3F7: Perl_yyparse (perly.y:1109)
==37418==    by 0x4E6494: perl_parse (perl.c:2273)
==37418==    by 0x429BBB: main (perlmain.c:114)
==37418==  Address 0x10805edc128 is not stack'd, malloc'd or (recently) free'd
==37418== 
==37418== 
==37418== Process terminating with default action of signal 11 (SIGSEGV): dumping core
==37418==  Access not within mapped region at address 0x10805EDC128
==37418==    at 0x464C79: Perl_newSVREF (op.c:9387)
==37418==    by 0x5BA3F7: Perl_yyparse (perly.y:1109)
==37418==    by 0x4E6494: perl_parse (perl.c:2273)
==37418==    by 0x429BBB: main (perlmain.c:114)
==37418==  If you believe this happened as a result of a stack
==37418==  overflow in your program's main thread (unlikely but
==37418==  possible), you can try to increase the size of the
==37418==  main thread stack using the --main-stacksize= flag.
==37418==  The main thread stack size used in this run was 8388608.
Segmentation fault

gdb /home/geeknik/perl5/perl core
Reading symbols from /home/geeknik/perl5/perl...done.
[New LWP 45131]

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 final-crasher4'.
Program terminated with signal 11, Segmentation fault.
#0  Perl_newSVREF (o=0x10800e043b8) at op.c:9387
9387    if (o->op_type == OP_PADANY) {
(gdb) bt
#0  Perl_newSVREF (o=0x10800e043b8) at op.c:9387
#1  0x00000000005ba3f8 in Perl_yyparse (gramtype=<optimized out>) at perly.y:1109
#2  0x00000000004e6495 in S_parse_body (xsinit=0x429fb0 <xs_init>, env=0x0) at perl.c:2273
#3  perl_parse (my_perl=<optimized out>, xsinit=0x429fb0 <xs_init>, argc=<optimized out>, argv=<optimized out>, env=0x0) at perl.c:1607
#4  0x0000000000429bbc in main (argc=2, argv=0x7fffffffe3c8, env=0x7fffffffe3e0) at perlmain.c:114
#5  0x00007ffff6f97ead 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=0x7fffffffe3b8) at libc-start.c:244
#6  0x0000000000429ed5 in _start ()
(gdb) i r
rax            0xc8 200
rbx            0xe00f80 14684032
rcx            0x2 2
rdx            0xc7 199
rsi            0xffffffffffffffff -1
rdi            0x10800e043b8 1133886063544
rbp            0xaaaaaaaaaaaaaaab 0xaaaaaaaaaaaaaaab
rsp            0x7fffffffdfb0 0x7fffffffdfb0
r8             0x200002800000024 144115359874547748
r9             0xffffffffffffffff -1
r10            0xfffffffffffffffd -3
r11            0xee 238
r12            0xee 238
r13            0x1 1
r14            0xe00b10 14682896
r15            0x70 112
rip            0x464c79 0x464c79 <Perl_newSVREF+1>
eflags         0x10283 [ CF SF IF RF ]
cs             0x33 51
ss             0x2b 43
ds             0x0 0
es             0x0 0
fs             0x0 0
gs             0x0 0
(gdb) 

Test case:
s)$0{0h());qx(@0);qx(@0);qx(@0)

hexdump:
0000000 2973 3024 307b 2868 2929 713b 2878 3040
0000010 3b29 7871 4028 2930 713b 2878 3040 0029
000001f

Download onelinecrash.tar.gz
application/x-gzip 59.1k

Message body not shown because it is not plain text.

Date: Mon, 26 Jan 2015 05:55:08 -0600
To: perlbug-followup [...] perl.org
From: Brian Carpenter <brian.carpenter [...] gmail.com>
Subject: [perl #123677]
Download (untitled) / with headers
text/plain 4.6k
A slightly different test case (30 bytes) provides a vastly different gdb and valgrind output. Not sure if related or needs a new bug:

perl -e 's)$0{0h());qx(@0);qx(@0);qx[-]'
Bareword found where operator expected at -e line 1, near "0h"
(Missing operator before h?)
syntax error at -e line 1, near "0h"
syntax error at -e line 1, next char ^E
syntax error at -e line 1, next char \225
syntax error at -e line 1, at EOF
Execution of -e aborted due to compilation errors.
Segmentation fault (core dumped)

(Core was generated by `perl -e s)$0{0h());qx(@0);qx(@0);qx[-]'.
Program terminated with signal 11, Segmentation fault.
#0  0x00000000004f5b53 in S_gv_magicalize_isa (gv=0xe34e30) at gv.c:1532
1532    av = GvAVn(gv);
(gdb) bt
#0  0x00000000004f5b53 in S_gv_magicalize_isa (gv=0xe34e30) at gv.c:1532
#1  S_gv_magicalize (sv_type=14959792, addmg=7, len=<optimized out>, 
    name=0xe3ae90 "\200\316", <incomplete sequence \343>, stash=0x0, 
    gv=0xe34e30) at gv.c:1825
#2  Perl_gv_fetchpvn_flags (nambeg=0x4fb3a5 "D", full_len=<optimized out>, 
    flags=<optimized out>, sv_type=14959792) at gv.c:2348
#3  0x0000000000e3a638 in ?? ()
#4  0x0000000000000004 in ?? ()
#5  0x0000000000e3ae90 in ?? ()
#6  0x0000000000e3a638 in ?? ()
#7  0x0000000000509129 in S_gv_fetchmeth_internal (flags=0, level=-1, 
    len=11079778, name=0x7ffff70aa9bc <Address 0x7ffff70aa9bc out of bounds>, 
    meth=0x0, stash=0x7e76e2) at gv.c:793
#8  Perl_gv_fetchmeth_pvn (flags=0, level=-1, 
    len=<error reading variable: Cannot access memory at address 0x9019df631>, 
    name=<error reading variable: Cannot access memory at address 0x4807db35a8>, stash=0x7e76e2) at gv.c:862
#9  Perl_Gv_AMupdate (stash=0x7e76e2, destructing=false) at gv.c:2695
#10 0xdbb97c8a9c1ee400 in ?? ()
#11 0x0000000000000000 in ?? ()
(gdb) i r
rax            0x0 0
rbx            0xe34e30 14896688
rcx            0x0 0
rdx            0xe44378 14959480
rsi            0xe44418 14959640
rdi            0x0 0
rbp            0xe3ae90 0xe3ae90
rsp            0x7fffffffda80 0x7fffffffda80
r8             0x58 88
r9             0x101010101010101 72340172838076673
r10            0x0 0
r11            0x7ffff6ffc532 140737337345330
r12            0x2 2
r13            0x0 0
r14            0xe3ae90 14921360
r15            0x7 7
rip            0x4f5b53 0x4f5b53 <Perl_gv_fetchpvn_flags+9115>
eflags         0x10206 [ PF IF RF ]
cs             0x33 51
ss             0x2b 43
ds             0x0 0
es             0x0 0
fs             0x0 0
gs             0x0 0

Bareword found where operator expected at -e line 1, near "0h"
(Missing operator before h?)
syntax error at -e line 1, near "0h"
syntax error at -e line 1, next char ^E
syntax error at -e line 1, next char \225
syntax error at -e line 1, at EOF
Execution of -e aborted due to compilation errors.
==19553== Invalid read of size 8
==19553==    at 0x4F5B53: Perl_newGP (gv.c:194)
==19553==    by 0x4FB3A4: Perl_gv_init_pvn (gv.c:412)
==19553==    by 0x509128: S_gv_fetchmeth_internal (gv.c:755)
==19553==    by 0x50DA1B: Perl_gv_fetchmeth_pvn_autoload (gv.c:862)
==19553==    by 0x7B3056: S_curse (sv.c:6832)
==19553==    by 0x7B9046: Perl_sv_clear (sv.c:6499)
==19553==    by 0x7B1117: Perl_sv_free2 (sv.c:6972)
==19553==    by 0x525DF4: Perl_parser_free (inline.h:166)
==19553==    by 0x8B8ECF: Perl_leave_scope (scope.c:1250)
==19553==    by 0x4CF966: S_my_exit_jump (perl.c:5013)
==19553==    by 0x4F4434: Perl_my_failure_exit (perl.c:5000)
==19553==    by 0x903344: Perl_die_unwind (pp_ctl.c:1684)
==19553==  Address 0x20 is not stack'd, malloc'd or (recently) free'd
==19553== 
==19553== 
==19553== Process terminating with default action of signal 11 (SIGSEGV): dumping core
==19553==  Access not within mapped region at address 0x20
==19553==    at 0x4F5B53: Perl_newGP (gv.c:194)
==19553==    by 0x4FB3A4: Perl_gv_init_pvn (gv.c:412)
==19553==    by 0x509128: S_gv_fetchmeth_internal (gv.c:755)
==19553==    by 0x50DA1B: Perl_gv_fetchmeth_pvn_autoload (gv.c:862)
==19553==    by 0x7B3056: S_curse (sv.c:6832)
==19553==    by 0x7B9046: Perl_sv_clear (sv.c:6499)
==19553==    by 0x7B1117: Perl_sv_free2 (sv.c:6972)
==19553==    by 0x525DF4: Perl_parser_free (inline.h:166)
==19553==    by 0x8B8ECF: Perl_leave_scope (scope.c:1250)
==19553==    by 0x4CF966: S_my_exit_jump (perl.c:5013)
==19553==    by 0x4F4434: Perl_my_failure_exit (perl.c:5000)
==19553==    by 0x903344: Perl_die_unwind (pp_ctl.c:1684)
==19553==  If you believe this happened as a result of a stack
==19553==  overflow in your program's main thread (unlikely but
==19553==  possible), you can try to increase the size of the
==19553==  main thread stack using the --main-stacksize= flag.
==19553==  The main thread stack size used in this run was 8388608.
Segmentation fault
Download (untitled) / with headers
text/plain 205b
On Mon Jan 26 03:40:33 2015, brian.carpenter@gmail.com wrote: Show quoted text
> s)$0{0h());qx(@0);qx(@0);qx(@0)
Crashes Perl 5.21.7 (v5.21-6-602-ge9d2bd8)) Show quoted text
> s)$0{0h());qx(@0);qx(@0);qx[-]
Does not crash Perl 5.21.7
This crash is still present in v5.21.9 (v5.21.8-200-ga57d3d4).
RT-Send-CC: perl5-porters [...] perl.org
Download (untitled) / with headers
text/plain 574b
On Mon Jan 26 03:40:33 2015, brian.carpenter@gmail.com wrote: Show quoted text
> Good morning. The fuzzing attack against Perl continues with an interesting > (at least to me) test case.
Yes, very interesting. Show quoted text
> Test case: > s)$0{0h());qx(@0);qx(@0);qx(@0)
This is a case where a syntax error causes scopes to be popped when the lexing state is LEX_KNOWNEXT, and it changes to LEX_NORMAL, somehow corrupting the pending token stack. I suspect the fix will be to eliminate the LEX_KNOWNEXT state and check the number of items on the pending token stack instead. -- Father Chrysostomos
RT-Send-CC: perl5-porters [...] perl.org
Download (untitled) / with headers
text/plain 1.5k
On Sat Feb 07 17:39:18 2015, sprout wrote: Show quoted text
> > Test case: > > s)$0{0h());qx(@0);qx(@0);qx(@0)
> > This is a case where a syntax error causes scopes to be popped when > the lexing state is LEX_KNOWNEXT, and it changes to LEX_NORMAL, > somehow corrupting the pending token stack. I suspect the fix will be > to eliminate the LEX_KNOWNEXT state and check the number of items on > the pending token stack instead.
For what it's worth, I bisected this test case to: eae48c8938e50ebb341a72c2886c5ae8587092a5 is the first bad commit commit eae48c8938e50ebb341a72c2886c5ae8587092a5 Author: Zefram <zefram@fysh.org> Date: Tue Oct 19 21:16:11 2010 +0100 refactor and regularise label/statement grammar which is what the '$1=eval{a:}' case bisected to - https://rt.perl.org/Ticket/Display.html?id=123652. The bisect was... mhorsfall@dory:~/p5/perl$ cat ~/runner my $cmd = 's)$0{0h());qx(@0);qx(@0);qx[-]'; my $what = system("./perl -Ilib -e '$cmd'"); my $res = ($? >> 8) & 127; if ($res == 11) { die "Segfault!\n"; } else { print "Okay!\n"; } mhorfall@dory:~/p5/perl$ /home/mhorsfall/perl-1/Porting/bisect.pl --start=v5.13.6 --end=v5.13.7 -j 8 -- ./perl -Ilib /home/mhorsfall/runner I had to hack /home/mhorsfall/perl-1/Porting/bisect-runner.pl to comment out: # optimize => '-g', I can't get this bug to trigger if I compile with -D optimize=-g. It triggers with ./Configure -des -Dusedevel though. Also, I can't trigger it with threads: ./Configure -des -Dusedevel -Dusethreads -- Matthew Horsfall (alh)
RT-Send-CC: perl5-porters [...] perl.org
Download (untitled) / with headers
text/plain 780b
On Sun Feb 08 12:54:38 2015, alh wrote: Show quoted text
> mhorfall@dory:~/p5/perl$ /home/mhorsfall/perl-1/Porting/bisect.pl > --start=v5.13.6 --end=v5.13.7 -j 8 -- ./perl -Ilib > /home/mhorsfall/runner > > I had to hack /home/mhorsfall/perl-1/Porting/bisect-runner.pl to > comment out: > # optimize => '-g', > > I can't get this bug to trigger if I compile with -D optimize=-g. It > triggers with > > ./Configure -des -Dusedevel > > though. Also, I can't trigger it with threads: > > ./Configure -des -Dusedevel -Dusethreads > > -- Matthew Horsfall (alh)
Even if it doesn’t crash, the -DT output gets scrambled with lines like: ### 1:LEX_KNOWNEXT/XTERM "@0" ### <== ?? 63008 What happens if you bisect with -DT and check for ‘<== ??’ in the output? -- Father Chrysostomos
RT-Send-CC: perl5-porters [...] perl.org
OK, I’ve now fixed this one in 7aa8cb0dec17. -- Father Chrysostomos
Date: Mon, 9 Feb 2015 10:08:11 -0500
From: "Matthew Horsfall (alh)" <wolfsage [...] gmail.com>
CC: Perl5 Porters <perl5-porters [...] perl.org>
Subject: Re: [perl #123677] 31 byte one liner crashes Perl5.21.9
To: perlbug-followup [...] perl.org
Download (untitled) / with headers
text/plain 1.4k
On Sun, Feb 8, 2015 at 5:56 PM, Father Chrysostomos via RT <perlbug-followup@perl.org> wrote: Show quoted text
> Even if it doesn’t crash, the -DT output gets scrambled with lines like: > > ### 1:LEX_KNOWNEXT/XTERM "@0" > ### <== ?? 63008 > > What happens if you bisect with -DT and check for ‘<== ??’ in the output?
More fun here. I had to compile all versions with -O2 -g to get this bug to trigger. It led to this: mhorsfall@dory:~/perl-1$ git show f05d7009fffc72d5b11ea5e553117baa7256a9a7 commit f05d7009fffc72d5b11ea5e553117baa7256a9a7 Author: Rafael Garcia-Suarez <rgarciasuarez@gmail.com> Date: Fri May 16 14:13:23 2008 +0200 Prevent the tokenizer from segfaulting in debug mode when a FUNC token is forced From: "Rafael Garcia-Suarez" <rgarciasuarez@gmail.com> Message-ID: <b77c1dce0805160313r78cb1b2bxfeb64460d2e9a7df@mail.gmail.com> p4raw-id: //depot/perl@33833 diff --git a/toke.c b/toke.c index abdc54d..2a63a90 100644 --- a/toke.c +++ b/toke.c @@ -1359,7 +1359,7 @@ S_force_next(pTHX_ I32 type) #ifdef DEBUGGING if (DEBUG_T_TEST) { PerlIO_printf(Perl_debug_log, "### forced token:\n"); - tokereport(THING, &NEXTVAL_NEXTTOKE); + tokereport(type, &NEXTVAL_NEXTTOKE); } #endif #ifdef PERL_MAD Attached are the -DT output from before the commit and after the commit for comparison if it's of any interest. -- Matthew Horsfall (alh)
Download 06c0dd3.txt
text/plain 1.2k

Message body is not shown because sender requested not to inline it.

Download f05d700.txt
text/plain 2.3k

Message body is not shown because sender requested not to inline it.

RT-Send-CC: perl5-porters [...] perl.org
On Mon Feb 09 07:08:38 2015, alh wrote: Show quoted text
> On Sun, Feb 8, 2015 at 5:56 PM, Father Chrysostomos via RT > <perlbug-followup@perl.org> wrote:
> > Even if it doesn’t crash, the -DT output gets scrambled with lines like: > > > > ### 1:LEX_KNOWNEXT/XTERM "@0" > > ### <== ?? 63008 > > > > What happens if you bisect with -DT and check for ‘<== ??’ in the output?
> > More fun here. I had to compile all versions with -O2 -g to get this > bug to trigger. It led to this: > > mhorsfall@dory:~/perl-1$ git show f05d7009fffc72d5b11ea5e553117baa7256a9a7 > commit f05d7009fffc72d5b11ea5e553117baa7256a9a7 > Author: Rafael Garcia-Suarez <rgarciasuarez@gmail.com> > Date: Fri May 16 14:13:23 2008 +0200 > > Prevent the tokenizer from segfaulting in debug mode when a FUNC > token is forced > From: "Rafael Garcia-Suarez" <rgarciasuarez@gmail.com> > Message-ID: > <b77c1dce0805160313r78cb1b2bxfeb64460d2e9a7df@mail.gmail.com> > > p4raw-id: //depot/perl@33833 > > diff --git a/toke.c b/toke.c > index abdc54d..2a63a90 100644 > --- a/toke.c > +++ b/toke.c > @@ -1359,7 +1359,7 @@ S_force_next(pTHX_ I32 type) > #ifdef DEBUGGING > if (DEBUG_T_TEST) { > PerlIO_printf(Perl_debug_log, "### forced token:\n"); > - tokereport(THING, &NEXTVAL_NEXTTOKE); > + tokereport(type, &NEXTVAL_NEXTTOKE); > } > #endif > #ifdef PERL_MAD > > Attached are the -DT output from before the commit and after the > commit for comparison if it's of any interest.
Well, it is certainly interesting. The first one stops abruptly at the buffer overflow. Presumably it crashed because of the bug that 05d7009fff fixed. The second one shows definitely buggy output. When the overflow happens, nextval overflows into nexttype and nexttype overflows into nexttoke. Since nexttoke is an offset into the nexttype and nextval arrays, it is possible to read ahead into save_curcop, which is a memory address. That would explain why the bug is intermittent. I suspect this bug is *old* and predates -DT output. -- Father Chrysostomos
Date: Mon, 9 Feb 2015 12:44:51 -0500
From: "Matthew Horsfall (alh)" <wolfsage [...] gmail.com>
Subject: Re: [perl #123677] 31 byte one liner crashes Perl5.21.9
To: perlbug-followup [...] perl.org
Download (untitled) / with headers
text/plain 740b
On Mon, Feb 9, 2015 at 12:34 PM, Father Chrysostomos via RT <perlbug-followup@perl.org> wrote: Show quoted text
> Well, it is certainly interesting. The first one stops abruptly at the buffer overflow. Presumably it crashed because of the bug that 05d7009fff fixed. The second one shows definitely buggy output. > > When the overflow happens, nextval overflows into nexttype and nexttype overflows into nexttoke. Since nexttoke is an offset into the nexttype and nextval arrays, it is possible to read ahead into save_curcop, which is a memory address. That would explain why the bug is intermittent. > > I suspect this bug is *old* and predates -DT output. >
Yeah. Thanks for the explanations. I'm done digging I think :) -- Matthew Horsfall (alh)
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