Blob Blame History Raw
From fd411b0b71fc1d0bd1977d0a86e5711599f875d8 Mon Sep 17 00:00:00 2001
From: ph10 <ph10@2f5784b3-3f2a-0410-8824-cb99058d5e15>
Date: Fri, 8 Aug 2014 15:22:51 +0000
Subject: [PATCH] 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ř <ppisar@redhat.com>

Petr Pisar: Ported to 8.35.

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
-- 
1.9.3