Join GitHub today
GitHub is home to over 40 million developers working together to host and review code, manage projects, and build software together.Sign up
Segmentation fault in Perl 5.23.2 while fuzzing Perl binary #14843
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:
A reduced version of this testcase reads:
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:
op.c:allocmy: Don’t depend on null termination
This function has a len argument, but still depends on its argument’s
: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:
optimize & rmv from public API Perl_tmps_grow and related code
Previously in PUSH_EXTEND_MORTAL__SV_C, "PL_tmps_ix + 1" would execute
Summary of my perl5 (revision 5 version 23 subversion 2) configuration:
Characteristics of this binary (from libperl):
valgrind: the 'impossible' happened:
Thread 1: status = VgTs_Runnable
Program received signal SIGSEGV, Segmentation fault.
On Mon Aug 10 07:48:19 2015, firstname.lastname@example.org wrote:
The attached fixes both of these for me.
From ea697ae3ebfc94d365efb0e69a56c9b4f3ac44c0 Mon Sep 17 00:00:00 2001 From: Tony Cook <email@example.com> Date: Tue, 11 Aug 2015 15:49:37 +1000 Subject: [perl #125781] handle range overflow when Size_t is smaller than IV --- pp_ctl.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/pp_ctl.c b/pp_ctl.c index cc6a55f..499e382 100644 --- a/pp_ctl.c +++ b/pp_ctl.c @@ -1206,7 +1206,11 @@ PP(pp_flop) /* The wraparound of signed integers is undefined * behavior, but here we aim for count >=1, and * negative count is just wrong. */ - if (n < 1) + if (n < 1 +#if IVSIZE > Size_t_size + || n > SSize_t_MAX +#endif + ) overflow = TRUE; } if (overflow) -- 2.5.0
On Mon Aug 10 23:13:43 2015, tonyc wrote:
Applied as a1e2717.