Skip to content

Commit

Permalink
don't segfault given string repeat count larger than 2^31
Browse files Browse the repository at this point in the history
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"
  • Loading branch information
meyering authored and Father Chrysostomos committed Oct 23, 2011
1 parent dd8fc02 commit 26e1303
Show file tree
Hide file tree
Showing 3 changed files with 6 additions and 6 deletions.
2 changes: 1 addition & 1 deletion embed.fnc
Expand Up @@ -1066,7 +1066,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
Expand Down
2 changes: 1 addition & 1 deletion proto.h
Expand Up @@ -3244,7 +3244,7 @@ PERL_CALLCONV void Perl_regprop(pTHX_ const regexp *prog, SV* sv, const regnode*
#define PERL_ARGS_ASSERT_REGPROP \
assert(sv); assert(o)

PERL_CALLCONV void Perl_repeatcpy(char* to, const char* from, I32 len, I32 count)
PERL_CALLCONV void Perl_repeatcpy(char* to, const char* from, I32 len, IV count)
__attribute__nonnull__(1)
__attribute__nonnull__(2);
#define PERL_ARGS_ASSERT_REPEATCPY \
Expand Down
8 changes: 4 additions & 4 deletions util.c
Expand Up @@ -3404,27 +3404,27 @@ 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;

if (len == 1)
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;
Expand Down

0 comments on commit 26e1303

Please sign in to comment.