Add recursion limit to auto-possessification code.
This commit is contained in:
parent
a4ceadbf47
commit
a066d12022
|
@ -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
|
||||||
---------------------------
|
---------------------------
|
||||||
|
|
|
@ -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)
|
||||||
{
|
{
|
||||||
|
|
|
@ -5710,4 +5710,6 @@ name)/mark
|
||||||
|
|
||||||
/(\2)(\1)/
|
/(\2)(\1)/
|
||||||
|
|
||||||
|
"Z*(|d*){216}"
|
||||||
|
|
||||||
# End of testinput1
|
# End of testinput1
|
||||||
|
|
|
@ -9420,4 +9420,6 @@ No match
|
||||||
|
|
||||||
/(\2)(\1)/
|
/(\2)(\1)/
|
||||||
|
|
||||||
|
"Z*(|d*){216}"
|
||||||
|
|
||||||
# End of testinput1
|
# End of testinput1
|
||||||
|
|
Loading…
Reference in New Issue