Skip to content

Commit c9a6743

Browse files
committed
Merge branch 'PHP-8.4' into PHP-8.5
* PHP-8.4: Fix GH-21454: Missing write lock validation in SplHeap
2 parents 0b2d813 + 8796d75 commit c9a6743

File tree

3 files changed

+43
-1
lines changed

3 files changed

+43
-1
lines changed

NEWS

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,10 @@ PHP NEWS
4343
. Fixed Set-Cookie parsing bug wrong offset while scanning attributes.
4444
(David Carlier)
4545

46+
- SPL:
47+
. Fixed bug GH-21454 (missing write lock validation in SplHeap).
48+
(ndossche)
49+
4650
- Standard:
4751
. Fixed bug GH-20906 (Assertion failure when messing up output buffers).
4852
(ndossche)

ext/spl/spl_heap.c

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

959-
if (UNEXPECTED(spl_heap_consistency_validations(object, false) != SUCCESS)) {
959+
if (UNEXPECTED(spl_heap_consistency_validations(object, true) != SUCCESS)) {
960960
return;
961961
}
962962

@@ -987,6 +987,10 @@ PHP_METHOD(SplHeap, next)
987987
RETURN_THROWS();
988988
}
989989

990+
if (UNEXPECTED(spl_heap_consistency_validations(intern, true) != SUCCESS)) {
991+
RETURN_THROWS();
992+
}
993+
990994
spl_ptr_heap_delete_top(intern->heap, NULL, ZEND_THIS);
991995
}
992996
/* }}} */
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)