Blob Blame History Raw
From 647b6565b7d935eb9b92e057d0c7ae5fe54726e2 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Petr=20P=C3=ADsa=C5=99?= <ppisar@redhat.com>
Date: Thu, 6 Oct 2011 16:35:49 +0200
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"

    http://thread.gmane.org/gmane.comp.lang.perl.perl5.porters/96812
    https://rt.perl.org/rt3/Ticket/Display.html?id=94560

Original author: Jim Meyering <meyering@redhat.com>
Petr Pisar: Modify embed.fnc instead of generated proto.h
---
 embed.fnc |    2 +-
 util.c    |    8 ++++----
 2 files changed, 5 insertions(+), 5 deletions(-)

diff --git a/embed.fnc b/embed.fnc
index bce167e..8c86a3e 100644
--- a/embed.fnc
+++ b/embed.fnc
@@ -1032,7 +1032,7 @@ EXp	|SV*|reg_qr_package|NN REGEXP * const rx
 
 : FIXME - why the E?
 Ep	|void	|regprop	|NULLOK const regexp *prog|NN SV* sv|NN const regnode* o
-Anp	|void	|repeatcpy	|NN char* to|NN const char* from|I32 len|I32 count
+Anp	|void	|repeatcpy	|NN char* to|NN const char* from|I32 len|IV count
 AnpP	|char*	|rninstr	|NN const char* big|NN const char* bigend \
 				|NN const char* little|NN const char* lend
 Ap	|Sighandler_t|rsignal	|int i|Sighandler_t t
diff --git a/util.c b/util.c
index 0ea39c6..3d4dcc7 100644
--- a/util.c
+++ b/util.c
@@ -3315,7 +3315,7 @@ Perl_my_pclose(pTHX_ PerlIO *ptr)
 
 #define PERL_REPEATCPY_LINEAR 4
 void
-Perl_repeatcpy(register char *to, register const char *from, I32 len, register I32 count)
+Perl_repeatcpy(register char *to, register const char *from, I32 len, register IV count)
 {
     PERL_ARGS_ASSERT_REPEATCPY;
 
@@ -3323,19 +3323,19 @@ Perl_repeatcpy(register char *to, register const char *from, I32 len, register I
 	memset(to, *from, count);
     else if (count) {
 	register char *p = to;
-	I32 items, linear, half;
+	IV items, linear, half;
 
 	linear = count < PERL_REPEATCPY_LINEAR ? count : PERL_REPEATCPY_LINEAR;
 	for (items = 0; items < linear; ++items) {
 	    register const char *q = from;
-	    I32 todo;
+	    IV todo;
 	    for (todo = len; todo > 0; todo--)
 		*p++ = *q++;
         }
 
 	half = count / 2;
 	while (items <= half) {
-	    I32 size = items * len;
+	    IV size = items * len;
 	    memcpy(p, to, size);
 	    p     += size;
 	    items *= 2;
-- 
1.7.6.4