Commit 66ceedae95d for php.net

commit 66ceedae95d9bfc3d286aa86f12ae6c92077f719
Author: Weilin Du <weilindu@php.net>
Date:   Mon Aug 10 15:58:31 2026 +0800

    ext/intl: Fix stale intl error state in IntlNumberRangeFormatter (#23191)

    IntlNumberRangeFormatter::createFromSkeleton() and
    IntlNumberRangeFormatter::format() did not reset intl error state. This commit
    fix it.

    I know this is yet another "error state" fixes. Unfortunately we couldn't use
    the function macro added before because these are methods, and we can only
    reset the error state manually so far.

    I personally hate the error state design. I think we should throw exceptions
    instead. But considering BC breaks... this is just an idea in the void.

    IntlNumberRangeFormatter is added in 8.6 so this is the correct branch.

diff --git a/NEWS b/NEWS
index b091ea27614..8ea376a2c24 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/ext/intl/rangeformatter/rangeformatter_class.cpp b/ext/intl/rangeformatter/rangeformatter_class.cpp
index 2dbb60c5b63..95acfccd245 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 00000000000..fb19da87d58
--- /dev/null
+++ b/ext/intl/tests/rangeformatter/rangeformatter_create_error_reset.phpt
@@ -0,0 +1,54 @@
+--TEST--
+IntlNumberRangeFormatter resets stale errors
+--EXTENSIONS--
+intl
+--SKIPIF--
+<?php
+if (version_compare(INTL_ICU_VERSION, '63.0') < 0) {
+    die('skip for ICU < 63.0');
+}
+?>
+--FILE--
+<?php
+try {
+    IntlNumberRangeFormatter::createFromSkeleton(
+        'invalid skeleton here',
+        'en_US',
+        IntlNumberRangeFormatter::COLLAPSE_AUTO,
+        IntlNumberRangeFormatter::IDENTITY_FALLBACK_RANGE
+    );
+} catch (IntlException $exception) {
+    var_dump(str_contains(intl_get_error_message(), 'U_NUMBER_SKELETON_SYNTAX_ERROR'));
+}
+
+$formatter = IntlNumberRangeFormatter::createFromSkeleton(
+    '',
+    'en_US',
+    IntlNumberRangeFormatter::COLLAPSE_AUTO,
+    IntlNumberRangeFormatter::IDENTITY_FALLBACK_RANGE
+);
+
+var_dump(intl_get_error_code());
+var_dump(intl_get_error_message());
+
+try {
+    IntlNumberRangeFormatter::createFromSkeleton(
+        'invalid skeleton here',
+        'en_US',
+        IntlNumberRangeFormatter::COLLAPSE_AUTO,
+        IntlNumberRangeFormatter::IDENTITY_FALLBACK_RANGE
+    );
+} catch (IntlException $exception) {
+}
+
+$formatter->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"