Skip to content

Commit a16ace8

Browse files
committed
Merge branch 'PHP-8.5'
* PHP-8.5: Fix GH-21454: Missing write lock validation in SplHeap
2 parents 8cf9179 + c9a6743 commit a16ace8

File tree

2 files changed

+39
-1
lines changed

2 files changed

+39
-1
lines changed

ext/spl/spl_heap.c

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -938,7 +938,7 @@ static void spl_heap_it_move_forward(zend_object_iterator *iter) /* {{{ */
938938
{
939939
spl_heap_object *object = Z_SPLHEAP_P(&iter->data);
940940

941-
if (UNEXPECTED(spl_heap_consistency_validations(object, false) != SUCCESS)) {
941+
if (UNEXPECTED(spl_heap_consistency_validations(object, true) != SUCCESS)) {
942942
return;
943943
}
944944

@@ -965,6 +965,10 @@ PHP_METHOD(SplHeap, next)
965965

966966
ZEND_PARSE_PARAMETERS_NONE();
967967

968+
if (UNEXPECTED(spl_heap_consistency_validations(intern, true) != SUCCESS)) {
969+
RETURN_THROWS();
970+
}
971+
968972
spl_ptr_heap_delete_top(intern->heap, NULL, ZEND_THIS);
969973
}
970974
/* }}} */
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
--TEST--
2+
SplHeap::next() write lock
3+
--CREDITS--
4+
cnitlrt
5+
--FILE--
6+
<?php
7+
8+
class EvilPQ extends SplPriorityQueue {
9+
private bool $did = false;
10+
11+
public function compare(mixed $p1, mixed $p2): int {
12+
if (!$this->did) {
13+
$this->did = true;
14+
// Re-entrant write during internal heap insertion comparison.
15+
if (!$this->isEmpty()) {
16+
$this->next(); // no write-lock validation
17+
}
18+
}
19+
return parent::compare($p1, $p2);
20+
}
21+
}
22+
23+
$q = new EvilPQ();
24+
try {
25+
for ($i = 0; $i < 200; $i++) {
26+
$q->insert("d$i", 100 - $i);
27+
}
28+
} catch (RuntimeException $e) {
29+
echo $e::class, ": ", $e->getMessage(), "\n";
30+
}
31+
32+
?>
33+
--EXPECT--
34+
RuntimeException: Heap cannot be changed when it is already being modified.

0 commit comments

Comments
 (0)