[php-src] PHP-8.5: ext/intl: Reset IntlChar error state on method entry (#22500)

Xuyang Zhang via Weilin Du <[email protected]>
Newsgroups gmane.comp.php.cvs.general
Message-ID <[email protected]>
Author: Xuyang Zhang (kn1g78)
Committer: Weilin Du (LamentXU123)
Date: 2026-06-29T22:46:40+08:00

Commit: https://github.com/php/php-src/commit/e44db0cdfd0bb3595dd7e95b48dd5ebf5a25eddd
Raw diff: https://github.com/php/php-src/commit/e44db0cdfd0bb3595dd7e95b48dd5ebf5a25eddd.diff

ext/intl: Reset IntlChar error state on method entry (#22500)

IntlChar methods could leave stale global intl error state after a later successful call.

Reset the intl error state when entering each IntlChar method so successful calls report U_ZERO_ERROR.

Closes #22500

Changed paths:
  A  ext/intl/tests/intlchar_reset_error.phpt
  M  NEWS
  M  ext/intl/uchar/uchar.c


Diff:

diff --git a/NEWS b/NEWS
index 86ef47098f77..57d91e345457 100644
--- a/NEWS
+++ b/NEWS
@@ -11,6 +11,8 @@ PHP                                                                        NEWS
     fallback locale when a language tag cannot be canonicalized. (Weilin Du)
   . Fixed memory leaks when calling Collator::__construct() or
     Spoofchecker::__construct() twice. (Weilin Du)
+  . Fixed IntlChar methods leaving stale global error state after successful
+    calls. (Xuyang Zhang)
 
 - Phar:
   . Fixed inconsistent handling of the magic ".phar" directory. Paths such as
diff --git a/ext/intl/tests/intlchar_reset_error.phpt b/ext/intl/tests/intlchar_reset_error.phpt
new file mode 100644
index 000000000000..45f6d1df2961
--- /dev/null
+++ b/ext/intl/tests/intlchar_reset_error.phpt
@@ -0,0 +1,19 @@
+--TEST--
+IntlChar methods reset intl error on success
+--EXTENSIONS--
+intl
+--FILE--
+<?php
+var_dump(IntlChar::digit('a', 1));
+var_dump(intl_get_error_code() !== U_ZERO_ERROR);
+
+var_dump(IntlChar::forDigit(1) === ord('1'));
+var_dump(intl_get_error_code() === U_ZERO_ERROR);
+var_dump(intl_get_error_message() === 'U_ZERO_ERROR');
+?>
+--EXPECT--
+bool(false)
+bool(true)
+bool(true)
+bool(true)
+bool(true)
diff --git a/ext/intl/uchar/uchar.c b/ext/intl/uchar/uchar.c
index f194e0e0b931..32bb83a09a4b 100644
--- a/ext/intl/uchar/uchar.c
+++ b/ext/intl/uchar/uchar.c
@@ -54,6 +54,8 @@ IC_METHOD(chr) {
 	char buffer[5];
 	int buffer_len = 0;
 
+	intl_error_reset(NULL);
+
 	if (parse_code_point_param(INTERNAL_FUNCTION_PARAM_PASSTHRU, &cp) == FAILURE) {
 		RETURN_NULL();
 	}
@@ -73,6 +75,8 @@ IC_METHOD(chr) {
 IC_METHOD(ord) {
 	UChar32 cp;
 
+	intl_error_reset(NULL);
+
 	if (parse_code_point_param(INTERNAL_FUNCTION_PARAM_PASSTHRU, &cp) == FAILURE) {
 		RETURN_NULL();
 	}
@@ -88,6 +92,8 @@ IC_METHOD(hasBinaryProperty) {
 	zend_string *string_codepoint;
 	zend_long int_codepoint = 0;
 
+	intl_error_reset(NULL);
+
 	ZEND_PARSE_PARAMETERS_START(2, 2)
 		Z_PARAM_STR_OR_LONG(string_codepoint, int_codepoint)
 		Z_PARAM_LONG(prop)
@@ -108,6 +114,8 @@ IC_METHOD(getIntPropertyValue) {
 	zend_string *string_codepoint;
 	zend_long int_codepoint = 0;
 
+	intl_error_reset(NULL);
+
 	ZEND_PARSE_PARAMETERS_START(2, 2)
 		Z_PARAM_STR_OR_LONG(string_codepoint, int_codepoint)
 		Z_PARAM_LONG(prop)
@@ -125,6 +133,8 @@ IC_METHOD(getIntPropertyValue) {
 IC_METHOD(getIntPropertyMinValue) {
 	zend_long prop;
 
+	intl_error_reset(NULL);
+
 	ZEND_PARSE_PARAMETERS_START(1, 1)
 		Z_PARAM_LONG(prop)
 	ZEND_PARSE_PARAMETERS_END();
@@ -137,6 +147,8 @@ IC_METHOD(getIntPropertyMinValue) {
 IC_METHOD(getIntPropertyMaxValue) {
 	zend_long prop;
 
+	intl_error_reset(NULL);
+
 	ZEND_PARSE_PARAMETERS_START(1, 1)
 		Z_PARAM_LONG(prop)
 	ZEND_PARSE_PARAMETERS_END();
@@ -149,6 +161,8 @@ IC_METHOD(getIntPropertyMaxValue) {
 IC_METHOD(getNumericValue) {
 	UChar32 cp;
 
+	intl_error_reset(NULL);
+
 	if (parse_code_point_param(INTERNAL_FUNCTION_PARAM_PASSTHRU, &cp) == FAILURE) {
 		RETURN_NULL();
 	}
@@ -191,6 +205,8 @@ static UBool enumCharType_callback(enumCharType_data *context,
 IC_METHOD(enumCharTypes) {
 	enumCharType_data context;
 
+	intl_error_reset(NULL);
+
 	ZEND_PARSE_PARAMETERS_START(1, 1)
 		Z_PARAM_FUNC(context.fci, context.fci_cache)
 	ZEND_PARSE_PARAMETERS_END();
@@ -202,6 +218,8 @@ IC_METHOD(enumCharTypes) {
 IC_METHOD(getBlockCode) {
 	UChar32 cp;
 
+	intl_error_reset(NULL);
+
 	if (parse_code_point_param(INTERNAL_FUNCTION_PARAM_PASSTHRU, &cp) == FAILURE) {
 		RETURN_NULL();
 	}
@@ -220,6 +238,8 @@ IC_METHOD(charName) {
 	zend_string *buffer = NULL;
 	int32_t buffer_len;
 
+	intl_error_reset(NULL);
+
 	ZEND_PARSE_PARAMETERS_START(1, 2)
 		Z_PARAM_STR_OR_LONG(string_codepoint, int_codepoint)
 		Z_PARAM_OPTIONAL
@@ -250,6 +270,8 @@ IC_METHOD(charFromName) {
 	UChar32 ret;
 	UErrorCode error = U_ZERO_ERROR;
 
+	intl_error_reset(NULL);
+
 	ZEND_PARSE_PARAMETERS_START(1, 2)
 		Z_PARAM_STRING(name, name_len)
 		Z_PARAM_OPTIONAL
@@ -301,6 +323,7 @@ IC_METHOD(enumCharNames) {
 	zend_long nameChoice = U_UNICODE_CHAR_NAME;
 	UErrorCode error = U_ZERO_ERROR;
 
+	intl_error_reset(NULL);
 
 	ZEND_PARSE_PARAMETERS_START(3, 4)
 		Z_PARAM_STR_OR_LONG(string_start, int_start)
@@ -326,6 +349,8 @@ IC_METHOD(getPropertyName) {
 	zend_long nameChoice = U_LONG_PROPERTY_NAME;
 	const char *ret;
 
+	intl_error_reset(NULL);
+
 	ZEND_PARSE_PARAMETERS_START(1, 2)
 		Z_PARAM_LONG(property)
 		Z_PARAM_OPTIONAL
@@ -348,6 +373,8 @@ IC_METHOD(getPropertyEnum) {
 	char *alias;
 	size_t alias_len;
 
+	intl_error_reset(NULL);
+
 	ZEND_PARSE_PARAMETERS_START(1, 1)
 		Z_PARAM_STRING(alias, alias_len)
 	ZEND_PARSE_PARAMETERS_END();
@@ -361,6 +388,8 @@ IC_METHOD(getPropertyValueName) {
 	zend_long property, value, nameChoice = U_LONG_PROPERTY_NAME;
 	const char *ret;
 
+	intl_error_reset(NULL);
+
 	ZEND_PARSE_PARAMETERS_START(2, 3)
 		Z_PARAM_LONG(property)
 		Z_PARAM_LONG(value)
@@ -385,6 +414,8 @@ IC_METHOD(getPropertyValueEnum) {
 	char *name;
 	size_t name_len;
 
+	intl_error_reset(NULL);
+
 	ZEND_PARSE_PARAMETERS_START(2, 2)
 		Z_PARAM_LONG(property)
 		Z_PARAM_STRING(name, name_len)
@@ -401,6 +432,8 @@ IC_METHOD(foldCase) {
 	zend_string *string_codepoint;
 	zend_long int_codepoint = 0;
 
+	intl_error_reset(NULL);
+
 	ZEND_PARSE_PARAMETERS_START(1, 2)
 		Z_PARAM_STR_OR_LONG(string_codepoint, int_codepoint)
 		Z_PARAM_OPTIONAL
@@ -432,6 +465,8 @@ IC_METHOD(digit) {
 	zend_string *string_codepoint;
 	zend_long int_codepoint = 0;
 
+	intl_error_reset(NULL);
+
 	ZEND_PARSE_PARAMETERS_START(1, 2)
 		Z_PARAM_STR_OR_LONG(string_codepoint, int_codepoint)
 		Z_PARAM_OPTIONAL
@@ -456,6 +491,8 @@ IC_METHOD(digit) {
 IC_METHOD(forDigit) {
 	zend_long digit, radix = 10;
 
+	intl_error_reset(NULL);
+
 	ZEND_PARSE_PARAMETERS_START(1, 2)
 		Z_PARAM_LONG(digit)
 		Z_PARAM_OPTIONAL
@@ -472,6 +509,8 @@ IC_METHOD(charAge) {
 	UVersionInfo version;
 	int i;
 
+	intl_error_reset(NULL);
+
 	if (parse_code_point_param(INTERNAL_FUNCTION_PARAM_PASSTHRU, &cp) == FAILURE) {
 		RETURN_NULL();
 	}
@@ -489,6 +528,8 @@ IC_METHOD(getUnicodeVersion) {
 	UVersionInfo version;
 	int i;
 
+	intl_error_reset(NULL);
+
 	ZEND_PARSE_PARAMETERS_NONE();
 
 	u_getUnicodeVersion(version);
@@ -507,6 +548,8 @@ IC_METHOD(getFC_NFKC_Closure) {
 	int32_t closure_len;
 	UErrorCode error = U_ZERO_ERROR;
 
+	intl_error_reset(NULL);
+
 	if (parse_code_point_param(INTERNAL_FUNCTION_PARAM_PASSTHRU, &cp) == FAILURE) {
 		RETURN_NULL();
 	}
@@ -535,6 +578,7 @@ IC_METHOD(getFC_NFKC_Closure) {
 #define IC_BOOL_METHOD_CHAR(name) \
 IC_METHOD(name) { \
 	UChar32 cp; \
+	intl_error_reset(NULL); \
 	if (parse_code_point_param(INTERNAL_FUNCTION_PARAM_PASSTHRU, &cp) == FAILURE) { \
 		RETURN_NULL(); \
 	} \
@@ -575,6 +619,7 @@ IC_BOOL_METHOD_CHAR(isJavaIDPart)
 #define IC_INT_METHOD_CHAR(name) \
 IC_METHOD(name) { \
 	UChar32 cp; \
+	intl_error_reset(NULL); \
 	if (parse_code_point_param(INTERNAL_FUNCTION_PARAM_PASSTHRU, &cp) == FAILURE) { \
 		RETURN_NULL(); \
 	} \
@@ -595,6 +640,7 @@ IC_METHOD(name) { \
 	UChar32 cp, ret; \
 	zend_string *string_codepoint; \
 		zend_long int_codepoint = -1; \
+		intl_error_reset(NULL); \
 		ZEND_PARSE_PARAMETERS_START(1, 1) \
 			Z_PARAM_STR_OR_LONG(string_codepoint, int_codepoint) \
 		ZEND_PARSE_PARAMETERS_END(); \
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.