]> granicus.if.org Git - php/commitdiff
Fixed bug #79820
authorChristopher Broadbent <chris-broadbent@zencontrol.com>
Wed, 15 Jul 2020 04:47:21 +0000 (14:47 +1000)
committerNikita Popov <nikita.ppv@gmail.com>
Wed, 15 Jul 2020 08:58:56 +0000 (10:58 +0200)
Similar to what is done for ReflectionType itself, copy the
type name stored inside ReflectionProperty. Also make sure the
type field is always initialized for dynamic properties.

This is a non-issue in PHP 8, because we store a pointer to the
property_info there, rather than a copy.

NEWS
ext/reflection/php_reflection.c
ext/reflection/tests/bug79820.phpt [new file with mode: 0644]

diff --git a/NEWS b/NEWS
index cda6442fa0746344b12126c6dc917ae75ec64422..09f59a02eb4328c0ad3c69f65133ff892572aae5 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -38,8 +38,10 @@ PHP                                                                        NEWS
 - Reflection:
   . Fixed bug #79487 (::getStaticProperties() ignores property modifications).
     (cmb, Nikita)
-  . Fixed bug #69804 ()::getStaticPropertyValue() throws on protected props).
+  . Fixed bug #69804 (::getStaticPropertyValue() throws on protected props).
     (cmb, Nikita)
+  . Fixed bug #79820 (Use after free when type duplicated into
+    ReflectionProperty gets resolved). (Christopher Broadbent)
 
 - Standard:
   . Fixed bug #70362 (Can't copy() large 'data://' with open_basedir). (cmb)
index c3c29d880b5cf2b18c1a621dc1435e051807ef00..f62dd15e1c90e0c060449831980ce367ddb70be9 100644 (file)
@@ -238,6 +238,11 @@ static void reflection_free_objects_storage(zend_object *object) /* {{{ */
                case REF_TYPE_PROPERTY:
                        prop_reference = (property_reference*)intern->ptr;
                        zend_string_release_ex(prop_reference->unmangled_name, 0);
+
+                       if (ZEND_TYPE_IS_NAME(prop_reference->prop.type)) {
+                               zend_string_release(ZEND_TYPE_NAME(prop_reference->prop.type));
+                       }
+
                        efree(intern->ptr);
                        break;
                case REF_TYPE_GENERATOR:
@@ -1233,6 +1238,11 @@ static void reflection_property_factory(zend_class_entry *ce, zend_string *name,
        intern = Z_REFLECTION_P(object);
        reference = (property_reference*) emalloc(sizeof(property_reference));
        reference->prop = *prop;
+
+       if (ZEND_TYPE_IS_NAME(reference->prop.type)) {
+               zend_string_addref(ZEND_TYPE_NAME(reference->prop.type));
+       }
+
        reference->unmangled_name = zend_string_copy(name);
        reference->dynamic = dynamic;
        intern->ptr = reference;
@@ -4258,6 +4268,7 @@ ZEND_METHOD(reflection_class, getProperty)
                        property_info_tmp.name = name;
                        property_info_tmp.doc_comment = NULL;
                        property_info_tmp.ce = ce;
+                       property_info_tmp.type = 0;
 
                        reflection_property_factory(ce, name, &property_info_tmp, return_value, 1);
                        return;
@@ -4339,6 +4350,7 @@ static void _adddynproperty(zval *ptr, zend_string *key, zend_class_entry *ce, z
        property_info.name = key;
        property_info.ce = ce;
        property_info.offset = -1;
+       property_info.type = 0;
        reflection_property_factory(ce, key, &property_info, &property, 1);
        add_next_index_zval(retval, &property);
 }
@@ -5319,10 +5331,15 @@ ZEND_METHOD(reflection_property, __construct)
                reference->prop.name = name;
                reference->prop.doc_comment = NULL;
                reference->prop.ce = ce;
+               reference->prop.type = 0;
                reference->dynamic = 1;
        } else {
                reference->prop = *property_info;
                reference->dynamic = 0;
+
+               if (ZEND_TYPE_IS_NAME(reference->prop.type)) {
+                       zend_string_addref(ZEND_TYPE_NAME(reference->prop.type));
+               }
        }
        reference->unmangled_name = zend_string_copy(name);
        intern->ptr = reference;
diff --git a/ext/reflection/tests/bug79820.phpt b/ext/reflection/tests/bug79820.phpt
new file mode 100644 (file)
index 0000000..ff81f0e
--- /dev/null
@@ -0,0 +1,22 @@
+--TEST--
+Bug #79820: Use after free when type duplicated into ReflectionProperty gets resolved
+--FILE--
+<?php
+
+class Test {
+    public stdClass $prop;
+}
+
+$rp = new ReflectionProperty(Test::class, 'prop');
+$test = new Test;
+$test->prop = new stdClass;
+var_dump($rp->getType()->getName());
+$test->dynProp = 42;
+
+$rp = new ReflectionProperty($test, 'dynProp');
+var_dump($rp->getType());
+
+?>
+--EXPECT--
+string(8) "stdClass"
+NULL