Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit 0458b3c

Browse files
committed
Fix GH-20101: SplHeap/SplPriorityQueue serialization exposes INDIRECTs
Exposing INDIRECTs to userland is not allowed and can lead to all sorts of wrong behaviour. In this case it lead to UAF bugs. Solve it by duplicating the properties table, which de-indirects the elements and also decouples it for future modifications. Closes GH-20102.
1 parent d0615d7 commit 0458b3c

File tree

4 files changed

+63
-28
lines changed

4 files changed

+63
-28
lines changed

‎NEWS‎

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,9 @@ PHP NEWS
22
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
33
?? ??? ????, PHP 8.5.0RC3
44

5+
- SPL:
6+
. Fixed bug GH-20101 (SplHeap/SplPriorityQueue serialization
7+
exposes INDIRECTs). (nielsdos)
58

69
09 Oct 2025, PHP 8.5.0RC2
710

‎ext/spl/spl_heap.c‎

Lines changed: 9 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -1167,7 +1167,7 @@ static zend_result spl_heap_unserialize_internal_state(HashTable *state_ht, spl_
11671167
return SUCCESS;
11681168
}
11691169

1170-
PHP_METHOD(SplPriorityQueue, __serialize)
1170+
staticvoidspl_heap_serialize_internal(INTERNAL_FUNCTION_PARAMETERS, boolis_pqueue)
11711171
{
11721172
spl_heap_object *intern = Z_SPLHEAP_P(ZEND_THIS);
11731173
zval props, state;
@@ -1185,14 +1185,18 @@ PHP_METHOD(SplPriorityQueue, __serialize)
11851185

11861186
array_init(return_value);
11871187

1188-
ZVAL_ARR(&props, zend_std_get_properties(&intern->std));
1189-
Z_TRY_ADDREF(props);
1188+
ZVAL_ARR(&props, zend_array_dup(zend_std_get_properties(&intern->std)));
11901189
zend_hash_next_index_insert(Z_ARRVAL_P(return_value), &props);
11911190

1192-
spl_heap_serialize_internal_state(&state, intern, true);
1191+
spl_heap_serialize_internal_state(&state, intern, is_pqueue);
11931192
zend_hash_next_index_insert(Z_ARRVAL_P(return_value), &state);
11941193
}
11951194

1195+
PHP_METHOD(SplPriorityQueue, __serialize)
1196+
{
1197+
spl_heap_serialize_internal(INTERNAL_FUNCTION_PARAM_PASSTHRU, true);
1198+
}
1199+
11961200
PHP_METHOD(SplPriorityQueue, __unserialize)
11971201
{
11981202
HashTable *data;
@@ -1241,28 +1245,7 @@ PHP_METHOD(SplPriorityQueue, __unserialize)
12411245

12421246
PHP_METHOD(SplHeap, __serialize)
12431247
{
1244-
spl_heap_object *intern = Z_SPLHEAP_P(ZEND_THIS);
1245-
zval props, state;
1246-
1247-
ZEND_PARSE_PARAMETERS_NONE();
1248-
1249-
if (UNEXPECTED(spl_heap_consistency_validations(intern, false) != SUCCESS)) {
1250-
RETURN_THROWS();
1251-
}
1252-
1253-
if (intern->heap->flags & SPL_HEAP_WRITE_LOCKED) {
1254-
zend_throw_exception(spl_ce_RuntimeException, "Cannot serialize heap while it is being modified.", 0);
1255-
RETURN_THROWS();
1256-
}
1257-
1258-
array_init(return_value);
1259-
1260-
ZVAL_ARR(&props, zend_std_get_properties(&intern->std));
1261-
Z_TRY_ADDREF(props);
1262-
zend_hash_next_index_insert(Z_ARRVAL_P(return_value), &props);
1263-
1264-
spl_heap_serialize_internal_state(&state, intern, false);
1265-
zend_hash_next_index_insert(Z_ARRVAL_P(return_value), &state);
1248+
spl_heap_serialize_internal(INTERNAL_FUNCTION_PARAM_PASSTHRU, false);
12661249
}
12671250

12681251
PHP_METHOD(SplHeap, __unserialize)

‎ext/spl/tests/SplHeap_serialize_indexed_format.phpt‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -74,9 +74,9 @@ array(2) {
7474
[0]=>
7575
array(2) {
7676
["flags"]=>
77-
UNKNOWN:0
77+
string(13) "user_property"
7878
["heap_elements"]=>
79-
UNKNOWN:0
79+
string(13) "user_property"
8080
}
8181
[1]=>
8282
array(2) {

‎ext/spl/tests/gh20101.phpt‎

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
--TEST--
2+
GH-20101 (SplHeap/SplPriorityQueue serialization exposes INDIRECTs)
3+
--FILE--
4+
<?php
5+
class CustomHeap extends SplMaxHeap {
6+
public $field = 0;
7+
}
8+
$heap = new CustomHeap();
9+
$data = $heap->__serialize();
10+
var_dump($data);
11+
12+
class CustomPriorityQueue extends SplPriorityQueue {
13+
public $field = 0;
14+
}
15+
$pqueue = new CustomPriorityQueue();
16+
$data = $pqueue->__serialize();
17+
var_dump($data);
18+
?>
19+
--EXPECT--
20+
array(2) {
21+
[0]=>
22+
array(1) {
23+
["field"]=>
24+
int(0)
25+
}
26+
[1]=>
27+
array(2) {
28+
["flags"]=>
29+
int(0)
30+
["heap_elements"]=>
31+
array(0) {
32+
}
33+
}
34+
}
35+
array(2) {
36+
[0]=>
37+
array(1) {
38+
["field"]=>
39+
int(0)
40+
}
41+
[1]=>
42+
array(2) {
43+
["flags"]=>
44+
int(1)
45+
["heap_elements"]=>
46+
array(0) {
47+
}
48+
}
49+
}

0 commit comments

Comments
(0)

AltStyle によって変換されたページ (->オリジナル) /