Skip to content

Commit ee7c7a8

Browse files
Christopher Broadbentnikic
Christopher Broadbent
authored andcommitted
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.
1 parent f855b59 commit ee7c7a8

File tree

3 files changed

+42
-1
lines changed

3 files changed

+42
-1
lines changed

NEWS

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,8 +38,10 @@ PHP NEWS
3838
- Reflection:
3939
. Fixed bug #79487 (::getStaticProperties() ignores property modifications).
4040
(cmb, Nikita)
41-
. Fixed bug #69804 ()::getStaticPropertyValue() throws on protected props).
41+
. Fixed bug #69804 (::getStaticPropertyValue() throws on protected props).
4242
(cmb, Nikita)
43+
. Fixed bug #79820 (Use after free when type duplicated into
44+
ReflectionProperty gets resolved). (Christopher Broadbent)
4345

4446
- Standard:
4547
. Fixed bug #70362 (Can't copy() large 'data://' with open_basedir). (cmb)

ext/reflection/php_reflection.c

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -238,6 +238,11 @@ static void reflection_free_objects_storage(zend_object *object) /* {{{ */
238238
case REF_TYPE_PROPERTY:
239239
prop_reference = (property_reference*)intern->ptr;
240240
zend_string_release_ex(prop_reference->unmangled_name, 0);
241+
242+
if (ZEND_TYPE_IS_NAME(prop_reference->prop.type)) {
243+
zend_string_release(ZEND_TYPE_NAME(prop_reference->prop.type));
244+
}
245+
241246
efree(intern->ptr);
242247
break;
243248
case REF_TYPE_GENERATOR:
@@ -1233,6 +1238,11 @@ static void reflection_property_factory(zend_class_entry *ce, zend_string *name,
12331238
intern = Z_REFLECTION_P(object);
12341239
reference = (property_reference*) emalloc(sizeof(property_reference));
12351240
reference->prop = *prop;
1241+
1242+
if (ZEND_TYPE_IS_NAME(reference->prop.type)) {
1243+
zend_string_addref(ZEND_TYPE_NAME(reference->prop.type));
1244+
}
1245+
12361246
reference->unmangled_name = zend_string_copy(name);
12371247
reference->dynamic = dynamic;
12381248
intern->ptr = reference;
@@ -4258,6 +4268,7 @@ ZEND_METHOD(reflection_class, getProperty)
42584268
property_info_tmp.name = name;
42594269
property_info_tmp.doc_comment = NULL;
42604270
property_info_tmp.ce = ce;
4271+
property_info_tmp.type = 0;
42614272

42624273
reflection_property_factory(ce, name, &property_info_tmp, return_value, 1);
42634274
return;
@@ -4339,6 +4350,7 @@ static void _adddynproperty(zval *ptr, zend_string *key, zend_class_entry *ce, z
43394350
property_info.name = key;
43404351
property_info.ce = ce;
43414352
property_info.offset = -1;
4353+
property_info.type = 0;
43424354
reflection_property_factory(ce, key, &property_info, &property, 1);
43434355
add_next_index_zval(retval, &property);
43444356
}
@@ -5319,10 +5331,15 @@ ZEND_METHOD(reflection_property, __construct)
53195331
reference->prop.name = name;
53205332
reference->prop.doc_comment = NULL;
53215333
reference->prop.ce = ce;
5334+
reference->prop.type = 0;
53225335
reference->dynamic = 1;
53235336
} else {
53245337
reference->prop = *property_info;
53255338
reference->dynamic = 0;
5339+
5340+
if (ZEND_TYPE_IS_NAME(reference->prop.type)) {
5341+
zend_string_addref(ZEND_TYPE_NAME(reference->prop.type));
5342+
}
53265343
}
53275344
reference->unmangled_name = zend_string_copy(name);
53285345
intern->ptr = reference;

ext/reflection/tests/bug79820.phpt

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
--TEST--
2+
Bug #79820: Use after free when type duplicated into ReflectionProperty gets resolved
3+
--FILE--
4+
<?php
5+
6+
class Test {
7+
public stdClass $prop;
8+
}
9+
10+
$rp = new ReflectionProperty(Test::class, 'prop');
11+
$test = new Test;
12+
$test->prop = new stdClass;
13+
var_dump($rp->getType()->getName());
14+
$test->dynProp = 42;
15+
16+
$rp = new ReflectionProperty($test, 'dynProp');
17+
var_dump($rp->getType());
18+
19+
?>
20+
--EXPECT--
21+
string(8) "stdClass"
22+
NULL

0 commit comments

Comments
 (0)