1
0
mirror of https://github.com/php/php-src.git synced 2026-03-24 00:02:20 +01:00

Fix GH-21454: Missing write lock validation in SplHeap

Closes GH-21448.
This commit is contained in:
ndossche
2026-03-15 00:05:23 +01:00
parent a5637221ee
commit 8796d75365
3 changed files with 43 additions and 1 deletions

4
NEWS
View File

@@ -33,6 +33,10 @@ PHP NEWS
. Fixed Set-Cookie parsing bug wrong offset while scanning attributes.
(David Carlier)
- SPL:
. Fixed bug GH-21454 (missing write lock validation in SplHeap).
(ndossche)
- Standard:
. Fixed bug GH-20906 (Assertion failure when messing up output buffers).
(ndossche)

View File

@@ -961,7 +961,7 @@ static void spl_heap_it_move_forward(zend_object_iterator *iter) /* {{{ */
{
spl_heap_object *object = Z_SPLHEAP_P(&iter->data);
if (UNEXPECTED(spl_heap_consistency_validations(object, false) != SUCCESS)) {
if (UNEXPECTED(spl_heap_consistency_validations(object, true) != SUCCESS)) {
return;
}
@@ -992,6 +992,10 @@ PHP_METHOD(SplHeap, next)
RETURN_THROWS();
}
if (UNEXPECTED(spl_heap_consistency_validations(intern, true) != SUCCESS)) {
RETURN_THROWS();
}
spl_ptr_heap_delete_top(intern->heap, NULL, ZEND_THIS);
}
/* }}} */

View File

@@ -0,0 +1,34 @@
--TEST--
SplHeap::next() write lock
--CREDITS--
cnitlrt
--FILE--
<?php
class EvilPQ extends SplPriorityQueue {
private bool $did = false;
public function compare(mixed $p1, mixed $p2): int {
if (!$this->did) {
$this->did = true;
// Re-entrant write during internal heap insertion comparison.
if (!$this->isEmpty()) {
$this->next(); // no write-lock validation
}
}
return parent::compare($p1, $p2);
}
}
$q = new EvilPQ();
try {
for ($i = 0; $i < 200; $i++) {
$q->insert("d$i", 100 - $i);
}
} catch (RuntimeException $e) {
echo $e::class, ": ", $e->getMessage(), "\n";
}
?>
--EXPECT--
RuntimeException: Heap cannot be changed when it is already being modified.