Commit e44db0cdfd0 for php.net
commit e44db0cdfd0bb3595dd7e95b48dd5ebf5a25eddd
Author: Xuyang Zhang <119476662+kn1g78@users.noreply.github.com>
Date: Mon Jun 29 22:12:46 2026 +0800
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
diff --git a/NEWS b/NEWS
index 86ef47098f7..57d91e34545 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 00000000000..45f6d1df296
--- /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 f194e0e0b93..32bb83a09a4 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(); \