From ca5667bc14da111fe8e1bae804d9809809122a89 Mon Sep 17 00:00:00 2001 From: Gina Peter Banyard Date: Thu, 7 Aug 2025 13:46:58 +0100 Subject: [PATCH] ext/intl: prevent creation of invalid UConverter instance (#19396) --- ext/intl/converter/converter.c | 23 ++++++++++++++++--- ext/intl/tests/bug75317.phpt | 2 +- .../tests/uconverter___construct_error.phpt | 23 ++++++++++++------- ext/intl/tests/uconverter_bug66873.phpt | 6 ++++- 4 files changed, 41 insertions(+), 13 deletions(-) diff --git a/ext/intl/converter/converter.c b/ext/intl/converter/converter.c index 6fa654aaa87..759db5e1887 100644 --- a/ext/intl/converter/converter.c +++ b/ext/intl/converter/converter.c @@ -24,6 +24,7 @@ #include "../intl_error.h" #include "../intl_common.h" #include "converter_arginfo.h" +#include "php_intl.h" typedef struct _php_converter_object { UConverter *src, *dest; @@ -370,7 +371,10 @@ static bool php_converter_set_encoding(php_converter_object *objval, /* Should never happen */ actual_encoding = "(unknown)"; } - php_error_docref(NULL, E_WARNING, "Ambiguous encoding specified, using %s", actual_encoding); + char *msg; + spprintf(&msg, 0, "Ambiguous encoding specified, using %s", actual_encoding); + intl_error_set(NULL, error, msg); + efree(msg); } else if (U_FAILURE(error)) { if (objval) { THROW_UFAILURE(objval, error); @@ -530,10 +534,23 @@ PHP_METHOD(UConverter, __construct) { Z_PARAM_STRING_OR_NULL(src, src_len) ZEND_PARSE_PARAMETERS_END(); - php_converter_set_encoding(objval, &(objval->src), src, src_len ); - php_converter_set_encoding(objval, &(objval->dest), dest, dest_len); + const bool old_use_exception = INTL_G(use_exceptions); + const zend_long old_error_level = INTL_G(error_level); + INTL_G(use_exceptions) = true; + INTL_G(error_level) = 0; + if (UNEXPECTED(!php_converter_set_encoding(objval, &(objval->src), src, src_len))) { + ZEND_ASSERT(EG(exception)); + goto cleanup; + } + if (UNEXPECTED(!php_converter_set_encoding(objval, &(objval->dest), dest, dest_len))) { + ZEND_ASSERT(EG(exception)); + goto cleanup; + } php_converter_resolve_callback(&objval->to_cache, Z_OBJ_P(ZEND_THIS), ZEND_STRL("toUCallback")); php_converter_resolve_callback(&objval->from_cache, Z_OBJ_P(ZEND_THIS), ZEND_STRL("fromUCallback")); +cleanup: + INTL_G(use_exceptions) = old_use_exception; + INTL_G(error_level) = old_error_level; } /* }}} */ diff --git a/ext/intl/tests/bug75317.phpt b/ext/intl/tests/bug75317.phpt index 1dd96950bb0..4df45f37bf8 100644 --- a/ext/intl/tests/bug75317.phpt +++ b/ext/intl/tests/bug75317.phpt @@ -1,5 +1,5 @@ --TEST-- -Bug #75317 (UConverter::setDestinationEncoding changes source instead of destinatination) +Bug #75317 (UConverter::setDestinationEncoding changes source instead of destination) --EXTENSIONS-- intl --FILE-- diff --git a/ext/intl/tests/uconverter___construct_error.phpt b/ext/intl/tests/uconverter___construct_error.phpt index f47ed8b508b..7237f799f88 100644 --- a/ext/intl/tests/uconverter___construct_error.phpt +++ b/ext/intl/tests/uconverter___construct_error.phpt @@ -1,15 +1,22 @@ --TEST-- Basic UConverter::convert() usage ---INI-- -intl.error_level = E_WARNING --EXTENSIONS-- intl --FILE-- ---EXPECTF-- -Warning: UConverter::__construct(): returned error 4: U_FILE_ACCESS_ERROR in %s on line %d -object(UConverter)#%d (0) { +try { + $c = new UConverter("\x80", 'utf-8'); + var_dump($c); +} catch (Throwable $e) { + echo $e::class, ': ', $e->getMessage(), PHP_EOL; } +try { + $c = new UConverter('utf-8', "\x80"); + var_dump($c); +} catch (Throwable $e) { + echo $e::class, ': ', $e->getMessage(), PHP_EOL; +} +?> +--EXPECT-- +IntlException: UConverter::__construct(): returned error 4: U_FILE_ACCESS_ERROR +IntlException: UConverter::__construct(): returned error 4: U_FILE_ACCESS_ERROR diff --git a/ext/intl/tests/uconverter_bug66873.phpt b/ext/intl/tests/uconverter_bug66873.phpt index 9ea684fbd38..68a01eee93d 100644 --- a/ext/intl/tests/uconverter_bug66873.phpt +++ b/ext/intl/tests/uconverter_bug66873.phpt @@ -4,9 +4,13 @@ Bug #66873 - crash in UConverter with invalid encoding intl --FILE-- toUCallback(1, 1, 1, $b); var_dump($o->getErrorCode()); +} catch (Throwable $e) { + echo $e::class, ': ', $e->getMessage(), PHP_EOL; +} ?> --EXPECT-- -int(27) +IntlException: UConverter::__construct(): returned error 4: U_FILE_ACCESS_ERROR