From: Christopher Broadbent Date: Wed, 15 Jul 2020 04:47:21 +0000 (+1000) Subject: Fixed bug #79820 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=ee7c7a8e26b99e3b25a7d41abfe1a2c37b3f6968;p=php Fixed bug #79820 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. --- diff --git a/NEWS b/NEWS index cda6442fa0..09f59a02eb 100644 --- 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) diff --git a/ext/reflection/php_reflection.c b/ext/reflection/php_reflection.c index c3c29d880b..f62dd15e1c 100644 --- a/ext/reflection/php_reflection.c +++ b/ext/reflection/php_reflection.c @@ -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 index 0000000000..ff81f0e738 --- /dev/null +++ b/ext/reflection/tests/bug79820.phpt @@ -0,0 +1,22 @@ +--TEST-- +Bug #79820: Use after free when type duplicated into ReflectionProperty gets resolved +--FILE-- +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