summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorph10 <ph10@2f5784b3-3f2a-0410-8824-cb99058d5e15>2015-03-25 16:51:51 +0000
committerph10 <ph10@2f5784b3-3f2a-0410-8824-cb99058d5e15>2015-03-25 16:51:51 +0000
commit067c48c80569b0519568d6e1994a662327da9e18 (patch)
tree13931d27c3812b2ae0c8eaf473cb309b874ec92d
parent0838dce0fce0c9fc927fd5509da3151004606052 (diff)
downloadpcre-067c48c80569b0519568d6e1994a662327da9e18.tar.gz
Add recursion depth limit to auto-possessification.
git-svn-id: svn://vcs.exim.org/pcre/code/trunk@1535 2f5784b3-3f2a-0410-8824-cb99058d5e15
-rw-r--r--ChangeLog5
-rw-r--r--pcre_compile.c17
-rw-r--r--testdata/testinput12
-rw-r--r--testdata/testoutput12
4 files changed, 21 insertions, 5 deletions
diff --git a/ChangeLog b/ChangeLog
index f443197..d16d265 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -110,6 +110,11 @@ Version 8.37 xx-xxx-2015
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
error about an unsupported item.
+
+29. 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 1000 has been imposed to limit the resources used by this
+ optimization.
Version 8.36 26-September-2014
diff --git a/pcre_compile.c b/pcre_compile.c
index 3ed17ef..f0f5e2e 100644
--- a/pcre_compile.c
+++ b/pcre_compile.c
@@ -3093,7 +3093,7 @@ Returns: TRUE if the auto-possessification is possible
static BOOL
compare_opcodes(const pcre_uchar *code, BOOL utf, const compile_data *cd,
- const pcre_uint32 *base_list, const pcre_uchar *base_end)
+ const pcre_uint32 *base_list, const pcre_uchar *base_end, int *rec_limit)
{
pcre_uchar c;
pcre_uint32 list[8];
@@ -3110,6 +3110,9 @@ pcre_uint32 chr;
BOOL accepted, invert_bits;
BOOL entered_a_group = FALSE;
+if (*rec_limit == 0) return FALSE;
+--(*rec_limit);
+
/* Note: the base_list[1] contains whether the current opcode has greedy
(represented by a non-zero value) quantifier. This is a different from
other character type lists, which stores here that the character iterator
@@ -3180,7 +3183,8 @@ for(;;)
while (*next_code == OP_ALT)
{
- if (!compare_opcodes(code, utf, cd, base_list, base_end)) return FALSE;
+ if (!compare_opcodes(code, utf, cd, base_list, base_end, rec_limit))
+ return FALSE;
code = next_code + 1 + LINK_SIZE;
next_code += GET(next_code, 1);
}
@@ -3200,7 +3204,7 @@ for(;;)
/* The bracket content will be checked by the
OP_BRA/OP_CBRA case above. */
next_code += 1 + LINK_SIZE;
- if (!compare_opcodes(next_code, utf, cd, base_list, base_end))
+ if (!compare_opcodes(next_code, utf, cd, base_list, base_end, rec_limit))
return FALSE;
code += PRIV(OP_lengths)[c];
@@ -3633,6 +3637,7 @@ register pcre_uchar c;
const pcre_uchar *end;
pcre_uchar *repeat_opcode;
pcre_uint32 list[8];
+int rec_limit;
for (;;)
{
@@ -3653,7 +3658,8 @@ for (;;)
get_chr_property_list(code, utf, cd->fcc, list) : NULL;
list[1] = c == OP_STAR || c == OP_PLUS || c == OP_QUERY || c == OP_UPTO;
- if (end != NULL && compare_opcodes(end, utf, cd, list, end))
+ rec_limit = 10000;
+ if (end != NULL && compare_opcodes(end, utf, cd, list, end, &rec_limit))
{
switch(c)
{
@@ -3709,7 +3715,8 @@ for (;;)
list[1] = (c & 1) == 0;
- if (compare_opcodes(end, utf, cd, list, end))
+ rec_limit = 10000;
+ if (compare_opcodes(end, utf, cd, list, end, &rec_limit))
{
switch (c)
{
diff --git a/testdata/testinput1 b/testdata/testinput1
index da96dd2..d475331 100644
--- a/testdata/testinput1
+++ b/testdata/testinput1
@@ -5725,4 +5725,6 @@ AbcdCBefgBhiBqz
/(\2)(\1)/
+"Z*(|d*){216}"
+
/-- End of testinput1 --/
diff --git a/testdata/testoutput1 b/testdata/testoutput1
index 61f14a4..25368fc 100644
--- a/testdata/testoutput1
+++ b/testdata/testoutput1
@@ -9422,4 +9422,6 @@ No match
/(\2)(\1)/
+"Z*(|d*){216}"
+
/-- End of testinput1 --/