]> granicus.if.org Git - php/commitdiff
Fix removal of type source during unserialization
authorNikita Popov <nikita.ppv@gmail.com>
Fri, 4 Dec 2020 11:56:05 +0000 (12:56 +0100)
committerNikita Popov <nikita.ppv@gmail.com>
Fri, 4 Dec 2020 11:56:05 +0000 (12:56 +0100)
Missed a check for info in this code. Add it, and add an assertion
in type source removal to make it easier to catch this issue.

Fixes oss-fuzz #28208 and #28257.

Zend/zend_execute.c
ext/standard/tests/serialize/overwrite_untyped_ref.phpt [new file with mode: 0644]
ext/standard/var_unserializer.re

index fb35b8a1162ce0241a010f03eb184bebf0e62f9b..cb6e63c5154a466621d365eab9eb0b1ffb1603a8 100644 (file)
@@ -3262,6 +3262,7 @@ ZEND_API void ZEND_FASTCALL zend_ref_del_type_source(zend_property_info_source_l
        zend_property_info_list *list = ZEND_PROPERTY_INFO_SOURCE_TO_LIST(source_list->list);
        zend_property_info **ptr, **end;
 
+       ZEND_ASSERT(prop);
        if (!ZEND_PROPERTY_INFO_SOURCE_IS_LIST(source_list->list)) {
                ZEND_ASSERT(source_list->ptr == prop);
                source_list->ptr = NULL;
diff --git a/ext/standard/tests/serialize/overwrite_untyped_ref.phpt b/ext/standard/tests/serialize/overwrite_untyped_ref.phpt
new file mode 100644 (file)
index 0000000..d6f3b78
--- /dev/null
@@ -0,0 +1,17 @@
+--TEST--
+Overwrite reference in untyped property
+--FILE--
+<?php
+class Test {
+    public $prop;
+}
+$s = <<<'STR'
+O:4:"Test":2:{s:4:"prop";R:1;s:4:"prop";i:0;}
+STR;
+var_dump(unserialize($s));
+?>
+--EXPECT--
+object(Test)#1 (1) {
+  ["prop"]=>
+  int(0)
+}
index 04f02cd7622741e6a4738abdbf85c75efd67ec6b..1c787034dd98f25a1343d796fde8ff6680a3424b 100644 (file)
@@ -556,7 +556,7 @@ 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 (info && 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);
                                                }