Skip to content

Commit 2dfc044

Browse files
committed
Merge branch 'PHP-8.4' into PHP-8.5
* PHP-8.4: Fix use-after-free when ArrayObject sort comparator replaces backing store
2 parents 85231e8 + 2210fda commit 2dfc044

2 files changed

Lines changed: 38 additions & 0 deletions

File tree

ext/spl/spl_array.c

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -928,6 +928,10 @@ static zend_result spl_array_skip_protected(spl_array_object *intern, HashTable
928928
static void spl_array_set_array(zval *object, spl_array_object *intern, zval *array, zend_long ar_flags, bool just_array) {
929929
/* Handled by ZPP prior to this, or for __unserialize() before passing to here */
930930
ZEND_ASSERT(Z_TYPE_P(array) == IS_ARRAY || Z_TYPE_P(array) == IS_OBJECT);
931+
if (intern->nApplyCount > 0) {
932+
zend_throw_error(NULL, "Modification of ArrayObject during sorting is prohibited");
933+
return;
934+
}
931935
zval garbage;
932936
ZVAL_UNDEF(&garbage);
933937
if (Z_TYPE_P(array) == IS_ARRAY) {
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
--TEST--
2+
Can't use __construct() to replace the backing store while ArrayObject is being sorted
3+
--FILE--
4+
<?php
5+
6+
$ao = new ArrayObject([1, 2, 3]);
7+
$other = new ArrayObject([4, 5, 6]);
8+
$i = 0;
9+
$ao->uasort(function($a, $b) use ($ao, $other, &$i) {
10+
if ($i++ == 0) {
11+
try {
12+
$ao->__construct($other);
13+
} catch (Error $e) {
14+
echo $e->getMessage(), "\n";
15+
}
16+
}
17+
return $a <=> $b;
18+
});
19+
var_dump($ao);
20+
21+
?>
22+
--EXPECT--
23+
Modification of ArrayObject during sorting is prohibited
24+
object(ArrayObject)#1 (1) {
25+
["storage":"ArrayObject":private]=>
26+
array(3) {
27+
[0]=>
28+
int(1)
29+
[1]=>
30+
int(2)
31+
[2]=>
32+
int(3)
33+
}
34+
}

0 commit comments

Comments
 (0)