summaryrefslogtreecommitdiffstats
path: root/bug73174.patch
diff options
context:
space:
mode:
Diffstat (limited to 'bug73174.patch')
-rw-r--r--bug73174.patch76
1 files changed, 76 insertions, 0 deletions
diff --git a/bug73174.patch b/bug73174.patch
new file mode 100644
index 0000000..d67e3d9
--- /dev/null
+++ b/bug73174.patch
@@ -0,0 +1,76 @@
+Backported from 5.6.27 by Remi.
+
+
+From 29e2a204fb42af061e66a9f847ffbc8f1d13897a Mon Sep 17 00:00:00 2001
+From: Stanislav Malyshev <stas@php.net>
+Date: Wed, 28 Sep 2016 22:29:25 -0700
+Subject: [PATCH] Fixed bug #73174 - heap overflow in php_pcre_replace_impl
+
+---
+ ext/pcre/php_pcre.c | 22 ++++++++++++++--------
+ 1 file changed, 14 insertions(+), 8 deletions(-)
+
+diff --git a/ext/pcre/php_pcre.c b/ext/pcre/php_pcre.c
+index 7589a78..2a8ff19 100644
+--- a/ext/pcre/php_pcre.c
++++ b/ext/pcre/php_pcre.c
+@@ -1040,8 +1040,8 @@ PHPAPI char *php_pcre_replace_impl(pcre_cache_entry *pce, char *subject, int sub
+ char **subpat_names; /* Array for named subpatterns */
+ int num_subpats; /* Number of captured subpatterns */
+ int size_offsets; /* Size of the offsets array */
+- int new_len; /* Length of needed storage */
+- int alloc_len; /* Actual allocated length */
++ size_t new_len; /* Length of needed storage */
++ size_t alloc_len; /* Actual allocated length */
+ int eval_result_len=0; /* Length of the eval'ed or
+ function-returned string */
+ int match_len; /* Length of the current match */
+@@ -1106,8 +1106,8 @@ PHPAPI char *php_pcre_replace_impl(pcre_cache_entry *pce, char *subject, int sub
+
+ offsets = (int *)safe_emalloc(size_offsets, sizeof(int), 0);
+
+- alloc_len = 2 * subject_len + 1;
+- result = safe_emalloc(alloc_len, sizeof(char), 0);
++ result = safe_emalloc(subject_len, 2*sizeof(char), 1);
++ alloc_len = 2 * (size_t)subject_len + 1;
+
+ /* Initialize */
+ match = NULL;
+@@ -1172,8 +1172,8 @@ PHPAPI char *php_pcre_replace_impl(pcre_cache_entry *pce, char *subject, int sub
+ }
+
+ if (new_len + 1 > alloc_len) {
+- alloc_len = 1 + alloc_len + 2 * new_len;
+- new_buf = emalloc(alloc_len);
++ new_buf = safe_emalloc(2, new_len + 1, alloc_len);
++ alloc_len = 1 + alloc_len + 2 * (size_t)new_len;
+ memcpy(new_buf, result, *result_len);
+ efree(result);
+ result = new_buf;
+@@ -1236,8 +1236,8 @@ PHPAPI char *php_pcre_replace_impl(pcre_cache_entry *pce, char *subject, int sub
+ } else {
+ new_len = *result_len + subject_len - start_offset;
+ if (new_len + 1 > alloc_len) {
+- alloc_len = new_len + 1; /* now we know exactly how long it is */
+- new_buf = safe_emalloc(alloc_len, sizeof(char), 0);
++ new_buf = safe_emalloc(new_len, sizeof(char), 1);
++ alloc_len = (size_t)new_len + 1; /* now we know exactly how long it is */
+ memcpy(new_buf, result, *result_len);
+ efree(result);
+ result = new_buf;
+@@ -1268,6 +1268,12 @@ PHPAPI char *php_pcre_replace_impl(pcre_cache_entry *pce, char *subject, int sub
+ efree(offsets);
+ efree(subpat_names);
+
++ if(result && (size_t)(*result_len) > INT_MAX) {
++ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Result is too big, max is %d", INT_MAX);
++ efree(result);
++ result = NULL;
++ }
++
+ return result;
+ }
+ /* }}} */
+--
+2.1.4
+