php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Bug #72209 ReflectionProperty#getValue() doesn't fail if object doesn't match type
Submitted: 2016-05-12 15:37 UTC Modified: 2016-05-14 05:24 UTC
From: ocramius at gmail dot com Assigned:
Status: Closed Package: Reflection related
PHP Version: 7.0.7RC1 OS:
Private report: No CVE-ID: None
 [2016-05-12 15:37 UTC] ocramius at gmail dot com
Description:
------------
`ReflectionProperty#getValue($object)` does not check whether the given `$object` matches the expected type.

If `$r = ReflectionProperty(Foo::class, 'bar')`, then only instances of `Foo` should be allowed by `ReflectionProperty#getValue()` and `ReflectionProperty#setValue()`. All other values should cause an exception to be raised.

As a reference, `ReflectionMethod` behaves correctly ( https://3v4l.org/U2u0h ), since `ReflectionMethod#invoke($object)` and `ReflectionMethod#invokeArgs($object)` reject incompatible `$object` instances.


Test script:
---------------
<?php

class Foo
{
    public $bar = __LINE__;
}

class Baz
{
    public $bar = __LINE__;
}

var_dump((new ReflectionProperty(Foo::class, 'bar'))->getValue(new Baz()));

Expected result:
----------------
Fatal error: Uncaught ReflectionException: Expected an instance of Foo, got 'Baz' instead does not exist in /.../test-script.php

Actual result:
--------------
(int) 10

Patches

Pull Requests

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2016-05-13 09:35 UTC] krakjoe@php.net
This can't be fixed without changing a test, and the test doesn't make any sense at all.

The test seems to imply that what you are seeing is expected behaviour ...

Here's a patch:

diff --git a/ext/reflection/php_reflection.c b/ext/reflection/php_reflection.c
index 4c3f624..ae1e932 100644
--- a/ext/reflection/php_reflection.c
+++ b/ext/reflection/php_reflection.c
@@ -5382,6 +5382,11 @@ ZEND_METHOD(reflection_property, getValue)
                        return;
                }
 
+               if (!instanceof_function(Z_OBJCE_P(object), ref->ce)) {
+                       _DO_THROW("Given object is not an instance of the class this property was declared in");
+                       /* Returns from this function */
+               }
+
                zend_unmangle_property_name_ex(ref->prop.name, &class_name, &prop_name, &prop_name_len);
                member_p = zend_read_property(ref->ce, object, prop_name, prop_name_len, 0, &rv);
                if (member_p != &rv) {

This is the stupid test (last test in ReflectionProperty_getValue_error.phpt):

echo "\n\nInstance without property:\n";
$propInfo = new ReflectionProperty('TestClass', 'pub2');
var_dump($propInfo->getValue($instanceWithNoProperties));
 [2016-05-13 22:56 UTC] ocramius at gmail dot com
Indeed, that last test makes no sense: https://github.com/php/php-src/blob/8462b353d0ca8840788cdf0fcceea28bc9b0f57e/ext/reflection/tests/ReflectionProperty_getValue_error.phpt#L48-L50

Nothing useful can be done with a `ReflectionProperty` against an invalid instance, and therefore there are no BC breaks either.
 [2016-05-14 05:28 UTC] krakjoe@php.net
Automatic comment on behalf of krakjoe
Revision: http://git.php.net/?p=php-src.git;a=commit;h=3684d411721c3b5dc85be74c5317e4d6311ad021
Log: fix #72209 (ReflectionProperty::getValue() doesn't fail if object doesn't match type)
 [2016-05-14 05:28 UTC] krakjoe@php.net
-Status: Open +Status: Closed
 [2016-07-20 11:31 UTC] davey@php.net
Automatic comment on behalf of krakjoe
Revision: http://git.php.net/?p=php-src.git;a=commit;h=3684d411721c3b5dc85be74c5317e4d6311ad021
Log: fix #72209 (ReflectionProperty::getValue() doesn't fail if object doesn't match type)
 
PHP Copyright © 2001-2024 The PHP Group
All rights reserved.
Last updated: Sat Dec 21 15:01:29 2024 UTC