From 58c834052f0985406919de157297e0c340c5b2ed Mon Sep 17 00:00:00 2001 From: ph10 Date: Fri, 8 Aug 2014 15:22:51 +0000 Subject: [PATCH 2/2] Fix compile-time loop for recursive reference within a group with an indefinite repeat. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit git-svn-id: svn://vcs.exim.org/pcre/code/trunk@1498 2f5784b3-3f2a-0410-8824-cb99058d5e15 Signed-off-by: Petr Písař Petr Pisar: Ported to 8.32. Signed-off-by: Petr Písař --- pcre_compile.c | 17 +++++++---------- testdata/testinput1 | 6 ++++++ testdata/testoutput1 | 10 ++++++++++ 3 files changed, 23 insertions(+), 10 deletions(-) diff --git a/pcre_compile.c b/pcre_compile.c index ce72527..86cd0c8 100644 --- a/pcre_compile.c +++ b/pcre_compile.c @@ -2398,6 +2398,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 @@ -2412,20 +2413,16 @@ 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 */ diff --git a/testdata/testinput1 b/testdata/testinput1 index 3e1061e..c45e1ba 100644 --- a/testdata/testinput1 +++ b/testdata/testinput1 @@ -4967,6 +4967,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 5015448..f0eae49 100644 --- a/testdata/testoutput1 +++ b/testdata/testoutput1 @@ -8271,6 +8271,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 -- 2.5.5