diff --git a/NEWS b/NEWS index b091ea276142..8ea376a2c247 100644 --- a/NEWS +++ b/NEWS @@ -46,6 +46,8 @@ PHP NEWS string. (Weilin Du) . Fixed IntlListFormatter::__construct() leaving stale global error state after successful calls. (Weilin Du) + . Fixed IntlNumberRangeFormatter leaving stale global error state after + successful createFromSkeleton() and format() calls. (Weilin Du) . Implemented GH-20255 (Add a predefined calendar constant in IntlDateFormatter for the proleptic gregorian calendar). (David Carlier) . Added SpoofChecker::areBidiConfusable(). (David Carlier) diff --git a/Zend/tests/gh18572.phpt b/Zend/tests/gh18572.phpt index ff178ebef24f..cf45d2afaaba 100644 --- a/Zend/tests/gh18572.phpt +++ b/Zend/tests/gh18572.phpt @@ -36,4 +36,4 @@ try { } ?> --EXPECTREGEX-- -(Maximum call stack size reached during object comparison|Nesting level too deep - recursive dependency\?) +(Maximum call stack size reached during (object )?comparison|Nesting level too deep - recursive dependency\?) diff --git a/Zend/tests/gh23088.phpt b/Zend/tests/gh23088.phpt new file mode 100644 index 000000000000..59153a1f2ba3 --- /dev/null +++ b/Zend/tests/gh23088.phpt @@ -0,0 +1,40 @@ +--TEST-- +GH-23088 (Stack overflow when comparing deeply nested arrays) +--SKIPIF-- + +--INI-- +zend.max_allowed_stack_size=256K +--FILE-- +getMessage(), PHP_EOL; +} + +try { + var_dump($a === $b); +} catch (Error $e) { + echo $e->getMessage(), PHP_EOL; +} + +?> +--EXPECT-- +Maximum call stack size reached during comparison +Maximum call stack size reached during comparison diff --git a/Zend/zend_compile.c b/Zend/zend_compile.c index a2f126fb101d..882b1bf990bf 100644 --- a/Zend/zend_compile.c +++ b/Zend/zend_compile.c @@ -5916,6 +5916,8 @@ static void zend_compile_static_var_common(zend_string *var_name, zval *value, u opline = zend_emit_op(NULL, ZEND_BIND_STATIC, NULL, NULL); opline->op1_type = IS_CV; opline->op1.var = lookup_cv(var_name); + + ZEND_STATIC_ASSERT(sizeof(Bucket) % 8 == 0, "Bucket size not compatible with storing flags in lower three bits"); opline->extended_value = (uint32_t)((char*)value - (char*)CG(active_op_array)->static_variables->arData) | mode; } /* }}} */ diff --git a/Zend/zend_hash.c b/Zend/zend_hash.c index acc342bc267d..99406f9e4192 100644 --- a/Zend/zend_hash.c +++ b/Zend/zend_hash.c @@ -3221,6 +3221,13 @@ ZEND_API int zend_hash_compare(HashTable *ht1, const HashTable *ht2, compare_fun return 0; } +#ifdef ZEND_CHECK_STACK_LIMIT + if (UNEXPECTED(zend_call_stack_overflowed(EG(stack_limit)))) { + zend_throw_error(NULL, "Maximum call stack size reached during comparison"); + return ZEND_UNCOMPARABLE; + } +#endif + /* It's enough to protect only one of the arrays. * The second one may be referenced from the first and this may cause * false recursion detection. diff --git a/ext/intl/rangeformatter/rangeformatter_class.cpp b/ext/intl/rangeformatter/rangeformatter_class.cpp index 2dbb60c5b639..95acfccd2452 100644 --- a/ext/intl/rangeformatter/rangeformatter_class.cpp +++ b/ext/intl/rangeformatter/rangeformatter_class.cpp @@ -88,6 +88,8 @@ U_CFUNC PHP_METHOD(IntlNumberRangeFormatter, createFromSkeleton) zend_long collapse; zend_long identityFallback; + intl_error_reset(NULL); + ZEND_PARSE_PARAMETERS_START(4,4) Z_PARAM_STRING(skeleton, skeleton_len) Z_PARAM_STRING(locale, locale_len) @@ -158,7 +160,10 @@ U_CFUNC PHP_METHOD(IntlNumberRangeFormatter, format) zval *start; zval *end; + intl_error_reset(NULL); + IntlNumberRangeFormatter_object* obj = Z_INTL_RANGEFORMATTER_P(ZEND_THIS); + intl_error_reset(RANGEFORMATTER_ERROR_P(obj)); ZEND_PARSE_PARAMETERS_START(2, 2) Z_PARAM_NUMBER(start) @@ -179,13 +184,13 @@ U_CFUNC PHP_METHOD(IntlNumberRangeFormatter, format) INTL_G(error_level) = 0; if (U_FAILURE(error)) { - intl_error_set(NULL, error, "Failed to format number range"); + intl_errors_set(RANGEFORMATTER_ERROR_P(obj), error, "Failed to format number range"); } zend_string *ret = intl_charFromString(result, &error); if (U_FAILURE(error)) { - intl_error_set(NULL, error, "Failed to convert result to UTF-8"); + intl_errors_set(RANGEFORMATTER_ERROR_P(obj), error, "Failed to convert result to UTF-8"); } INTL_G(use_exceptions) = old_use_exception; diff --git a/ext/intl/tests/rangeformatter/rangeformatter_create_error_reset.phpt b/ext/intl/tests/rangeformatter/rangeformatter_create_error_reset.phpt new file mode 100644 index 000000000000..fb19da87d58d --- /dev/null +++ b/ext/intl/tests/rangeformatter/rangeformatter_create_error_reset.phpt @@ -0,0 +1,54 @@ +--TEST-- +IntlNumberRangeFormatter resets stale errors +--EXTENSIONS-- +intl +--SKIPIF-- + +--FILE-- +format(1, 2); + +var_dump(intl_get_error_code()); +var_dump(intl_get_error_message()); +?> +--EXPECT-- +bool(true) +int(0) +string(12) "U_ZERO_ERROR" +int(0) +string(12) "U_ZERO_ERROR" diff --git a/ext/uri/php_uri.c b/ext/uri/php_uri.c index 74a559fd591c..6ede828b69fe 100644 --- a/ext/uri/php_uri.c +++ b/ext/uri/php_uri.c @@ -66,13 +66,14 @@ static zend_always_inline zval *php_uri_deref(zval *zv) return zv; } -#define Z_RFC3986_URI_PROP_SCHEME_P(zv) php_uri_deref(OBJ_PROP_NUM(Z_OBJ_P(zv), 0)) -#define Z_RFC3986_URI_PROP_USERINFO_P(zv) php_uri_deref(OBJ_PROP_NUM(Z_OBJ_P(zv), 1)) -#define Z_RFC3986_URI_PROP_HOST_P(zv) php_uri_deref(OBJ_PROP_NUM(Z_OBJ_P(zv), 2)) -#define Z_RFC3986_URI_PROP_PORT_P(zv) php_uri_deref(OBJ_PROP_NUM(Z_OBJ_P(zv), 3)) -#define Z_RFC3986_URI_PROP_PATH_P(zv) php_uri_deref(OBJ_PROP_NUM(Z_OBJ_P(zv), 4)) -#define Z_RFC3986_URI_PROP_QUERY_P(zv) php_uri_deref(OBJ_PROP_NUM(Z_OBJ_P(zv), 5)) -#define Z_RFC3986_URI_PROP_FRAGMENT_P(zv) php_uri_deref(OBJ_PROP_NUM(Z_OBJ_P(zv), 6)) +#define Z_RFC3986_URI_PROP_SCHEME_DEREF_P(zv) php_uri_deref(OBJ_PROP_NUM(Z_OBJ_P(zv), 0)) +#define Z_RFC3986_URI_PROP_USERINFO_DEREF_P(zv) php_uri_deref(OBJ_PROP_NUM(Z_OBJ_P(zv), 1)) +#define Z_RFC3986_URI_PROP_HOST_DEREF_P(zv) php_uri_deref(OBJ_PROP_NUM(Z_OBJ_P(zv), 2)) +#define Z_RFC3986_URI_PROP_PORT_DEREF_P(zv) php_uri_deref(OBJ_PROP_NUM(Z_OBJ_P(zv), 3)) +#define Z_RFC3986_URI_PROP_PATH_P(zv) OBJ_PROP_NUM(Z_OBJ_P(zv), 4) +#define Z_RFC3986_URI_PROP_PATH_DEREF_P(zv) php_uri_deref(Z_RFC3986_URI_PROP_PATH_P(zv)) +#define Z_RFC3986_URI_PROP_QUERY_DEREF_P(zv) php_uri_deref(OBJ_PROP_NUM(Z_OBJ_P(zv), 5)) +#define Z_RFC3986_URI_PROP_FRAGMENT_DEREF_P(zv) php_uri_deref(OBJ_PROP_NUM(Z_OBJ_P(zv), 6)) static HashTable *uri_get_debug_properties(php_uri_object *object) { @@ -1069,14 +1070,17 @@ PHP_METHOD(Uri_Rfc3986_UriBuilder, reset) { ZEND_PARSE_PARAMETERS_NONE(); - convert_to_null(Z_RFC3986_URI_PROP_SCHEME_P(ZEND_THIS)); - convert_to_null(Z_RFC3986_URI_PROP_USERINFO_P(ZEND_THIS)); - convert_to_null(Z_RFC3986_URI_PROP_HOST_P(ZEND_THIS)); - convert_to_null(Z_RFC3986_URI_PROP_PORT_P(ZEND_THIS)); - zval_ptr_dtor(Z_RFC3986_URI_PROP_PATH_P(ZEND_THIS)); + zend_object *object = Z_OBJ_P(ZEND_THIS); + zval *property = object->properties_table; + const zval *end = property + object->ce->default_properties_count; + + while (property != end) { + zend_object_dtor_property(object, property); + ZVAL_NULL(property); + property++; + } + ZVAL_EMPTY_STRING(Z_RFC3986_URI_PROP_PATH_P(ZEND_THIS)); - convert_to_null(Z_RFC3986_URI_PROP_QUERY_P(ZEND_THIS)); - convert_to_null(Z_RFC3986_URI_PROP_FRAGMENT_P(ZEND_THIS)); RETVAL_COPY(ZEND_THIS); } @@ -1219,13 +1223,13 @@ PHP_METHOD(Uri_Rfc3986_UriBuilder, build) Z_PARAM_OBJECT_OF_CLASS_OR_NULL(base_url, php_uri_ce_rfc3986_uri) ZEND_PARSE_PARAMETERS_END(); - const zval *scheme = Z_RFC3986_URI_PROP_SCHEME_P(ZEND_THIS); - const zval *userinfo = Z_RFC3986_URI_PROP_USERINFO_P(ZEND_THIS); - const zval *host = Z_RFC3986_URI_PROP_HOST_P(ZEND_THIS); - const zval *port = Z_RFC3986_URI_PROP_PORT_P(ZEND_THIS); - const zval *path = Z_RFC3986_URI_PROP_PATH_P(ZEND_THIS); - const zval *query = Z_RFC3986_URI_PROP_QUERY_P(ZEND_THIS); - const zval *fragment = Z_RFC3986_URI_PROP_FRAGMENT_P(ZEND_THIS); + const zval *scheme = Z_RFC3986_URI_PROP_SCHEME_DEREF_P(ZEND_THIS); + const zval *userinfo = Z_RFC3986_URI_PROP_USERINFO_DEREF_P(ZEND_THIS); + const zval *host = Z_RFC3986_URI_PROP_HOST_DEREF_P(ZEND_THIS); + const zval *port = Z_RFC3986_URI_PROP_PORT_DEREF_P(ZEND_THIS); + const zval *path = Z_RFC3986_URI_PROP_PATH_DEREF_P(ZEND_THIS); + const zval *query = Z_RFC3986_URI_PROP_QUERY_DEREF_P(ZEND_THIS); + const zval *fragment = Z_RFC3986_URI_PROP_FRAGMENT_DEREF_P(ZEND_THIS); php_uri_parser_rfc3986_uris *base_uris = NULL; if (base_url != NULL) {