From 490dadea6e3df844d273ab87d746033f3d5be5a8 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 1/2] 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. --- ext/spl/spl_fixedarray.c | 9 ++- ext/spl/tests/gh10907.phpt | 135 +++++++++++++++++++++++++++++++++++++ 2 files changed, 142 insertions(+), 2 deletions(-) create mode 100644 ext/spl/tests/gh10907.phpt diff --git a/ext/spl/spl_fixedarray.c b/ext/spl/spl_fixedarray.c index cf304e738a4da..bf9ec4e695fb4 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 0000000000000..0f16e11dcfe1b --- /dev/null +++ b/ext/spl/tests/gh10907.phpt @@ -0,0 +1,135 @@ +--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-- +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 +} From 39cd0e42bbd47c2cabf84d04db15ee8fb60a75bc Mon Sep 17 00:00:00 2001 From: Niels Dossche <7771979+nielsdos@users.noreply.github.com> Date: Fri, 24 Mar 2023 11:43:06 +0100 Subject: [PATCH 2/2] Update test --- ext/spl/tests/gh10907.phpt | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/ext/spl/tests/gh10907.phpt b/ext/spl/tests/gh10907.phpt index 0f16e11dcfe1b..034c5f1d5a33c 100644 --- a/ext/spl/tests/gh10907.phpt +++ b/ext/spl/tests/gh10907.phpt @@ -2,7 +2,7 @@ GH-10907 (Unable to serialize processed SplFixedArrays in PHP 8.2.4) --FILE-- --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]=> @@ -62,6 +63,7 @@ object(SplFixedArray)#1 (2) { string(12) "test value 2" } ================= +Test with rebuilding properties object(SplFixedArray)#2 (2) { [0]=> string(12) "test value 1" @@ -82,6 +84,7 @@ object(SplFixedArray)#2 (2) { string(12) "test value 2" } ================= +Test with partially rebuilding properties object(SplFixedArray)#1 (3) { [0]=> string(12) "test value 1" @@ -108,6 +111,7 @@ object(SplFixedArray)#1 (3) { 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"]=>