Commit d8e741838a5 for php.net

commit d8e741838a534d30e9e329c25d90592d988398a7
Author: Weilin Du <weilindu@php.net>
Date:   Tue Jun 16 20:53:37 2026 +0800

    ext/intl: Fix argument positions in transliterator_transliterate() error message

    Fix a missed case in #22044, that argument positions in transliterator_transliterate() error message could be wrong.

    Closes #22331

diff --git a/NEWS b/NEWS
index 3c7f104a24d..05bdd1b35ff 100644
--- a/NEWS
+++ b/NEWS
@@ -33,7 +33,8 @@ PHP                                                                        NEWS

 - Intl:
   . Fix incorrect argument positions for uninitialized calendar arguments in
-    IntlCalendar::equals(), ::before(), ::after(), and ::isEquivalentTo().
+    IntlCalendar::equals(), ::before(), ::after(), and ::isEquivalentTo(), and
+    for invalid start/end arguments in transliterator_transliterate().
     (Weilin Du)
   . Fixed IntlTimeZone::getDisplayName() to synchronize object error state
     for invalid display types. (Weilin Du)
diff --git a/ext/intl/tests/transliterator_transliterate_error.phpt b/ext/intl/tests/transliterator_transliterate_error.phpt
index 4a354465bf2..aefdd72b400 100644
--- a/ext/intl/tests/transliterator_transliterate_error.phpt
+++ b/ext/intl/tests/transliterator_transliterate_error.phpt
@@ -9,14 +9,36 @@

 $tr = Transliterator::create("latin");

+function dump_value_error(callable $callback): void {
+    try {
+        $callback();
+    } catch (ValueError $exception) {
+        echo $exception->getMessage() . "\n";
+    }
+}
+
 //Arguments
 var_dump(transliterator_transliterate($tr,"str",7));

-try {
+dump_value_error(function() use ($tr) {
     transliterator_transliterate($tr,"str",7,6);
-} catch (ValueError $exception) {
-    echo $exception->getMessage() . "\n";
-}
+});
+
+dump_value_error(function() use ($tr) {
+    transliterator_transliterate($tr,"str", 0, -2);
+});
+
+dump_value_error(function() use ($tr) {
+    transliterator_transliterate($tr,"str", -1);
+});
+
+dump_value_error(function() {
+    transliterator_transliterate("latin","str", -1);
+});
+
+dump_value_error(function() use ($tr) {
+    $tr->transliterate("str", 7, 6);
+});

 //bad UTF-8
 transliterator_transliterate($tr, "\x80\x03");
@@ -26,7 +48,11 @@
 --EXPECTF--
 Warning: transliterator_transliterate(): transliterator_transliterate: Neither "start" nor the "end" arguments can exceed the number of UTF-16 code units (in this case, 3) in %s on line %d
 bool(false)
-transliterator_transliterate(): Argument #2 ($string) must be less than or equal to argument #3 ($end)
+transliterator_transliterate(): Argument #3 ($start) must be less than or equal to argument #4 ($end)
+transliterator_transliterate(): Argument #4 ($end) must be greater than or equal to -1
+transliterator_transliterate(): Argument #3 ($start) must be greater than or equal to 0
+transliterator_transliterate(): Argument #3 ($start) must be greater than or equal to 0
+Transliterator::transliterate(): Argument #2 ($start) must be less than or equal to argument #3 ($end)

 Warning: transliterator_transliterate(): String conversion of string to UTF-16 failed in %s on line %d
 Done.
diff --git a/ext/intl/transliterator/transliterator_methods.c b/ext/intl/transliterator/transliterator_methods.c
index 81e83414a4f..5bdfc567a57 100644
--- a/ext/intl/transliterator/transliterator_methods.c
+++ b/ext/intl/transliterator/transliterator_methods.c
@@ -271,14 +271,16 @@ PHP_FUNCTION( transliterator_transliterate )
 	zend_long	start		= 0,
 				limit		= -1;
 	int			success     = 0;
+	bool		is_method;
 	zval 		tmp_object;
 	TRANSLITERATOR_METHOD_INIT_VARS;

 	object = getThis();
+	is_method = object != NULL;

 	ZVAL_UNDEF(&tmp_object);

-	if (object == NULL) {
+	if (!is_method) {
 		/* in non-OOP version, accept both a transliterator and a string */
 		zend_string *arg1_str;
 		zend_object *arg1_obj;
@@ -315,17 +317,17 @@ PHP_FUNCTION( transliterator_transliterate )
 	}

 	if (limit < -1) {
-		zend_argument_value_error(object ? 3 : 4, "must be greater than or equal to -1");
+		zend_argument_value_error(is_method ? 3 : 4, "must be greater than or equal to -1");
 		goto cleanup_object;
 	}

 	if (start < 0) {
-		zend_argument_value_error(object ? 2 : 3, "must be greater than or equal to 0");
+		zend_argument_value_error(is_method ? 2 : 3, "must be greater than or equal to 0");
 		goto cleanup_object;
 	}

 	if (limit != -1 && start > limit) {
-		zend_argument_value_error(object ? 2 : 3, "must be less than or equal to argument #%d ($end)", object ? 3 : 4);
+		zend_argument_value_error(is_method ? 2 : 3, "must be less than or equal to argument #%d ($end)", is_method ? 3 : 4);
 		goto cleanup_object;
 	}