summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRemi Collet <fedora@famillecollet.com>2016-07-22 19:29:20 +0200
committerRemi Collet <fedora@famillecollet.com>2016-07-22 19:29:20 +0200
commit2f649ee4cbea50aaf88ae480ecfe36651dd135a2 (patch)
treea354b0289ff36de74a82652f9946413b6917dd95
parentd3a4c0e1202c51c100fe28a60ed9beab1918de91 (diff)
PHP 5.4.45 with security fix from 5.5.38
-rw-r--r--bug69975.patch89
-rw-r--r--bug70480.patch29
-rw-r--r--bug72479.patch408
-rw-r--r--bug72513.patch48
-rw-r--r--bug72519.patch54
-rw-r--r--bug72520.patch78
-rw-r--r--bug72533.patch80
-rw-r--r--bug72562.patch73
-rw-r--r--bug72573.patch464
-rw-r--r--bug72603.patch76
-rw-r--r--bug72606.patch152
-rw-r--r--bug72613.patch281
-rw-r--r--bug72618.patch110
-rw-r--r--failed.txt7
-rw-r--r--php54.spec45
15 files changed, 1991 insertions, 3 deletions
diff --git a/bug69975.patch b/bug69975.patch
new file mode 100644
index 0000000..4aafb17
--- /dev/null
+++ b/bug69975.patch
@@ -0,0 +1,89 @@
+Adapted for 5.4, by Remi Collet, from:
+
+
+From 82637e818776d4fe778fb1dbac26eeece02e900c Mon Sep 17 00:00:00 2001
+From: "Christoph M. Becker" <cmb@php.net>
+Date: Fri, 3 Jul 2015 00:04:50 +0200
+Subject: [PATCH] Fix #69975: PHP segfaults when accessing nvarchar(max)
+ defined columns
+
+The SQL Server Native Client 11.0 and maybe other ODBC drivers report
+NVARCHAR(MAX) columns as SQL_WVARCHAR with size 0. This causes too small a
+buffer to be emalloc'd, likely causing a segfault in the following. As we don't
+know the real size of the column data, we treat such colums as
+SQL_WLONGVARCHAR.
+
+The related bug #67437 suggests that some drivers report a size of ~4GB. It is
+not certain that this is really the case (there might be some integer overflow
+involved, and anyway, there has been no feedback), so we do not cater for this
+now. However, it would not be hard to treat all sizes above a certain threshold
+in a similar way, i.e. as SQL_WLONGVARCHAR.
+
+(cherry picked from commit 16db4d1462bf3eacb93c0cd940f799160a284b24)
+(cherry picked from commit 344ff5dd4c538eaebea075f7705321f8b86d0b47)
+---
+ ext/odbc/php_odbc.c | 7 +++++++
+ ext/odbc/tests/bug69975.phpt | 32 ++++++++++++++++++++++++++++++++
+ 2 files changed, 39 insertions(+)
+ create mode 100644 ext/odbc/tests/bug69975.phpt
+
+diff --git a/ext/odbc/php_odbc.c b/ext/odbc/php_odbc.c
+index ddfbc4e..1d70b7f 100644
+--- a/ext/odbc/php_odbc.c
++++ b/ext/odbc/php_odbc.c
+@@ -1005,6 +1005,14 @@ int odbc_bindcols(odbc_result *result TS
+ default:
+ rc = SQLColAttributes(result->stmt, (SQLUSMALLINT)(i+1), colfieldid,
+ NULL, 0, NULL, &displaysize);
++#if defined(ODBCVER) && (ODBCVER >= 0x0300)
++ /* Workaround for drivers that report NVARCHAR(MAX) columns as SQL_WVARCHAR with size 0 (bug #69975) */
++ if (result->values[i].coltype == SQL_WVARCHAR && displaysize == 0) {
++ result->values[i].coltype = SQL_WLONGVARCHAR;
++ result->values[i].value = NULL;
++ break;
++ }
++#endif
+ /* Workaround for Oracle ODBC Driver bug (#50162) when fetching TIMESTAMP column */
+ if (result->values[i].coltype == SQL_TIMESTAMP) {
+ displaysize += 3;
+diff --git a/ext/odbc/tests/bug69975.phpt b/ext/odbc/tests/bug69975.phpt
+new file mode 100644
+index 0000000..eca7564
+--- /dev/null
++++ b/ext/odbc/tests/bug69975.phpt
+@@ -0,0 +1,32 @@
++--TEST--
++Bug #69975 (PHP segfaults when accessing nvarchar(max) defined columns)
++--SKIPIF--
++<?php include 'skipif.inc'; ?>
++--FILE--
++<?php
++include 'config.inc';
++
++$conn = odbc_connect($dsn, $user, $pass);
++@odbc_exec($conn, 'CREATE DATABASE odbcTEST');
++odbc_exec($conn, 'CREATE TABLE FOO (ID INT, VARCHAR_COL NVARCHAR(MAX))');
++odbc_exec($conn, "INSERT INTO FOO VALUES (1, 'foo')");
++
++$result = odbc_exec($conn, "SELECT VARCHAR_COL FROM FOO");
++var_dump(odbc_fetch_array($result));
++
++echo "ready";
++?>
++--EXPECT--
++array(1) {
++ ["VARCHAR_COL"]=>
++ string(3) "foo"
++}
++ready
++--CLEAN--
++<?php
++include 'config.inc';
++
++$conn = odbc_connect($dsn, $user, $pass);
++odbc_exec($conn, 'DROP TABLE FOO');
++odbc_exec($conn, 'DROP DATABASE odbcTEST');
++?>
+--
+2.1.4
+
diff --git a/bug70480.patch b/bug70480.patch
new file mode 100644
index 0000000..e39ea89
--- /dev/null
+++ b/bug70480.patch
@@ -0,0 +1,29 @@
+Adapted for 5.4, by Remi Collet, from:
+
+
+From e1ba58f068f4bfc8ced75bb017cd31d8beddf3c2 Mon Sep 17 00:00:00 2001
+From: Stanislav Malyshev <stas@php.net>
+Date: Mon, 28 Sep 2015 11:31:14 -0700
+Subject: [PATCH] Fix bug #70480 (php_url_parse_ex() buffer overflow read)
+
+(cherry picked from commit 629e4da7cc8b174acdeab84969cbfc606a019b31)
+---
+ ext/standard/url.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/ext/standard/url.c b/ext/standard/url.c
+index fc3f080..b5739f0 100644
+--- a/ext/standard/url.c
++++ b/ext/standard/url.c
+@@ -321,7 +321,7 @@ PHPAPI php_url *php_url_parse_ex(char co
+ nohost:
+
+ if ((p = memchr(s, '?', (ue - s)))) {
+- pp = strchr(s, '#');
++ pp = memchr(s, '#', (ue - s));
+
+ if (pp && pp < p) {
+ if (pp - s) {
+--
+2.1.4
+
diff --git a/bug72479.patch b/bug72479.patch
new file mode 100644
index 0000000..6d459be
--- /dev/null
+++ b/bug72479.patch
@@ -0,0 +1,408 @@
+From cab1c3b3708eead315e033359d07049b23b147a3 Mon Sep 17 00:00:00 2001
+From: Stanislav Malyshev <stas@php.net>
+Date: Sun, 26 Jun 2016 17:52:09 -0700
+Subject: [PATCH] Fixed bug #72479 - same as #72434
+
+---
+ ext/snmp/snmp.c | 89 ++++++++++++++++++++++++--------------------
+ ext/snmp/tests/bug72479.phpt | 35 +++++++++++++++++
+ 2 files changed, 84 insertions(+), 40 deletions(-)
+ create mode 100644 ext/snmp/tests/bug72479.phpt
+
+diff --git a/ext/snmp/snmp.c b/ext/snmp/snmp.c
+index 6c1da4c..e1161c7 100644
+--- a/ext/snmp/snmp.c
++++ b/ext/snmp/snmp.c
+@@ -475,7 +475,7 @@ static void php_snmp_session_destructor(zend_rsrc_list_entry *rsrc TSRMLS_DC)
+ static void php_snmp_object_free_storage(void *object TSRMLS_DC)
+ {
+ php_snmp_object *intern = (php_snmp_object *)object;
+-
++
+ if (!intern) {
+ return;
+ }
+@@ -483,7 +483,7 @@ static void php_snmp_object_free_storage(void *object TSRMLS_DC)
+ netsnmp_session_free(&(intern->session));
+
+ zend_object_std_dtor(&intern->zo TSRMLS_CC);
+-
++
+ efree(intern);
+ }
+
+@@ -503,7 +503,7 @@ static zend_object_value php_snmp_object_new(zend_class_entry *class_type TSRMLS
+ retval.handlers = (zend_object_handlers *) &php_snmp_object_handlers;
+
+ return retval;
+-
++
+ }
+
+ /* {{{ php_snmp_error
+@@ -556,7 +556,7 @@ static void php_snmp_getvalue(struct variable_list *vars, zval *snmpval TSRMLS_D
+ char *dbuf = (char *)NULL;
+ int buflen = sizeof(sbuf) - 1;
+ int val_len = vars->val_len;
+-
++
+ /* use emalloc() for large values, use static array otherwize */
+
+ /* There is no way to know the size of buffer snprint_value() needs in order to print a value there.
+@@ -702,7 +702,7 @@ static void php_snmp_getvalue(struct variable_list *vars, zval *snmpval TSRMLS_D
+ * SNMP object fetcher/setter for all SNMP versions
+ *
+ */
+-static void php_snmp_internal(INTERNAL_FUNCTION_PARAMETERS, int st,
++static void php_snmp_internal(INTERNAL_FUNCTION_PARAMETERS, int st,
+ struct snmp_session *session,
+ struct objid_query *objid_query)
+ {
+@@ -721,7 +721,7 @@ static void php_snmp_internal(INTERNAL_FUNCTION_PARAMETERS, int st,
+
+ /* we start with retval=FALSE. If any actual data is acquired, retval will be set to appropriate type */
+ RETVAL_FALSE;
+-
++
+ /* reset errno and errstr */
+ php_snmp_error(getThis(), NULL TSRMLS_CC, PHP_SNMP_ERRNO_NOERROR, "");
+
+@@ -805,8 +805,8 @@ retry:
+ }
+ for (vars = response->variables; vars; vars = vars->next_variable) {
+ /* do not output errors as values */
+- if ( vars->type == SNMP_ENDOFMIBVIEW ||
+- vars->type == SNMP_NOSUCHOBJECT ||
++ if ( vars->type == SNMP_ENDOFMIBVIEW ||
++ vars->type == SNMP_NOSUCHOBJECT ||
+ vars->type == SNMP_NOSUCHINSTANCE ) {
+ if ((st & SNMP_CMD_WALK) && Z_TYPE_P(return_value) == IS_ARRAY) {
+ break;
+@@ -816,8 +816,8 @@ retry:
+ php_snmp_error(getThis(), NULL TSRMLS_CC, PHP_SNMP_ERRNO_ERROR_IN_REPLY, "Error in packet at '%s': %s", buf, buf2);
+ continue;
+ }
+-
+- if ((st & SNMP_CMD_WALK) &&
++
++ if ((st & SNMP_CMD_WALK) &&
+ (vars->name_length < rootlen || memcmp(root, vars->name, rootlen * sizeof(oid)))) { /* not part of this subtree */
+ if (Z_TYPE_P(return_value) == IS_ARRAY) { /* some records are fetched already, shut down further lookup */
+ keepwalking = 0;
+@@ -1101,7 +1101,7 @@ static int php_snmp_parse_oid(zval *object, int st, struct objid_query *objid_qu
+ efree(objid_query->vars);
+ return FALSE;
+ }
+- } else {
++ } else {
+ memmove((char *)objid_query->vars[0].name, (char *)objid_mib, sizeof(objid_mib));
+ objid_query->vars[0].name_length = sizeof(objid_mib) / sizeof(oid);
+ }
+@@ -1437,7 +1437,7 @@ static void php_snmp(INTERNAL_FUNCTION_PARAMETERS, int st, int version)
+ int session_less_mode = (getThis() == NULL);
+ php_snmp_object *snmp_object;
+ php_snmp_object glob_snmp_object;
+-
++
+ objid_query.max_repetitions = -1;
+ objid_query.non_repeaters = 0;
+ objid_query.valueretrieval = SNMP_G(valueretrieval);
+@@ -1550,7 +1550,7 @@ static void php_snmp(INTERNAL_FUNCTION_PARAMETERS, int st, int version)
+ }
+
+ php_snmp_internal(INTERNAL_FUNCTION_PARAM_PASSTHRU, st, session, &objid_query);
+-
++
+ efree(objid_query.vars);
+
+ if (session_less_mode) {
+@@ -1563,7 +1563,7 @@ static void php_snmp(INTERNAL_FUNCTION_PARAMETERS, int st, int version)
+ }
+ /* }}} */
+
+-/* {{{ proto mixed snmpget(string host, string community, mixed object_id [, int timeout [, int retries]])
++/* {{{ proto mixed snmpget(string host, string community, mixed object_id [, int timeout [, int retries]])
+ Fetch a SNMP object */
+ PHP_FUNCTION(snmpget)
+ {
+@@ -1571,7 +1571,7 @@ PHP_FUNCTION(snmpget)
+ }
+ /* }}} */
+
+-/* {{{ proto mixed snmpgetnext(string host, string community, mixed object_id [, int timeout [, int retries]])
++/* {{{ proto mixed snmpgetnext(string host, string community, mixed object_id [, int timeout [, int retries]])
+ Fetch a SNMP object */
+ PHP_FUNCTION(snmpgetnext)
+ {
+@@ -1579,7 +1579,7 @@ PHP_FUNCTION(snmpgetnext)
+ }
+ /* }}} */
+
+-/* {{{ proto mixed snmpwalk(string host, string community, mixed object_id [, int timeout [, int retries]])
++/* {{{ proto mixed snmpwalk(string host, string community, mixed object_id [, int timeout [, int retries]])
+ Return all objects under the specified object id */
+ PHP_FUNCTION(snmpwalk)
+ {
+@@ -1595,7 +1595,7 @@ PHP_FUNCTION(snmprealwalk)
+ }
+ /* }}} */
+
+-/* {{{ proto bool snmpset(string host, string community, mixed object_id, mixed type, mixed value [, int timeout [, int retries]])
++/* {{{ proto bool snmpset(string host, string community, mixed object_id, mixed type, mixed value [, int timeout [, int retries]])
+ Set the value of a SNMP object */
+ PHP_FUNCTION(snmpset)
+ {
+@@ -1642,7 +1642,7 @@ PHP_FUNCTION(snmp_set_enum_print)
+
+ netsnmp_ds_set_boolean(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_PRINT_NUMERIC_ENUM, (int) a1);
+ RETURN_TRUE;
+-}
++}
+ /* }}} */
+
+ /* {{{ proto bool snmp_set_oid_output_format(int oid_format)
+@@ -1670,10 +1670,10 @@ PHP_FUNCTION(snmp_set_oid_output_format)
+ RETURN_FALSE;
+ break;
+ }
+-}
++}
+ /* }}} */
+
+-/* {{{ proto mixed snmp2_get(string host, string community, mixed object_id [, int timeout [, int retries]])
++/* {{{ proto mixed snmp2_get(string host, string community, mixed object_id [, int timeout [, int retries]])
+ Fetch a SNMP object */
+ PHP_FUNCTION(snmp2_get)
+ {
+@@ -1681,7 +1681,7 @@ PHP_FUNCTION(snmp2_get)
+ }
+ /* }}} */
+
+-/* {{{ proto mixed snmp2_getnext(string host, string community, mixed object_id [, int timeout [, int retries]])
++/* {{{ proto mixed snmp2_getnext(string host, string community, mixed object_id [, int timeout [, int retries]])
+ Fetch a SNMP object */
+ PHP_FUNCTION(snmp2_getnext)
+ {
+@@ -1689,7 +1689,7 @@ PHP_FUNCTION(snmp2_getnext)
+ }
+ /* }}} */
+
+-/* {{{ proto mixed snmp2_walk(string host, string community, mixed object_id [, int timeout [, int retries]])
++/* {{{ proto mixed snmp2_walk(string host, string community, mixed object_id [, int timeout [, int retries]])
+ Return all objects under the specified object id */
+ PHP_FUNCTION(snmp2_walk)
+ {
+@@ -1705,7 +1705,7 @@ PHP_FUNCTION(snmp2_real_walk)
+ }
+ /* }}} */
+
+-/* {{{ proto bool snmp2_set(string host, string community, mixed object_id, mixed type, mixed value [, int timeout [, int retries]])
++/* {{{ proto bool snmp2_set(string host, string community, mixed object_id, mixed type, mixed value [, int timeout [, int retries]])
+ Set the value of a SNMP object */
+ PHP_FUNCTION(snmp2_set)
+ {
+@@ -1821,7 +1821,7 @@ PHP_METHOD(snmp, __construct)
+
+ snmp_object = (php_snmp_object *)zend_object_store_get_object(object TSRMLS_CC);
+ zend_replace_error_handling(EH_THROW, NULL, &error_handling TSRMLS_CC);
+-
++
+ if (zend_parse_parameters(argc TSRMLS_CC, "lss|ll", &version, &a1, &a1_len, &a2, &a2_len, &timeout, &retries) == FAILURE) {
+ zend_restore_error_handling(&error_handling TSRMLS_CC);
+ return;
+@@ -1843,7 +1843,7 @@ PHP_METHOD(snmp, __construct)
+ if (snmp_object->session) {
+ netsnmp_session_free(&(snmp_object->session));
+ }
+-
++
+ if (netsnmp_session_init(&(snmp_object->session), version, a1, a2, timeout, retries TSRMLS_CC)) {
+ return;
+ }
+@@ -1857,7 +1857,7 @@ PHP_METHOD(snmp, __construct)
+ }
+ /* }}} */
+
+-/* {{{ proto bool SNMP::close()
++/* {{{ proto bool SNMP::close()
+ Close SNMP session */
+ PHP_METHOD(snmp, close)
+ {
+@@ -1900,7 +1900,7 @@ PHP_METHOD(snmp, walk)
+ }
+ /* }}} */
+
+-/* {{{ proto bool SNMP::set(mixed object_id, mixed type, mixed value)
++/* {{{ proto bool SNMP::set(mixed object_id, mixed type, mixed value)
+ Set the value of a SNMP object */
+ PHP_METHOD(snmp, set)
+ {
+@@ -1918,7 +1918,7 @@ PHP_METHOD(snmp, setSecurity)
+ int argc = ZEND_NUM_ARGS();
+
+ snmp_object = (php_snmp_object *)zend_object_store_get_object(object TSRMLS_CC);
+-
++
+ if (zend_parse_parameters(argc TSRMLS_CC, "s|ssssss", &a1, &a1_len, &a2, &a2_len, &a3, &a3_len,
+ &a4, &a4_len, &a5, &a5_len, &a6, &a6_len, &a7, &a7_len) == FAILURE) {
+ RETURN_FALSE;
+@@ -1932,7 +1932,7 @@ PHP_METHOD(snmp, setSecurity)
+ }
+ /* }}} */
+
+-/* {{{ proto long SNMP::getErrno()
++/* {{{ proto long SNMP::getErrno()
+ Get last error code number */
+ PHP_METHOD(snmp, getErrno)
+ {
+@@ -1946,7 +1946,7 @@ PHP_METHOD(snmp, getErrno)
+ }
+ /* }}} */
+
+-/* {{{ proto long SNMP::getError()
++/* {{{ proto long SNMP::getError()
+ Get last error message */
+ PHP_METHOD(snmp, getError)
+ {
+@@ -2095,6 +2095,14 @@ static int php_snmp_has_property(zval *object, zval *member, int has_set_exists,
+ }
+ /* }}} */
+
++static HashTable *php_snmp_get_gc(zval *object, zval ***gc_data, int *gc_data_count TSRMLS_DC) /* {{{ */
++{
++ *gc_data = NULL;
++ *gc_data_count = 0;
++ return zend_std_get_properties(object TSRMLS_CC);
++}
++/* }}} */
++
+ /* {{{ php_snmp_get_properties(zval *object)
+ Returns all object properties. Injects SNMP properties into object on first call */
+ static HashTable *php_snmp_get_properties(zval *object TSRMLS_DC)
+@@ -2137,23 +2145,23 @@ static int php_snmp_read_info(php_snmp_object *snmp_object, zval **retval TSRMLS
+ if (snmp_object->session == NULL) {
+ return SUCCESS;
+ }
+-
++
+ MAKE_STD_ZVAL(val);
+ ZVAL_STRINGL(val, snmp_object->session->peername, strlen(snmp_object->session->peername), 1);
+ add_assoc_zval(*retval, "hostname", val);
+-
++
+ MAKE_STD_ZVAL(val);
+ ZVAL_LONG(val, snmp_object->session->remote_port);
+ add_assoc_zval(*retval, "port", val);
+-
++
+ MAKE_STD_ZVAL(val);
+ ZVAL_LONG(val, snmp_object->session->timeout);
+ add_assoc_zval(*retval, "timeout", val);
+-
++
+ MAKE_STD_ZVAL(val);
+ ZVAL_LONG(val, snmp_object->session->retries);
+ add_assoc_zval(*retval, "retries", val);
+-
++
+ return SUCCESS;
+ }
+ /* }}} */
+@@ -2226,7 +2234,7 @@ static int php_snmp_write_max_oids(php_snmp_object *snmp_object, zval *newval TS
+ } else {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "max_oids should be positive integer or NULL, got %ld", Z_LVAL_P(newval));
+ }
+-
++
+ if (newval == &ztmp) {
+ zval_dtor(newval);
+ }
+@@ -2254,7 +2262,7 @@ static int php_snmp_write_valueretrieval(php_snmp_object *snmp_object, zval *new
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unknown SNMP value retrieval method '%ld'", Z_LVAL_P(newval));
+ ret = FAILURE;
+ }
+-
++
+ if (newval == &ztmp) {
+ zval_dtor(newval);
+ }
+@@ -2297,7 +2305,7 @@ static int php_snmp_write_oid_output_format(php_snmp_object *snmp_object, zval *
+ convert_to_long(&ztmp);
+ newval = &ztmp;
+ }
+-
++
+ switch(Z_LVAL_P(newval)) {
+ case NETSNMP_OID_OUTPUT_SUFFIX:
+ case NETSNMP_OID_OUTPUT_MODULE:
+@@ -2332,7 +2340,7 @@ static int php_snmp_write_exceptions_enabled(php_snmp_object *snmp_object, zval
+ newval = &ztmp;
+ }
+
+- snmp_object->exceptions_enabled = Z_LVAL_P(newval);
++ snmp_object->exceptions_enabled = Z_LVAL_P(newval);
+
+ if (newval == &ztmp) {
+ zval_dtor(newval);
+@@ -2401,6 +2409,7 @@ PHP_MINIT_FUNCTION(snmp)
+ php_snmp_object_handlers.write_property = php_snmp_write_property;
+ php_snmp_object_handlers.has_property = php_snmp_has_property;
+ php_snmp_object_handlers.get_properties = php_snmp_get_properties;
++ php_snmp_object_handlers.get_gc = php_snmp_get_gc;
+
+ /* Register SNMP Class */
+ INIT_CLASS_ENTRY(ce, "SNMP", php_snmp_class_methods);
+@@ -2467,7 +2476,7 @@ PHP_MINIT_FUNCTION(snmp)
+ PHP_MSHUTDOWN_FUNCTION(snmp)
+ {
+ snmp_shutdown("snmpapp");
+-
++
+ zend_hash_destroy(&php_snmp_properties);
+
+ return SUCCESS;
+diff --git a/ext/snmp/tests/bug72479.phpt b/ext/snmp/tests/bug72479.phpt
+new file mode 100644
+index 0000000..0308754
+--- /dev/null
++++ b/ext/snmp/tests/bug72479.phpt
+@@ -0,0 +1,35 @@
++--TEST--
++Bug #72479: Use After Free Vulnerability in SNMP with GC and unserialize()
++--SKIPIF--
++<?php
++require_once(dirname(__FILE__).'/skipif.inc');
++?>
++--FILE--
++<?php
++$arr = [1, [1, 2, 3, 4, 5], 3, 4, 5];
++$poc = 'a:3:{i:1;N;i:2;O:4:"snmp":1:{s:11:"quick_print";'.serialize($arr).'}i:1;R:7;}';
++$out = unserialize($poc);
++gc_collect_cycles();
++$fakezval = ptr2str(1122334455);
++$fakezval .= ptr2str(0);
++$fakezval .= "\x00\x00\x00\x00";
++$fakezval .= "\x01";
++$fakezval .= "\x00";
++$fakezval .= "\x00\x00";
++for ($i = 0; $i < 5; $i++) {
++ $v[$i] = $fakezval.$i;
++}
++var_dump($out[1]);
++
++function ptr2str($ptr)
++{
++ $out = '';
++ for ($i = 0; $i < 8; $i++) {
++ $out .= chr($ptr & 0xff);
++ $ptr >>= 8;
++ }
++ return $out;
++}
++?>
++--EXPECT--
++int(1)
+\ No newline at end of file
+--
+2.1.4
+
diff --git a/bug72513.patch b/bug72513.patch
new file mode 100644
index 0000000..5580e46
--- /dev/null
+++ b/bug72513.patch
@@ -0,0 +1,48 @@
+From 0218acb7e756a469099c4ccfb22bce6c2bd1ef87 Mon Sep 17 00:00:00 2001
+From: Stanislav Malyshev <stas@php.net>
+Date: Tue, 12 Jul 2016 21:48:00 -0700
+Subject: [PATCH] Fix for bug #72513
+
+---
+ TSRM/tsrm_virtual_cwd.c | 8 ++++----
+ 1 file changed, 4 insertions(+), 4 deletions(-)
+
+diff --git a/TSRM/tsrm_virtual_cwd.c b/TSRM/tsrm_virtual_cwd.c
+index ba92711..6c22ee8 100644
+--- a/TSRM/tsrm_virtual_cwd.c
++++ b/TSRM/tsrm_virtual_cwd.c
+@@ -621,14 +621,14 @@ CWD_API void realpath_cache_del(const char *path, int path_len TSRMLS_DC) /* {{{
+ memcmp(path, (*bucket)->path, path_len) == 0) {
+ realpath_cache_bucket *r = *bucket;
+ *bucket = (*bucket)->next;
+-
++
+ /* if the pointers match then only subtract the length of the path */
+ if(r->path == r->realpath) {
+ CWDG(realpath_cache_size) -= sizeof(realpath_cache_bucket) + r->path_len + 1;
+ } else {
+ CWDG(realpath_cache_size) -= sizeof(realpath_cache_bucket) + r->path_len + 1 + r->realpath_len + 1;
+ }
+-
++
+ free(r);
+ return;
+ } else {
+@@ -704,7 +704,7 @@ static inline realpath_cache_bucket* realpath_cache_find(const char *path, int p
+ realpath_cache_bucket *r = *bucket;
+ *bucket = (*bucket)->next;
+
+- /* if the pointers match then only subtract the length of the path */
++ /* if the pointers match then only subtract the length of the path */
+ if(r->path == r->realpath) {
+ CWDG(realpath_cache_size) -= sizeof(realpath_cache_bucket) + r->path_len + 1;
+ } else {
+@@ -1159,7 +1159,7 @@ CWD_API int virtual_file_ex(cwd_state *state, const char *path, verify_path_func
+ int add_slash;
+ void *tmp;
+
+- if (path_length == 0 || path_length >= MAXPATHLEN-1) {
++ if (path_length <= 0 || path_length >= MAXPATHLEN-1) {
+ #ifdef TSRM_WIN32
+ # if _MSC_VER < 1300
+ errno = EINVAL;
diff --git a/bug72519.patch b/bug72519.patch
new file mode 100644
index 0000000..a7f67c4
--- /dev/null
+++ b/bug72519.patch
@@ -0,0 +1,54 @@
+From 7b1572b1772dc92b2e73b7cf6d51dca88a60f411 Mon Sep 17 00:00:00 2001
+From: Pierre Joye <pierre.php@gmail.com>
+Date: Tue, 19 Jul 2016 07:11:44 +0700
+Subject: [PATCH] fix #72519, possible OOB using imagegif
+
+fix #72519, possible OOB using imagegif
+---
+ ext/gd/libgd/gd_gif_out.c | 18 ++++++++++++++++--
+ 1 file changed, 16 insertions(+), 2 deletions(-)
+
+diff --git a/ext/gd/libgd/gd_gif_out.c b/ext/gd/libgd/gd_gif_out.c
+index 1404538..0178dd9 100644
+--- a/ext/gd/libgd/gd_gif_out.c
++++ b/ext/gd/libgd/gd_gif_out.c
+@@ -601,14 +601,26 @@ compress(int init_bits, gdIOCtxPtr outfile, gdImagePtr im, GifCtx *ctx)
+ * code in turn. When the buffer fills up empty it and start over.
+ */
+
+-static unsigned long masks[] = { 0x0000, 0x0001, 0x0003, 0x0007, 0x000F,
++static const unsigned long masks[] = { 0x0000, 0x0001, 0x0003, 0x0007, 0x000F,
+ 0x001F, 0x003F, 0x007F, 0x00FF,
+ 0x01FF, 0x03FF, 0x07FF, 0x0FFF,
+ 0x1FFF, 0x3FFF, 0x7FFF, 0xFFFF };
+
++
++/* Arbitrary value to mark output is done. When we see EOFCode, then we don't
++ * expect to see any more data. If we do (e.g. corrupt image inputs), cur_bits
++ * might be negative, so flag it to return early.
++ */
++#define CUR_BITS_FINISHED -1000
++
++
+ static void
+ output(code_int code, GifCtx *ctx)
+ {
++ if (ctx->cur_bits == CUR_BITS_FINISHED) {
++ return;
++ }
++
+ ctx->cur_accum &= masks[ ctx->cur_bits ];
+
+ if( ctx->cur_bits > 0 )
+@@ -655,8 +667,10 @@ output(code_int code, GifCtx *ctx)
+ ctx->cur_bits -= 8;
+ }
+
+- flush_char(ctx);
++ /* Flag that it's done to prevent re-entry. */
++ ctx->cur_bits = CUR_BITS_FINISHED;
+
++ flush_char(ctx);
+ }
+ }
+
diff --git a/bug72520.patch b/bug72520.patch
new file mode 100644
index 0000000..3aadc04
--- /dev/null
+++ b/bug72520.patch
@@ -0,0 +1,78 @@
+From 81406c0c1d45f75fcc7972ed974d2597abb0b9e9 Mon Sep 17 00:00:00 2001
+From: Stanislav Malyshev <stas@php.net>
+Date: Tue, 12 Jul 2016 22:03:40 -0700
+Subject: [PATCH] Fix fir bug #72520
+
+---
+ ext/zip/zip_stream.c | 8 ++++----
+ 1 file changed, 4 insertions(+), 4 deletions(-)
+
+diff --git a/ext/zip/zip_stream.c b/ext/zip/zip_stream.c
+index 400edd6..a9192d2 100644
+--- a/ext/zip/zip_stream.c
++++ b/ext/zip/zip_stream.c
+@@ -214,7 +214,7 @@ php_stream *php_stream_zip_open(char *filename, char *path, char *mode STREAMS_D
+ self = emalloc(sizeof(*self));
+
+ self->za = stream_za;
+- self->zf = zf;
++ self->zf = zf;
+ self->stream = NULL;
+ self->cursor = 0;
+ stream = php_stream_alloc(&php_stream_zipio_ops, self, NULL, mode);
+@@ -241,7 +241,7 @@ php_stream *php_stream_zip_opener(php_stream_wrapper *wrapper,
+ char **opened_path,
+ php_stream_context *context STREAMS_DC TSRMLS_DC)
+ {
+- int path_len;
++ size_t path_len;
+
+ char *file_basename;
+ size_t file_basename_len;
+@@ -250,7 +250,7 @@ php_stream *php_stream_zip_opener(php_stream_wrapper *wrapper,
+ struct zip *za;
+ struct zip_file *zf = NULL;
+ char *fragment;
+- int fragment_len;
++ size_t fragment_len;
+ int err;
+
+ php_stream *stream = NULL;
+@@ -293,7 +293,7 @@ php_stream *php_stream_zip_opener(php_stream_wrapper *wrapper,
+ self = emalloc(sizeof(*self));
+
+ self->za = za;
+- self->zf = zf;
++ self->zf = zf;
+ self->stream = NULL;
+ self->cursor = 0;
+ stream = php_stream_alloc(&php_stream_zipio_ops, self, NULL, mode);
+From 8ebdb1f5fd19cb15dd6ac7700c781ede5dcbba95 Mon Sep 17 00:00:00 2001
+From: Stanislav Malyshev <stas@php.net>
+Date: Tue, 19 Jul 2016 22:37:03 -0700
+Subject: [PATCH] Improve fix for #72520
+
+---
+ ext/zip/zip_stream.c | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+diff --git a/ext/zip/zip_stream.c b/ext/zip/zip_stream.c
+index a9192d2..4517122 100644
+--- a/ext/zip/zip_stream.c
++++ b/ext/zip/zip_stream.c
+@@ -101,13 +101,13 @@ static int php_zip_ops_stat(php_stream *stream, php_stream_statbuf *ssb TSRMLS_D
+ {
+ struct zip_stat sb;
+ const char *path = stream->orig_path;
+- int path_len = strlen(stream->orig_path);
++ size_t path_len = strlen(stream->orig_path);
+ char *file_basename;
+ size_t file_basename_len;
+ char file_dirname[MAXPATHLEN];
+ struct zip *za;
+ char *fragment;
+- int fragment_len;
++ size_t fragment_len;
+ int err;
+
+ fragment = strchr(path, '#');
diff --git a/bug72533.patch b/bug72533.patch
new file mode 100644
index 0000000..63cfa1a
--- /dev/null
+++ b/bug72533.patch
@@ -0,0 +1,80 @@
+Adapted for 5.4, by Remi Collet, from:
+
+
+From aa82e99ed8003c01f1ef4f0940e56b85c5b032d4 Mon Sep 17 00:00:00 2001
+From: Stanislav Malyshev <stas@php.net>
+Date: Tue, 12 Jul 2016 22:37:36 -0700
+Subject: [PATCH] Fix bug #72533 (locale_accept_from_http out-of-bounds access)
+
+---
+ ext/intl/locale/locale_methods.c | 18 ++++++++++++++++++
+ ext/intl/tests/bug72533.phpt | 30 ++++++++++++++++++++++++++++++
+ 2 files changed, 48 insertions(+)
+ create mode 100644 ext/intl/tests/bug72533.phpt
+
+diff --git a/ext/intl/locale/locale_methods.c b/ext/intl/locale/locale_methods.c
+index 31f60b3..443856f 100644
+--- a/ext/intl/locale/locale_methods.c
++++ b/ext/intl/locale/locale_methods.c
+@@ -1596,6 +1596,24 @@ PHP_FUNCTION(locale_accept_from_http)
+ "locale_accept_from_http: unable to parse input parameters", 0 TSRMLS_CC );
+ RETURN_FALSE;
+ }
++ if(http_accept_len > ULOC_FULLNAME_CAPACITY) {
++ /* check each fragment, if any bigger than capacity, can't do it due to bug #72533 */
++ char *start = http_accept;
++ char *end;
++ size_t len;
++ do {
++ end = strchr(start, ',');
++ len = end ? end-start : http_accept_len-(start-http_accept);
++ if(len > ULOC_FULLNAME_CAPACITY) {
++ intl_error_set( NULL, U_ILLEGAL_ARGUMENT_ERROR,
++ "locale_accept_from_http: locale string too long", 0 TSRMLS_CC );
++ RETURN_FALSE;
++ }
++ if(end) {
++ start = end+1;
++ }
++ } while(end != NULL);
++ }
+
+ available = ures_openAvailableLocales(NULL, &status);
+ INTL_CHECK_STATUS(status, "locale_accept_from_http: failed to retrieve locale list");
+diff --git a/ext/intl/tests/bug72533.phpt b/ext/intl/tests/bug72533.phpt
+new file mode 100644
+index 0000000..c7fcba3
+--- /dev/null
++++ b/ext/intl/tests/bug72533.phpt
+@@ -0,0 +1,30 @@
++--TEST--
++Bug #72533 (locale_accept_from_http out-of-bounds access)
++--SKIPIF--
++<?php if( !extension_loaded( 'intl' ) ) print 'skip'; ?>
++--FILE--
++<?php
++
++function ut_main()
++{
++ $ret = var_export(ut_loc_accept_http(str_repeat('x', 256)), true);
++ $ret .= "\n";
++ if(intl_is_failure(intl_get_error_code())) {
++ $ret .= var_export(intl_get_error_message(), true);
++ }
++ $ret .= "\n";
++ $ret .= var_export(ut_loc_accept_http(str_repeat('en,', 256)), true);
++ $ret .= "\n";
++ if(intl_is_failure(intl_get_error_code())) {
++ $ret .= var_export(intl_get_error_message(), true);
++ }
++ return $ret;
++}
++
++include_once( 'ut_common.inc' );
++ut_run();
++?>
++--EXPECTF--
++false
++'locale_accept_from_http: locale string too long: U_ILLEGAL_ARGUMENT_ERROR'
++'en'
+\ No newline at end of file
diff --git a/bug72562.patch b/bug72562.patch
new file mode 100644
index 0000000..cbed3d6
--- /dev/null
+++ b/bug72562.patch
@@ -0,0 +1,73 @@
+From 3798eb6fd5dddb211b01d41495072fd9858d4e32 Mon Sep 17 00:00:00 2001
+From: Stanislav Malyshev <stas@php.net>
+Date: Tue, 12 Jul 2016 23:27:45 -0700
+Subject: [PATCH] Fix bug #72562 - destroy var_hash properly
+
+---
+ ext/session/session.c | 3 ++-
+ ext/session/tests/bug72562.phpt | 44 +++++++++++++++++++++++++++++++++++++++++
+ 2 files changed, 46 insertions(+), 1 deletion(-)
+ create mode 100644 ext/session/tests/bug72562.phpt
+
+diff --git a/ext/session/session.c b/ext/session/session.c
+index f5439ea..cb6cc01 100644
+--- a/ext/session/session.c
++++ b/ext/session/session.c
+@@ -837,6 +837,7 @@ PS_SERIALIZER_DECODE_FUNC(php_binary) /* {{{ */
+ namelen = ((unsigned char)(*p)) & (~PS_BIN_UNDEF);
+
+ if (namelen < 0 || namelen > PS_BIN_MAX || (p + namelen) >= endptr) {
++ PHP_VAR_UNSERIALIZE_DESTROY(var_hash);
+ return FAILURE;
+ }
+
+diff --git a/ext/session/tests/bug72562.phpt b/ext/session/tests/bug72562.phpt
+new file mode 100644
+index 0000000..d85e48b
+--- /dev/null
++++ b/ext/session/tests/bug72562.phpt
+@@ -0,0 +1,44 @@
++--TEST--
++Bug #72562: Use After Free in unserialize() with Unexpected Session Deserialization
++--SKIPIF--
++<?php include('skipif.inc'); ?>
++--FILE--
++<?php
++
++ini_set('session.serialize_handler', 'php_binary');
++session_start();
++$sess = "\x1xi:1;\x2y";
++session_decode($sess);
++$uns_1 = '{';
++$out_1[] = unserialize($uns_1);
++unset($out_1);
++$fakezval = ptr2str(1122334455);
++$fakezval .= ptr2str(0);
++$fakezval .= "\x00\x00\x00\x00";
++$fakezval .= "\x01";
++$fakezval .= "\x00";
++$fakezval .= "\x00\x00";
++for ($i = 0; $i < 5; $i++) {
++ $v[$i] = $fakezval.$i;
++}
++$uns_2 = 'R:2;';
++$out_2 = unserialize($uns_2);
++var_dump($out_2);
++
++function ptr2str($ptr)
++{
++ $out = '';
++ for ($i = 0; $i < 8; $i++) {
++ $out .= chr($ptr & 0xff);
++ $ptr >>= 8;
++ }
++ return $out;
++}
++?>
++--EXPECTF--
++Warning: session_decode(): Failed to decode session object. Session has been destroyed in %s/bug72562.php on line %d
++
++Notice: unserialize(): Error at offset 0 of 1 bytes in %s/bug72562.php on line %d
++
++Notice: unserialize(): Error at offset 4 of 4 bytes in %s/bug72562.php on line %d
++bool(false)
diff --git a/bug72573.patch b/bug72573.patch
new file mode 100644
index 0000000..52fa50f
--- /dev/null
+++ b/bug72573.patch
@@ -0,0 +1,464 @@
+Adapted for 5.4, by Remi Collet, from:
+
+
+From 98b9dfaec95e6f910f125ed172cdbd25abd006ec Mon Sep 17 00:00:00 2001
+From: Stanislav Malyshev <stas@php.net>
+Date: Sun, 10 Jul 2016 16:17:54 -0700
+Subject: [PATCH] Fix for HTTP_PROXY issue.
+
+The following changes are made:
+- _SERVER/_ENV only has HTTP_PROXY if the local environment has it,
+ and only one from the environment.
+- getenv('HTTP_PROXY') only returns one from the local environment
+- getenv has optional second parameter, telling it to only consider
+ local environment
+---
+ UPGRADING | 3 +++
+ ext/standard/basic_functions.c | 17 +++++++------
+ main/SAPI.c | 48 +++++++++++++++++++-----------------
+ main/php_variables.c | 56 ++++++++++++++++++++++++++++--------------
+ 4 files changed, 76 insertions(+), 48 deletions(-)
+
+diff --git a/ext/standard/basic_functions.c b/ext/standard/basic_functions.c
+index 50b6bc7..8cbba14 100644
+--- a/ext/standard/basic_functions.c
++++ b/ext/standard/basic_functions.c
+@@ -3955,21 +3955,24 @@ PHP_FUNCTION(long2ip)
+ * System Functions *
+ ********************/
+
+-/* {{{ proto string getenv(string varname)
++/* {{{ proto string getenv(string varname[, bool local_only])
+ Get the value of an environment variable */
+ PHP_FUNCTION(getenv)
+ {
+ char *ptr, *str;
+ int str_len;
++ zend_bool local_only = 0;
+
+- if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &str, &str_len) == FAILURE) {
++ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|b", &str, &str_len, &local_only) == FAILURE) {
+ RETURN_FALSE;
+ }
+
+- /* SAPI method returns an emalloc()'d string */
+- ptr = sapi_getenv(str, str_len TSRMLS_CC);
+- if (ptr) {
+- RETURN_STRING(ptr, 0);
++ if (!local_only) {
++ /* SAPI method returns an emalloc()'d string */
++ ptr = sapi_getenv(str, str_len TSRMLS_CC);
++ if (ptr) {
++ RETURN_STRING(ptr, 0);
++ }
+ }
+ #ifdef PHP_WIN32
+ {
+diff --git a/main/SAPI.c b/main/SAPI.c
+index 0dd0b55..8a56c6d 100644
+--- a/main/SAPI.c
++++ b/main/SAPI.c
+@@ -1,4 +1,4 @@
+-/*
++/*
+ +----------------------------------------------------------------------+
+ | PHP Version 5 |
+ +----------------------------------------------------------------------+
+@@ -132,7 +132,7 @@ PHP_FUNCTION(header_register_callback)
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z", &callback_func) == FAILURE) {
+ return;
+ }
+-
++
+ if (!zend_is_callable(callback_func, 0, &callback_name TSRMLS_CC)) {
+ efree(callback_name);
+ RETURN_FALSE;
+@@ -160,10 +160,10 @@ static void sapi_run_header_callback(TSRMLS_D)
+ char *callback_name = NULL;
+ char *callback_error = NULL;
+ zval *retval_ptr = NULL;
+-
++
+ if (zend_fcall_info_init(SG(callback_func), 0, &fci, &SG(fci_cache), &callback_name, &callback_error TSRMLS_CC) == SUCCESS) {
+ fci.retval_ptr_ptr = &retval_ptr;
+-
++
+ error = zend_call_function(&fci, &SG(fci_cache) TSRMLS_CC);
+ if (error == FAILURE) {
+ goto callback_failed;
+@@ -174,13 +174,13 @@ static void sapi_run_header_callback(TSRMLS_D)
+ callback_failed:
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Could not call the sapi_header_callback");
+ }
+-
++
+ if (callback_name) {
+ efree(callback_name);
+ }
+ if (callback_error) {
+ efree(callback_error);
+- }
++ }
+ }
+
+ SAPI_API void sapi_handle_post(void *arg TSRMLS_DC)
+@@ -386,11 +386,11 @@ SAPI_API void sapi_activate_headers_only(TSRMLS_D)
+ if (SG(request_info).headers_read == 1)
+ return;
+ SG(request_info).headers_read = 1;
+- zend_llist_init(&SG(sapi_headers).headers, sizeof(sapi_header_struct),
++ zend_llist_init(&SG(sapi_headers).headers, sizeof(sapi_header_struct),
+ (void (*)(void *)) sapi_free_header, 0);
+ SG(sapi_headers).send_default_content_type = 1;
+
+- /* SG(sapi_headers).http_response_code = 200; */
++ /* SG(sapi_headers).http_response_code = 200; */
+ SG(sapi_headers).http_status_line = NULL;
+ SG(sapi_headers).mimetype = NULL;
+ SG(read_post_bytes) = 0;
+@@ -403,7 +403,7 @@ SAPI_API void sapi_activate_headers_only(TSRMLS_D)
+ SG(global_request_time) = 0;
+
+ /*
+- * It's possible to override this general case in the activate() callback,
++ * It's possible to override this general case in the activate() callback,
+ * if necessary.
+ */
+ if (SG(request_info).request_method && !strcmp(SG(request_info).request_method, "HEAD")) {
+@@ -465,8 +465,8 @@ SAPI_API void sapi_activate(TSRMLS_D)
+ * depending on given content type */
+ sapi_read_post_data(TSRMLS_C);
+ } else {
+- /* Any other method with content payload will fill $HTTP_RAW_POST_DATA
+- * if it is enabled by always_populate_raw_post_data.
++ /* Any other method with content payload will fill $HTTP_RAW_POST_DATA
++ * if it is enabled by always_populate_raw_post_data.
+ * It's up to the webserver to decide whether to allow a method or not. */
+ SG(request_info).content_type_dup = NULL;
+ if (sapi_module.default_post_reader) {
+@@ -497,14 +497,14 @@ static void sapi_send_headers_free(TSRMLS_D)
+ SG(sapi_headers).http_status_line = NULL;
+ }
+ }
+-
++
+ SAPI_API void sapi_deactivate(TSRMLS_D)
+ {
+ zend_llist_destroy(&SG(sapi_headers).headers);
+ if (SG(request_info).post_data) {
+ efree(SG(request_info).post_data);
+ } else if (SG(server_context)) {
+- if(sapi_module.read_post) {
++ if(sapi_module.read_post) {
+ /* make sure we've consumed all request input data */
+ char dummy[SAPI_POST_BLOCK_SIZE];
+ int read_bytes;
+@@ -516,7 +516,7 @@ SAPI_API void sapi_deactivate(TSRMLS_D)
+ }
+ if (SG(request_info).raw_post_data) {
+ efree(SG(request_info).raw_post_data);
+- }
++ }
+ if (SG(request_info).auth_user) {
+ efree(SG(request_info).auth_user);
+ }
+@@ -574,7 +574,7 @@ static int sapi_extract_response_code(const char *header_line)
+ break;
+ }
+ }
+-
++
+ return code;
+ }
+
+@@ -594,7 +594,7 @@ static void sapi_update_response_code(int ncode TSRMLS_DC)
+ SG(sapi_headers).http_response_code = ncode;
+ }
+
+-/*
++/*
+ * since zend_llist_del_element only remove one matched item once,
+ * we should remove them by ourself
+ */
+@@ -630,7 +630,7 @@ SAPI_API int sapi_add_header_ex(char *header_line, uint header_line_len, zend_bo
+ {
+ sapi_header_line ctr = {0};
+ int r;
+-
++
+ ctr.line = header_line;
+ ctr.line_len = header_line_len;
+
+@@ -724,7 +724,7 @@ SAPI_API int sapi_header_op(sapi_header_op_enum op, void *arg TSRMLS_DC)
+ } while(header_line_len && isspace(header_line[header_line_len-1]));
+ header_line[header_line_len]='\0';
+ }
+-
++
+ if (op == SAPI_HEADER_DELETE) {
+ if (strchr(header_line, ':')) {
+ efree(header_line);
+@@ -762,7 +762,7 @@ SAPI_API int sapi_header_op(sapi_header_op_enum op, void *arg TSRMLS_DC)
+ sapi_header.header_len = header_line_len;
+
+ /* Check the header for a few cases that we have special support for in SAPI */
+- if (header_line_len>=5
++ if (header_line_len>=5
+ && !strncasecmp(header_line, "HTTP/", 5)) {
+ /* filter out the response code */
+ sapi_update_response_code(sapi_extract_response_code(header_line) TSRMLS_CC);
+@@ -821,8 +821,8 @@ SAPI_API int sapi_header_op(sapi_header_op_enum op, void *arg TSRMLS_DC)
+ /* Return a Found Redirect if one is not already specified */
+ if (http_response_code) { /* user specified redirect code */
+ sapi_update_response_code(http_response_code TSRMLS_CC);
+- } else if (SG(request_info).proto_num > 1000 &&
+- SG(request_info).request_method &&
++ } else if (SG(request_info).proto_num > 1000 &&
++ SG(request_info).request_method &&
+ strcmp(SG(request_info).request_method, "HEAD") &&
+ strcmp(SG(request_info).request_method, "GET")) {
+ sapi_update_response_code(303 TSRMLS_CC);
+@@ -1011,7 +1011,11 @@ SAPI_API struct stat *sapi_get_stat(TSRMLS_D)
+
+ SAPI_API char *sapi_getenv(char *name, size_t name_len TSRMLS_DC)
+ {
+- if (sapi_module.getenv) {
++ if (!strncasecmp(name, "HTTP_PROXY", name_len)) {
++ /* Ugly fix for HTTP_PROXY issue */
++ return NULL;
++ }
++ if (sapi_module.getenv) {
+ char *value, *tmp = sapi_module.getenv(name, name_len TSRMLS_CC);
+ if (tmp) {
+ value = estrdup(tmp);
+diff --git a/main/php_variables.c b/main/php_variables.c
+index bf6b9f3..bbe57d3 100644
+--- a/main/php_variables.c
++++ b/main/php_variables.c
+@@ -44,7 +4443,7 @@ PHPAPI void php_register_variable_safe(char *var, char *strval, int str_len, zva
+ {
+ zval new_entry;
+ assert(strval != NULL);
+-
++
+ /* Prepare value */
+ Z_STRLEN(new_entry) = str_len;
+ Z_STRVAL(new_entry) = estrndup(strval, Z_STRLEN(new_entry));
+@@ -82,7 +82,7 @@ PHPAPI void php_register_variable_ex(char *var_name, zval *val, zval *track_vars
+ while (*var_name && *var_name==' ') {
+ var_name++;
+ }
+-
++
+ /*
+ * Prepare variable name
+ */
+@@ -168,7 +168,7 @@ PHPAPI void php_register_variable_ex(char *var_name, zval *val, zval *track_vars
+ return;
+ }
+ *ip = 0;
+- new_idx_len = strlen(index_s);
++ new_idx_len = strlen(index_s);
+ }
+
+ if (!index) {
+@@ -211,7 +211,7 @@ PHPAPI void php_register_variable_ex(char *var_name, zval *val, zval *track_vars
+ zval_ptr_dtor(&gpc_element);
+ }
+ } else {
+- /*
++ /*
+ * According to rfc2965, more specific paths are listed above the less specific ones.
+ * If we encounter a duplicate cookie name, we should skip it, since it is not possible
+ * to have the same (plain text) cookie name for the same path and we should not overwrite
+@@ -237,7 +237,7 @@ SAPI_API SAPI_POST_HANDLER_FUNC(php_std_post_handler)
+
+ if (SG(request_info).post_data == NULL) {
+ return;
+- }
++ }
+
+ s = SG(request_info).post_data;
+ e = s + SG(request_info).post_data_length;
+@@ -285,7 +285,7 @@ SAPI_API SAPI_TREAT_DATA_FUNC(php_default_treat_data)
+ int free_buffer = 0;
+ char *strtok_buf = NULL;
+ long count = 0;
+-
++
+ switch (arg) {
+ case PARSE_POST:
+ case PARSE_GET:
+@@ -358,9 +358,9 @@ SAPI_API SAPI_TREAT_DATA_FUNC(php_default_treat_data)
+ separator = ";\0";
+ break;
+ }
+-
++
+ var = php_strtok_r(res, separator, &strtok_buf);
+-
++
+ while (var) {
+ val = strchr(var, '=');
+
+@@ -455,11 +455,11 @@ static void php_build_argv(char *s, zval *track_vars_array TSRMLS_DC)
+ zval *arr, *argc, *tmp;
+ int count = 0;
+ char *ss, *space;
+-
++
+ if (!(SG(request_info).argc || track_vars_array)) {
+ return;
+ }
+-
++
+ ALLOC_INIT_ZVAL(arr);
+ array_init(arr);
+
+@@ -520,7 +520,7 @@ static void php_build_argv(char *s, zval *track_vars_array TSRMLS_DC)
+ Z_ADDREF_P(argc);
+ zend_hash_update(&EG(symbol_table), "argv", sizeof("argv"), &arr, sizeof(zval *), NULL);
+ zend_hash_update(&EG(symbol_table), "argc", sizeof("argc"), &argc, sizeof(zval *), NULL);
+- }
++ }
+ if (track_vars_array) {
+ Z_ADDREF_P(arr);
+ Z_ADDREF_P(argc);
+@@ -666,7 +666,7 @@ static zend_bool php_auto_globals_create_get(const char *name, uint name_len TSR
+
+ zend_hash_update(&EG(symbol_table), name, name_len + 1, &vars, sizeof(zval *), NULL);
+ Z_ADDREF_P(vars);
+-
++
+ return 0; /* don't rearm */
+ }
+
+@@ -693,7 +693,7 @@ static zend_bool php_auto_globals_create_post(const char *name, uint name_len TS
+
+ zend_hash_update(&EG(symbol_table), name, name_len + 1, &vars, sizeof(zval *), NULL);
+ Z_ADDREF_P(vars);
+-
++
+ return 0; /* don't rearm */
+ }
+
+@@ -716,7 +716,7 @@ static zend_bool php_auto_globals_create_cookie(const char *name, uint name_len
+
+ zend_hash_update(&EG(symbol_table), name, name_len + 1, &vars, sizeof(zval *), NULL);
+ Z_ADDREF_P(vars);
+-
++
+ return 0; /* don't rearm */
+ }
+
+@@ -735,10 +735,26 @@ static zend_bool php_auto_globals_create_files(const char *name, uint name_len T
+
+ zend_hash_update(&EG(symbol_table), name, name_len + 1, &vars, sizeof(zval *), NULL);
+ Z_ADDREF_P(vars);
+-
++
+ return 0; /* don't rearm */
+ }
+
++/* Upgly hack to fix HTTP_PROXY issue */
++static void check_http_proxy(HashTable *var_table) {
++ if (zend_hash_exists(var_table, "HTTP_PROXY", sizeof("HTTP_PROXY"))) {
++ char *local_proxy = getenv("HTTP_PROXY");
++
++ if (!local_proxy) {
++ zend_hash_del(var_table, "HTTP_PROXY", sizeof("HTTP_PROXY"));
++ } else {
++ zval *local_zval;
++ ALLOC_INIT_ZVAL(local_zval);
++ ZVAL_STRING(local_zval, local_proxy, 1);
++ zend_hash_update(var_table, "HTTP_PROXY", sizeof("HTTP_PROXY"), &local_zval, sizeof(zval **), NULL);
++ }
++ }
++}
++
+ static zend_bool php_auto_globals_create_server(const char *name, uint name_len TSRMLS_DC)
+ {
+ if (PG(variables_order) && (strchr(PG(variables_order),'S') || strchr(PG(variables_order),'s'))) {
+@@ -747,7 +763,7 @@ static zend_bool php_auto_globals_create_server(const char *name, uint name_len
+ if (PG(register_argc_argv)) {
+ if (SG(request_info).argc) {
+ zval **argc, **argv;
+-
++
+ if (zend_hash_find(&EG(symbol_table), "argc", sizeof("argc"), (void**)&argc) == SUCCESS &&
+ zend_hash_find(&EG(symbol_table), "argv", sizeof("argv"), (void**)&argv) == SUCCESS) {
+ Z_ADDREF_PP(argc);
+@@ -759,7 +775,7 @@ static zend_bool php_auto_globals_create_server(const char *name, uint name_len
+ php_build_argv(SG(request_info).query_string, PG(http_globals)[TRACK_VARS_SERVER] TSRMLS_CC);
+ }
+ }
+-
++
+ } else {
+ zval *server_vars=NULL;
+ ALLOC_ZVAL(server_vars);
+@@ -771,9 +787,10 @@ static zend_bool php_auto_globals_create_server(const char *name, uint name_len
+ PG(http_globals)[TRACK_VARS_SERVER] = server_vars;
+ }
+
++ check_http_proxy(Z_ARRVAL_P(PG(http_globals)[TRACK_VARS_SERVER]));
+ zend_hash_update(&EG(symbol_table), name, name_len + 1, &PG(http_globals)[TRACK_VARS_SERVER], sizeof(zval *), NULL);
+ Z_ADDREF_P(PG(http_globals)[TRACK_VARS_SERVER]);
+-
++
+ return 0; /* don't rearm */
+ }
+
+@@ -787,11 +804,12 @@ static zend_bool php_auto_globals_create_env(const char *name, uint name_len TSR
+ zval_ptr_dtor(&PG(http_globals)[TRACK_VARS_ENV]);
+ }
+ PG(http_globals)[TRACK_VARS_ENV] = env_vars;
+-
++
+ if (PG(variables_order) && (strchr(PG(variables_order),'E') || strchr(PG(variables_order),'e'))) {
+ php_import_environment_variables(PG(http_globals)[TRACK_VARS_ENV] TSRMLS_CC);
+ }
+
++ check_http_proxy(Z_ARRVAL_P(PG(http_globals)[TRACK_VARS_ENV]));
+ zend_hash_update(&EG(symbol_table), name, name_len + 1, &PG(http_globals)[TRACK_VARS_ENV], sizeof(zval *), NULL);
+ Z_ADDREF_P(PG(http_globals)[TRACK_VARS_ENV]);
+
+From aca4f65c7e98b9f07ac625eaf6be8eadbeb55929 Mon Sep 17 00:00:00 2001
+From: Stanislav Malyshev <stas@php.net>
+Date: Tue, 12 Jul 2016 21:35:02 -0700
+Subject: [PATCH] CS fix and comments with bug ID
+
+---
+ main/SAPI.c | 2 +-
+ main/php_variables.c | 5 +++--
+ 2 files changed, 4 insertions(+), 3 deletions(-)
+
+diff --git a/main/SAPI.c b/main/SAPI.c
+index 8a56c6d..223c510 100644
+--- a/main/SAPI.c
++++ b/main/SAPI.c
+@@ -1012,7 +1012,7 @@ SAPI_API struct stat *sapi_get_stat(TSRMLS_D)
+ SAPI_API char *sapi_getenv(char *name, size_t name_len TSRMLS_DC)
+ {
+ if (!strncasecmp(name, "HTTP_PROXY", name_len)) {
+- /* Ugly fix for HTTP_PROXY issue */
++ /* Ugly fix for HTTP_PROXY issue, see bug #72573 */
+ return NULL;
+ }
+ if (sapi_module.getenv) {
+diff --git a/main/php_variables.c b/main/php_variables.c
+index bbe57d3..5977a5e 100644
+--- a/main/php_variables.c
++++ b/main/php_variables.c
+@@ -739,8 +739,9 @@ static zend_bool php_auto_globals_create_files(const char *name, uint name_len T
+ return 0; /* don't rearm */
+ }
+
+-/* Upgly hack to fix HTTP_PROXY issue */
+-static void check_http_proxy(HashTable *var_table) {
++/* Upgly hack to fix HTTP_PROXY issue, see bug #72573 */
++static void check_http_proxy(HashTable *var_table)
++{
+ if (zend_hash_exists(var_table, "HTTP_PROXY", sizeof("HTTP_PROXY"))) {
+ char *local_proxy = getenv("HTTP_PROXY");
+
diff --git a/bug72603.patch b/bug72603.patch
new file mode 100644
index 0000000..91d7965
--- /dev/null
+++ b/bug72603.patch
@@ -0,0 +1,76 @@
+Adapted for 5.4, by Remi Collet, binary patch removed, from:
+
+
+From eebcbd5de38a0f1c2876035402cb770e37476519 Mon Sep 17 00:00:00 2001
+From: Stanislav Malyshev <stas@php.net>
+Date: Sun, 17 Jul 2016 16:34:21 -0700
+Subject: [PATCH] Fix bug #72603: Out of bound read in
+ exif_process_IFD_in_MAKERNOTE
+
+---
+ ext/exif/exif.c | 22 ++++++++++++++++++++--
+ ext/exif/tests/bug72603.jpeg | Bin 0 -> 3711 bytes
+ ext/exif/tests/bug72603.phpt | 11 +++++++++++
+ 3 files changed, 31 insertions(+), 2 deletions(-)
+ create mode 100644 ext/exif/tests/bug72603.jpeg
+ create mode 100644 ext/exif/tests/bug72603.phpt
+
+diff --git a/ext/exif/exif.c b/ext/exif/exif.c
+index f366acc..760e746 100644
+--- a/ext/exif/exif.c
++++ b/ext/exif/exif.c
+@@ -2742,6 +2742,12 @@ static int exif_process_IFD_in_MAKERNOTE(image_info_type *ImageInfo, char * valu
+ break;
+ }
+
++ if (maker_note->offset >= value_len) {
++ /* Do not go past the value end */
++ exif_error_docref("exif_read_data#error_ifd" EXIFERR_CC, ImageInfo, E_WARNING, "IFD data too short: 0x%04X offset 0x%04X", value_len, maker_note->offset);
++ return FALSE;
++ }
++
+ dir_start = value_ptr + maker_note->offset;
+
+ #ifdef EXIF_DEBUG
+@@ -2770,10 +2776,19 @@ static int exif_process_IFD_in_MAKERNOTE(image_info_type *ImageInfo, char * valu
+ offset_base = value_ptr;
+ break;
+ case MN_OFFSET_GUESS:
++ if (maker_note->offset + 10 + 4 >= value_len) {
++ /* Can not read dir_start+10 since it's beyond value end */
++ exif_error_docref("exif_read_data#error_ifd" EXIFERR_CC, ImageInfo, E_WARNING, "IFD data too short: 0x%04X", value_len);
++ return FALSE;
++ }
+ offset_diff = 2 + NumDirEntries*12 + 4 - php_ifd_get32u(dir_start+10, ImageInfo->motorola_intel);
+ #ifdef EXIF_DEBUG
+ exif_error_docref(NULL EXIFERR_CC, ImageInfo, E_NOTICE, "Using automatic offset correction: 0x%04X", ((int)dir_start-(int)offset_base+maker_note->offset+displacement) + offset_diff);
+ #endif
++ if (offset_diff < 0 || offset_diff >= value_len ) {
++ exif_error_docref("exif_read_data#error_ifd" EXIFERR_CC, ImageInfo, E_WARNING, "IFD data bad offset: 0x%04X length 0x%04X", offset_diff, value_len);
++ return FALSE;
++ }
+ offset_base = value_ptr + offset_diff;
+ break;
+ default:
+@@ -2782,7 +2797,7 @@ static int exif_process_IFD_in_MAKERNOTE(image_info_type *ImageInfo, char * valu
+ }
+
+ if ((2+NumDirEntries*12) > value_len) {
+- exif_error_docref("exif_read_data#error_ifd" EXIFERR_CC, ImageInfo, E_WARNING, "Illegal IFD size: 2 + x%04X*12 = x%04X > x%04X", NumDirEntries, 2+NumDirEntries*12, value_len);
++ exif_error_docref("exif_read_data#error_ifd" EXIFERR_CC, ImageInfo, E_WARNING, "Illegal IFD size: 2 + 0x%04X*12 = 0x%04X > 0x%04X", NumDirEntries, 2+NumDirEntries*12, value_len);
+ return FALSE;
+ }
+
+@@ -3068,7 +3083,10 @@ static int exif_process_IFD_TAG(image_info_type *ImageInfo, char *dir_entry, cha
+ break;
+
+ case TAG_MAKER_NOTE:
+- exif_process_IFD_in_MAKERNOTE(ImageInfo, value_ptr, byte_count, offset_base, IFDlength, displacement TSRMLS_CC);
++ if (!exif_process_IFD_in_MAKERNOTE(ImageInfo, value_ptr, byte_count, offset_base, IFDlength, displacement TSRMLS_CC)) {
++ EFREE_IF(outside);
++ return FALSE;
++ }
+ break;
+
+ case TAG_EXIF_IFD_POINTER:
+
diff --git a/bug72606.patch b/bug72606.patch
new file mode 100644
index 0000000..1d2707a
--- /dev/null
+++ b/bug72606.patch
@@ -0,0 +1,152 @@
+From e6c48213c22ed50b2b987b479fcc1ac709394caa Mon Sep 17 00:00:00 2001
+From: Stanislav Malyshev <stas@php.net>
+Date: Mon, 18 Jul 2016 21:44:39 -0700
+Subject: [PATCH] Fix bug #72606: heap-buffer-overflow (write)
+ simplestring_addn simplestring.c
+
+---
+ ext/xmlrpc/libxmlrpc/simplestring.c | 61 ++++++++++++++++++++++---------------
+ ext/xmlrpc/libxmlrpc/simplestring.h | 2 +-
+ 2 files changed, 38 insertions(+), 25 deletions(-)
+
+diff --git a/ext/xmlrpc/libxmlrpc/simplestring.c b/ext/xmlrpc/libxmlrpc/simplestring.c
+index a084d0e..6477734 100644
+--- a/ext/xmlrpc/libxmlrpc/simplestring.c
++++ b/ext/xmlrpc/libxmlrpc/simplestring.c
+@@ -5,28 +5,28 @@
+ Epinions.com may be contacted at feedback@epinions-inc.com
+ */
+
+-/*
+- Copyright 2000 Epinions, Inc.
++/*
++ Copyright 2000 Epinions, Inc.
+
+- Subject to the following 3 conditions, Epinions, Inc. permits you, free
+- of charge, to (a) use, copy, distribute, modify, perform and display this
+- software and associated documentation files (the "Software"), and (b)
+- permit others to whom the Software is furnished to do so as well.
++ Subject to the following 3 conditions, Epinions, Inc. permits you, free
++ of charge, to (a) use, copy, distribute, modify, perform and display this
++ software and associated documentation files (the "Software"), and (b)
++ permit others to whom the Software is furnished to do so as well.
+
+- 1) The above copyright notice and this permission notice shall be included
+- without modification in all copies or substantial portions of the
+- Software.
++ 1) The above copyright notice and this permission notice shall be included
++ without modification in all copies or substantial portions of the
++ Software.
+
+- 2) THE SOFTWARE IS PROVIDED "AS IS", WITHOUT ANY WARRANTY OR CONDITION OF
+- ANY KIND, EXPRESS, IMPLIED OR STATUTORY, INCLUDING WITHOUT LIMITATION ANY
+- IMPLIED WARRANTIES OF ACCURACY, MERCHANTABILITY, FITNESS FOR A PARTICULAR
+- PURPOSE OR NONINFRINGEMENT.
++ 2) THE SOFTWARE IS PROVIDED "AS IS", WITHOUT ANY WARRANTY OR CONDITION OF
++ ANY KIND, EXPRESS, IMPLIED OR STATUTORY, INCLUDING WITHOUT LIMITATION ANY
++ IMPLIED WARRANTIES OF ACCURACY, MERCHANTABILITY, FITNESS FOR A PARTICULAR
++ PURPOSE OR NONINFRINGEMENT.
+
+- 3) IN NO EVENT SHALL EPINIONS, INC. BE LIABLE FOR ANY DIRECT, INDIRECT,
+- SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES OR LOST PROFITS ARISING OUT
+- OF OR IN CONNECTION WITH THE SOFTWARE (HOWEVER ARISING, INCLUDING
+- NEGLIGENCE), EVEN IF EPINIONS, INC. IS AWARE OF THE POSSIBILITY OF SUCH
+- DAMAGES.
++ 3) IN NO EVENT SHALL EPINIONS, INC. BE LIABLE FOR ANY DIRECT, INDIRECT,
++ SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES OR LOST PROFITS ARISING OUT
++ OF OR IN CONNECTION WITH THE SOFTWARE (HOWEVER ARISING, INCLUDING
++ NEGLIGENCE), EVEN IF EPINIONS, INC. IS AWARE OF THE POSSIBILITY OF SUCH
++ DAMAGES.
+
+ */
+
+@@ -71,7 +71,7 @@ static const char rcsid[] = "#(@) $Id$";
+ *
+ * Oh, and it is also binary safe, ie it can handle strings with embedded NULLs,
+ * so long as the real length is passed in.
+- *
++ *
+ * And the masses rejoiced.
+ *
+ * BUGS
+@@ -136,7 +136,7 @@ static void simplestring_init_str(simplestring* string) {
+ * NOTES
+ * This function is very fast as it does not de-allocate any memory.
+ * SEE ALSO
+- *
++ *
+ * SOURCE
+ */
+ void simplestring_clear(simplestring* string) {
+@@ -190,18 +190,31 @@ void simplestring_free(simplestring* string) {
+ * simplestring_add ()
+ * SOURCE
+ */
+-void simplestring_addn(simplestring* target, const char* source, int add_len) {
++void simplestring_addn(simplestring* target, const char* source, size_t add_len) {
++ size_t newsize = target->size, incr = 0;
+ if(target && source) {
+ if(!target->str) {
+ simplestring_init_str(target);
+ }
++
++ if((SIZE_MAX - add_len) < target->len || (SIZE_MAX - add_len - 1) < target->len) {
++ /* check for overflows, if there's a potential overflow do nothing */
++ return;
++ }
++
+ if(target->len + add_len + 1 > target->size) {
+ /* newsize is current length + new length */
+- int newsize = target->len + add_len + 1;
+- int incr = target->size * 2;
++ newsize = target->len + add_len + 1;
++ incr = target->size * 2;
+
+ /* align to SIMPLESTRING_INCR increments */
+- newsize = newsize - (newsize % incr) + incr;
++ if (incr) {
++ newsize = newsize - (newsize % incr) + incr;
++ }
++ if(newsize < (target->len + add_len + 1)) {
++ /* some kind of overflow happened */
++ return;
++ }
+ target->str = (char*)realloc(target->str, newsize);
+
+ target->size = target->str ? newsize : 0;
+diff --git a/ext/xmlrpc/libxmlrpc/simplestring.h b/ext/xmlrpc/libxmlrpc/simplestring.h
+index c5d98cf..7e88cd0 100644
+--- a/ext/xmlrpc/libxmlrpc/simplestring.h
++++ b/ext/xmlrpc/libxmlrpc/simplestring.h
+@@ -63,7 +63,7 @@ void simplestring_init(simplestring* string);
+ void simplestring_clear(simplestring* string);
+ void simplestring_free(simplestring* string);
+ void simplestring_add(simplestring* string, const char* add);
+-void simplestring_addn(simplestring* string, const char* add, int add_len);
++void simplestring_addn(simplestring* string, const char* add, size_t add_len);
+
+ #ifdef __cplusplus
+ }
+From 33c1a55b40900c61ce7e162648eb71ce9b25837c Mon Sep 17 00:00:00 2001
+From: Stanislav Malyshev <stas@php.net>
+Date: Tue, 19 Jul 2016 00:13:25 -0700
+Subject: [PATCH] Apparently some envs miss SIZE_MAX
+
+---
+ ext/xmlrpc/libxmlrpc/simplestring.c | 3 +++
+ 1 file changed, 3 insertions(+)
+
+diff --git a/ext/xmlrpc/libxmlrpc/simplestring.c b/ext/xmlrpc/libxmlrpc/simplestring.c
+index 6477734..c88754f 100644
+--- a/ext/xmlrpc/libxmlrpc/simplestring.c
++++ b/ext/xmlrpc/libxmlrpc/simplestring.c
+@@ -172,6 +172,9 @@ void simplestring_free(simplestring* string) {
+ }
+ /******/
+
++#ifndef SIZE_MAX
++#define SIZE_MAX ((size_t)-1)
++#endif
+ /****f* FUNC/simplestring_addn
+ * NAME
+ * simplestring_addn
diff --git a/bug72613.patch b/bug72613.patch
new file mode 100644
index 0000000..231f573
--- /dev/null
+++ b/bug72613.patch
@@ -0,0 +1,281 @@
+Adapted for 5.4, by Remi Collet, binary patch removed, from:
+
+
+From f3feddb5b45b5abd93abb1a95044b7e099d51c84 Mon Sep 17 00:00:00 2001
+From: Stanislav Malyshev <stas@php.net>
+Date: Mon, 18 Jul 2016 22:20:45 -0700
+Subject: [PATCH] Partial fix for bug #72613 - do not treat negative returns
+ from bz2 as size_t
+
+---
+ ext/bz2/bz2.c | 80 +++++++++++++++++++++++---------------------
+ ext/bz2/tests/72613.bz2 | Bin 0 -> 351 bytes
+ ext/bz2/tests/bug72613.phpt | 23 +++++++++++++
+ 3 files changed, 65 insertions(+), 38 deletions(-)
+ create mode 100644 ext/bz2/tests/72613.bz2
+ create mode 100644 ext/bz2/tests/bug72613.phpt
+
+diff --git a/ext/bz2/bz2.c b/ext/bz2/bz2.c
+index de3250e..7cfcaa8 100644
+--- a/ext/bz2/bz2.c
++++ b/ext/bz2/bz2.c
+@@ -15,7 +15,7 @@
+ | Author: Sterling Hughes <sterling@php.net> |
+ +----------------------------------------------------------------------+
+ */
+-
++
+ /* $Id$ */
+
+ #ifdef HAVE_CONFIG_H
+@@ -137,29 +137,33 @@ struct php_bz2_stream_data_t {
+ static size_t php_bz2iop_read(php_stream *stream, char *buf, size_t count TSRMLS_DC)
+ {
+ struct php_bz2_stream_data_t *self = (struct php_bz2_stream_data_t *) stream->abstract;
+- size_t ret;
+-
+- ret = BZ2_bzread(self->bz_file, buf, count);
++ int bz2_ret;
++
++ bz2_ret = BZ2_bzread(self->bz_file, buf, count);
+
+- if (ret == 0) {
++ if (bz2_ret < 0) {
++ stream->eof = 1;
++ return -1;
++ }
++ if (bz2_ret == 0) {
+ stream->eof = 1;
+ }
+
+- return ret;
++ return (size_t)bz2_ret;
+ }
+
+ static size_t php_bz2iop_write(php_stream *stream, const char *buf, size_t count TSRMLS_DC)
+ {
+ struct php_bz2_stream_data_t *self = (struct php_bz2_stream_data_t *) stream->abstract;
+
+- return BZ2_bzwrite(self->bz_file, (char*)buf, count);
++ return BZ2_bzwrite(self->bz_file, (char*)buf, count);
+ }
+
+ static int php_bz2iop_close(php_stream *stream, int close_handle TSRMLS_DC)
+ {
+ struct php_bz2_stream_data_t *self = (struct php_bz2_stream_data_t *)stream->abstract;
+ int ret = EOF;
+-
++
+ if (close_handle) {
+ BZ2_bzclose(self->bz_file);
+ }
+@@ -191,11 +195,11 @@ php_stream_ops php_stream_bz2io_ops = {
+ };
+
+ /* {{{ Bzip2 stream openers */
+-PHP_BZ2_API php_stream *_php_stream_bz2open_from_BZFILE(BZFILE *bz,
++PHP_BZ2_API php_stream *_php_stream_bz2open_from_BZFILE(BZFILE *bz,
+ char *mode, php_stream *innerstream STREAMS_DC TSRMLS_DC)
+ {
+ struct php_bz2_stream_data_t *self;
+-
++
+ self = emalloc(sizeof(*self));
+
+ self->stream = innerstream;
+@@ -226,7 +230,7 @@ PHP_BZ2_API php_stream *_php_stream_bz2open(php_stream_wrapper *wrapper,
+ virtual_filepath_ex(path, &path_copy, NULL TSRMLS_CC);
+ #else
+ path_copy = path;
+-#endif
++#endif
+
+ if (php_check_open_basedir(path_copy TSRMLS_CC)) {
+ #ifdef VIRTUAL_DIR
+@@ -234,7 +238,7 @@ PHP_BZ2_API php_stream *_php_stream_bz2open(php_stream_wrapper *wrapper,
+ #endif
+ return NULL;
+ }
+-
++
+ /* try and open it directly first */
+ bz_file = BZ2_bzopen(path_copy, mode);
+
+@@ -245,11 +249,11 @@ PHP_BZ2_API php_stream *_php_stream_bz2open(php_stream_wrapper *wrapper,
+ free(path_copy);
+ #endif
+ path_copy = NULL;
+-
++
+ if (bz_file == NULL) {
+ /* that didn't work, so try and get something from the network/wrapper */
+ stream = php_stream_open_wrapper(path, mode, options | STREAM_WILL_CAST, opened_path);
+-
++
+ if (stream) {
+ int fd;
+ if (SUCCESS == php_stream_cast(stream, PHP_STREAM_AS_FD, (void **) &fd, REPORT_ERRORS)) {
+@@ -264,7 +268,7 @@ PHP_BZ2_API php_stream *_php_stream_bz2open(php_stream_wrapper *wrapper,
+ VCWD_UNLINK(*opened_path);
+ }
+ }
+-
++
+ if (bz_file) {
+ retstream = _php_stream_bz2open_from_BZFILE(bz_file, mode, stream STREAMS_REL_CC TSRMLS_CC);
+ if (retstream) {
+@@ -340,7 +344,7 @@ static PHP_FUNCTION(bzread)
+ if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r|l", &bz, &len)) {
+ RETURN_FALSE;
+ }
+-
++
+ php_stream_from_zval(stream, &bz);
+
+ if ((len + 1) < 1) {
+@@ -350,13 +354,13 @@ static PHP_FUNCTION(bzread)
+
+ Z_STRVAL_P(return_value) = emalloc(len + 1);
+ Z_STRLEN_P(return_value) = php_stream_read(stream, Z_STRVAL_P(return_value), len);
+-
++
+ if (Z_STRLEN_P(return_value) < 0) {
+ efree(Z_STRVAL_P(return_value));
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "could not read valid bz2 data from stream");
+- RETURN_FALSE;
++ RETURN_FALSE;
+ }
+-
++
+ Z_STRVAL_P(return_value)[Z_STRLEN_P(return_value)] = 0;
+ Z_TYPE_P(return_value) = IS_STRING;
+ }
+@@ -372,7 +376,7 @@ static PHP_FUNCTION(bzopen)
+
+ BZFILE *bz; /* The compressed file stream */
+ php_stream *stream = NULL;
+-
++
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "Zs", &file, &mode, &mode_len) == FAILURE) {
+ return;
+ }
+@@ -388,15 +392,15 @@ static PHP_FUNCTION(bzopen)
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "filename cannot be empty");
+ RETURN_FALSE;
+ }
+-
++
+ if (CHECK_ZVAL_NULL_PATH(*file)) {
+ RETURN_FALSE;
+ }
+
+ stream = php_stream_bz2open(NULL,
+- Z_STRVAL_PP(file),
+- mode,
+- REPORT_ERRORS,
++ Z_STRVAL_PP(file),
++ mode,
++ REPORT_ERRORS,
+ NULL);
+ } else if (Z_TYPE_PP(file) == IS_RESOURCE) {
+ /* If it is a resource, than its a stream resource */
+@@ -405,7 +409,7 @@ static PHP_FUNCTION(bzopen)
+
+ php_stream_from_zval(stream, file);
+ stream_mode_len = strlen(stream->mode);
+-
++
+ if (stream_mode_len != 1 && !(stream_mode_len == 2 && memchr(stream->mode, 'b', 2))) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "cannot use stream opened in mode '%s'", stream->mode);
+ RETURN_FALSE;
+@@ -439,7 +443,7 @@ static PHP_FUNCTION(bzopen)
+ if (FAILURE == php_stream_cast(stream, PHP_STREAM_AS_FD, (void *) &fd, REPORT_ERRORS)) {
+ RETURN_FALSE;
+ }
+-
++
+ bz = BZ2_bzdopen(fd, mode);
+
+ stream = php_stream_bz2open_from_BZFILE(bz, mode, stream);
+@@ -493,7 +497,7 @@ static PHP_FUNCTION(bzcompress)
+ work_factor = 0, /* Work factor for compression algorithm */
+ argc; /* Argument count */
+ int source_len; /* Length of the source data */
+- unsigned int dest_len; /* Length of the destination buffer */
++ unsigned int dest_len; /* Length of the destination buffer */
+
+ argc = ZEND_NUM_ARGS();
+
+@@ -502,19 +506,19 @@ static PHP_FUNCTION(bzcompress)
+ }
+
+ /* Assign them to easy to use variables, dest_len is initially the length of the data
+- + .01 x length of data + 600 which is the largest size the results of the compression
+- could possibly be, at least that's what the libbz2 docs say (thanks to jeremy@nirvani.net
++ + .01 x length of data + 600 which is the largest size the results of the compression
++ could possibly be, at least that's what the libbz2 docs say (thanks to jeremy@nirvani.net
+ for pointing this out). */
+ dest_len = (unsigned int) (source_len + (0.01 * source_len) + 600);
+-
++
+ /* Allocate the destination buffer */
+ dest = emalloc(dest_len + 1);
+-
++
+ /* Handle the optional arguments */
+ if (argc > 1) {
+ block_size = zblock_size;
+ }
+-
++
+ if (argc > 2) {
+ work_factor = zwork_factor;
+ }
+@@ -564,7 +568,7 @@ static PHP_FUNCTION(bzdecompress)
+ /* in most cases bz2 offers at least 2:1 compression, so we use that as our base */
+ bzs.avail_out = source_len * 2;
+ bzs.next_out = dest = emalloc(bzs.avail_out + 1);
+-
++
+ while ((error = BZ2_bzDecompress(&bzs)) == BZ_OK && bzs.avail_in > 0) {
+ /* compression is better then 2:1, need to allocate more memory */
+ bzs.avail_out = source_len;
+@@ -590,13 +594,13 @@ static PHP_FUNCTION(bzdecompress)
+ /* {{{ php_bz2_error()
+ The central error handling interface, does the work for bzerrno, bzerrstr and bzerror */
+ static void php_bz2_error(INTERNAL_FUNCTION_PARAMETERS, int opt)
+-{
++{
+ zval *bzp; /* BZip2 Resource Pointer */
+ php_stream *stream;
+ const char *errstr; /* Error string */
+ int errnum; /* Error number */
+ struct php_bz2_stream_data_t *self;
+-
++
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &bzp) == FAILURE) {
+ return;
+ }
+@@ -608,10 +612,10 @@ static void php_bz2_error(INTERNAL_FUNCTION_PARAMETERS, int opt)
+ }
+
+ self = (struct php_bz2_stream_data_t *) stream->abstract;
+-
++
+ /* Fetch the error information */
+ errstr = BZ2_bzerror(self->bz_file, &errnum);
+-
++
+ /* Determine what to return */
+ switch (opt) {
+ case PHP_BZ_ERRNO:
+@@ -622,7 +626,7 @@ static void php_bz2_error(INTERNAL_FUNCTION_PARAMETERS, int opt)
+ break;
+ case PHP_BZ_ERRBOTH:
+ array_init(return_value);
+-
++
+ add_assoc_long (return_value, "errno", errnum);
+ add_assoc_string(return_value, "errstr", (char*)errstr, 1);
+ break;
+
diff --git a/bug72618.patch b/bug72618.patch
new file mode 100644
index 0000000..04814ab
--- /dev/null
+++ b/bug72618.patch
@@ -0,0 +1,110 @@
+Adapted for 5.4, by Remi Collet, binary patch removed, from:
+
+
+From 41131cd41d2fd2e0c2f332a27988df75659c42e4 Mon Sep 17 00:00:00 2001
+From: Stanislav Malyshev <stas@php.net>
+Date: Mon, 18 Jul 2016 23:21:51 -0700
+Subject: [PATCH] Fix bug #72618: NULL Pointer Dereference in
+ exif_process_user_comment
+
+---
+ ext/exif/exif.c | 17 +++++++++++------
+ ext/exif/tests/bug72618.jpg | Bin 0 -> 3711 bytes
+ ext/exif/tests/bug72618.phpt | 11 +++++++++++
+ 3 files changed, 22 insertions(+), 6 deletions(-)
+ create mode 100644 ext/exif/tests/bug72618.jpg
+ create mode 100644 ext/exif/tests/bug72618.phpt
+
+diff --git a/ext/exif/exif.c b/ext/exif/exif.c
+index 760e746..74b652b 100644
+--- a/ext/exif/exif.c
++++ b/ext/exif/exif.c
+@@ -2623,6 +2623,7 @@ static int exif_process_user_comment(image_info_type *ImageInfo, char **pszInfoP
+ *pszEncoding = NULL;
+ /* Copy the comment */
+ if (ByteCount>=8) {
++ const zend_encoding *from, *to;
+ if (!memcmp(szValuePtr, "UNICODE\0", 8)) {
+ *pszEncoding = estrdup((const char*)szValuePtr);
+ szValuePtr = szValuePtr+8;
+@@ -2643,14 +2644,16 @@ static int exif_process_user_comment(image_info_type *ImageInfo, char **pszInfoP
+ } else {
+ decode = ImageInfo->decode_unicode_le;
+ }
++ to = zend_multibyte_fetch_encoding(ImageInfo->encode_unicode TSRMLS_CC);
++ from = zend_multibyte_fetch_encoding(decode TSRMLS_CC);
+ /* XXX this will fail again if encoding_converter returns on error something different than SIZE_MAX */
+- if (zend_multibyte_encoding_converter(
++ if (!to || !from || zend_multibyte_encoding_converter(
+ (unsigned char**)pszInfoPtr,
+ &len,
+ (unsigned char*)szValuePtr,
+ ByteCount,
+- zend_multibyte_fetch_encoding(ImageInfo->encode_unicode TSRMLS_CC),
+- zend_multibyte_fetch_encoding(decode TSRMLS_CC)
++ to,
++ from
+ TSRMLS_CC) == (size_t)-1) {
+ len = exif_process_string_raw(pszInfoPtr, szValuePtr, ByteCount);
+ }
+@@ -2665,13 +2668,15 @@ static int exif_process_user_comment(image_info_type *ImageInfo, char **pszInfoP
+ szValuePtr = szValuePtr+8;
+ ByteCount -= 8;
+ /* XXX this will fail again if encoding_converter returns on error something different than SIZE_MAX */
+- if (zend_multibyte_encoding_converter(
++ to = zend_multibyte_fetch_encoding(ImageInfo->encode_jis TSRMLS_CC);
++ from = zend_multibyte_fetch_encoding(ImageInfo->motorola_intel ? ImageInfo->decode_jis_be : ImageInfo->decode_jis_le TSRMLS_CC);
++ if (!to || !from || zend_multibyte_encoding_converter(
+ (unsigned char**)pszInfoPtr,
+ &len,
+ (unsigned char*)szValuePtr,
+ ByteCount,
+- zend_multibyte_fetch_encoding(ImageInfo->encode_jis TSRMLS_CC),
+- zend_multibyte_fetch_encoding(ImageInfo->motorola_intel ? ImageInfo->decode_jis_be : ImageInfo->decode_jis_le TSRMLS_CC)
++ to,
++ from
+ TSRMLS_CC) == (size_t)-1) {
+ len = exif_process_string_raw(pszInfoPtr, szValuePtr, ByteCount);
+ }
+
+From 1364742be9757e594fd1b203d45805106ecd31c7 Mon Sep 17 00:00:00 2001
+From: Stanislav Malyshev <stas@php.net>
+Date: Mon, 18 Jul 2016 23:30:51 -0700
+Subject: [PATCH] Fix tests
+
+---
+ ext/exif/tests/bug54002.phpt | 6 +-----
+ ext/exif/tests/bug62523_2.phpt | 6 ++++--
+ 2 files changed, 5 insertions(+), 7 deletions(-)
+
+diff --git a/ext/exif/tests/bug54002.phpt b/ext/exif/tests/bug54002.phpt
+index c51fa58..8f85339 100644
+--- a/ext/exif/tests/bug54002.phpt
++++ b/ext/exif/tests/bug54002.phpt
+@@ -13,8 +13,4 @@ exif_read_data(__DIR__ . '/bug54002_2.jpeg');
+ --EXPECTF--
+ Warning: exif_read_data(bug54002_1.jpeg): Process tag(x0205=UndefinedTa): Illegal byte_count in %sbug54002.php on line %d
+
+-Warning: exif_read_data(bug54002_1.jpeg): Process tag(xA000=FlashPixVer): Illegal pointer offset(%s) in %sbug54002.php on line %d
+-
+-Warning: exif_read_data(bug54002_2.jpeg): Process tag(x0205=UndefinedTa): Illegal byte_count in %sbug54002.php on line %d
+-
+-Warning: exif_read_data(bug54002_2.jpeg): Process tag(xA000=FlashPixVer): Illegal pointer offset(%s) in %sbug54002.php on line %d
++Warning: exif_read_data(bug54002_2.jpeg): Process tag(x0205=UndefinedTa): Illegal byte_count in %sbug54002.php on line %d
+\ No newline at end of file
+diff --git a/ext/exif/tests/bug62523_2.phpt b/ext/exif/tests/bug62523_2.phpt
+index ddc8ae8..c533d42 100644
+--- a/ext/exif/tests/bug62523_2.phpt
++++ b/ext/exif/tests/bug62523_2.phpt
+@@ -10,7 +10,9 @@ echo "Test\n";
+ var_dump(count(exif_read_data(__DIR__."/bug62523_2.jpg")));
+ ?>
+ Done
+---EXPECT--
++--EXPECTF--
+ Test
+-int(76)
++
++Warning: exif_read_data(bug62523_2.jpg): IFD data bad offset: 0xADB23672 length 0x0D94 in %s/bug62523_2.php on line %d
++int(30)
+ Done
diff --git a/failed.txt b/failed.txt
index 14a47b2..20cd299 100644
--- a/failed.txt
+++ b/failed.txt
@@ -1,13 +1,16 @@
-===== 5.5.45-10 (2016-06-23)
+===== 5.5.45-11 (2016-07-22)
$ grep -r 'Tests failed' /var/lib/mock/*/build.log
-/var/lib/mock/el5i/build.log:Tests failed : 7
+/var/lib/mock/el5i/build.log:Tests failed : 9
/var/lib/mock/el5x/build.log:Tests failed : 3
/var/lib/mock/el6i/build.log:Tests failed : 5
/var/lib/mock/el6x/build.log:Tests failed : 1
/var/lib/mock/el7x/build.log:Tests failed : 0
+el5i
+ IPv4 Loopback test [ext/sockets/tests/ipv4loop.phpt]
+ ext/sockets - socket_getpeername_ipv4loop - basic test [ext/sockets/tests/socket_getpeername_ipv4loop.phpt]
el5i, el5x
Bug #33414 [1] (Comprehensive list of incorrect days returned after strotime() / date() tests) [ext/date/tests/bug33414-1.phpt]
Bug #66501: EC private key support in openssl_sign [ext/openssl/tests/bug66501.phpt]
diff --git a/php54.spec b/php54.spec
index ba036b9..3671a2b 100644
--- a/php54.spec
+++ b/php54.spec
@@ -98,7 +98,7 @@
Summary: PHP scripting language for creating dynamic web sites
Name: php
Version: 5.4.45
-Release: 10%{?dist}
+Release: 11%{?dist}
# All files licensed under PHP version 3.01, except
# Zend is licensed under Zend
# TSRM is licensed under BSD
@@ -200,6 +200,19 @@ Patch239: bug72433.patch
Patch240: bug72434.patch
Patch241: bug72455.patch
Patch242: bug72446.patch
+Patch243: bug70480.patch
+Patch244: bug69975.patch
+Patch245: bug72479.patch
+Patch246: bug72573.patch
+Patch247: bug72513.patch
+Patch248: bug72520.patch
+Patch249: bug72533.patch
+Patch250: bug72562.patch
+Patch251: bug72603.patch
+Patch252: bug72606.patch
+Patch253: bug72613.patch
+Patch254: bug72618.patch
+Patch255: bug72519.patch
# Fixes for tests
# no_NO issue
@@ -950,6 +963,19 @@ rm -f ext/json/utf8_to_utf16.*
%patch240 -p1 -b .bug72434
%patch241 -p1 -b .bug72455
%patch242 -p1 -b .bug72446
+%patch243 -p1 -b .bug70480
+%patch244 -p1 -b .bug69975
+%patch245 -p1 -b .bug72479
+%patch246 -p1 -b .bug72573
+%patch247 -p1 -b .bug72513
+%patch248 -p1 -b .bug72520
+%patch249 -p1 -b .bug72533
+%patch250 -p1 -b .bug72562
+%patch251 -p1 -b .bug72603
+%patch252 -p1 -b .bug72606
+%patch253 -p1 -b .bug72613
+%patch254 -p1 -b .bug72618
+%patch255 -p1 -b .bug72519
# Fixes for tests
%patch301 -p1 -b .datetests2
@@ -1839,6 +1865,23 @@ fi
%changelog
+* Fri Jul 22 2016 Remi Collet <remi@fedoraproject.org> 5.4.45-11
+- Fix #70480: php_url_parse_ex() buffer overflow read
+- Fix #69975: PHP segfaults when accessing nvarchar(max) defined columns
+- Fix #72479: Use After Free Vulnerability in SNMP with GC and unserialize()
+- Fix #72573: HTTP_PROXY is improperly trusted by some PHP libraries
+ CVE-2016-5385
+- Fix #72513: buffer overflow vulnerability in virtual_file_ex
+- Fix #72520: buffer overflow vulnerability in php_stream_zip_opener
+- Fix #72533: locale_accept_from_http out-of-bounds access
+- Fix #72562: Use After Free in unserialize() with Unexpected Session
+ Deserialization
+- Fix #72603: Out of bound read in exif_process_IFD_in_MAKERNOTE
+- Fix #72606: heap-buffer-overflow (write) simplestring_addn simplestring.c
+- Partial fix #72613: do not treat negative returns from bz2 as size_t
+- Fix #72618: NULL Pointer Dereference in exif_process_user_comment
+- Fix #72519: possible OOB using imagegif
+
* Tue Jun 21 2016 Remi Collet <remi@fedoraproject.org> 5.4.45-10
- Fix #66387: Stack overflow with imagefilltoborder
- Fix #72340: Double Free Courruption in wddx_deserialize