Skip to content

Commit 6ef7fe5

Browse files
committed
PATCH: [perl #131551] Too deep regex compilation recursion
This patch, started by Yves Orton, and refined in consultation with Tony Cook, imposes a maximum depth of unclosed left parentheses, at which point it croaks. This is to prevent the segfault in the ticket. The patch adds a variable that can be set to increase or decrease this limit at run time (actually regex compilation time) should this be desired, and hence our pre-determined limit of 1000 can be changed if necessary.
1 parent 3b89859 commit 6ef7fe5

File tree

5 files changed

+42
-0
lines changed

5 files changed

+42
-0
lines changed

pod/perldiag.pod

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6285,6 +6285,15 @@ The message attempts to include the name of the called subroutine. If the
62856285
subroutine has been aliased, the subroutine's original name will be shown,
62866286
regardless of what name the caller used.
62876287

6288+
=item Too many nested open parens in regex; marked by <-- HERE in m/%s/
6289+
6290+
(F) You have exceeded the number of open C<"("> parentheses that haven't
6291+
been matched by corresponding closing ones. This limit prevents eating
6292+
up too much memory. It is initially set to 1000, but may be changed by
6293+
setting C<${^RE_COMPILE_RECURSION_LIMIT}> to some other value. This may
6294+
need to be done in a BEGIN block before the regular expression pattern
6295+
is compiled.
6296+
62886297
=item Too many )'s
62896298

62906299
(A) You've accidentally run your script through B<csh> instead of Perl.

pod/perlvar.pod

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1249,6 +1249,17 @@ regular expression assertion (see L<perlre>). May be written to.
12491249

12501250
This variable was added in Perl 5.005.
12511251

1252+
=item ${^RE_COMPILE_RECURSION_LIMIT}
1253+
X<${^RE_COMPILE_RECURSION_LIMIT}>
1254+
1255+
The current value giving the maximum number of open but unclosed
1256+
parenthetical groups there may be at any point during a regular
1257+
expression compilation. The default is currently 1000 nested groups.
1258+
You may adjust it depending on your needs and the amount of memory
1259+
available.
1260+
1261+
This variable was added in Perl v5.30.0.
1262+
12521263
=item ${^RE_DEBUG_FLAGS}
12531264
X<${^RE_DEBUG_FLAGS}>
12541265

regcomp.c

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11009,6 +11009,7 @@ S_reg(pTHX_ RExC_state_t *pRExC_state, I32 paren, I32 *flagp, U32 depth)
1100911009
I32 freeze_paren = 0;
1101011010
I32 after_freeze = 0;
1101111011
I32 num; /* numeric backreferences */
11012+
SV * max_open; /* Max number of unclosed parens */
1101211013

1101311014
char * parse_start = RExC_parse; /* MJD */
1101411015
char * const oregcomp_parse = RExC_parse;
@@ -11018,6 +11019,17 @@ S_reg(pTHX_ RExC_state_t *pRExC_state, I32 paren, I32 *flagp, U32 depth)
1101811019
PERL_ARGS_ASSERT_REG;
1101911020
DEBUG_PARSE("reg ");
1102011021

11022+
11023+
max_open = get_sv(RE_COMPILE_RECURSION_LIMIT, GV_ADD);
11024+
assert(max_open);
11025+
if (!SvIOK(max_open)) {
11026+
sv_setiv(max_open, RE_COMPILE_RECURSION_INIT);
11027+
}
11028+
if (depth > 4 * SvIV(max_open)) { /* We increase depth by 4 for each open
11029+
paren */
11030+
vFAIL("Too many nested open parens");
11031+
}
11032+
1102111033
*flagp = 0; /* Tentatively. */
1102211034

1102311035
/* Having this true makes it feasible to have a lot fewer tests for the

regcomp.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -946,6 +946,9 @@ typedef struct _reg_ac_data reg_ac_data;
946946
#define RE_TRIE_MAXBUF_NAME "\022E_TRIE_MAXBUF"
947947
#define RE_DEBUG_FLAGS "\022E_DEBUG_FLAGS"
948948

949+
#define RE_COMPILE_RECURSION_INIT 1000
950+
#define RE_COMPILE_RECURSION_LIMIT "\022E_COMPILE_RECURSION_LIMIT"
951+
949952
/*
950953
951954
RE_DEBUG_FLAGS is used to control what debug output is emitted

t/lib/croak/regcomp

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,3 +63,10 @@ my $p00="[\\x59\\N{U+.}]"; qr/$p00/ui;
6363
EXPECT
6464
Invalid hexadecimal number in \N{U+...} in regex; marked by <-- HERE in m/[\x59\N{U+. <-- HERE }]/ at - line 1.
6565
########
66+
# NAME ${^RE_COMPILE_RECURSION_LIMIT} [perl #131551]
67+
BEGIN { ${^RE_COMPILE_RECURSION_LIMIT} = ${^RE_COMPILE_RECURSION_LIMIT} = 2; }
68+
qr/(a)/;
69+
qr/((a))/;
70+
EXPECT
71+
Too many nested open parens in regex; marked by <-- HERE in m/(( <-- HERE a))/ at - line 3.
72+
########

0 commit comments

Comments
 (0)