develooper Front page | perl.perl5.porters | Postings from September 2011

[perl #94560] [PATCH v5.12.4-1-gea42574] large repeat count causes heap corruption

Father Chrysostomos via RT
September 18, 2011 13:31
[perl #94560] [PATCH v5.12.4-1-gea42574] large repeat count causes heap corruption
Message ID:
On Mon Jul 11 11:47:03 2011, meyering wrote:
> I first noticed this using Fedora 15's perl-5.12.4-159.fc15.x86_64,
> but reproduced (below) using the latest built from git on the maint-
> 5.12
> branch.
> Using a large string repeat count makes perl overrun a heap buffer:
>   $ ./perl -le 'print "v"x(2**31+1)'
>   [Exit 139 (SEGV)]
> If you use an approx. doubled count (s/31/32), you can make Perl
> fail to initialize a 4GiB buffer and then proceed to write all of
> that uninitialized data to output:
>   $ ./perl -le 'print "v"x(2**32+1)' > out
>   ("out" starts with "v", and the following 4GiB are from
>   uninitialized heap)
> Why?  Because the caller of Perl_repeatcpy uses a type of IV
> for the "count" variable corresponding to our counts, while
> Perl_repeatcpy itself uses the narrower type of I32.
> When you pass "count - 1" to Perl_repeatcpy you get INT_MIN
> in the first case, and 0 in the second.
> Passing INT_MIN as the count here,
>     util.c:3037:	memset(to, *from, count);
> sign-extends to SIZE_MAX, and no one has that much memory,
> so the memset scribbles well beyond the "to" buffer.
> As for fixing it, I've included a patch that works for me, but it's
> probably not so simple.  I doubt you can so easily change a public API
> like Perl_repeatcpy, even if it's so fundamentally limited.  Besides,
> if you want to fix this, I suspect that this is just one manifestation
> of a larger problem.  For example, what if the string itself has
> length
> larger than INT_MAX?  Same problem, maybe, since the "len" parameter
> also has type I32.

See also <>.

> -- >8 --
> Subject: [PATCH] don't segfault given string repeat count larger than
> 2^31
> E.g., this overflows INT_MAX and overruns heap memory:
>     $ perl -le 'print "v"x(2**31+1)'
>     [Exit 139 (SEGV)]
> (Perl_repeatcpy): Use the same type for "count" as our sole
> callers in pp.c: IV (long), not I32 (int).  Otherwise, passing
> the wider value to a narrower "I32 count"

Why IV and not UV?  Should we perhaps introduce a new function with a
suffix (repeatcpy_uv), and make repeatcpy a macro that calls it with a
cast (since casting to a larger type should be safe)? Perl Programming lists via nntp and http.
Comments to Ask Bjørn Hansen at | Group listing | About