Fix instable array during in-place modification in uksort

The array isn't just observable if the array has RCn, but also if it is inside a
reference that is RCn. By-ref parameters are always RCn and as such always
observable.

Fixes GH-13279
Closes GH-13285
This commit is contained in:
Ilija Tovilo 2024-01-31 13:15:49 +01:00
parent 1a349ab209
commit d65c395049
No known key found for this signature in database
GPG Key ID: A4F5D403F118200A
3 changed files with 23 additions and 10 deletions

3
NEWS
View File

@ -2,6 +2,9 @@ PHP NEWS
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||| |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
?? ??? ????, PHP 8.3.4 ?? ??? ????, PHP 8.3.4
- Standard:
. Fixed bug GH-13279 (Instable array during in-place modification in uksort).
(ilutov)
15 Feb 2024, PHP 8.3.3 15 Feb 2024, PHP 8.3.3

View File

@ -901,19 +901,11 @@ static void php_usort(INTERNAL_FUNCTION_PARAMETERS, bucket_compare_func_t compar
RETURN_TRUE; RETURN_TRUE;
} }
/* Copy array, so the in-place modifications will not be visible to the callback function. /* Copy array, so the in-place modifications will not be visible to the callback function */
* Unless there are no other references since we know for sure it won't be visible. */ arr = zend_array_dup(arr);
bool in_place = zend_may_modify_arg_in_place(array);
if (!in_place) {
arr = zend_array_dup(arr);
}
zend_hash_sort(arr, compare_func, renumber); zend_hash_sort(arr, compare_func, renumber);
if (in_place) {
GC_ADDREF(arr);
}
zval garbage; zval garbage;
ZVAL_COPY_VALUE(&garbage, array); ZVAL_COPY_VALUE(&garbage, array);
ZVAL_ARR(array, arr); ZVAL_ARR(array, arr);

View File

@ -0,0 +1,18 @@
--TEST--
GH-13279: Instable array during in-place modification in uksort
--FILE--
<?php
// Make sure the array is not const
$array = [];
$array['a'] = 1;
$array['b'] = 2;
uksort($array, function ($a, $b) use (&$array) {
return $array[$a] - $array[$b];
});
?>
===DONE===
--EXPECT--
===DONE===