From a082696699e28dbd84f2f9aa3129a6b502142bcc Mon Sep 17 00:00:00 2001 From: Niels Dossche <7771979+nielsdos@users.noreply.github.com> Date: Wed, 22 Mar 2023 20:44:54 +0100 Subject: [PATCH] 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. --- NEWS | 2 + ext/spl/spl_fixedarray.c | 9 ++- ext/spl/tests/gh10907.phpt | 139 +++++++++++++++++++++++++++++++++++++ 3 files changed, 148 insertions(+), 2 deletions(-) create mode 100644 ext/spl/tests/gh10907.phpt diff --git a/NEWS b/NEWS index 271cdede47c..e5cb7bb60f4 100644 --- a/NEWS +++ b/NEWS @@ -62,6 +62,8 @@ PHP NEWS - SPL: . Fixed bug GH-10519 (Array Data Address Reference Issue). (Nathan Freeman) + . Fixed bug GH-10907 (Unable to serialize processed SplFixedArrays in + PHP 8.2.4). (nielsdos) - Standard: . Fixed bug GH-10885 (stream_socket_server context leaks). (ilutov) diff --git a/ext/spl/spl_fixedarray.c b/ext/spl/spl_fixedarray.c index cf304e738a4..bf9ec4e695f 100644 --- a/ext/spl/spl_fixedarray.c +++ b/ext/spl/spl_fixedarray.c @@ -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(); } } diff --git a/ext/spl/tests/gh10907.phpt b/ext/spl/tests/gh10907.phpt new file mode 100644 index 00000000000..034c5f1d5a3 --- /dev/null +++ b/ext/spl/tests/gh10907.phpt @@ -0,0 +1,139 @@ +--TEST-- +GH-10907 (Unable to serialize processed SplFixedArrays in PHP 8.2.4) +--FILE-- +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-- +Test without rebuilding properties +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" +} +================= +Test with rebuilding properties +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" +} +================= +Test with partially rebuilding properties +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 +} +================= +Test with adding members +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 +}