Repository navigation
Segmentation fault in pack (S_pack_rec tries to access unallocated memory) #14977
Description
Activity
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 testAnd 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 segmentation fault in the perl interpreter. The testcase is the file:
pack+WH200000,\0
Today I'm reporting a pair of bugs related to pack/unpack. They appeared to be related, but GDB shows that they have very different behaviours. This is by far the tamer of the two.
**GDB**
(gdb) run
Starting program: /usr/local/perl-afl/bin/perl -e pack+WH200000,\\0
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/lib/x86_64-linux-gnu/libthread_db.so.1".Program received signal SIGSEGV, Segmentation fault.
S_pack_rec (cat=0x0, cat@entry=0x1205af0, symptr=0x2fcc0, beglist=0x1,
beglist@entry=0x11f3a30, endlist=0x7ffff7e1d015, endlist@entry=0x11f3a38)
at pp_pack.c:2503
2503 } else if (isALPHA(*str))
(gdb) bt
#0 S_pack_rec (cat=0x0, cat@entry=0x1205af0, symptr=0x2fcc0, beglist=0x1,
beglist@entry=0x11f3a30, endlist=0x7ffff7e1d015, endlist@entry=0x11f3a38)
at pp_pack.c:2503
#1 0x0000000000eb2f5f in Perl_packlist (endlist=0x11f3a38,
beglist=0x11f3a30, patend=<optimized out>, pat=<optimized out>,
cat=0x1205af0) at pp_pack.c:1971
#2 Perl_pp_pack () at pp_pack.c:3128
#3 0x00000000007dec7f in Perl_runops_debug () at dump.c:2224
#4 0x0000000000544469 in S_run_body (oldscope=1) at perl.c:2456
#5 perl_run (my_perl=<optimized out>) at perl.c:2379
#6 0x000000000042c6f8 in main (argc=3, argv=0x7fffffffe648,
env=0x7fffffffe668) at perlmain.c:116
(gdb) info locals
str = 0xfeb000 <error: Cannot access memory at address 0xfeb000>
utf8_flags = 195775
fromlen = 0
howlen = e_number
lookahead = {patptr = 0x120e788 "", patend = 0x120e788 "", grpbeg = 0x0,
grpend = 0x0, code = 72, length = 200000, howlen = e_number, level = 0,
flags = 9, strbeg = 0, previous = 0x0}
utf8 = 207
__PRETTY_FUNCTION__ = "S_pack_rec"
(gdb) f 1
#1 0x0000000000eb2f5f in Perl_packlist (endlist=0x11f3a38,
beglist=0x11f3a30, patend=<optimized out>, pat=<optimized out>,
cat=0x1205af0) at pp_pack.c:1971
1971 (void)pack_rec( cat, &sym, beglist, endlist );
(gdb) info locals
sym = {patptr = 0x120e788 "", patend = 0x120e788 "", grpbeg = 0x0,
grpend = 0x0, code = 72, length = 200000, howlen = e_number, level = 0,
flags = 9, strbeg = 0, previous = 0x0}**VALGRIND**
==31388== Memcheck, a memory error detector
==31388== Copyright (C) 2002-2015, and GNU GPL'd, by Julian Seward et al.
==31388== Using Valgrind-3.11.0 and LibVEX; rerun with -h for copyright info
==31388== Command: ../bin/perl -e pack+WH200000,\\0
==31388==
==31388== Invalid read of size 1
==31388== at 0xEA3014: S_pack_rec (pp_pack.c:2503)
==31388== by 0xEB2F5E: Perl_packlist (pp_pack.c:1971)
==31388== by 0xEB2F5E: Perl_pp_pack (pp_pack.c:3128)
==31388== by 0x7DEC7E: Perl_runops_debug (dump.c:2224)
==31388== by 0x544468: S_run_body (perl.c:2456)
==31388== by 0x544468: perl_run (perl.c:2379)
==31388== by 0x42C6F7: main (perlmain.c:116)
==31388== Address 0xfeb000 is not stack'd, malloc'd or (recently) free'd
==31388==
==31388==
==31388== Process terminating with default action of signal 11 (SIGSEGV)
==31388== Access not within mapped region at address 0xFEB000
==31388== at 0xEA3014: S_pack_rec (pp_pack.c:2503)
==31388== by 0xEB2F5E: Perl_packlist (pp_pack.c:1971)
==31388== by 0xEB2F5E: Perl_pp_pack (pp_pack.c:3128)
==31388== by 0x7DEC7E: Perl_runops_debug (dump.c:2224)
==31388== by 0x544468: S_run_body (perl.c:2456)
==31388== by 0x544468: perl_run (perl.c:2379)
==31388== by 0x42C6F7: main (perlmain.c:116)
==31388== If you believe this happened as a result of a stack
==31388== overflow in your program's main thread (unlikely but
==31388== possible), you can try to increase the size of the
==31388== main thread stack using the --main-stacksize= flag.
==31388== The main thread stack size used in this run was 8388608.
==31388==
==31388== HEAP SUMMARY:
==31388== in use at exit: 310,063 bytes in 540 blocks
==31388== total heap usage: 639 allocs, 99 frees, 327,593 bytes allocated
==31388==
==31388== LEAK SUMMARY:
==31388== definitely lost: 176 bytes in 1 blocks
==31388== indirectly lost: 1,989 bytes in 20 blocks
==31388== possibly lost: 0 bytes in 0 blocks
==31388== still reachable: 307,898 bytes in 519 blocks
==31388== suppressed: 0 bytes in 0 blocks
==31388== Rerun with --leak-check=full to see details of leaked memory
==31388==
==31388== For counts of detected and suppressed errors, rerun with: -v
==31388== ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 0 from 0)
Segmentation fault**PERL -V**
Summary of my perl5 (revision 5 version 23 subversion 4) configuration:
Commit id: 94757bf
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 -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 afl-gcc', 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='4.9.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='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/lib/gcc/x86_64-linux-gnu/4.9/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: 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_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 Sep 30 2015 16:39:59
@INC:
/usr/local/perl-afl/lib/site_perl/5.23.4/x86_64-linux-ld
/usr/local/perl-afl/lib/site_perl/5.23.4
/usr/local/perl-afl/lib/5.23.4/x86_64-linux-ld
/usr/local/perl-afl/lib/5.23.4
.From @tonycoz
On Sun Oct 11 04:49:37 2015, dcollinsn@gmail.com wrote:
After reducing testcases using `afl-tmin` and performing additional
minimization by hand, I have located the following testcase that
triggers a segmentation fault in the perl interpreter. The testcase is
the file:pack+WH200000,\0
The attached seems to fix it.
I'm going to review the other pack handlers to check for similar issues.
Tony
From @tonycoz
0001-perl-126325-don-t-read-past-the-end-of-the-source-fo.patch
From 45f3993798e8339daceeb6b1a0ce606da9e8a613 Mon Sep 17 00:00:00 2001 From: Tony Cook <tony@develop-help.com> Date: Thu, 22 Oct 2015 12:03:05 +1100 Subject: [perl #126325] don't read past the end of the source for pack [Hh] With a utf8 target but a non-utf8 source, pack Hh would read past the end of the source when given a length, due to an incorrect condition. --- pp_pack.c | 2 +- t/op/pack.t | 22 +++++++++++++++++++++- 2 files changed, 22 insertions(+), 2 deletions(-) diff --git a/pp_pack.c b/pp_pack.c index 96dfd20..044ea7f 100644 --- a/pp_pack.c +++ b/pp_pack.c @@ -2488,7 +2488,7 @@ S_pack_rec(pTHX_ SV *cat, tempsym_t* symptr, SV **beglist, SV **endlist ) if (howlen == e_star) len = fromlen; field_len = (len+1)/2; GROWING(utf8, cat, start, cur, field_len); - if (!utf8 && len > (I32)fromlen) len = fromlen; + if (!utf8_source && len > (I32)fromlen) len = fromlen; bits = 0; l = 0; if (datumtype == 'H') diff --git a/t/op/pack.t b/t/op/pack.t index e348693..a2da636 100644 --- a/t/op/pack.t +++ b/t/op/pack.t @@ -12,7 +12,7 @@ my $no_endianness = $] > 5.009 ? '' : my $no_signedness = $] > 5.009 ? '' : "Signed/unsigned pack modifiers not available on this perl"; -plan tests => 14708; +plan tests => 14712; use strict; use warnings qw(FATAL all); @@ -2024,3 +2024,23 @@ is $o::num, 1, 'pack "c" does call num overloading'; #[perl #123874]: argument underflow leads to corrupt length eval q{ pack "pi/x" }; ok(1, "argument underflow did not crash"); + +{ + # [perl #126325] pack [hH] with a unicode string + # the hex encoders would read past the end of the string, using + # invalid source bytes + my $twenty_nuls = "\0" x 20; + # This is the case that failed + is(pack("WH40", 0x100, ""), "\x{100}$twenty_nuls", + "check pack H zero fills (utf8 target)"); + my $up_nul = "\0"; + + utf8::upgrade($up_nul); + # check the other combinations too + is(pack("WH40", 0x100, $up_nul), "\x{100}$twenty_nuls", + "check pack H zero fills (utf8 target/source)"); + is(pack("H40", ""), $twenty_nuls, + "check pack H zero fills (utf8 none)"); + is(pack("H40", $up_nul), $twenty_nuls, + "check pack H zero fills (utf8 source)"); +} -- 2.1.4
The RT System itself - Status changed from 'new' to 'open'
From @tonycoz
On Wed Oct 21 18:05:47 2015, tonyc wrote:
On Sun Oct 11 04:49:37 2015, dcollinsn@gmail.com wrote:
After reducing testcases using `afl-tmin` and performing additional
minimization by hand, I have located the following testcase that
triggers a segmentation fault in the perl interpreter. The testcase is
the file:pack+WH200000,\0
The attached seems to fix it.
Pushed as 0403a1a.
I'm going to review the other pack handlers to check for similar issues.
The others seemed ok to me.
Tony
@tonycoz - Status changed from 'open' to 'resolved'
Migrated from rt.perl.org#126325 (status was 'resolved')
Searchable as RT126325$