Discussion:
[perl #125781] Segmentation fault in Perl 5.23.2 while fuzzing Perl binary
Tony Cook via RT
2015-08-11 06:13:43 UTC
Permalink
While fuzzing the blead Perl binary (as a learning exercise), I found
a testcase that causes a segfault under -Duse64bitint but which works
fine (exits with an error but without receiving a fatal signal)
without 64bitint. Perl -V, Valgrind, and GDB output are below. The
f$x 1...888888888888888
g
0000000 66 24 78 20 20 31 2e 2e 2e 38 38 38 38 38 38 38
0000020 38 38 38 38 38 38 38 38 0a 67 0a
0000033
f$0 1..880000000000000g
0000000 66 24 30 20 31 2e 2e 38 38 30 30 30 30 30 30 30
0000020 30 30 30 30 30 30 67
0000027
The attached fixes both of these for me.

Tony

---
via perlbug: queue: perl5 status: new
https://rt.perl.org/Ticket/Display.html?id=125781
Dan Collins (via RT)
2015-08-10 14:48:20 UTC
Permalink
# New Ticket Created by Dan Collins
# Please include the string: [perl #125781]
# in the subject line of all future correspondence about this issue.
# <URL: https://rt.perl.org/Ticket/Display.html?id=125781 >


While fuzzing the blead Perl binary (as a learning exercise), I found a testcase that causes a segfault under -Duse64bitint but which works fine (exits with an error but without receiving a fatal signal) without 64bitint. Perl -V, Valgrind, and GDB output are below. The original testcase reads:

f$x 1...888888888888888
g

hexdump:
0000000 66 24 78 20 20 31 2e 2e 2e 38 38 38 38 38 38 38
0000020 38 38 38 38 38 38 38 38 0a 67 0a
0000033

A reduced version of this testcase reads:

f$0 1..880000000000000g

hexdump:
0000000 66 24 30 20 31 2e 2e 38 38 30 30 30 30 30 30 30
0000020 30 30 30 30 30 30 67
0000027

Miniperl simply hangs under this testcase. A git bisect revealed that under old versions of Perl, this resulted in a hang. The hang changed to "Killed" at:
ef00320bc9879f8f099601e89cecb3a191f372f6 is the first bad commit
commit ef00320bc9879f8f099601e89cecb3a191f372f6
Author: Father Chrysostomos <***@cpan.org>
Date: Thu Oct 9 20:32:58 2014 -0700

op.c:allocmy: Don’t depend on null termination

This function has a len argument, but still depends on its argument’s
being null-terminated in one spot. (All other parts of the function
use the length.)

:100644 100644 d54651bacf6748b59d4c76645aa3019191f00158 0f646ed853fdfb519512c85fc3d5839dd6e237b5 M op.c

This may just be an out-of-memory condition, I can't actually find the first segfault right now, however it is definitely segfaulting in:
commit a953aca586d48d6f0b2c4db3572de328ed6d85e8
Author: Daniel Dragan <***@hotmail.com>
Date: Fri Oct 10 13:29:33 2014 -0400

optimize & rmv from public API Perl_tmps_grow and related code

Previously in PUSH_EXTEND_MORTAL__SV_C, "PL_tmps_ix + 1" would execute
twice, once for the nonmutable if(>=), then again after the potential
tmps_grow call. tmps_grow has an unused return register/void proto, put it
to use by returning ix. Also change tmps_grow to take the result of
"PL_tmps_ix + the constant (usually 1) or non-constant (EXTEND_MORTAL)".
This avoid having to put the constant twice in machine code, once for the
if test, 2nd time for extend length param for tmps_grow call. For
non-constant/EXTEND_MORTAL usage, it allows the C optimizer to have the
length var to go out of liveness sooner if possible. Also the var used for
the if(>=) test is more likely to be in a register than length var.
So "if test variable" is closer on hand to the CPU than length var. In some
cases, if non-const len var isn't used again, it becomes the "ix" variable
by having PL_tmps_ix added to it. Change sv_2mortal to return sv instead
of NULL to remove a unique branch/block of machine code that assigns 0 to
return variable (Visual C didn't figure out return sv == returned NULL,
not sv). See also [perl #121845].


Summary of my perl5 (revision 5 version 23 subversion 2) configuration:
Commit id: 749f0eb1485a7bb7561d71f9539d9b7655363136
Platform:
osname=linux, osvers=2.6.32-5-686, archname=i686-linux-thread-multi-ld-64int
uname='linux nagios 2.6.32-5-686 #1 smp tue may 13 16:33:32 utc 2014 i686 gnulinux '
config_args=''
hint=previous, useposix=true, d_sigaction=define
useithreads=undef, usemultiplicity=define
use64bitint=define, use64bitall=undef, uselongdouble=define
usemymalloc=n, bincompat5005=undef
Compiler:
cc='afl-gcc', ccflags ='-D_REENTRANT -D_GNU_SOURCE -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='-D_REENTRANT -D_GNU_SOURCE -fwrapv -fno-strict-aliasing -pipe -fstack-protector -I/usr/local/include -D_REENTRANT -D_GNU_SOURCE -fwrapv -fno-strict-aliasing -pipe -fstack-protector -I/usr/local/include -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64 -D_FORTIFY_SOURCE=2'
ccversion='', gccversion='4.4.5', 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 -L/usr/local/lib'
libpth=/usr/local/lib /usr/lib/gcc/i486-linux-gnu/4.4.5/include-fixed /usr/lib /lib/../lib /usr/lib/../lib /lib /usr/lib/i486-linux-gnu /usr/lib64 /usr/local/lib /usr/lib/gcc/i486-linux-gnu/4.4.5/include-fixed /usr/lib
libs=-lpthread -lnsl -ldl -lm -lcrypt -lutil -lc
perllibs=-lpthread -lnsl -ldl -lm -lcrypt -lutil -lc
libc=libc-2.11.3.so, so=so, useshrplib=false, libperl=libperl.a
gnulibc_version='2.11.3'
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'


Characteristics of this binary (from libperl):
Compile-time options: HAS_TIMES MULTIPLICITY PERLIO_LAYERS
PERL_COPY_ON_WRITE PERL_DONT_CREATE_GVSV
PERL_HASH_FUNC_ONE_AT_A_TIME_HARD
PERL_IMPLICIT_CONTEXT PERL_MALLOC_WRAP
PERL_PRESERVE_IVUV 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 Aug 7 2015 19:24:52
@INC:
/usr/local/perl-afl/lib/site_perl/5.23.2/i686-linux-thread-multi-ld
/usr/local/perl-afl/lib/site_perl/5.23.2
/usr/local/perl-afl/lib/5.23.2/i686-linux-thread-multi-ld
/usr/local/perl-afl/lib/5.23.2
.


***VALGRIND OUTPUT***
==10717== Memcheck, a memory error detector
==10717== Copyright (C) 2002-2010, and GNU GPL'd, by Julian Seward et al.
==10717== Using Valgrind-3.6.0.SVN-Debian and LibVEX; rerun with -h for copyright info
==10717== Command: ../../bin/perl 000000_min.pl
==10717==
Bareword found where operator expected at 000000_min.pl line 1, near "880000000000000g"
(Missing operator before g?)
==10717== Invalid write of size 4
==10717== at 0x84D4ACD: Perl_pp_flop (pp_ctl.c:1221)
==10717== by 0x836459F: Perl_runops_standard (run.c:41)
==10717== by 0x80AF547: Perl_list (op.c:4420)
==10717== by 0x80AF8CB: Perl_ck_entersub_args_list (op.c:11321)
==10717== by 0x80B0842: Perl_ck_subr (op.c:11911)
==10717== by 0x80C84C5: Perl_op_convert_list (op.c:4605)
==10717== by 0x81D71D5: Perl_yyparse (perly.y:707)
==10717== by 0x810FE82: S_parse_body (perl.c:2296)
==10717== by 0x81131DE: perl_parse (perl.c:1626)
==10717== by 0x806217C: main (perlmain.c:114)
==10717== Address 0x42179d0 is 0 bytes after a block of size 512 alloc'd
==10717== at 0x4023F50: malloc (vg_replace_malloc.c:236)
==10717== by 0x82CC357: Perl_safesysmalloc (util.c:149)
==10717== by 0x835BB89: Perl_av_extend_guts (av.c:182)
==10717== by 0x835BD6D: Perl_av_extend (av.c:80)
==10717== by 0x8473F0F: Perl_new_stackinfo (scope.c:56)
==10717== by 0x80F3D8C: Perl_init_stacks (perl.c:4055)
==10717== by 0x80F63E0: perl_construct (perl.c:249)
==10717== by 0x80623BF: main (perlmain.c:110)
==10717==
--10717-- VALGRIND INTERNAL ERROR: Valgrind received a signal 11 (SIGSEGV) - exiting
--10717-- si_code=1; Faulting address: 0x65736165; sp: 0x62db7a38

valgrind: the 'impossible' happened:
Killed by fatal signal
==10717== at 0x3809DE01: myvprintf_str (m_debuglog.c:530)
==10717== by 0x3809E5E2: vgPlain_debugLog_vprintf (m_debuglog.c:877)
==10717== by 0x380297F5: vprintf_WRK (m_libcprint.c:111)
==10717== by 0x380298B7: vgPlain_printf (m_libcprint.c:143)
==10717== by 0x38027966: vgPlain_assert_fail (m_libcassert.c:259)
==10717== by 0x61206F66: ???

sched status:
running_tid=1

Thread 1: status = VgTs_Runnable
==10717== at 0x4024046: realloc (vg_replace_malloc.c:525)
==10717== by 0x82CCE03: Perl_safesysrealloc (util.c:270)
==10717== by 0x84713A9: Perl_tmps_grow_p (scope.c:161)
==10717== by 0x839A16F: Perl_sv_2mortal (sv.c:8979)
==10717== by 0x84D4AC1: Perl_pp_flop (pp_ctl.c:1220)
==10717== by 0x836459F: Perl_runops_standard (run.c:41)
==10717== by 0x80AF547: Perl_list (op.c:4420)
==10717== by 0x80AF8CB: Perl_ck_entersub_args_list (op.c:11321)
==10717== by 0x80B0842: Perl_ck_subr (op.c:11911)
==10717== by 0x80C84C5: Perl_op_convert_list (op.c:4605)
==10717== by 0x81D71D5: Perl_yyparse (perly.y:707)
==10717== by 0x810FE82: S_parse_body (perl.c:2296)
==10717== by 0x81131DE: perl_parse (perl.c:1626)
==10717== by 0x806217C: main (perlmain.c:114)

***GDB OUTPUT***
(gdb) run
Starting program: /usr/local/perl-afl/bin/perl 000000_min.pl
[Thread debugging using libthread_db enabled]
Bareword found where operator expected at 000000_min.pl line 1, near "880000000000000g"
(Missing operator before g?)

Program received signal SIGSEGV, Segmentation fault.
0xb7e65a59 in _int_malloc (av=<value optimized out>,
bytes=<value optimized out>) at malloc.c:4534
4534 malloc.c: No such file or directory.
in malloc.c
(gdb) bt
#0 0xb7e65a59 in _int_malloc (av=<value optimized out>,
bytes=<value optimized out>) at malloc.c:4534
#1 0xb7e6797c in *__GI___libc_malloc (bytes=4080) at malloc.c:3661
#2 0x082cc358 in Perl_safesysmalloc (size=4080) at util.c:149
#3 0x08397ee0 in S_more_sv (my_perl=0x8734008) at sv.c:304
#4 0x083d5a57 in Perl_newSViv (my_perl=0x8734008, i=20388) at sv.c:9252
#5 0x084d4ab3 in Perl_pp_flop (my_perl=0x8734008) at pp_ctl.c:1220
#6 0x083645a0 in Perl_runops_standard (my_perl=0x8734008) at run.c:41
#7 0x080af548 in S_gen_constant_list (my_perl=0x8734008, o=0x8750754)
at op.c:4420
#8 Perl_list (my_perl=0x8734008, o=0x8750754) at op.c:2215
#9 0x080af8cc in Perl_ck_entersub_args_list (my_perl=0x8734008,
entersubop=0x875070c) at op.c:11321
#10 0x080b0843 in Perl_ck_subr (my_perl=0x8734008, o=0x875070c) at op.c:11911
#11 0x080c84c6 in Perl_op_convert_list (my_perl=0x8734008, type=185, flags=0,
o=0x1) at op.c:4605
#12 0x081d71d6 in Perl_yyparse (my_perl=0x8734008, gramtype=258) at perly.y:707
#13 0x0810fe83 in S_parse_body (my_perl=0x8734008, env=<value optimized out>,
xsinit=<value optimized out>) at perl.c:2296
#14 0x081131df in perl_parse (my_perl=0x8734008, xsinit=0x8062430 <xs_init>,
argc=2, argv=0xbffff7e4, env=0x0) at perl.c:1626
#15 0x0806217d in main (argc=2, argv=0xbffff7e4, env=0xbffff7f0)
at perlmain.c:114

Loading...