Skip to content

Commit f24623d

Browse files
hvdskhwilliamson
authored andcommitted
GH16319: avoid recursion parsing 'pack' template
A template with many open brackets or open parentheses could overflow the stack, modify the parsing loop to avoid that.
1 parent dae8ab8 commit f24623d

File tree

3 files changed

+26
-8
lines changed

3 files changed

+26
-8
lines changed

pod/perldiag.pod

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3704,6 +3704,11 @@ See L</500 Server error>.
37043704
by a missing delimiter on a string or pattern, because it eventually
37053705
ended earlier on the current line.
37063706

3707+
=item Mismatched brackets in template
3708+
3709+
(F) A pack template could not be parsed because pairs of C<[...]> or
3710+
C<(...)> could not be matched up. See L<perlfunc/pack>.
3711+
37073712
=item Misplaced _ in number
37083713

37093714
(W syntax) An underscore (underbar) in a numeric constant did not

pp_pack.c

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -541,22 +541,24 @@ STATIC const char *
541541
S_group_end(pTHX_ const char *patptr, const char *patend, char ender)
542542
{
543543
PERL_ARGS_ASSERT_GROUP_END;
544+
Size_t opened = 0; /* number of pending opened brackets */
544545

545546
while (patptr < patend) {
546547
const char c = *patptr++;
547548

548-
if (isSPACE(c))
549-
continue;
550-
else if (c == ender)
549+
if (opened == 0 && c == ender)
551550
return patptr-1;
552551
else if (c == '#') {
553552
while (patptr < patend && *patptr != '\n')
554553
patptr++;
555554
continue;
556-
} else if (c == '(')
557-
patptr = group_end(patptr, patend, ')') + 1;
558-
else if (c == '[')
559-
patptr = group_end(patptr, patend, ']') + 1;
555+
} else if (c == '(' || c == '[')
556+
++opened;
557+
else if (c == ')' || c == ']') {
558+
if (opened == 0)
559+
Perl_croak(aTHX_ "Mismatched brackets in template");
560+
--opened;
561+
}
560562
}
561563
Perl_croak(aTHX_ "No group ending character '%c' found in template",
562564
ender);

t/op/pack.t

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ BEGIN {
66
set_up_inc(qw '../lib ../cpan/Math-BigInt/lib');
77
}
88

9-
plan tests => 14720;
9+
plan tests => 14722;
1010

1111
use strict;
1212
use warnings qw(FATAL all);
@@ -2044,3 +2044,14 @@ SKIP:
20442044
fresh_perl_is('0.0 + unpack("u", "ab")', "", { stderr => 1 },
20452045
"ensure unpack u of invalid data nul terminates result");
20462046
}
2047+
2048+
{
2049+
# [GH #16319] SEGV caused by recursion
2050+
my $x = eval { pack "[" x 1_000_000 };
2051+
like("$@", qr{No group ending character \Q']'\E found in template},
2052+
"many opening brackets should not smash the stack");
2053+
2054+
$x = eval { pack "[(][)]" };
2055+
like("$@", qr{Mismatched brackets in template},
2056+
"should match brackets correctly even without recursion");
2057+
}

0 commit comments

Comments
 (0)