Skip to content

Commit a082696

Browse files
committed
Fix GH-10907: Unable to serialize processed SplFixedArrays in PHP 8.2.4
The properties table can also contain numeric entries after a rebuild of the table based on the array. Since the array can only contain numeric entries, and the properties table can contain a mix of both, we'll add the numeric entries from the array and only the string entries from the properties table. To implement this we simply check if the key from the properties table is a string. Closes GH-10921.
1 parent 337973f commit a082696

File tree

3 files changed

+148
-2
lines changed

3 files changed

+148
-2
lines changed

NEWS

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,8 @@ PHP NEWS
6262

6363
- SPL:
6464
. Fixed bug GH-10519 (Array Data Address Reference Issue). (Nathan Freeman)
65+
. Fixed bug GH-10907 (Unable to serialize processed SplFixedArrays in
66+
PHP 8.2.4). (nielsdos)
6567

6668
- Standard:
6769
. Fixed bug GH-10885 (stream_socket_server context leaks). (ilutov)

ext/spl/spl_fixedarray.c

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -611,8 +611,13 @@ PHP_METHOD(SplFixedArray, __serialize)
611611
/* members */
612612
if (intern->std.properties) {
613613
ZEND_HASH_FOREACH_STR_KEY_VAL(intern->std.properties, key, current) {
614-
zend_hash_add(Z_ARRVAL_P(return_value), key, current);
615-
Z_TRY_ADDREF_P(current);
614+
/* The properties hash table can also contain the array elements if the properties table was already rebuilt.
615+
* In this case we'd have a NULL key. We can't simply use the properties table in all cases because it's
616+
* potentially out of sync (missing elements, or containing removed elements) and might need a rebuild. */
617+
if (key != NULL) {
618+
zend_hash_add_new(Z_ARRVAL_P(return_value), key, current);
619+
Z_TRY_ADDREF_P(current);
620+
}
616621
} ZEND_HASH_FOREACH_END();
617622
}
618623
}

ext/spl/tests/gh10907.phpt

Lines changed: 139 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,139 @@
1+
--TEST--
2+
GH-10907 (Unable to serialize processed SplFixedArrays in PHP 8.2.4)
3+
--FILE--
4+
<?php
5+
echo "Test without rebuilding properties\n";
6+
$array = new SplFixedArray(2);
7+
$array[0] = "test value 1";
8+
$array[1] = "test value 2";
9+
var_dump(serialize($array));
10+
var_dump(unserialize(serialize($array)));
11+
var_dump($array);
12+
13+
echo "=================\n";
14+
15+
echo "Test with rebuilding properties\n";
16+
$array = new SplFixedArray(2);
17+
$array[0] = "test value 1";
18+
$array[1] = "test value 2";
19+
var_dump($array); // Rebuilds properties
20+
var_dump(serialize($array));
21+
var_dump(unserialize(serialize($array)));
22+
var_dump($array);
23+
24+
echo "=================\n";
25+
26+
echo "Test with partially rebuilding properties\n";
27+
$array = new SplFixedArray(3);
28+
$array[0] = "test value 1";
29+
var_dump($array); // Rebuilds properties
30+
$array[1] = "test value 2";
31+
var_dump(serialize($array));
32+
var_dump(unserialize(serialize($array)));
33+
var_dump($array);
34+
35+
echo "=================\n";
36+
37+
echo "Test with adding members\n";
38+
#[AllowDynamicProperties]
39+
class MySplFixedArray extends SplFixedArray {
40+
public string $my_string = "my_string_value";
41+
}
42+
$array = new MySplFixedArray(3);
43+
$array->my_dynamic_property = "my_dynamic_property_value";
44+
$array[0] = "test value 1";
45+
$array[1] = "test value 2";
46+
var_dump(serialize($array));
47+
var_dump(unserialize(serialize($array)));
48+
var_dump($array);
49+
?>
50+
--EXPECT--
51+
Test without rebuilding properties
52+
string(73) "O:13:"SplFixedArray":2:{i:0;s:12:"test value 1";i:1;s:12:"test value 2";}"
53+
object(SplFixedArray)#2 (2) {
54+
[0]=>
55+
string(12) "test value 1"
56+
[1]=>
57+
string(12) "test value 2"
58+
}
59+
object(SplFixedArray)#1 (2) {
60+
[0]=>
61+
string(12) "test value 1"
62+
[1]=>
63+
string(12) "test value 2"
64+
}
65+
=================
66+
Test with rebuilding properties
67+
object(SplFixedArray)#2 (2) {
68+
[0]=>
69+
string(12) "test value 1"
70+
[1]=>
71+
string(12) "test value 2"
72+
}
73+
string(73) "O:13:"SplFixedArray":2:{i:0;s:12:"test value 1";i:1;s:12:"test value 2";}"
74+
object(SplFixedArray)#1 (2) {
75+
[0]=>
76+
string(12) "test value 1"
77+
[1]=>
78+
string(12) "test value 2"
79+
}
80+
object(SplFixedArray)#2 (2) {
81+
[0]=>
82+
string(12) "test value 1"
83+
[1]=>
84+
string(12) "test value 2"
85+
}
86+
=================
87+
Test with partially rebuilding properties
88+
object(SplFixedArray)#1 (3) {
89+
[0]=>
90+
string(12) "test value 1"
91+
[1]=>
92+
NULL
93+
[2]=>
94+
NULL
95+
}
96+
string(79) "O:13:"SplFixedArray":3:{i:0;s:12:"test value 1";i:1;s:12:"test value 2";i:2;N;}"
97+
object(SplFixedArray)#2 (3) {
98+
[0]=>
99+
string(12) "test value 1"
100+
[1]=>
101+
string(12) "test value 2"
102+
[2]=>
103+
NULL
104+
}
105+
object(SplFixedArray)#1 (3) {
106+
[0]=>
107+
string(12) "test value 1"
108+
[1]=>
109+
string(12) "test value 2"
110+
[2]=>
111+
NULL
112+
}
113+
=================
114+
Test with adding members
115+
string(161) "O:15:"MySplFixedArray":5:{i:0;s:12:"test value 1";i:1;s:12:"test value 2";i:2;N;s:9:"my_string";i:0;s:19:"my_dynamic_property";s:25:"my_dynamic_property_value";}"
116+
object(MySplFixedArray)#1 (5) {
117+
["my_string"]=>
118+
int(0)
119+
["my_dynamic_property"]=>
120+
string(25) "my_dynamic_property_value"
121+
[0]=>
122+
string(12) "test value 1"
123+
[1]=>
124+
string(12) "test value 2"
125+
[2]=>
126+
NULL
127+
}
128+
object(MySplFixedArray)#2 (5) {
129+
["my_string"]=>
130+
string(15) "my_string_value"
131+
["my_dynamic_property"]=>
132+
string(25) "my_dynamic_property_value"
133+
[0]=>
134+
string(12) "test value 1"
135+
[1]=>
136+
string(12) "test value 2"
137+
[2]=>
138+
NULL
139+
}

0 commit comments

Comments
 (0)