From 42fbc76d9cee94241e56c82a8550ee6221d0f239 Mon Sep 17 00:00:00 2001 From: Nikita Popov Date: Mon, 10 Feb 2020 11:05:26 +0100 Subject: [PATCH] Always invoke zpp in ReflectionProperty::getValue/isInitialized Make sure we still perform a zpp check for the static case, and also always enforce that the parameter is ?object. Otherwise we violate the specified signature. --- ext/reflection/php_reflection.c | 18 ++++++++--- ext/reflection/php_reflection.stub.php | 2 +- ext/reflection/php_reflection_arginfo.h | 4 +-- .../ReflectionProperty_getValue_error.phpt | 31 +++++++++++++------ .../ReflectionProperty_isInitialized.phpt | 7 +++++ 5 files changed, 45 insertions(+), 17 deletions(-) diff --git a/ext/reflection/php_reflection.c b/ext/reflection/php_reflection.c index 6fb415f2ad..95c4859e94 100644 --- a/ext/reflection/php_reflection.c +++ b/ext/reflection/php_reflection.c @@ -5467,9 +5467,13 @@ ZEND_METHOD(reflection_property, getValue) { reflection_object *intern; property_reference *ref; - zval *object, *name; + zval *object = NULL, *name; zval *member_p = NULL; + if (zend_parse_parameters(ZEND_NUM_ARGS(), "|o!", &object) == FAILURE) { + RETURN_THROWS(); + } + GET_REFLECTION_OBJECT_PTR(ref); if (!(prop_get_flags(ref) & ZEND_ACC_PUBLIC) && intern->ignore_visibility == 0) { @@ -5487,7 +5491,8 @@ ZEND_METHOD(reflection_property, getValue) } else { zval rv; - if (zend_parse_parameters(ZEND_NUM_ARGS(), "o", &object) == FAILURE) { + if (!object) { + zend_type_error("No object provided for getValue() on instance property"); RETURN_THROWS(); } @@ -5553,9 +5558,13 @@ ZEND_METHOD(reflection_property, isInitialized) { reflection_object *intern; property_reference *ref; - zval *object, *name; + zval *object = NULL, *name; zval *member_p = NULL; + if (zend_parse_parameters(ZEND_NUM_ARGS(), "|o!", &object) == FAILURE) { + RETURN_THROWS(); + } + GET_REFLECTION_OBJECT_PTR(ref); if (!(prop_get_flags(ref) & ZEND_ACC_PUBLIC) && intern->ignore_visibility == 0) { @@ -5575,7 +5584,8 @@ ZEND_METHOD(reflection_property, isInitialized) zend_class_entry *old_scope; int retval; - if (zend_parse_parameters(ZEND_NUM_ARGS(), "o", &object) == FAILURE) { + if (!object) { + zend_type_error("No object provided for isInitialized() on instance property"); RETURN_THROWS(); } diff --git a/ext/reflection/php_reflection.stub.php b/ext/reflection/php_reflection.stub.php index 26e38ae37f..76cbe75dd7 100644 --- a/ext/reflection/php_reflection.stub.php +++ b/ext/reflection/php_reflection.stub.php @@ -391,7 +391,7 @@ class ReflectionProperty implements Reflector public function setValue($object_or_value, $value = UNKNOWN) {} /** @return bool */ - public function isInitialized(object $object = UNKNOWN) {} + public function isInitialized(?object $object = null) {} /** @return bool */ public function isPublic() {} diff --git a/ext/reflection/php_reflection_arginfo.h b/ext/reflection/php_reflection_arginfo.h index 68d61026b0..35ee713732 100644 --- a/ext/reflection/php_reflection_arginfo.h +++ b/ext/reflection/php_reflection_arginfo.h @@ -317,9 +317,7 @@ ZEND_BEGIN_ARG_INFO_EX(arginfo_class_ReflectionProperty_setValue, 0, 0, 1) ZEND_ARG_INFO(0, value) ZEND_END_ARG_INFO() -ZEND_BEGIN_ARG_INFO_EX(arginfo_class_ReflectionProperty_isInitialized, 0, 0, 0) - ZEND_ARG_TYPE_INFO(0, object, IS_OBJECT, 0) -ZEND_END_ARG_INFO() +#define arginfo_class_ReflectionProperty_isInitialized arginfo_class_ReflectionProperty_getValue #define arginfo_class_ReflectionProperty_isPublic arginfo_class_Reflector___toString diff --git a/ext/reflection/tests/ReflectionProperty_getValue_error.phpt b/ext/reflection/tests/ReflectionProperty_getValue_error.phpt index 2ffd244501..c5da067c32 100644 --- a/ext/reflection/tests/ReflectionProperty_getValue_error.phpt +++ b/ext/reflection/tests/ReflectionProperty_getValue_error.phpt @@ -22,7 +22,11 @@ echo "\nInstance without property:\n"; $propInfo = new ReflectionProperty('TestClass', 'stat'); echo "\nStatic property / too many args:\n"; -var_dump($propInfo->getValue($instance, true)); +try { + var_dump($propInfo->getValue($instance, true)); +} catch (TypeError $e) { + echo $e->getMessage(), "\n"; +} echo "\nProtected property:\n"; try { @@ -35,22 +39,31 @@ catch(Exception $exc) { echo "\n\nInvalid instance:\n"; $propInfo = new ReflectionProperty('TestClass', 'pub2'); -var_dump($propInfo->getValue($invalidInstance)); +try { + var_dump($propInfo->getValue($invalidInstance)); +} catch (ReflectionException $e) { + echo $e->getMessage(); +} + +echo "\n\nMissing instance:\n"; +try { + var_dump($propInfo->getValue()); +} catch (TypeError $e) { + echo $e->getMessage(); +} ?> ---EXPECTF-- +--EXPECT-- Instance without property: Static property / too many args: -string(15) "static property" +ReflectionProperty::getValue() expects at most 1 parameter, 2 given Protected property: Cannot access non-public member TestClass::$prot Invalid instance: +Given object is not an instance of the class this property was declared in -Fatal error: Uncaught ReflectionException: Given object is not an instance of the class this property was declared in in %s:%d -Stack trace: -#0 %s(%d): ReflectionProperty->getValue(Object(AnotherClass)) -#1 {main} - thrown in %s on line %d +Missing instance: +No object provided for getValue() on instance property diff --git a/ext/reflection/tests/ReflectionProperty_isInitialized.phpt b/ext/reflection/tests/ReflectionProperty_isInitialized.phpt index 260084fae4..29541e405b 100644 --- a/ext/reflection/tests/ReflectionProperty_isInitialized.phpt +++ b/ext/reflection/tests/ReflectionProperty_isInitialized.phpt @@ -62,6 +62,12 @@ try { echo $e->getMessage(), "\n"; } +try { + var_dump($rp->isInitialized()); +} catch (TypeError $e) { + echo $e->getMessage(), "\n"; +} + class WithMagic { public $prop; public int $intProp; @@ -108,6 +114,7 @@ bool(false) Object type: bool(false) Given object is not an instance of the class this property was declared in +No object provided for isInitialized() on instance property Class with __isset: bool(false) bool(false) -- 2.40.0