diff options
author | ph10 <ph10@2f5784b3-3f2a-0410-8824-cb99058d5e15> | 2015-03-25 16:51:51 +0000 |
---|---|---|
committer | ph10 <ph10@2f5784b3-3f2a-0410-8824-cb99058d5e15> | 2015-03-25 16:51:51 +0000 |
commit | 067c48c80569b0519568d6e1994a662327da9e18 (patch) | |
tree | 13931d27c3812b2ae0c8eaf473cb309b874ec92d | |
parent | 0838dce0fce0c9fc927fd5509da3151004606052 (diff) | |
download | pcre-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-- | ChangeLog | 5 | ||||
-rw-r--r-- | pcre_compile.c | 17 | ||||
-rw-r--r-- | testdata/testinput1 | 2 | ||||
-rw-r--r-- | testdata/testoutput1 | 2 |
4 files changed, 21 insertions, 5 deletions
@@ -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 --/ |