Skip to content

Fix GH-10907: Unable to serialize processed SplFixedArrays in PHP 8.2.4 #10921

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 2 commits into from
Closed
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 7 additions & 2 deletions ext/spl/spl_fixedarray.c
Original file line number Diff line number Diff line change
Expand Up @@ -611,8 +611,13 @@ PHP_METHOD(SplFixedArray, __serialize)
/* members */
if (intern->std.properties) {
ZEND_HASH_FOREACH_STR_KEY_VAL(intern->std.properties, key, current) {
zend_hash_add(Z_ARRVAL_P(return_value), key, current);
Z_TRY_ADDREF_P(current);
/* The properties hash table can also contain the array elements if the properties table was already rebuilt.
* In this case we'd have a NULL key. We can't simply use the properties table in all cases because it's
* potentially out of sync (missing elements, or containing removed elements) and might need a rebuild. */
if (key != NULL) {
zend_hash_add_new(Z_ARRVAL_P(return_value), key, current);
Z_TRY_ADDREF_P(current);
}
} ZEND_HASH_FOREACH_END();
}
}
Expand Down
135 changes: 135 additions & 0 deletions ext/spl/tests/gh10907.phpt
Original file line number Diff line number Diff line change
@@ -0,0 +1,135 @@
--TEST--
GH-10907 (Unable to serialize processed SplFixedArrays in PHP 8.2.4)
--FILE--
<?php
// Test without rebuilding properties
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could you echo the comments? It makes understanding what var_dumps correspond to what easier IMHO

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thx for the review, makes sense. I've done that now (ofc I'll squash that into the first commit when I merge this)

$array = new SplFixedArray(2);
$array[0] = "test value 1";
$array[1] = "test value 2";
var_dump(serialize($array));
var_dump(unserialize(serialize($array)));
var_dump($array);

echo "=================\n";

// Test with rebuilding properties
$array = new SplFixedArray(2);
$array[0] = "test value 1";
$array[1] = "test value 2";
var_dump($array); // Rebuilds properties
var_dump(serialize($array));
var_dump(unserialize(serialize($array)));
var_dump($array);

echo "=================\n";

// Test with partially rebuilding properties
$array = new SplFixedArray(3);
$array[0] = "test value 1";
var_dump($array); // Rebuilds properties
$array[1] = "test value 2";
var_dump(serialize($array));
var_dump(unserialize(serialize($array)));
var_dump($array);

echo "=================\n";

// Test with adding members
#[AllowDynamicProperties]
class MySplFixedArray extends SplFixedArray {
public string $my_string = "my_string_value";
}
$array = new MySplFixedArray(3);
$array->my_dynamic_property = "my_dynamic_property_value";
$array[0] = "test value 1";
$array[1] = "test value 2";
var_dump(serialize($array));
var_dump(unserialize(serialize($array)));
var_dump($array);
?>
--EXPECT--
string(73) "O:13:"SplFixedArray":2:{i:0;s:12:"test value 1";i:1;s:12:"test value 2";}"
object(SplFixedArray)#2 (2) {
[0]=>
string(12) "test value 1"
[1]=>
string(12) "test value 2"
}
object(SplFixedArray)#1 (2) {
[0]=>
string(12) "test value 1"
[1]=>
string(12) "test value 2"
}
=================
object(SplFixedArray)#2 (2) {
[0]=>
string(12) "test value 1"
[1]=>
string(12) "test value 2"
}
string(73) "O:13:"SplFixedArray":2:{i:0;s:12:"test value 1";i:1;s:12:"test value 2";}"
object(SplFixedArray)#1 (2) {
[0]=>
string(12) "test value 1"
[1]=>
string(12) "test value 2"
}
object(SplFixedArray)#2 (2) {
[0]=>
string(12) "test value 1"
[1]=>
string(12) "test value 2"
}
=================
object(SplFixedArray)#1 (3) {
[0]=>
string(12) "test value 1"
[1]=>
NULL
[2]=>
NULL
}
string(79) "O:13:"SplFixedArray":3:{i:0;s:12:"test value 1";i:1;s:12:"test value 2";i:2;N;}"
object(SplFixedArray)#2 (3) {
[0]=>
string(12) "test value 1"
[1]=>
string(12) "test value 2"
[2]=>
NULL
}
object(SplFixedArray)#1 (3) {
[0]=>
string(12) "test value 1"
[1]=>
string(12) "test value 2"
[2]=>
NULL
}
=================
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";}"
object(MySplFixedArray)#1 (5) {
["my_string"]=>
int(0)
["my_dynamic_property"]=>
string(25) "my_dynamic_property_value"
[0]=>
string(12) "test value 1"
[1]=>
string(12) "test value 2"
[2]=>
NULL
}
object(MySplFixedArray)#2 (5) {
["my_string"]=>
string(15) "my_string_value"
["my_dynamic_property"]=>
string(25) "my_dynamic_property_value"
[0]=>
string(12) "test value 1"
[1]=>
string(12) "test value 2"
[2]=>
NULL
}