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

Improve __unserialize() hardening for SplHeap/SplPriorityQueue

It was possible to make the heap accept unserialize data when the heap
was corrupted or under modification. This adds the necessary check to
prevent that from happening.
Also, the exception check at the bottom is pointless,
spl_heap_unserialize_internal_state() already returns FAILURE on
exception. If it *is* necessary, it should be documented why.

Closes GH-20109.
This commit is contained in:
Niels Dossche
2025-10-08 19:22:03 +02:00
parent 234577ee90
commit bc76b3fca9
3 changed files with 35 additions and 4 deletions

1
NEWS
View File

@@ -19,6 +19,7 @@ PHP NEWS
- SPL:
. Fixed bug GH-20101 (SplHeap/SplPriorityQueue serialization
exposes INDIRECTs). (nielsdos)
. Improve __unserialize() hardening for SplHeap/SplPriorityQueue. (nielsdos)
09 Oct 2025, PHP 8.5.0RC2

View File

@@ -1257,6 +1257,10 @@ PHP_METHOD(SplHeap, __unserialize)
Z_PARAM_ARRAY_HT(data)
ZEND_PARSE_PARAMETERS_END();
if (UNEXPECTED(spl_heap_consistency_validations(intern, true) != SUCCESS)) {
RETURN_THROWS();
}
if (zend_hash_num_elements(data) != 2) {
zend_throw_exception_ex(NULL, 0, "Invalid serialization data for %s object", ZSTR_VAL(intern->std.ce->name));
RETURN_THROWS();
@@ -1285,10 +1289,6 @@ PHP_METHOD(SplHeap, __unserialize)
RETURN_THROWS();
}
if (EG(exception)) {
RETURN_THROWS();
}
if (UNEXPECTED(spl_heap_consistency_validations(intern, false) != SUCCESS)) {
RETURN_THROWS();
}

View File

@@ -0,0 +1,30 @@
--TEST--
SplHeap should not accept unserialize data when it is corrupted or under modification
--FILE--
<?php
class MyHeap extends SplMaxHeap {
public function compare($a, $b): int {
global $array;
static $counter = 0;
if ($counter++ === 0)
$this->__unserialize($array);
return $a < $b ? -1 : ($a == $b ? 0 : 1);
}
}
$heap = new SplMaxHeap;
$heap->insert(1);
$array = $heap->__serialize();
$heap = new MyHeap;
$heap->insert(0);
try {
$heap->insert(2);
} catch (RuntimeException $e) {
echo $e->getMessage(), "\n";
}
?>
--EXPECT--
Heap cannot be changed when it is already being modified.