From a49c6c5a453edf008ea33de49d45857b073cca5a Mon Sep 17 00:00:00 2001 From: Remi Collet Date: Fri, 22 Jul 2016 19:29:20 +0200 Subject: PHP 5.4.45 with security fix from 5.5.38 --- bug69975.patch | 89 +++++++++++ bug70480.patch | 29 ++++ bug72479.patch | 408 ++++++++++++++++++++++++++++++++++++++++++++++++++ bug72513.patch | 48 ++++++ bug72519.patch | 54 +++++++ bug72520.patch | 78 ++++++++++ bug72533.patch | 80 ++++++++++ bug72562.patch | 73 +++++++++ bug72573.patch | 464 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ bug72603.patch | 76 ++++++++++ bug72606.patch | 152 +++++++++++++++++++ bug72613.patch | 281 ++++++++++++++++++++++++++++++++++ bug72618.patch | 110 ++++++++++++++ failed.txt | 10 +- php.spec | 47 +++++- 15 files changed, 1994 insertions(+), 5 deletions(-) create mode 100644 bug69975.patch create mode 100644 bug70480.patch create mode 100644 bug72479.patch create mode 100644 bug72513.patch create mode 100644 bug72519.patch create mode 100644 bug72520.patch create mode 100644 bug72533.patch create mode 100644 bug72562.patch create mode 100644 bug72573.patch create mode 100644 bug72603.patch create mode 100644 bug72606.patch create mode 100644 bug72613.patch create mode 100644 bug72618.patch 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" +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-- ++ ++--FILE-- ++ ++--EXPECT-- ++array(1) { ++ ["VARCHAR_COL"]=> ++ string(3) "foo" ++} ++ready ++--CLEAN-- ++ +-- +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 +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 +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-- ++ ++--FILE-- ++>= 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 +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 +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 +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 +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 +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-- ++ ++--FILE-- ++ ++--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 +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-- ++ ++--FILE-- ++>= 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 +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 +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 +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 +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 +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 +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 | + +----------------------------------------------------------------------+ + */ +- ++ + /* $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 +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 +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 899fc52..ebd0afc 100644 --- a/failed.txt +++ b/failed.txt @@ -1,4 +1,4 @@ -===== 5.5.45-10 (2016-06-23) +===== 5.5.45-11 (2016-07-22) $ grep -r 'Tests failed' /var/lib/mock/scl54*/build.log @@ -7,15 +7,17 @@ $ grep -r 'Tests failed' /var/lib/mock/scl54*/build.log /var/lib/mock/scl54fc21x/build.log:Tests failed : 1 /var/lib/mock/scl54fc22x/build.log:Tests failed : 1 /var/lib/mock/scl54fc23x/build.log:Tests failed : 3 -/var/lib/mock/scl54fc24x/build.log:Tests failed : 3 +/var/lib/mock/scl54fc24x/build.log:Tests failed : 4 f23, f24 - Bug #64802: openssl_x509_parse fails to parse subject properly in some cases [ext/openssl/tests/bug64802.phpt] Bug #33414 [1] (Comprehensive list of incorrect days returned after strotime() / date() tests) [ext/date/tests/bug33414-1.phpt] + Bug #64802: openssl_x509_parse fails to parse subject properly in some cases [ext/openssl/tests/bug64802.phpt] +f24 + file_get_contents() test using offset parameter out of range [ext/standard/tests/file/file_get_contents_error001.phpt] f21, f22, f23, f24 Test strptime() function : basic functionality [ext/standard/tests/time/strptime_basic.phpt] el6 Bug #32001 (xml_parse*() goes into infinite loop when autodetection in effect), using UTF-* [ext/xml/tests/bug32001.phpt] -* bug33414-1.phpt fails with tzdata-2016e +* bug33414-1.phpt fails since tzdata-2016e diff --git a/php.spec b/php.spec index a12ed6e..7b9f36a 100644 --- a/php.spec +++ b/php.spec @@ -119,7 +119,7 @@ Summary: PHP scripting language for creating dynamic web sites Name: %{?scl_prefix}php Version: 5.4.45 -Release: 10.1%{?dist} +Release: 11%{?dist} # All files licensed under PHP version 3.01, except # Zend is licensed under Zend # TSRM is licensed under BSD @@ -223,6 +223,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 (300+) # Backported from 5.5 @@ -903,6 +916,21 @@ support for using the enchant library to PHP. %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 +: ------------------------ +# exit 1 # Fixes for tests %patch300 -p1 -b .datetests1 @@ -1731,6 +1759,23 @@ EOF %changelog +* Fri Jul 22 2016 Remi Collet 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 + * Thu Jun 30 2016 Remi Collet 5.4.45-10.1 - own tests/doc directories for pecl packages (f24) -- cgit