From: Stanislav Malyshev Date: Tue, 4 Aug 2015 23:14:24 +0000 (-0700) Subject: Merge branch 'PHP-5.6' X-Git-Tag: php-7.0.0beta3~1^2~7 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=97047e7665368d0cf30501f7a4b6a124de25957b;p=php Merge branch 'PHP-5.6' * PHP-5.6: update NEWS fix test update NEWS Fix bug #70019 - limit extracted files to given directory Do not do convert_to_* on unserialize, it messes up references Fix #69793 - limit what we accept when unserializing exception Fixed bug #70169 (Use After Free Vulnerability in unserialize() with SplDoublyLinkedList) Fixed bug #70166 - Use After Free Vulnerability in unserialize() with SPLArrayObject ignore signatures for packages too Fix bug #70168 - Use After Free Vulnerability in unserialize() with SplObjectStorage Fixed bug #69892 Fix bug #70014 - use RAND_bytes instead of deprecated RAND_pseudo_bytes Improved fix for Bug #69441 Fix bug #70068 (Dangling pointer in the unserialization of ArrayObject items) Fix bug #70121 (unserialize() could lead to unexpected methods execution / NULL pointer deref) Fix bug #70081: check types for SOAP variables Conflicts: Zend/zend_exceptions.c ext/date/php_date.c ext/openssl/openssl.c ext/phar/phar_internal.h ext/soap/php_http.c ext/spl/spl_array.c ext/spl/spl_dllist.c ext/spl/spl_observer.c ext/standard/tests/serialize/bug69152.phpt sapi/cli/tests/005.phpt --- 97047e7665368d0cf30501f7a4b6a124de25957b diff --cc Zend/zend_exceptions.c index 5d6cc59259,806c2ef9e3..51ea2319bf --- a/Zend/zend_exceptions.c +++ b/Zend/zend_exceptions.c @@@ -197,25 -155,16 +197,25 @@@ static zend_object *zend_default_except object_properties_init(object, class_type); - ALLOC_ZVAL(trace); - Z_UNSET_ISREF_P(trace); - Z_SET_REFCOUNT_P(trace, 0); - zend_fetch_debug_backtrace(trace, skip_top_traces, 0, 0 TSRMLS_CC); + if (EG(current_execute_data)) { + zend_fetch_debug_backtrace(&trace, skip_top_traces, 0, 0); + } else { + array_init(&trace); + } + Z_SET_REFCOUNT(trace, 0); - ++ + base_ce = i_get_exception_base(&obj); - zend_update_property_string(default_exception_ce, &obj, "file", sizeof("file")-1, zend_get_executed_filename(TSRMLS_C) TSRMLS_CC); - zend_update_property_long(default_exception_ce, &obj, "line", sizeof("line")-1, zend_get_executed_lineno(TSRMLS_C) TSRMLS_CC); - zend_update_property(default_exception_ce, &obj, "trace", sizeof("trace")-1, trace TSRMLS_CC); + if (EXPECTED(class_type != zend_ce_parse_error || !(filename = zend_get_compiled_filename()))) { + zend_update_property_string(base_ce, &obj, "file", sizeof("file")-1, zend_get_executed_filename()); + zend_update_property_long(base_ce, &obj, "line", sizeof("line")-1, zend_get_executed_lineno()); + } else { + zend_update_property_string(base_ce, &obj, "file", sizeof("file")-1, ZSTR_VAL(filename)); + zend_update_property_long(base_ce, &obj, "line", sizeof("line")-1, zend_get_compiled_lineno()); + } + zend_update_property(base_ce, &obj, "trace", sizeof("trace")-1, &trace); - return Z_OBJVAL(obj); + return object; } /* }}} */ @@@ -279,7 -218,34 +279,33 @@@ ZEND_METHOD(exception, __construct } /* }}} */ + /* {{{ proto Exception::__wakeup() + Exception unserialize checks */ + #define CHECK_EXC_TYPE(name, type) \ - value = zend_read_property(default_exception_ce, object, name, sizeof(name)-1, 0 TSRMLS_CC); \ ++ zend_read_property(i_get_exception_base(object), (object), name, sizeof(name) - 1, 1, &value); \ + if(value && Z_TYPE_P(value) != type) { \ + zval *tmp; \ + MAKE_STD_ZVAL(tmp); \ + ZVAL_STRINGL(tmp, name, sizeof(name)-1, 1); \ + Z_OBJ_HANDLER_P(object, unset_property)(object, tmp, 0 TSRMLS_CC); \ + zval_ptr_dtor(&tmp); \ + } + + ZEND_METHOD(exception, __wakeup) + { - zval *value; ++ zval value; + zval *object = getThis(); - HashTable *intern_ht = zend_std_get_properties(getThis() TSRMLS_CC); + CHECK_EXC_TYPE("message", IS_STRING); + CHECK_EXC_TYPE("string", IS_STRING); + CHECK_EXC_TYPE("code", IS_LONG); + CHECK_EXC_TYPE("file", IS_STRING); + CHECK_EXC_TYPE("line", IS_LONG); + CHECK_EXC_TYPE("trace", IS_ARRAY); + CHECK_EXC_TYPE("previous", IS_OBJECT); + } + /* }}} */ + -/* {{{ proto ErrorException::__construct(string message, int code, int severity [, string filename [, int lineno [, Exception previous]]]) +/* {{{ proto ErrorException::__construct(string message, int code, int severity [, string filename [, int lineno [, Throwable previous]]]) ErrorException constructor */ ZEND_METHOD(error_exception, __construct) { @@@ -600,19 -608,13 +626,19 @@@ static void _build_trace_string(smart_s Obtain the backtrace for the exception as a string (instead of an array) */ ZEND_METHOD(exception, getTraceAsString) { - zval *trace; - char *res, **str, *s_tmp; - int res_len = 0, *len = &res_len, num = 0; + zval *trace, *frame, rv; + zend_ulong index; + zval *object; + zend_class_entry *base_ce; + smart_str str = {0}; + uint32_t num = 0; DEFAULT_0_PARAMS; - + - trace = zend_read_property(default_exception_ce, getThis(), "trace", sizeof("trace")-1, 1 TSRMLS_CC); + object = getThis(); + base_ce = i_get_exception_base(object); + + trace = zend_read_property(base_ce, object, "trace", sizeof("trace")-1, 1, &rv); if (Z_TYPE_P(trace) != IS_ARRAY) { RETURN_FALSE; } @@@ -779,9 -752,10 +805,10 @@@ ZEND_BEGIN_ARG_INFO_EX(arginfo_exceptio ZEND_ARG_INFO(0, previous) ZEND_END_ARG_INFO() -const static zend_function_entry default_exception_functions[] = { +static const zend_function_entry default_exception_functions[] = { ZEND_ME(exception, __clone, NULL, ZEND_ACC_PRIVATE|ZEND_ACC_FINAL) ZEND_ME(exception, __construct, arginfo_exception___construct, ZEND_ACC_PUBLIC) + ZEND_ME(exception, __wakeup, NULL, ZEND_ACC_PUBLIC|ZEND_ACC_FINAL) ZEND_ME(exception, getMessage, NULL, ZEND_ACC_PUBLIC|ZEND_ACC_FINAL) ZEND_ME(exception, getCode, NULL, ZEND_ACC_PUBLIC|ZEND_ACC_FINAL) ZEND_ME(exception, getFile, NULL, ZEND_ACC_PUBLIC|ZEND_ACC_FINAL) @@@ -809,12 -783,13 +836,12 @@@ static const zend_function_entry error_ }; /* }}} */ -void zend_register_default_exception(TSRMLS_D) /* {{{ */ +void zend_register_default_exception(void) /* {{{ */ { zend_class_entry ce; - + - INIT_CLASS_ENTRY(ce, "Exception", default_exception_functions); - default_exception_ce = zend_register_internal_class(&ce TSRMLS_CC); - default_exception_ce->create_object = zend_default_exception_new; + REGISTER_MAGIC_INTERFACE(throwable, Throwable); + memcpy(&default_exception_handlers, zend_get_std_object_handlers(), sizeof(zend_object_handlers)); default_exception_handlers.clone_obj = NULL; @@@ -867,10 -808,9 +894,10 @@@ } /* }}} */ -ZEND_API zend_class_entry *zend_exception_get_default(TSRMLS_D) /* {{{ */ +/* {{{ Deprecated - Use zend_ce_exception directly instead */ - ZEND_API zend_class_entry *zend_exception_get_default(void) ++ZEND_API zend_class_entry *zend_exception_get_default(void) { - return default_exception_ce; + return zend_ce_exception; } /* }}} */ diff --cc ext/openssl/openssl.c index b3ef5ad003,ef5162283b..8f2adab7f7 --- a/ext/openssl/openssl.c +++ b/ext/openssl/openssl.c @@@ -5425,12 -5387,11 +5425,11 @@@ PHP_FUNCTION(openssl_dh_compute_key Returns a string of the length specified filled with random pseudo bytes */ PHP_FUNCTION(openssl_random_pseudo_bytes) { - long buffer_length; - unsigned char *buffer = NULL; + zend_long buffer_length; + zend_string *buffer = NULL; zval *zstrong_result_returned = NULL; - int strong_result = 0; - if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l|z", &buffer_length, &zstrong_result_returned) == FAILURE) { + if (zend_parse_parameters(ZEND_NUM_ARGS(), "l|z/", &buffer_length, &zstrong_result_returned) == FAILURE) { return; } @@@ -5440,36 -5401,35 +5439,35 @@@ if (zstrong_result_returned) { zval_dtor(zstrong_result_returned); - ZVAL_BOOL(zstrong_result_returned, 0); + ZVAL_FALSE(zstrong_result_returned); } - buffer = emalloc(buffer_length + 1); + buffer = zend_string_alloc(buffer_length, 0); #ifdef PHP_WIN32 - strong_result = 1; /* random/urandom equivalent on Windows */ - if (php_win32_get_random_bytes(buffer, (size_t) buffer_length) == FAILURE){ - efree(buffer); + if (php_win32_get_random_bytes((unsigned char*)buffer->val, (size_t) buffer_length) == FAILURE){ + zend_string_release(buffer); if (zstrong_result_returned) { - ZVAL_BOOL(zstrong_result_returned, 0); + ZVAL_FALSE(zstrong_result_returned); } RETURN_FALSE; } #else - if ((strong_result = RAND_pseudo_bytes((unsigned char*)ZSTR_VAL(buffer), buffer_length)) < 0) { - if (RAND_bytes(buffer, buffer_length) <= 0) { - efree(buffer); ++ if (RAND_bytes((unsigned char*)ZSTR_VAL(buffer), buffer_length) <= 0) { + zend_string_release(buffer); if (zstrong_result_returned) { - ZVAL_BOOL(zstrong_result_returned, 0); + ZVAL_FALSE(zstrong_result_returned); } RETURN_FALSE; } #endif - buffer[buffer_length] = 0; - RETVAL_STRINGL((char *)buffer, buffer_length, 0); + ZSTR_VAL(buffer)[buffer_length] = 0; + RETVAL_STR(buffer); if (zstrong_result_returned) { - ZVAL_BOOL(zstrong_result_returned, strong_result); + ZVAL_BOOL(zstrong_result_returned, 1); } } /* }}} */ diff --cc ext/phar/phar_internal.h index 48dfb9f7fa,aa369abe3a..184f966623 --- a/ext/phar/phar_internal.h +++ b/ext/phar/phar_internal.h @@@ -524,14 -536,17 +524,17 @@@ static inline void phar_set_inode(phar_ { char tmp[MAXPATHLEN]; int tmp_len; - size_t len; + size_t len1, len2; tmp_len = MIN(MAXPATHLEN, entry->filename_len + entry->phar->fname_len); - len = MIN(entry->phar->fname_len, tmp_len); - memcpy(tmp, entry->phar->fname, len); - len = MIN(tmp_len - len, entry->filename_len); - memcpy(tmp + entry->phar->fname_len, entry->filename, len); - entry->inode = (unsigned short)zend_hash_func(tmp, tmp_len); + + len1 = MIN(entry->phar->fname_len, tmp_len); + memcpy(tmp, entry->phar->fname, len1); + + len2 = MIN(tmp_len - len1, entry->filename_len); + memcpy(tmp + len1, entry->filename, len2); + - entry->inode = (unsigned short)zend_get_hash_value(tmp, tmp_len); ++ entry->inode = (unsigned short) zend_hash_func(tmp, tmp_len); } /* }}} */ diff --cc ext/soap/php_http.c index 60dd9dd3ae,c8eba98bc8..61573eb77e --- a/ext/soap/php_http.c +++ b/ext/soap/php_http.c @@@ -810,28 -817,31 +810,29 @@@ try_again int i, n; has_cookies = 1; - n = zend_hash_num_elements(Z_ARRVAL_PP(cookies)); + n = zend_hash_num_elements(Z_ARRVAL_P(cookies)); if (n > 0) { - zend_hash_internal_pointer_reset(Z_ARRVAL_PP(cookies)); + zend_hash_internal_pointer_reset(Z_ARRVAL_P(cookies)); smart_str_append_const(&soap_headers, "Cookie: "); for (i = 0; i < n; i++) { + ulong numindx; - int res = zend_hash_get_current_key_ex(Z_ARRVAL_PP(cookies), &key, &key_len, &numindx, 0, NULL); - zend_hash_get_current_data(Z_ARRVAL_PP(cookies), (void **)&data); - - if (res == HASH_KEY_IS_STRING && Z_TYPE_PP(data) == IS_ARRAY) { - zval** value; - - if (zend_hash_index_find(Z_ARRVAL_PP(data), 0, (void**)&value) == SUCCESS && - Z_TYPE_PP(value) == IS_STRING) { - zval **tmp; - if ((zend_hash_index_find(Z_ARRVAL_PP(data), 1, (void**)&tmp) == FAILURE || - Z_TYPE_PP(tmp) != IS_STRING || - strncmp(phpurl->path?phpurl->path:"/",Z_STRVAL_PP(tmp),Z_STRLEN_PP(tmp)) == 0) && - (zend_hash_index_find(Z_ARRVAL_PP(data), 2, (void**)&tmp) == FAILURE || - Z_TYPE_PP(tmp) != IS_STRING || - in_domain(phpurl->host,Z_STRVAL_PP(tmp))) && - (use_ssl || zend_hash_index_find(Z_ARRVAL_PP(data), 3, (void**)&tmp) == FAILURE)) { - smart_str_appendl(&soap_headers, key, key_len-1); ++ int res = zend_hash_get_current_key(Z_ARRVAL_P(cookies), &key, &numindx); + data = zend_hash_get_current_data(Z_ARRVAL_P(cookies)); - zend_hash_get_current_key(Z_ARRVAL_P(cookies), &key, NULL); - - if (Z_TYPE_P(data) == IS_ARRAY) { ++ ++ if (res == HASH_KEY_IS_STRING && Z_TYPE_P(data) == IS_ARRAY) { + zval *value; + + if ((value = zend_hash_index_find(Z_ARRVAL_P(data), 0)) != NULL && + Z_TYPE_P(value) == IS_STRING) { + zval *tmp; + if (((tmp = zend_hash_index_find(Z_ARRVAL_P(data), 1)) == NULL || + strncmp(phpurl->path?phpurl->path:"/",Z_STRVAL_P(tmp),Z_STRLEN_P(tmp)) == 0) && + ((tmp = zend_hash_index_find(Z_ARRVAL_P(data), 2)) == NULL || + in_domain(phpurl->host,Z_STRVAL_P(tmp))) && + (use_ssl || (tmp = zend_hash_index_find(Z_ARRVAL_P(data), 3)) == NULL)) { + smart_str_append(&soap_headers, key); smart_str_appendc(&soap_headers, '='); - smart_str_appendl(&soap_headers, Z_STRVAL_PP(value), Z_STRLEN_PP(value)); + smart_str_append(&soap_headers, Z_STR_P(value)); smart_str_appendc(&soap_headers, ';'); } } diff --cc ext/spl/spl_array.c index 2835876e33,42490fc007..1ec6ea17b2 --- a/ext/spl/spl_array.c +++ b/ext/spl/spl_array.c @@@ -1741,8 -1773,9 +1741,9 @@@ SPL_METHOD(Array, unserialize goto outexcept; } + var_push_dtor(&var_hash, &pflags); --p; /* for ';' */ - flags = Z_LVAL_P(pflags); + flags = Z_LVAL(zflags); /* flags needs to be verified and we also need to verify whether the next * thing we get is ';'. After that we require an 'm' or somethign else * where 'm' stands for members and anything else should be an array. If @@@ -1760,9 -1793,11 +1761,10 @@@ intern->ar_flags &= ~SPL_ARRAY_CLONE_MASK; intern->ar_flags |= flags & SPL_ARRAY_CLONE_MASK; zval_ptr_dtor(&intern->array); - ALLOC_INIT_ZVAL(intern->array); - if (!php_var_unserialize(&intern->array, &p, s + buf_len, &var_hash TSRMLS_CC)) { + if (!php_var_unserialize(&intern->array, &p, s + buf_len, &var_hash)) { goto outexcept; } + var_push_dtor(&var_hash, &intern->array); } if (*p != ';') { goto outexcept; @@@ -1781,9 -1816,13 +1783,10 @@@ goto outexcept; } + var_push_dtor(&var_hash, &pmembers); /* copy members */ - if (!intern->std.properties) { - rebuild_object_properties(&intern->std); - } - zend_hash_copy(intern->std.properties, Z_ARRVAL_P(pmembers), (copy_ctor_func_t) zval_add_ref, (void *) NULL, sizeof(zval *)); - zval_ptr_dtor(&pmembers); + object_properties_load(&intern->std, Z_ARRVAL(members)); + zval_ptr_dtor(&members); /* done reading $serialized */ diff --cc ext/spl/spl_observer.c index 6a9e27a601,43f4d7d29d..315c0f8bcd --- a/ext/spl/spl_observer.c +++ b/ext/spl/spl_observer.c @@@ -809,12 -838,14 +809,13 @@@ SPL_METHOD(SplObjectStorage, unserializ goto outexcept; } + var_push_dtor(&var_hash, &pcount); --p; /* for ';' */ - count = Z_LVAL_P(pcount); + count = Z_LVAL(pcount); - while(count-- > 0) { + while (count-- > 0) { spl_SplObjectStorageElement *pelement; - char *hash; - int hash_len; + zend_string *hash; if (*p != ';') { goto outexcept; diff --cc ext/standard/tests/serialize/bug69152.phpt index b766c0afbd,bc2b302ddb..be3aa273ed --- a/ext/standard/tests/serialize/bug69152.phpt +++ b/ext/standard/tests/serialize/bug69152.phpt @@@ -9,7 -9,8 +9,8 @@@ $x->test() ?> --EXPECTF-- + Notice: Undefined property: Exception::$previous in %s on line %d -exception 'Exception' in %s:%d +Exception in %s:%d Stack trace: #0 {main} diff --cc sapi/cli/tests/005.phpt index 60af3fc992,a840e8ffd2..cf50a968f4 --- a/sapi/cli/tests/005.phpt +++ b/sapi/cli/tests/005.phpt @@@ -74,28 -74,31 +74,31 @@@ string(1544) "Class [ c } } - Method [ final public method __wakeup ] { ++ Method [ final public method __wakeup ] { + } + - Method [ final public method getMessage ] { + Method [ final public method getMessage ] { } - Method [ final public method getCode ] { + Method [ final public method getCode ] { } - Method [ final public method getFile ] { + Method [ final public method getFile ] { } - Method [ final public method getLine ] { + Method [ final public method getLine ] { } - Method [ final public method getTrace ] { + Method [ final public method getTrace ] { } - Method [ final public method getPrevious ] { + Method [ final public method getPrevious ] { } - Method [ final public method getTraceAsString ] { + Method [ final public method getTraceAsString ] { } - Method [ public method __toString ] { + Method [ public method __toString ] { } } }