diff --git a/ext/spl/spl_fixedarray.c b/ext/spl/spl_fixedarray.c index bf9ec4e695fb4..c333c6d621843 100644 --- a/ext/spl/spl_fixedarray.c +++ b/ext/spl/spl_fixedarray.c @@ -597,8 +597,8 @@ PHP_METHOD(SplFixedArray, __serialize) RETURN_THROWS(); } - uint32_t num_properties = - intern->std.properties ? zend_hash_num_elements(intern->std.properties) : 0; + HashTable *ht = zend_std_get_properties(&intern->std); + uint32_t num_properties = zend_hash_num_elements(ht); array_init_size(return_value, intern->array.size + num_properties); /* elements */ @@ -609,17 +609,15 @@ PHP_METHOD(SplFixedArray, __serialize) } /* members */ - if (intern->std.properties) { - ZEND_HASH_FOREACH_STR_KEY_VAL(intern->std.properties, key, 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(); - } + ZEND_HASH_FOREACH_STR_KEY_VAL_IND(ht, key, current) { + /* If the properties table was already rebuild, it will also contain the + * array elements. The array elements are already added in the above loop. + * We can detect array elements by the fact that their key == NULL. */ + if (key != NULL) { + zend_hash_add_new(Z_ARRVAL_P(return_value), key, current); + Z_TRY_ADDREF_P(current); + } + } ZEND_HASH_FOREACH_END(); } PHP_METHOD(SplFixedArray, __unserialize) diff --git a/ext/spl/tests/gh10907.phpt b/ext/spl/tests/gh10907.phpt index 034c5f1d5a33c..49d98ae5ef360 100644 --- a/ext/spl/tests/gh10907.phpt +++ b/ext/spl/tests/gh10907.phpt @@ -112,10 +112,10 @@ object(SplFixedArray)#1 (3) { } ================= 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";}" +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";}" object(MySplFixedArray)#1 (5) { ["my_string"]=> - int(0) + string(15) "my_string_value" ["my_dynamic_property"]=> string(25) "my_dynamic_property_value" [0]=> diff --git a/ext/spl/tests/gh10925.phpt b/ext/spl/tests/gh10925.phpt new file mode 100644 index 0000000000000..5e6cc0347b46d --- /dev/null +++ b/ext/spl/tests/gh10925.phpt @@ -0,0 +1,69 @@ +--TEST-- +Properties serialization for SplFixedArray should have updated properties +--FILE-- +y); +$x->y = 2; +var_dump($x->y); +$serialized = serialize($x); +var_dump($serialized); +var_dump(unserialize($serialized)); + +$x->dynamic_property = "dynamic_property_value"; +$serialized = serialize($x); +var_dump($serialized); +var_dump(unserialize($serialized)); + +$x->dynamic_property = "dynamic_property_value2"; +$x->y = 4; +$serialized = serialize($x); +var_dump($serialized); +var_dump(unserialize($serialized)); +?> +--EXPECT-- +int(3) +int(2) +string(61) "O:15:"MySplFixedArray":4:{i:0;N;i:1;N;s:1:"x";N;s:1:"y";i:2;}" +object(MySplFixedArray)#2 (4) { + ["x"]=> + NULL + ["y"]=> + int(2) + [0]=> + NULL + [1]=> + NULL +} +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";}" +object(MySplFixedArray)#2 (5) { + ["x"]=> + NULL + ["y"]=> + int(2) + ["dynamic_property"]=> + string(22) "dynamic_property_value" + [0]=> + NULL + [1]=> + NULL +} +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";}" +object(MySplFixedArray)#2 (5) { + ["x"]=> + NULL + ["y"]=> + int(4) + ["dynamic_property"]=> + string(23) "dynamic_property_value2" + [0]=> + NULL + [1]=> + NULL +}