Blob Blame History Raw
From cdefe642dc2e6b5b8e6703773934813f317bc488 Mon Sep 17 00:00:00 2001
From: ph10 <ph10@6239d852-aaf2-0410-a92c-79f79f948069>
Date: Thu, 4 Jul 2019 17:01:53 +0000
Subject: [PATCH] Check for integer overflow when computing lookbehind lengths.
 Fixes Clusterfuzz issue 13656.
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

git-svn-id: svn://vcs.exim.org/pcre2/code/trunk@1126 6239d852-aaf2-0410-a92c-79f79f948069
Petr Písař: Ported to 10.33.

Signed-off-by: Petr Písař <ppisar@redhat.com>
---
 src/pcre2_compile.c  | 38 ++++++++++++++++++++++++++++----------
 testdata/testinput2  |  2 ++
 testdata/testoutput2 |  3 +++
 3 files changed, 33 insertions(+), 10 deletions(-)

diff --git a/src/pcre2_compile.c b/src/pcre2_compile.c
index c82c6ca..f6e0a0b 100644
--- a/src/pcre2_compile.c
+++ b/src/pcre2_compile.c
@@ -9197,8 +9197,26 @@ for (;; pptr++)
     case META_MINMAX_QUERY:
     if (pptr[1] == pptr[2])
       {
-      if (pptr[1] == 0) branchlength -= lastitemlength;
-        else itemlength = (pptr[1] - 1) * lastitemlength;
+      switch(pptr[1])
+        {
+        case 0:
+        branchlength -= lastitemlength;
+        break;
+
+        case 1:
+        itemlength = 0;
+        break;
+
+        default:  /* Check for integer overflow */
+        if (lastitemlength != 0 &&  /* Should not occur, but just in case */
+            INT_MAX/lastitemlength < pptr[1] - 1)
+          {
+          *errcodeptr = ERR87;  /* Integer overflow; lookbehind too big */
+          return -1;
+          }
+        itemlength = (pptr[1] - 1) * lastitemlength;
+        break;
+        }
       pptr += 2;
       break;
       }
@@ -9212,19 +9230,19 @@ for (;; pptr++)
     return -1;
     }
 
-  /* Add the item length to the branchlength, and save it for use if the next
-  thing is a quantifier. */
-
-  branchlength += itemlength;
-  lastitemlength = itemlength;
-
-  /* Ensure that the length does not overflow the limit. */
+  /* Add the item length to the branchlength, checking for integer overflow and
+  for the branch length exceeding the limit. */
 
-  if (branchlength > LOOKBEHIND_MAX)
+  if (INT_MAX - branchlength < (int)itemlength ||
+      (branchlength += itemlength) > LOOKBEHIND_MAX)
     {
     *errcodeptr = ERR87;
     return -1;
     }
+
+  /* Save this item length for use if the next item is a quantifier. */
+
+  lastitemlength = itemlength;
   }
 
 EXIT:
diff --git a/testdata/testinput2 b/testdata/testinput2
index 8a98f94..079d6d8 100644
--- a/testdata/testinput2
+++ b/testdata/testinput2
@@ -5591,4 +5591,6 @@ a)"xI
 
 /\[()]{65535}(?<A>)/expand
 
+/( {32742} {42})(?<!\1{65481})/
+
 # End of testinput2
diff --git a/testdata/testoutput2 b/testdata/testoutput2
index 158fbad..bfe61a3 100644
--- a/testdata/testoutput2
+++ b/testdata/testoutput2
@@ -16940,6 +16940,9 @@ Failed: error 197 at offset 131071: too many capturing groups (maximum 65535)
 /\[()]{65535}(?<A>)/expand
 Failed: error 197 at offset 131075: too many capturing groups (maximum 65535)
 
+/( {32742} {42})(?<!\1{65481})/
+Failed: error 187 at offset 15: lookbehind assertion is too long
+
 # End of testinput2
 Error -70: PCRE2_ERROR_BADDATA (unknown error number)
 Error -62: bad serialized data
-- 
2.20.1