[php-src] master: Merge branch 'PHP-8.4' into PHP-8.5
Ilia Alshanetsky <[email protected]>
| Newsgroups | gmane.comp.php.cvs.general |
|---|---|
| Message-ID | <[email protected]> |
Author: Ilia Alshanetsky (iliaal)
Date: 2026-06-26T14:37:55-04:00
Commit: https://github.com/php/php-src/commit/a311f0502d60f49d64956995db91d6f37b41d35e
Raw diff: https://github.com/php/php-src/commit/a311f0502d60f49d64956995db91d6f37b41d35e.diff
Merge branch 'PHP-8.4' into PHP-8.5
* PHP-8.4:
Fix use-after-free in Collator::sort() with a mutating comparator
Changed paths:
A ext/intl/tests/collator_sort_modify_during_compare.phpt
M ext/intl/collator/collator_sort.c
Diff:
diff --git a/ext/intl/collator/collator_sort.c b/ext/intl/collator/collator_sort.c
index 99b75aa0ef2b..ca489a19eafb 100644
--- a/ext/intl/collator/collator_sort.c
+++ b/ext/intl/collator/collator_sort.c
@@ -255,12 +255,13 @@ static void collator_sort_internal( int renumber, INTERNAL_FUNCTION_PARAMETERS )
UCollator* saved_collator;
zval* array = NULL;
HashTable* hash = NULL;
+ zend_array* sorted = NULL;
zend_long sort_flags = COLLATOR_SORT_REGULAR;
COLLATOR_METHOD_INIT_VARS
/* Parse parameters. */
- if( zend_parse_method_parameters( ZEND_NUM_ARGS(), getThis(), "Oa/|l",
+ if( zend_parse_method_parameters( ZEND_NUM_ARGS(), getThis(), "Oa|l",
&object, Collator_ce_ptr, &array, &sort_flags ) == FAILURE )
{
RETURN_THROWS();
@@ -279,8 +280,14 @@ static void collator_sort_internal( int renumber, INTERNAL_FUNCTION_PARAMETERS )
hash = Z_ARRVAL_P( array );
+ /* Copy array, so the in-place modifications will not be visible to the callback function */
+ sorted = zend_array_dup( hash );
+
/* Convert strings in the specified array from UTF-8 to UTF-16. */
- collator_convert_hash_from_utf8_to_utf16( hash, COLLATOR_ERROR_CODE_P( co ) );
+ collator_convert_hash_from_utf8_to_utf16( sorted, COLLATOR_ERROR_CODE_P( co ) );
+ if( U_FAILURE( COLLATOR_ERROR_CODE( co ) ) ) {
+ zend_array_destroy( sorted );
+ }
COLLATOR_CHECK_STATUS( co, "Error converting hash from UTF-8 to UTF-16" );
/* Save specified collator in the request-global (?) variable. */
@@ -288,15 +295,23 @@ static void collator_sort_internal( int renumber, INTERNAL_FUNCTION_PARAMETERS )
INTL_G( current_collator ) = co->ucoll;
/* Sort specified array. */
- zend_hash_sort(hash, collator_compare_func, renumber);
+ zend_hash_sort( sorted, collator_compare_func, renumber );
/* Restore saved collator. */
INTL_G( current_collator ) = saved_collator;
/* Convert strings in the specified array back to UTF-8. */
- collator_convert_hash_from_utf16_to_utf8( hash, COLLATOR_ERROR_CODE_P( co ) );
+ collator_convert_hash_from_utf16_to_utf8( sorted, COLLATOR_ERROR_CODE_P( co ) );
+ if( U_FAILURE( COLLATOR_ERROR_CODE( co ) ) ) {
+ zend_array_destroy( sorted );
+ }
COLLATOR_CHECK_STATUS( co, "Error converting hash from UTF-16 to UTF-8" );
+ zval garbage;
+ ZVAL_COPY_VALUE( &garbage, array );
+ ZVAL_ARR( array, sorted );
+ zval_ptr_dtor( &garbage );
+
RETURN_TRUE;
}
/* }}} */
diff --git a/ext/intl/tests/collator_sort_modify_during_compare.phpt b/ext/intl/tests/collator_sort_modify_during_compare.phpt
new file mode 100644
index 000000000000..427f5833f1fc
--- /dev/null
+++ b/ext/intl/tests/collator_sort_modify_during_compare.phpt
@@ -0,0 +1,36 @@
+--TEST--
+Collator::sort(): mutating the array from __toString() during comparison must not corrupt the sort
+--EXTENSIONS--
+intl
+--FILE--
+<?php
+$c = new Collator('en_US');
+
+class Grow {
+ public static array $ref;
+ public function __toString(): string {
+ for ($i = 0; $i < 2000; $i++) {
+ self::$ref[] = "x$i";
+ }
+ return "m";
+ }
+}
+
+$arr = ["z", new Grow(), "a", "b"];
+Grow::$ref = &$arr;
+var_dump($c->sort($arr));
+var_dump($arr);
+?>
+--EXPECT--
+bool(true)
+array(4) {
+ [0]=>
+ string(1) "a"
+ [1]=>
+ string(1) "b"
+ [2]=>
+ object(Grow)#2 (0) {
+ }
+ [3]=>
+ string(1) "z"
+}