From e17cfab60a0a40f42c93aa1ff7d3157747d5ec5a Mon Sep 17 00:00:00 2001 From: ndossche <7771979+ndossche@users.noreply.github.com> Date: Sun, 15 Mar 2026 00:05:23 +0100 Subject: [PATCH 1/2] Fix missing write lock validation in SplHeap::next() --- ext/spl/spl_heap.c | 4 +++ ext/spl/tests/heap_next_write_lock.phpt | 34 +++++++++++++++++++++++++ 2 files changed, 38 insertions(+) create mode 100644 ext/spl/tests/heap_next_write_lock.phpt diff --git a/ext/spl/spl_heap.c b/ext/spl/spl_heap.c index d4450da42009c..6dd478f64c1d0 100644 --- a/ext/spl/spl_heap.c +++ b/ext/spl/spl_heap.c @@ -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); } /* }}} */ diff --git a/ext/spl/tests/heap_next_write_lock.phpt b/ext/spl/tests/heap_next_write_lock.phpt new file mode 100644 index 0000000000000..fcad94f3ccd3f --- /dev/null +++ b/ext/spl/tests/heap_next_write_lock.phpt @@ -0,0 +1,34 @@ +--TEST-- +SplHeap::next() write lock +--CREDITS-- +cnitlrt +--FILE-- +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. From e0dff23429655546193811849c27b1138410b45b Mon Sep 17 00:00:00 2001 From: ndossche <7771979+ndossche@users.noreply.github.com> Date: Sun, 15 Mar 2026 13:25:50 +0100 Subject: [PATCH 2/2] fix incorrect flag --- ext/spl/spl_heap.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ext/spl/spl_heap.c b/ext/spl/spl_heap.c index 6dd478f64c1d0..e2c090945b6c8 100644 --- a/ext/spl/spl_heap.c +++ b/ext/spl/spl_heap.c @@ -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; }