summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNikita Popov <nikita.ppv@gmail.com>2019-11-04 11:01:56 +0100
committerNikita Popov <nikita.ppv@gmail.com>2019-11-04 11:04:02 +0100
commitc9abfaec6bf61bcef6d9651827b49cc7789018fd (patch)
treea362fd430d32675f6c21d3b5be20343cf3130b02
parente84042cc7216c4d2ec1788756c78b00bfba413c1 (diff)
downloadphp-git-c9abfaec6bf61bcef6d9651827b49cc7789018fd.tar.gz
Fixed bug #78774
The string held by the zend_type may be released if the property type gets resolved to a CE. I initially wanted to fix this by storing a zend_type* instead (so the property type resolution propagates to the ReflectionType), but decided against this in light of upcoming union types support, where we also need to represent parts of the union, and will not have a single zend_type* we can reference.
-rw-r--r--NEWS3
-rw-r--r--ext/reflection/php_reflection.c14
-rw-r--r--ext/reflection/tests/bug78774.phpt22
3 files changed, 38 insertions, 1 deletions
diff --git a/NEWS b/NEWS
index a1f89a732d..4af45dc1e6 100644
--- a/NEWS
+++ b/NEWS
@@ -9,6 +9,9 @@ PHP NEWS
. Fixed bug #77930 (stream_copy_to_stream should use mmap more often).
(Nikita)
+- Reflection:
+ . Fixed bug #78774 (ReflectionNamedType on Typed Properties Crash). (Nikita)
+
31 Oct 2019, PHP 7.4.0RC5
- Core:
diff --git a/ext/reflection/php_reflection.c b/ext/reflection/php_reflection.c
index 94b2709763..d669ff6da2 100644
--- a/ext/reflection/php_reflection.c
+++ b/ext/reflection/php_reflection.c
@@ -224,8 +224,14 @@ static void reflection_free_objects_storage(zend_object *object) /* {{{ */
efree(intern->ptr);
break;
case REF_TYPE_TYPE:
- efree(intern->ptr);
+ {
+ type_reference *type_ref = intern->ptr;
+ if (ZEND_TYPE_IS_NAME(type_ref->type)) {
+ zend_string_release(ZEND_TYPE_NAME(type_ref->type));
+ }
+ efree(type_ref);
break;
+ }
case REF_TYPE_FUNCTION:
_free_function(intern->ptr);
break;
@@ -1152,6 +1158,12 @@ static void reflection_type_factory(zend_type type, zval *object)
reference->type = type;
intern->ptr = reference;
intern->ref_type = REF_TYPE_TYPE;
+
+ /* Property types may be resolved during the lifetime of the ReflectionType,
+ * so we need to make sure that the strings we reference are not released. */
+ if (ZEND_TYPE_IS_NAME(type)) {
+ zend_string_addref(ZEND_TYPE_NAME(type));
+ }
}
/* }}} */
diff --git a/ext/reflection/tests/bug78774.phpt b/ext/reflection/tests/bug78774.phpt
new file mode 100644
index 0000000000..1e419b1138
--- /dev/null
+++ b/ext/reflection/tests/bug78774.phpt
@@ -0,0 +1,22 @@
+--TEST--
+Bug #78774: ReflectionNamedType on Typed Properties Crash
+--FILE--
+<?php
+
+class Test {
+ public stdClass $prop;
+}
+
+$rc = new ReflectionClass(Test::class);
+$rp = $rc->getProperty('prop');
+$rt = $rp->getType();
+
+// Force a resolution of the property type
+$test = new Test;
+$test->prop = new stdClass;
+
+var_dump($rt->getName());
+
+?>
+--EXPECT--
+string(8) "stdClass"