Skip to content

Commit 47b3fe4

Browse files
committed
Handle indirect zvals and use up-to-date properties in SplFixedArray::__serialize
Closes GH-10925.
1 parent cd7d2c8 commit 47b3fe4

File tree

4 files changed

+86
-15
lines changed

4 files changed

+86
-15
lines changed

NEWS

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,10 @@ PHP NEWS
66
. Fixed bug #80602 (Segfault when using DOMChildNode::before()).
77
(Nathan Freeman)
88

9+
- SPL:
10+
. Handle indirect zvals and use up-to-date properties in
11+
SplFixedArray::__serialize. (nielsdos)
12+
913
- Streams:
1014
. Fixed bug GH-10406 (feof() behavior change for UNIX based socket
1115
resources). (Jakub Zelenka)

ext/spl/spl_fixedarray.c

Lines changed: 11 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -597,8 +597,8 @@ PHP_METHOD(SplFixedArray, __serialize)
597597
RETURN_THROWS();
598598
}
599599

600-
uint32_t num_properties =
601-
intern->std.properties ? zend_hash_num_elements(intern->std.properties) : 0;
600+
HashTable *ht = zend_std_get_properties(&intern->std);
601+
uint32_t num_properties = zend_hash_num_elements(ht);
602602
array_init_size(return_value, intern->array.size + num_properties);
603603

604604
/* elements */
@@ -609,17 +609,15 @@ PHP_METHOD(SplFixedArray, __serialize)
609609
}
610610

611611
/* members */
612-
if (intern->std.properties) {
613-
ZEND_HASH_FOREACH_STR_KEY_VAL(intern->std.properties, key, 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-
}
621-
} ZEND_HASH_FOREACH_END();
622-
}
612+
ZEND_HASH_FOREACH_STR_KEY_VAL_IND(ht, key, current) {
613+
/* If the properties table was already rebuild, it will also contain the
614+
* array elements. The array elements are already added in the above loop.
615+
* We can detect array elements by the fact that their key == NULL. */
616+
if (key != NULL) {
617+
zend_hash_add_new(Z_ARRVAL_P(return_value), key, current);
618+
Z_TRY_ADDREF_P(current);
619+
}
620+
} ZEND_HASH_FOREACH_END();
623621
}
624622

625623
PHP_METHOD(SplFixedArray, __unserialize)

ext/spl/tests/gh10907.phpt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -112,10 +112,10 @@ object(SplFixedArray)#1 (3) {
112112
}
113113
=================
114114
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";}"
115+
string(180) "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";s:15:"my_string_value";s:19:"my_dynamic_property";s:25:"my_dynamic_property_value";}"
116116
object(MySplFixedArray)#1 (5) {
117117
["my_string"]=>
118-
int(0)
118+
string(15) "my_string_value"
119119
["my_dynamic_property"]=>
120120
string(25) "my_dynamic_property_value"
121121
[0]=>

ext/spl/tests/gh10925.phpt

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
--TEST--
2+
Properties serialization for SplFixedArray should have updated properties
3+
--FILE--
4+
<?php
5+
#[AllowDynamicProperties]
6+
class MySplFixedArray extends SplFixedArray {
7+
public $x;
8+
public int $y = 3;
9+
}
10+
11+
$x = new MySplFixedArray(2);
12+
var_dump($x->y);
13+
$x->y = 2;
14+
var_dump($x->y);
15+
$serialized = serialize($x);
16+
var_dump($serialized);
17+
var_dump(unserialize($serialized));
18+
19+
$x->dynamic_property = "dynamic_property_value";
20+
$serialized = serialize($x);
21+
var_dump($serialized);
22+
var_dump(unserialize($serialized));
23+
24+
$x->dynamic_property = "dynamic_property_value2";
25+
$x->y = 4;
26+
$serialized = serialize($x);
27+
var_dump($serialized);
28+
var_dump(unserialize($serialized));
29+
?>
30+
--EXPECT--
31+
int(3)
32+
int(2)
33+
string(61) "O:15:"MySplFixedArray":4:{i:0;N;i:1;N;s:1:"x";N;s:1:"y";i:2;}"
34+
object(MySplFixedArray)#2 (4) {
35+
["x"]=>
36+
NULL
37+
["y"]=>
38+
int(2)
39+
[0]=>
40+
NULL
41+
[1]=>
42+
NULL
43+
}
44+
string(115) "O:15:"MySplFixedArray":5:{i:0;N;i:1;N;s:1:"x";N;s:1:"y";i:2;s:16:"dynamic_property";s:22:"dynamic_property_value";}"
45+
object(MySplFixedArray)#2 (5) {
46+
["x"]=>
47+
NULL
48+
["y"]=>
49+
int(2)
50+
["dynamic_property"]=>
51+
string(22) "dynamic_property_value"
52+
[0]=>
53+
NULL
54+
[1]=>
55+
NULL
56+
}
57+
string(116) "O:15:"MySplFixedArray":5:{i:0;N;i:1;N;s:1:"x";N;s:1:"y";i:4;s:16:"dynamic_property";s:23:"dynamic_property_value2";}"
58+
object(MySplFixedArray)#2 (5) {
59+
["x"]=>
60+
NULL
61+
["y"]=>
62+
int(4)
63+
["dynamic_property"]=>
64+
string(23) "dynamic_property_value2"
65+
[0]=>
66+
NULL
67+
[1]=>
68+
NULL
69+
}

0 commit comments

Comments
 (0)