Skip to content
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

null ptr deref -> bcmp (mc_replace_strmem.c:889) | S_scan_doc: Assertion 's' failed (toke.c:9314) #14789

Closed
p5pRT opened this issue Jul 3, 2015 · 14 comments

Comments

@p5pRT
Copy link

p5pRT commented Jul 3, 2015

Migrated from rt.perl.org#125540 (status was 'resolved')

Searchable as RT125540$

@p5pRT
Copy link
Author

p5pRT commented Jul 3, 2015

From @geeknik

While fuzzing Perl built from git source (v5.23.0-69-gf907dd3), I came across the following "script" that causes an assertion failure at toke.c​:9314​:

geeknik@​h5n2​:~$ ~/perl/perl test03-min
$# is no longer supported at test03-min line 1.
Use of bare << to mean <<"" is deprecated at test03-min line 1.
perl​: toke.c​:9314​: S_scan_heredoc​: Assertion `s' failed.
Aborted

It also causes Perl v5.21.6-602-ge9d2bd8 to segfault at mc_replace_strmem.c​:889​:

$# is no longer supported at test03-min line 1.
Use of bare << to mean <<"" is deprecated at test03-min line 1.
==54432== Invalid read of size 1
==54432== at 0x4C2B0B9​: bcmp (mc_replace_strmem.c​:889)
==54432== by 0x58CC9E​: Perl_yylex (toke.c​:9259)
==54432== by 0x5C60B4​: Perl_yyparse (perly.c​:322)
==54432== by 0x4F0874​: perl_parse (perl.c​:2271)
==54432== by 0x42A87B​: main (perlmain.c​:114)
==54432== Address 0x0 is not stack'd, malloc'd or (recently) free'd
==54432==
==54432==
==54432== Process terminating with default action of signal 11 (SIGSEGV)
==54432== Access not within mapped region at address 0x0
==54432== at 0x4C2B0B9​: bcmp (mc_replace_strmem.c​:889)
==54432== by 0x58CC9E​: Perl_yylex (toke.c​:9259)
==54432== by 0x5C60B4​: Perl_yyparse (perly.c​:322)
==54432== by 0x4F0874​: perl_parse (perl.c​:2271)
==54432== by 0x42A87B​: main (perlmain.c​:114)
==54432== If you believe this happened as a result of a stack
==54432== overflow in your program's main thread (unlikely but
==54432== possible), you can try to increase the size of the
==54432== main thread stack using the --main-stacksize= flag.
==54432== The main thread stack size used in this run was 8388608.
Segmentation fault

$# is no longer supported at test03-min line 1.
Use of bare << to mean <<"" is deprecated at test03-min line 1.

Program received signal SIGSEGV, Segmentation fault.
__memcmp_sse4_1 () at ../sysdeps/x86_64/multiarch/memcmp-sse4.S​:936
936 ../sysdeps/x86_64/multiarch/memcmp-sse4.S​: No such file or directory.
(gdb) bt
#0 __memcmp_sse4_1 () at ../sysdeps/x86_64/multiarch/memcmp-sse4.S​:936
#1 0x000000000058cc9f in S_scan_heredoc (s=0x0) at toke.c​:9259
#2 Perl_yylex () at toke.c​:5876
#3 0x00000000005c60b5 in Perl_yyparse (gramtype=<optimized out>) at perly.c​:322
#4 0x00000000004f0875 in S_parse_body (xsinit=0x42ac70 <xs_init>, env=0x0) at perl.c​:2271
#5 perl_parse (my_perl=<optimized out>, xsinit=0x42ac70 <xs_init>, argc=<optimized out>,
  argv=<optimized out>, env=0x0) at perl.c​:1605
#6 0x000000000042a87c in main (argc=2, argv=0x7fffffffe3a8, env=0x7fffffffe3c0) at perlmain.c​:114
#7 0x00007ffff6f98ead 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=0x7fffffffe398) at libc-start.c​:244
#8 0x000000000042ab95 in _start ()
(gdb) i r
rax 0xe4205b 14950491
rbx 0xe4205b 14950491
rcx 0xa0a 2570
rdx 0x2 2
rsi 0xe4300a 14954506
rdi 0x2 2
rbp 0xe42020 0xe42020
rsp 0x7fffffffd938 0x7fffffffd938
r8 0xe3fd60 14941536
r9 0x3 3
r10 0xe26f30 14839600
r11 0x7ffff70d03f0 140737338213360
r12 0xe3aff8 14921720
r13 0xe42eb0 14954160
r14 0x0 0
r15 0x0 0
rip 0x7ffff70b00b2 0x7ffff70b00b2 <__memcmp_sse4_1+3522>
eflags 0x10203 [ CF IF RF ]
cs 0x33 51
ss 0x2b 43
ds 0x0 0
es 0x0 0
fs 0x0 0
gs 0x0 0

@p5pRT
Copy link
Author

p5pRT commented Jul 3, 2015

From @geeknik

test03-min

@p5pRT
Copy link
Author

p5pRT commented Dec 5, 2015

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' -Duselongdouble -Duse64bitall -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 performing additional minimization by hand, I have located the following testcase that triggers a segfault in the Perl interpreter. The testcase is the attached file​:

$ od -c out/allcrash/f2i000048
0000000 - r \v d $ # < < < <
0000012

When executed, this prints the following​:
dcollins@​nightshade64​:~$ ./perl/perl f2i000048
$# is no longer supported at f2i000048 line 1.
Use of bare << to mean <<"" is deprecated at f2i000048 line 1.
Segmentation fault
dcollins@​nightshade64​:~$ ./perldebug/perl f2i000048
$# is no longer supported at f2i000048 line 1.
Use of bare << to mean <<"" is deprecated at f2i000048 line 1.
perl​: toke.c​:9575​: S_scan_heredoc​: Assertion `s' failed.
Aborted

**GDB**

(gdb) run
Starting program​: /home/dcollins/perl/perl f2i000048
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/lib/x86_64-linux-gnu/libthread_db.so.1".
$# is no longer supported at f2i000048 line 1.
Use of bare << to mean <<"" is deprecated at f2i000048 line 1.

Program received signal SIGSEGV, Segmentation fault.
0x00007ffff6e04f42 in ?? () from /lib/x86_64-linux-gnu/libc.so.6
(gdb) bt
#0 0x00007ffff6e04f42 in ?? () from /lib/x86_64-linux-gnu/libc.so.6
#1 0x0000000000598534 in S_scan_heredoc (s=0x0) at toke.c​:9581
#2 Perl_yylex () at toke.c​:6134
#3 0x00000000005b7d35 in Perl_yyparse (gramtype=gramtype@​entry=258) at perly.c​:322
#4 0x00000000004e78cd in S_parse_body (xsinit=0x4274e0 <xs_init>, env=0x0) at perl.c​:2312
#5 perl_parse (my_perl=<optimized out>, xsinit=xsinit@​entry=0x4274e0 <xs_init>, argc=<optimized out>, argv=<optimized out>, env=env@​entry=0x0) at perl.c​:1634
#6 0x0000000000427108 in main (argc=2, argv=0x7fffffffe358, env=0x7fffffffe370) at perlmain.c​:114
(gdb) f 1
#1 0x0000000000598534 in S_scan_heredoc (s=0x0) at toke.c​:9581
9581 && memNE(s,PL_tokenbuf,len) )
(gdb) info locals
linestr = 0xe65d08
bufend = 0xe6e25b ""
olds = 0xe6e25a ";"
cx = 0xe53dd8
term = <optimized out>
d = 0x0
peek = <optimized out>
origline = 1
tmpstr = 0xe65dc8
e = <optimized out>
infile = <optimized out>
shared = 0xe6e220
op_type = 2
len = 2

**VALGRIND**

==14515== Memcheck, a memory error detector
==14515== Copyright (C) 2002-2015, and GNU GPL'd, by Julian Seward et al.
==14515== Using Valgrind-3.11.0 and LibVEX; rerun with -h for copyright info
==14515== Command​: ./perl/perl f2i000048
==14515==
$# is no longer supported at f2i000048 line 1.
Use of bare << to mean <<"" is deprecated at f2i000048 line 1.
==14515== Invalid read of size 1
==14515== at 0x4C2D8B5​: __memcmp_sse4_1 (vg_replace_strmem.c​:1094)
==14515== by 0x598533​: S_scan_heredoc (toke.c​:9581)
==14515== by 0x598533​: Perl_yylex (toke.c​:6134)
==14515== by 0x5B7D34​: Perl_yyparse (perly.c​:322)
==14515== by 0x4E78CC​: S_parse_body (perl.c​:2312)
==14515== by 0x4E78CC​: perl_parse (perl.c​:1634)
==14515== by 0x427107​: main (perlmain.c​:114)
==14515== Address 0x0 is not stack'd, malloc'd or (recently) free'd
==14515==
==14515==
==14515== Process terminating with default action of signal 11 (SIGSEGV)
==14515== Access not within mapped region at address 0x0
==14515== at 0x4C2D8B5​: __memcmp_sse4_1 (vg_replace_strmem.c​:1094)
==14515== by 0x598533​: S_scan_heredoc (toke.c​:9581)
==14515== by 0x598533​: Perl_yylex (toke.c​:6134)
==14515== by 0x5B7D34​: Perl_yyparse (perly.c​:322)
==14515== by 0x4E78CC​: S_parse_body (perl.c​:2312)
==14515== by 0x4E78CC​: perl_parse (perl.c​:1634)
==14515== by 0x427107​: main (perlmain.c​:114)
==14515== If you believe this happened as a result of a stack
==14515== overflow in your program's main thread (unlikely but
==14515== possible), you can try to increase the size of the
==14515== main thread stack using the --main-stacksize= flag.
==14515== The main thread stack size used in this run was 8388608.
==14515==
==14515== HEAP SUMMARY​:
==14515== in use at exit​: 126,829 bytes in 646 blocks
==14515== total heap usage​: 739 allocs, 93 frees, 143,644 bytes allocated
==14515==
==14515== LEAK SUMMARY​:
==14515== definitely lost​: 328 bytes in 1 blocks
==14515== indirectly lost​: 2,617 bytes in 39 blocks
==14515== possibly lost​: 0 bytes in 0 blocks
==14515== still reachable​: 123,884 bytes in 606 blocks
==14515== suppressed​: 0 bytes in 0 blocks
==14515== Rerun with --leak-check=full to see details of leaked memory
==14515==
==14515== For counts of detected and suppressed errors, rerun with​: -v
==14515== ERROR SUMMARY​: 1 errors from 1 contexts (suppressed​: 0 from 0)
Segmentation fault

**PERL -V**

Summary of my perl5 (revision 5 version 23 subversion 6) configuration​:
  Commit id​: 572cd85
  Platform​:
  osname=linux, osvers=3.16.0-4-amd64, archname=x86_64-linux-ld
  uname='linux nightshade64 3.16.0-4-amd64 #1 smp debian 3.16.7-ckt11-1+deb8u4 (2015-09-19) x86_64 gnulinux '
  config_args='-Dusedevel -Dprefix=/usr/local/perl-afl -Dcc=ccache afl-gcc -Duselongdouble -Duse64bitall -Doptimize=-g -Uversiononly -Uman1dir -Uman3dir -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 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=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 afl-gcc', ldflags =' -fstack-protector-strong -L/usr/local/lib'
  libpth=/usr/local/lib /usr/local/lib/gcc/x86_64-unknown-linux-gnu/5.2.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.19.so, so=so, useshrplib=false, libperl=libperl.a
  gnulibc_version='2.19'
  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_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 Dec 4 2015 16​:50​:14
  @​INC​:
  perl/lib
  /usr/local/perl-afl/lib/site_perl/5.23.6/x86_64-linux-ld
  /usr/local/perl-afl/lib/site_perl/5.23.6
  /usr/local/perl-afl/lib/5.23.6/x86_64-linux-ld
  /usr/local/perl-afl/lib/5.23.6
  /usr/local/perl-afl/lib/site_perl/5.23.5
  /usr/local/perl-afl/lib/site_perl/5.23.4
  /usr/local/perl-afl/lib/site_perl
  .

@p5pRT
Copy link
Author

p5pRT commented Dec 5, 2015

From @dcollinsn

f2i000048

@p5pRT
Copy link
Author

p5pRT commented Dec 5, 2015

From @geeknik

Maybe a dupe of 125540?

@p5pRT
Copy link
Author

p5pRT commented Dec 5, 2015

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

@p5pRT
Copy link
Author

p5pRT commented Jan 20, 2016

From @tonycoz

On Fri Jul 03 09​:57​:24 2015, brian.carpenter@​gmail.com wrote​:

While fuzzing Perl built from git source (v5.23.0-69-gf907dd3), I came
across the following "script" that causes an assertion failure at
toke.c​:9314​:

geeknik@​h5n2​:~$ ~/perl/perl test03-min
$# is no longer supported at test03-min line 1.
Use of bare << to mean <<"" is deprecated at test03-min line 1.
perl​: toke.c​:9314​: S_scan_heredoc​: Assertion `s' failed.
Aborted

The attached should fix this.

Tony

@p5pRT
Copy link
Author

p5pRT commented Jan 20, 2016

From @tonycoz

0001-perl-125540-handle-already-being-at-EOF-while-not-fi.patch
From 87ee70413aa5b8f8c6ebeea5d0e3f9fe6a8300f1 Mon Sep 17 00:00:00 2001
From: Tony Cook <tony@develop-help.com>
Date: Wed, 20 Jan 2016 15:35:13 +1100
Subject: [perl #125540] handle already being at EOF while not finding a
 heredoc terminator

In some cases, S_scan_heredoc() can already be at end of file and
PL_rsfp is NULL.  If we're on the final line and that line has no
newline we'd assert or crash.

Now, if we don't find that newline, we obviously can't find the
terminator, so go straight to reporting the missing terminator.

I considered setting s to PL_bufend, but that would just be more
work to print the same message.
---
 t/op/heredoc.t | 10 +++++++++-
 toke.c         |  5 +++--
 2 files changed, 12 insertions(+), 3 deletions(-)

diff --git a/t/op/heredoc.t b/t/op/heredoc.t
index dadf105..8fe0c0f 100644
--- a/t/op/heredoc.t
+++ b/t/op/heredoc.t
@@ -7,7 +7,7 @@ BEGIN {
 }
 
 use strict;
-plan(tests => 40);
+plan(tests => 41);
 
 
 # heredoc without newline (#65838)
@@ -98,4 +98,12 @@ HEREDOC
         {},
         "don't use an invalid oldoldbufptr"
     );
+
+    # [perl #125540] this asserted or crashed
+    fresh_perl_like(
+	q(map d$#<<<<),
+	qr/Can't find string terminator "" anywhere before EOF at - line 1\./,
+	{},
+	"Don't assert parsing a here-doc if we hit EOF early"
+    );
 }
diff --git a/toke.c b/toke.c
index 23c3521..d1c3b23 100644
--- a/toke.c
+++ b/toke.c
@@ -9577,9 +9577,10 @@ S_scan_heredoc(pTHX_ char *s)
 		goto streaming;
 	    }
 	  }
-	else {	/* eval */
+	else {	/* eval or we've already hit EOF */
 	    s = (char*)memchr((void*)s, '\n', PL_bufend - s);
-	    assert(s);
+	    if (!s)
+                goto interminable;
 	}
 	linestr = shared->ls_linestr;
 	bufend = SvEND(linestr);
-- 
2.1.4

@p5pRT
Copy link
Author

p5pRT commented Jan 20, 2016

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

@p5pRT
Copy link
Author

p5pRT commented Feb 3, 2016

From @tonycoz

On Tue Jan 19 20​:36​:15 2016, tonyc wrote​:

On Fri Jul 03 09​:57​:24 2015, brian.carpenter@​gmail.com wrote​:

While fuzzing Perl built from git source (v5.23.0-69-gf907dd3), I came
across the following "script" that causes an assertion failure at
toke.c​:9314​:

geeknik@​h5n2​:~$ ~/perl/perl test03-min
$# is no longer supported at test03-min line 1.
Use of bare << to mean <<"" is deprecated at test03-min line 1.
perl​: toke.c​:9314​: S_scan_heredoc​: Assertion `s' failed.
Aborted

The attached should fix this.

Applied to blead as 23c4e91.

Tony

@p5pRT
Copy link
Author

p5pRT commented Feb 3, 2016

@tonycoz - Status changed from 'open' to 'pending release'

@p5pRT
Copy link
Author

p5pRT commented Feb 3, 2016

From @tonycoz

On Sat Dec 05 01​:36​:33 2015, brian.carpenter@​gmail.com wrote​:

Maybe a dupe of 125540?

Yes, it's a duplicate, the fix for 125540 fixes this.

Tony

@p5pRT
Copy link
Author

p5pRT commented May 13, 2016

From @khwilliamson

Thank you for submitting this report. You have helped make Perl better.
 
With the release of Perl 5.24.0 on May 9, 2016, this and 149 other issues have been resolved.

Perl 5.24.0 may be downloaded via https://metacpan.org/release/RJBS/perl-5.24.0

@p5pRT p5pRT closed this as completed May 13, 2016
@p5pRT
Copy link
Author

p5pRT commented May 13, 2016

@khwilliamson - Status changed from 'pending release' to 'resolved'

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

1 participant