[Pcre-svn] [1542] code/trunk: Fix stack overflow instead of …

Top Page
Delete this message
Author: Subversion repository
Date:  
To: pcre-svn
Subject: [Pcre-svn] [1542] code/trunk: Fix stack overflow instead of diagnostic for mutual recursion inside a
Revision: 1542
          http://vcs.pcre.org/viewvc?view=rev&revision=1542
Author:   ph10
Date:     2015-04-01 16:43:53 +0100 (Wed, 01 Apr 2015)


Log Message:
-----------
Fix stack overflow instead of diagnostic for mutual recursion inside a
lookbehind assertion.

Modified Paths:
--------------
    code/trunk/ChangeLog
    code/trunk/pcre_compile.c
    code/trunk/testdata/testinput2
    code/trunk/testdata/testoutput2


Modified: code/trunk/ChangeLog
===================================================================
--- code/trunk/ChangeLog    2015-04-01 13:43:02 UTC (rev 1541)
+++ code/trunk/ChangeLog    2015-04-01 15:43:53 UTC (rev 1542)
@@ -142,7 +142,11 @@
     incorrectly compiled and could trigger buffer overflow. This bug was
     discovered by the LLVM fuzzer.


+35. A mutual recursion within a lookbehind assertion such as (?<=((?2))((?1)))
+    caused a stack overflow instead of the diagnosis of a non-fixed length
+    lookbehind assertion. This bug was discovered by the LLVM fuzzer.


+
Version 8.36 26-September-2014
------------------------------


Modified: code/trunk/pcre_compile.c
===================================================================
--- code/trunk/pcre_compile.c    2015-04-01 13:43:02 UTC (rev 1541)
+++ code/trunk/pcre_compile.c    2015-04-01 15:43:53 UTC (rev 1542)
@@ -866,7 +866,15 @@
 };



+/* Structure for mutual recursion detection. */

+typedef struct recurse_check {
+  struct recurse_check *prev;
+  const pcre_uchar *group;
+} recurse_check;
+
+
+
 /*************************************************
 *            Find an error text                  *
 *************************************************/
@@ -1704,6 +1712,7 @@
   utf      TRUE in UTF-8 / UTF-16 / UTF-32 mode
   atend    TRUE if called when the pattern is complete
   cd       the "compile data" structure
+  recurses    chain of recurse_check to catch mutual recursion


 Returns:   the fixed length,
              or -1 if there is no fixed length,
@@ -1713,10 +1722,11 @@
 */


static int
-find_fixedlength(pcre_uchar *code, BOOL utf, BOOL atend, compile_data *cd)
+find_fixedlength(pcre_uchar *code, BOOL utf, BOOL atend, compile_data *cd,
+ recurse_check *recurses)
{
int length = -1;
-
+recurse_check this_recurse;
register int branchlength = 0;
register pcre_uchar *cc = code + 1 + LINK_SIZE;

@@ -1741,7 +1751,8 @@
     case OP_ONCE:
     case OP_ONCE_NC:
     case OP_COND:
-    d = find_fixedlength(cc + ((op == OP_CBRA)? IMM2_SIZE : 0), utf, atend, cd);
+    d = find_fixedlength(cc + ((op == OP_CBRA)? IMM2_SIZE : 0), utf, atend, cd,
+      recurses);
     if (d < 0) return d;
     branchlength += d;
     do cc += GET(cc, 1); while (*cc == OP_ALT);
@@ -1775,7 +1786,15 @@
     cs = ce = (pcre_uchar *)cd->start_code + GET(cc, 1);  /* Start subpattern */
     do ce += GET(ce, 1); while (*ce == OP_ALT);           /* End subpattern */
     if (cc > cs && cc < ce) return -1;                    /* Recursion */
-    d = find_fixedlength(cs + IMM2_SIZE, utf, atend, cd);
+    else   /* Check for mutual recursion */
+      {
+      recurse_check *r = recurses;
+      for (r = recurses; r != NULL; r = r->prev) if (r->group == cs) break;
+      if (r != NULL) return -1;   /* Mutual recursion */
+      }
+    this_recurse.prev = recurses;
+    this_recurse.group = cs;
+    d = find_fixedlength(cs + IMM2_SIZE, utf, atend, cd, &this_recurse);
     if (d < 0) return d;
     branchlength += d;
     cc += 1 + LINK_SIZE;
@@ -2362,11 +2381,6 @@
 Returns:      TRUE if what is matched could be empty
 */


-typedef struct recurse_check {
-  struct recurse_check *prev;
-  const pcre_uchar *group;
-} recurse_check;
-
 static BOOL
 could_be_empty_branch(const pcre_uchar *code, const pcre_uchar *endcode,
   BOOL utf, compile_data *cd, recurse_check *recurses)
@@ -5924,7 +5938,7 @@
       {
       register int i;
       int len = (int)(code - previous);
-      size_t base_hwm_offset = save_hwm_offset; 
+      size_t base_hwm_offset = save_hwm_offset;
       pcre_uchar *bralink = NULL;
       pcre_uchar *brazeroptr = NULL;


@@ -8291,7 +8305,7 @@
       int fixed_length;
       *code = OP_END;
       fixed_length = find_fixedlength(last_branch,  (options & PCRE_UTF8) != 0,
-        FALSE, cd);
+        FALSE, cd, NULL);
       DPRINTF(("fixed length = %d\n", fixed_length));
       if (fixed_length == -3)
         {
@@ -9394,7 +9408,7 @@
       int end_op = *be;
       *be = OP_END;
       fixed_length = find_fixedlength(cc, (re->options & PCRE_UTF8) != 0, TRUE,
-        cd);
+        cd, NULL);
       *be = end_op;
       DPRINTF(("fixed length = %d\n", fixed_length));
       if (fixed_length < 0)


Modified: code/trunk/testdata/testinput2
===================================================================
--- code/trunk/testdata/testinput2    2015-04-01 13:43:02 UTC (rev 1541)
+++ code/trunk/testdata/testinput2    2015-04-01 15:43:53 UTC (rev 1542)
@@ -4142,4 +4142,6 @@


"X((?2)()*+){2}"BZ

+"(?<=((?2))((?1)))"
+
/-- End of testinput2 --/

Modified: code/trunk/testdata/testoutput2
===================================================================
--- code/trunk/testdata/testoutput2    2015-04-01 13:43:02 UTC (rev 1541)
+++ code/trunk/testdata/testoutput2    2015-04-01 15:43:53 UTC (rev 1542)
@@ -14390,4 +14390,7 @@
         End
 ------------------------------------------------------------------


+"(?<=((?2))((?1)))"
+Failed: lookbehind assertion is not fixed length at offset 17
+
/-- End of testinput2 --/