diff options
author | ph10 <ph10@2f5784b3-3f2a-0410-8824-cb99058d5e15> | 2014-08-08 15:22:51 +0000 |
---|---|---|
committer | ph10 <ph10@2f5784b3-3f2a-0410-8824-cb99058d5e15> | 2014-08-08 15:22:51 +0000 |
commit | fd411b0b71fc1d0bd1977d0a86e5711599f875d8 (patch) | |
tree | 3f9343c8c2e1d7e3142c0d4882927b528e0ca61a | |
parent | 8f84be9bafcb49fd0482d2141e48c3cf3dbfa27c (diff) | |
download | pcre-fd411b0b71fc1d0bd1977d0a86e5711599f875d8.tar.gz |
Fix compile-time loop for recursive reference within a group with an indefinite
repeat.
git-svn-id: svn://vcs.exim.org/pcre/code/trunk@1498 2f5784b3-3f2a-0410-8824-cb99058d5e15
-rw-r--r-- | ChangeLog | 5 | ||||
-rw-r--r-- | pcre_compile.c | 21 | ||||
-rw-r--r-- | testdata/testinput1 | 6 | ||||
-rw-r--r-- | testdata/testoutput1 | 10 |
4 files changed, 30 insertions, 12 deletions
@@ -89,6 +89,11 @@ Version 8.36 xx-xxx-2014 back reference was optional (had quantifier with a minimum of zero). This example compiled incorrect code: /(((a\2)|(a*)\g<-1>))*/ and other examples caused segmentation faults because of stack overflows at compile time. + +20. A pattern such as /((?(R)a|(?1)))+/, which contains a recursion within a + group that is quantified with an indefinite repeat, caused a compile-time + loop which used up all the system stack and provoked a segmentation fault. + This was not the same bug as 19 above. Version 8.35 04-April-2014 diff --git a/pcre_compile.c b/pcre_compile.c index 8276d0f..4bb05b9 100644 --- a/pcre_compile.c +++ b/pcre_compile.c @@ -2374,6 +2374,7 @@ for (code = first_significant_code(code + PRIV(OP_lengths)[*code], TRUE); if (c == OP_RECURSE) { const pcre_uchar *scode = cd->start_code + GET(code, 1); + const pcre_uchar *endgroup = scode; BOOL empty_branch; /* Test for forward reference or uncompleted reference. This is disabled @@ -2388,24 +2389,20 @@ for (code = first_significant_code(code + PRIV(OP_lengths)[*code], TRUE); if (GET(scode, 1) == 0) return TRUE; /* Unclosed */ } - /* If we are scanning a completed pattern, there are no forward references - and all groups are complete. We need to detect whether this is a recursive - call, as otherwise there will be an infinite loop. If it is a recursion, - just skip over it. Simple recursions are easily detected. For mutual - recursions we keep a chain on the stack. */ + /* If the reference is to a completed group, we need to detect whether this + is a recursive call, as otherwise there will be an infinite loop. If it is + a recursion, just skip over it. Simple recursions are easily detected. For + mutual recursions we keep a chain on the stack. */ + do endgroup += GET(endgroup, 1); while (*endgroup == OP_ALT); + if (code >= scode && code <= endgroup) continue; /* Simple recursion */ else - { + { recurse_check *r = recurses; - const pcre_uchar *endgroup = scode; - - do endgroup += GET(endgroup, 1); while (*endgroup == OP_ALT); - if (code >= scode && code <= endgroup) continue; /* Simple recursion */ - for (r = recurses; r != NULL; r = r->prev) if (r->group == scode) break; if (r != NULL) continue; /* Mutual recursion */ - } + } /* Completed reference; scan the referenced group, remembering it on the stack chain to detect mutual recursions. */ diff --git a/testdata/testinput1 b/testdata/testinput1 index 6fd62ba..123e3d3 100644 --- a/testdata/testinput1 +++ b/testdata/testinput1 @@ -4937,6 +4937,12 @@ however, we need the complication for Perl. ---/ /((?(R1)a+|(?1)b))/ aaaabcde + +/((?(R)a|(?1)))*/ + aaa + +/((?(R)a|(?1)))+/ + aaa /a(*:any name)/K diff --git a/testdata/testoutput1 b/testdata/testoutput1 index eeddf0f..5e71900 100644 --- a/testdata/testoutput1 +++ b/testdata/testoutput1 @@ -8234,6 +8234,16 @@ MK: M aaaabcde 0: aaaab 1: aaaab + +/((?(R)a|(?1)))*/ + aaa + 0: aaa + 1: a + +/((?(R)a|(?1)))+/ + aaa + 0: aaa + 1: a /a(*:any name)/K |