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.
This commit is contained in:
Nikita Popov 2020-02-10 11:05:26 +01:00
parent 87f127d8fa
commit 42fbc76d9c
5 changed files with 45 additions and 17 deletions

View file

@ -5467,9 +5467,13 @@ ZEND_METHOD(reflection_property, getValue)
{ {
reflection_object *intern; reflection_object *intern;
property_reference *ref; property_reference *ref;
zval *object, *name; zval *object = NULL, *name;
zval *member_p = NULL; zval *member_p = NULL;
if (zend_parse_parameters(ZEND_NUM_ARGS(), "|o!", &object) == FAILURE) {
RETURN_THROWS();
}
GET_REFLECTION_OBJECT_PTR(ref); GET_REFLECTION_OBJECT_PTR(ref);
if (!(prop_get_flags(ref) & ZEND_ACC_PUBLIC) && intern->ignore_visibility == 0) { if (!(prop_get_flags(ref) & ZEND_ACC_PUBLIC) && intern->ignore_visibility == 0) {
@ -5487,7 +5491,8 @@ ZEND_METHOD(reflection_property, getValue)
} else { } else {
zval rv; 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(); RETURN_THROWS();
} }
@ -5553,9 +5558,13 @@ ZEND_METHOD(reflection_property, isInitialized)
{ {
reflection_object *intern; reflection_object *intern;
property_reference *ref; property_reference *ref;
zval *object, *name; zval *object = NULL, *name;
zval *member_p = NULL; zval *member_p = NULL;
if (zend_parse_parameters(ZEND_NUM_ARGS(), "|o!", &object) == FAILURE) {
RETURN_THROWS();
}
GET_REFLECTION_OBJECT_PTR(ref); GET_REFLECTION_OBJECT_PTR(ref);
if (!(prop_get_flags(ref) & ZEND_ACC_PUBLIC) && intern->ignore_visibility == 0) { 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; zend_class_entry *old_scope;
int retval; 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(); RETURN_THROWS();
} }

View file

@ -391,7 +391,7 @@ class ReflectionProperty implements Reflector
public function setValue($object_or_value, $value = UNKNOWN) {} public function setValue($object_or_value, $value = UNKNOWN) {}
/** @return bool */ /** @return bool */
public function isInitialized(object $object = UNKNOWN) {} public function isInitialized(?object $object = null) {}
/** @return bool */ /** @return bool */
public function isPublic() {} public function isPublic() {}

View file

@ -317,9 +317,7 @@ ZEND_BEGIN_ARG_INFO_EX(arginfo_class_ReflectionProperty_setValue, 0, 0, 1)
ZEND_ARG_INFO(0, value) ZEND_ARG_INFO(0, value)
ZEND_END_ARG_INFO() ZEND_END_ARG_INFO()
ZEND_BEGIN_ARG_INFO_EX(arginfo_class_ReflectionProperty_isInitialized, 0, 0, 0) #define arginfo_class_ReflectionProperty_isInitialized arginfo_class_ReflectionProperty_getValue
ZEND_ARG_TYPE_INFO(0, object, IS_OBJECT, 0)
ZEND_END_ARG_INFO()
#define arginfo_class_ReflectionProperty_isPublic arginfo_class_Reflector___toString #define arginfo_class_ReflectionProperty_isPublic arginfo_class_Reflector___toString

View file

@ -22,7 +22,11 @@ echo "\nInstance without property:\n";
$propInfo = new ReflectionProperty('TestClass', 'stat'); $propInfo = new ReflectionProperty('TestClass', 'stat');
echo "\nStatic property / too many args:\n"; 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"; echo "\nProtected property:\n";
try { try {
@ -35,22 +39,31 @@ catch(Exception $exc) {
echo "\n\nInvalid instance:\n"; echo "\n\nInvalid instance:\n";
$propInfo = new ReflectionProperty('TestClass', 'pub2'); $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: Instance without property:
Static property / too many args: Static property / too many args:
string(15) "static property" ReflectionProperty::getValue() expects at most 1 parameter, 2 given
Protected property: Protected property:
Cannot access non-public member TestClass::$prot Cannot access non-public member TestClass::$prot
Invalid instance: 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 Missing instance:
Stack trace: No object provided for getValue() on instance property
#0 %s(%d): ReflectionProperty->getValue(Object(AnotherClass))
#1 {main}
thrown in %s on line %d

View file

@ -62,6 +62,12 @@ try {
echo $e->getMessage(), "\n"; echo $e->getMessage(), "\n";
} }
try {
var_dump($rp->isInitialized());
} catch (TypeError $e) {
echo $e->getMessage(), "\n";
}
class WithMagic { class WithMagic {
public $prop; public $prop;
public int $intProp; public int $intProp;
@ -108,6 +114,7 @@ bool(false)
Object type: Object type:
bool(false) bool(false)
Given object is not an instance of the class this property was declared in 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: Class with __isset:
bool(false) bool(false)
bool(false) bool(false)