Fixes CVE-2016-3191 (remote execution of arbitrary code or denial of
service (stack-based buffer overflow) via a crafted regular expression).

See <https://bugzilla.redhat.com/show_bug.cgi?id=1311503>.

This is svn r489 at <svn://vcs.exim.org/pcre2/code>, omitting the
changes to 'testdata/testoutput8-16-4', which does not exist in the
source tarball.

git-svn-id: svn://vcs.exim.org/pcre2/code/trunk@489 6239d852-aaf2-0410-a92c-79f79f948069
---
 ChangeLog                 |  4 ++++
 src/pcre2_compile.c       | 16 ++++++++++++++--
 testdata/testinput8       |  2 ++
 testdata/testoutput8-16-2 |  3 +++
 testdata/testoutput8-16-3 |  3 +++
 testdata/testoutput8-16-4 |  3 +++
 testdata/testoutput8-32-2 |  3 +++
 testdata/testoutput8-32-3 |  3 +++
 testdata/testoutput8-32-4 |  3 +++
 testdata/testoutput8-8-2  |  3 +++
 testdata/testoutput8-8-3  |  3 +++
 testdata/testoutput8-8-4  |  3 +++
 12 files changed, 47 insertions(+), 2 deletions(-)

diff --git a/ChangeLog b/ChangeLog
index 3ce0207..65e333e 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -58,6 +58,10 @@ some head-scratching the next time this happens.
 assertion, caused pcre2test to output a very large number of spaces when the 
 callout was taken, making the program appearing to loop.
 
+12. A pattern that included (*ACCEPT) in the middle of a sufficiently deeply 
+nested set of parentheses of sufficient size caused an overflow of the 
+compiling workspace (which was diagnosed, but of course is not desirable).
+
 
 Version 10.21 12-January-2016
 -----------------------------
diff --git a/src/pcre2_compile.c b/src/pcre2_compile.c
index e33d620..887fbfd 100644
--- a/src/pcre2_compile.c
+++ b/src/pcre2_compile.c
@@ -5901,10 +5901,22 @@ for (;; ptr++)
               goto FAILED;
               }
             cb->had_accept = TRUE;
+            
+            /* In the first pass, just accumulate the length required;
+            otherwise hitting (*ACCEPT) inside many nested parentheses can
+            cause workspace overflow. */
+              
             for (oc = cb->open_caps; oc != NULL; oc = oc->next)
               {
-              *code++ = OP_CLOSE;
-              PUT2INC(code, 0, oc->number);
+              if (lengthptr != NULL)
+                {
+                *lengthptr += CU2BYTES(1) + IMM2_SIZE; 
+                }
+              else
+                {       
+                *code++ = OP_CLOSE;
+                PUT2INC(code, 0, oc->number);
+                } 
               }
             setverb = *code++ =
               (cb->assert_depth > 0)? OP_ASSERT_ACCEPT : OP_ACCEPT;
diff --git a/testdata/testinput8 b/testdata/testinput8
index ca3b1b9..7e2a1f0 100644
--- a/testdata/testinput8
+++ b/testdata/testinput8
@@ -182,4 +182,6 @@
 
 /((?1)(?2)(?3)(?4)(?5)(?6)(?7)(?8)(?9)(?9)(?8)(?7)(?6)(?5)(?4)(?3)(?2)(?1)(?0)){2,}()()()()()()()()()/debug
 
+/([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00](*ACCEPT)/
+
 # End of testinput8
diff --git a/testdata/testoutput8-16-2 b/testdata/testoutput8-16-2
index 05669bb..a5e8dec 100644
--- a/testdata/testoutput8-16-2
+++ b/testdata/testoutput8-16-2
@@ -1027,4 +1027,7 @@ Capturing subpattern count = 10
 May match empty string
 Subject length lower bound = 0
 
+/([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00](*ACCEPT)/
+Failed: error 186 at offset 490: regular expression is too complicated
+
 # End of testinput8
diff --git a/testdata/testoutput8-16-3 b/testdata/testoutput8-16-3
index 31884e1..36133b3 100644
--- a/testdata/testoutput8-16-3
+++ b/testdata/testoutput8-16-3
@@ -1023,4 +1023,7 @@ Capturing subpattern count = 10
 May match empty string
 Subject length lower bound = 0
 
+/([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00](*ACCEPT)/
+Failed: error 114 at offset 509: missing closing parenthesis
+
 # End of testinput8
diff --git a/testdata/testoutput8-32-2 b/testdata/testoutput8-32-2
index babd0c7..99c4fad 100644
--- a/testdata/testoutput8-32-2
+++ b/testdata/testoutput8-32-2
@@ -1023,4 +1023,7 @@ Capturing subpattern count = 10
 May match empty string
 Subject length lower bound = 0
 
+/([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00](*ACCEPT)/
+Failed: error 114 at offset 509: missing closing parenthesis
+
 # End of testinput8
diff --git a/testdata/testoutput8-32-3 b/testdata/testoutput8-32-3
index babd0c7..99c4fad 100644
--- a/testdata/testoutput8-32-3
+++ b/testdata/testoutput8-32-3
@@ -1023,4 +1023,7 @@ Capturing subpattern count = 10
 May match empty string
 Subject length lower bound = 0
 
+/([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00](*ACCEPT)/
+Failed: error 114 at offset 509: missing closing parenthesis
+
 # End of testinput8
diff --git a/testdata/testoutput8-32-4 b/testdata/testoutput8-32-4
index babd0c7..99c4fad 100644
--- a/testdata/testoutput8-32-4
+++ b/testdata/testoutput8-32-4
@@ -1023,4 +1023,7 @@ Capturing subpattern count = 10
 May match empty string
 Subject length lower bound = 0
 
+/([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00](*ACCEPT)/
+Failed: error 114 at offset 509: missing closing parenthesis
+
 # End of testinput8
diff --git a/testdata/testoutput8-8-2 b/testdata/testoutput8-8-2
index 6a9aa0a..6dc1f42 100644
--- a/testdata/testoutput8-8-2
+++ b/testdata/testoutput8-8-2
@@ -1026,4 +1026,7 @@ Capturing subpattern count = 10
 May match empty string
 Subject length lower bound = 0
 
+/([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00](*ACCEPT)/
+Failed: error 114 at offset 509: missing closing parenthesis
+
 # End of testinput8
diff --git a/testdata/testoutput8-8-3 b/testdata/testoutput8-8-3
index 2fe1168..ae14946 100644
--- a/testdata/testoutput8-8-3
+++ b/testdata/testoutput8-8-3
@@ -1024,4 +1024,7 @@ Capturing subpattern count = 10
 May match empty string
 Subject length lower bound = 0
 
+/([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00](*ACCEPT)/
+Failed: error 114 at offset 509: missing closing parenthesis
+
 # End of testinput8
diff --git a/testdata/testoutput8-8-4 b/testdata/testoutput8-8-4
index 91993b2..6c79956 100644
--- a/testdata/testoutput8-8-4
+++ b/testdata/testoutput8-8-4
@@ -1022,4 +1022,7 @@ Capturing subpattern count = 10
 May match empty string
 Subject length lower bound = 0
 
+/([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00](*ACCEPT)/
+Failed: error 114 at offset 509: missing closing parenthesis
+
 # End of testinput8
-- 
2.8.3