Add recursion limit to auto-possessification code.

This commit is contained in:
Philip.Hazel 2015-03-25 17:01:04 +00:00
parent a4ceadbf47
commit a066d12022
4 changed files with 22 additions and 5 deletions

View File

@ -25,6 +25,11 @@ when this assertion was used as a condition, for example (?(?!)a|b). In
pcre2_match() it worked by luck; in pcre2_dfa_match() it gave an incorrect pcre2_match() it worked by luck; in pcre2_dfa_match() it gave an incorrect
error about an unsupported item. error about an unsupported item.
8. For some types of pattern, for example /Z*(|d*){216}/, the auto-
possessification code could take exponential time to complete. A recursion
depth limit of 10000 has been imposed to limit the resources used by this
optimization. This infelicity was discovered by the LLVM fuzzer.
Version 10.10 06-March-2015 Version 10.10 06-March-2015
--------------------------- ---------------------------

View File

@ -561,13 +561,15 @@ Arguments:
utf TRUE in UTF mode utf TRUE in UTF mode
cb compile data block cb compile data block
base_list the data list of the base opcode base_list the data list of the base opcode
base_end the end of the data list
rec_limit points to recursion depth counter
Returns: TRUE if the auto-possessification is possible Returns: TRUE if the auto-possessification is possible
*/ */
static BOOL static BOOL
compare_opcodes(PCRE2_SPTR code, BOOL utf, const compile_block *cb, compare_opcodes(PCRE2_SPTR code, BOOL utf, const compile_block *cb,
const uint32_t *base_list, PCRE2_SPTR base_end) const uint32_t *base_list, PCRE2_SPTR base_end, int *rec_limit)
{ {
PCRE2_UCHAR c; PCRE2_UCHAR c;
uint32_t list[8]; uint32_t list[8];
@ -584,6 +586,8 @@ uint32_t chr;
BOOL accepted, invert_bits; BOOL accepted, invert_bits;
BOOL entered_a_group = FALSE; BOOL entered_a_group = FALSE;
if (--(*rec_limit) <= 0) return FALSE; /* Recursion has gone too deep */
/* Note: the base_list[1] contains whether the current opcode has a greedy /* Note: the base_list[1] contains whether the current opcode has a greedy
(represented by a non-zero value) quantifier. This is a different from (represented by a non-zero value) quantifier. This is a different from
other character type lists, which store here that the character iterator other character type lists, which store here that the character iterator
@ -660,7 +664,8 @@ for(;;)
while (*next_code == OP_ALT) while (*next_code == OP_ALT)
{ {
if (!compare_opcodes(code, utf, cb, base_list, base_end)) return FALSE; if (!compare_opcodes(code, utf, cb, base_list, base_end, rec_limit))
return FALSE;
code = next_code + 1 + LINK_SIZE; code = next_code + 1 + LINK_SIZE;
next_code += GET(next_code, 1); next_code += GET(next_code, 1);
} }
@ -680,7 +685,7 @@ for(;;)
/* The bracket content will be checked by the OP_BRA/OP_CBRA case above. */ /* The bracket content will be checked by the OP_BRA/OP_CBRA case above. */
next_code += 1 + LINK_SIZE; next_code += 1 + LINK_SIZE;
if (!compare_opcodes(next_code, utf, cb, base_list, base_end)) if (!compare_opcodes(next_code, utf, cb, base_list, base_end, rec_limit))
return FALSE; return FALSE;
code += PRIV(OP_lengths)[c]; code += PRIV(OP_lengths)[c];
@ -1116,6 +1121,7 @@ register PCRE2_UCHAR c;
PCRE2_SPTR end; PCRE2_SPTR end;
PCRE2_UCHAR *repeat_opcode; PCRE2_UCHAR *repeat_opcode;
uint32_t list[8]; uint32_t list[8];
int rec_limit;
for (;;) for (;;)
{ {
@ -1130,7 +1136,8 @@ for (;;)
get_chr_property_list(code, utf, cb->fcc, list) : NULL; get_chr_property_list(code, utf, cb->fcc, list) : NULL;
list[1] = c == OP_STAR || c == OP_PLUS || c == OP_QUERY || c == OP_UPTO; list[1] = c == OP_STAR || c == OP_PLUS || c == OP_QUERY || c == OP_UPTO;
if (end != NULL && compare_opcodes(end, utf, cb, list, end)) rec_limit = 10000;
if (end != NULL && compare_opcodes(end, utf, cb, list, end, &rec_limit))
{ {
switch(c) switch(c)
{ {
@ -1186,7 +1193,8 @@ for (;;)
list[1] = (c & 1) == 0; list[1] = (c & 1) == 0;
if (compare_opcodes(end, utf, cb, list, end)) rec_limit = 10000;
if (compare_opcodes(end, utf, cb, list, end, &rec_limit))
{ {
switch (c) switch (c)
{ {

2
testdata/testinput1 vendored
View File

@ -5710,4 +5710,6 @@ name)/mark
/(\2)(\1)/ /(\2)(\1)/
"Z*(|d*){216}"
# End of testinput1 # End of testinput1

View File

@ -9420,4 +9420,6 @@ No match
/(\2)(\1)/ /(\2)(\1)/
"Z*(|d*){216}"
# End of testinput1 # End of testinput1