diff --git a/ext/intl/rangeformatter/rangeformatter_class.cpp b/ext/intl/rangeformatter/rangeformatter_class.cpp index 95acfccd2452..37b49e4f1310 100644 --- a/ext/intl/rangeformatter/rangeformatter_class.cpp +++ b/ext/intl/rangeformatter/rangeformatter_class.cpp @@ -88,8 +88,6 @@ 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) @@ -97,6 +95,8 @@ U_CFUNC PHP_METHOD(IntlNumberRangeFormatter, createFromSkeleton) Z_PARAM_LONG(identityFallback) ZEND_PARSE_PARAMETERS_END(); + intl_error_reset(NULL); + if (locale_len == 0) { locale = (char *)intl_locale_get_default(); } @@ -138,6 +138,8 @@ U_CFUNC PHP_METHOD(IntlNumberRangeFormatter, createFromSkeleton) INTL_G(use_exceptions) = old_use_exception; INTL_G(error_level) = old_error_level; + + RETURN_THROWS(); } LocalizedNumberRangeFormatter* nrf = new LocalizedNumberRangeFormatter( @@ -160,16 +162,17 @@ 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) Z_PARAM_NUMBER(end) ZEND_PARSE_PARAMETERS_END(); + intl_errors_reset(RANGEFORMATTER_ERROR_P(obj)); + + ZEND_ASSERT(RANGEFORMATTER_OBJECT(obj) != NULL); + UErrorCode error = U_ZERO_ERROR; icu::Formattable start_formattable = rangeformatter_create_formattable(start); @@ -183,19 +186,29 @@ U_CFUNC PHP_METHOD(IntlNumberRangeFormatter, format) INTL_G(use_exceptions) = true; INTL_G(error_level) = 0; + zend_string *ret = NULL; + if (U_FAILURE(error)) { intl_errors_set(RANGEFORMATTER_ERROR_P(obj), error, "Failed to format number range"); - } + } else { + ret = intl_charFromString(result, &error); - zend_string *ret = intl_charFromString(result, &error); + if (UNEXPECTED(ret == NULL)) { + if (U_SUCCESS(error)) { + error = U_ILLEGAL_ARGUMENT_ERROR; + } - if (U_FAILURE(error)) { - intl_errors_set(RANGEFORMATTER_ERROR_P(obj), 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; INTL_G(error_level) = old_error_level; + if (UNEXPECTED(ret == NULL)) { + RETURN_THROWS(); + } + RETVAL_NEW_STR(ret); } diff --git a/ext/intl/tests/rangeformatter/rangeformatter_error_reset_scope.phpt b/ext/intl/tests/rangeformatter/rangeformatter_error_reset_scope.phpt new file mode 100644 index 000000000000..7fcd37a00c69 --- /dev/null +++ b/ext/intl/tests/rangeformatter/rangeformatter_error_reset_scope.phpt @@ -0,0 +1,64 @@ +--TEST-- +IntlNumberRangeFormatter keeps the intl error state on a parameter error +--EXTENSIONS-- +intl +--SKIPIF-- + +--FILE-- +format([], 2); +} catch (TypeError $error) { + echo $error::class, ': ', $error->getMessage(), PHP_EOL; +} + +var_dump(intl_get_error_code() !== 0); + +try { + IntlNumberRangeFormatter::createFromSkeleton( + [], + 'en_US', + IntlNumberRangeFormatter::COLLAPSE_AUTO, + IntlNumberRangeFormatter::IDENTITY_FALLBACK_RANGE + ); +} catch (TypeError $error) { + echo $error::class, ': ', $error->getMessage(), PHP_EOL; +} + +var_dump(intl_get_error_code() !== 0); + +$formatter->format(1, 2); + +var_dump(intl_get_error_code()); +var_dump($formatter->getErrorCode()); + +?> +--EXPECT-- +TypeError: IntlNumberRangeFormatter::format(): Argument #1 ($start) must be of type int|float, array given +bool(true) +TypeError: IntlNumberRangeFormatter::createFromSkeleton(): Argument #1 ($skeleton) must be of type string, array given +bool(true) +int(0) +int(0) diff --git a/ext/intl/tests/rangeformatter/rangeformatter_format_failure.phpt b/ext/intl/tests/rangeformatter/rangeformatter_format_failure.phpt new file mode 100644 index 000000000000..854d0f74b995 --- /dev/null +++ b/ext/intl/tests/rangeformatter/rangeformatter_format_failure.phpt @@ -0,0 +1,54 @@ +--TEST-- +IntlNumberRangeFormatter::format() with a failing formatter +--EXTENSIONS-- +intl +--SKIPIF-- + +--FILE-- +format(1, 2); +} catch (IntlException $exception) { + echo $exception::class, ': ', $exception->getMessage(), PHP_EOL; +} + +var_dump($formatter->getErrorCode() !== 0); +var_dump(str_starts_with( + $formatter->getErrorMessage(), + 'IntlNumberRangeFormatter::format(): Failed to format number range: ' +)); + +var_dump(intl_get_error_code() !== 0); + +$formatter = IntlNumberRangeFormatter::createFromSkeleton( + '', + 'en_US', + IntlNumberRangeFormatter::COLLAPSE_AUTO, + IntlNumberRangeFormatter::IDENTITY_FALLBACK_RANGE +); + +var_dump($formatter->format(1, 2) !== ''); +var_dump($formatter->getErrorCode()); +var_dump($formatter->getErrorMessage()); + +?> +--EXPECT-- +IntlException: IntlNumberRangeFormatter::format(): Failed to format number range +bool(true) +bool(true) +bool(true) +bool(true) +int(0) +string(12) "U_ZERO_ERROR"