]> granicus.if.org Git - php/commitdiff
Fix another ref source management bug in unserialize
authorNikita Popov <nikita.ppv@gmail.com>
Mon, 30 Nov 2020 13:23:17 +0000 (14:23 +0100)
committerNikita Popov <nikita.ppv@gmail.com>
Mon, 30 Nov 2020 13:23:54 +0000 (14:23 +0100)
When we overwrite an existing property during unserialization,
we also have to drop the ref source from it.

ext/standard/tests/serialize/typed_property_ref_overwrite.phpt [new file with mode: 0644]
ext/standard/var_unserializer.re

diff --git a/ext/standard/tests/serialize/typed_property_ref_overwrite.phpt b/ext/standard/tests/serialize/typed_property_ref_overwrite.phpt
new file mode 100644 (file)
index 0000000..148c66b
--- /dev/null
@@ -0,0 +1,19 @@
+--TEST--
+Overwriting a typed property reference
+--FILE--
+<?php
+
+class Test {
+    public ?object $prop;
+}
+$s = <<<'STR'
+O:4:"Test":2:{s:4:"prop";R:1;s:4:"prop";N;}}
+STR;
+var_dump(unserialize($s));
+
+?>
+--EXPECT--
+object(Test)#1 (1) {
+  ["prop"]=>
+  NULL
+}
index d684163e83833644bd2c71a05a4197eb6d18472c..04f02cd7622741e6a4738abdbf85c75efd67ec6b 100644 (file)
@@ -556,6 +556,10 @@ string_key:
                                                /* This is a property with a declaration */
                                                old_data = Z_INDIRECT_P(old_data);
                                                info = zend_get_typed_property_info_for_slot(obj, old_data);
+                                               if (Z_ISREF_P(old_data)) {
+                                                       /* If the value is overwritten, remove old type source from ref. */
+                                                       ZEND_REF_DEL_TYPE_SOURCE(Z_REF_P(old_data), info);
+                                               }
                                                var_push_dtor(var_hash, old_data);
                                                Z_TRY_DELREF_P(old_data);
                                                ZVAL_COPY_VALUE(old_data, &d);