php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Bug #46718 ReflectionProperty::setValue() and ReflectionProperty::setAccessible()
Submitted: 2008-11-29 14:48 UTC Modified: 2008-11-29 15:59 UTC
Votes:1
Avg. Score:5.0 ± 0.0
Reproduced:1 of 1 (100.0%)
Same Version:1 (100.0%)
Same OS:1 (100.0%)
From: sebastian@php.net Assigned:
Status: Closed Package: Reflection related
PHP Version: 5.3CVS-2008-11-29 (CVS) OS: irrelevant
Private report: No CVE-ID: None
 [2008-11-29 14:48 UTC] sebastian@php.net
Description:
------------
ReflectionProperty::setValue() ignores the setting made with ReflectionProperty::setAccessible(TRUE).

Reproduce code:
---------------
<?php
class A {
    protected $protected = 'a';
    protected static $protectedStatic = 'b';
    private $private = 'c';
    private static $privateStatic = 'd';
}

$a               = new A;
$protected       = new ReflectionProperty($a, 'protected');
$protectedStatic = new ReflectionProperty('A', 'protectedStatic');
$private         = new ReflectionProperty($a, 'private');
$privateStatic   = new ReflectionProperty('A', 'privateStatic');

try {
    var_dump($protected->getValue($a));
}

catch (ReflectionException $e) {
    var_dump($e->getMessage());
}

try {
    var_dump($protectedStatic->getValue());
}

catch (ReflectionException $e) {
    var_dump($e->getMessage());
}

try {
    var_dump($private->getValue($a));
}

catch (ReflectionException $e) {
    var_dump($e->getMessage());
}

try {
    var_dump($privateStatic->getValue());
}

catch (ReflectionException $e) {
    var_dump($e->getMessage());
}

$protected->setAccessible(TRUE);
$protectedStatic->setAccessible(TRUE);
$private->setAccessible(TRUE);
$privateStatic->setAccessible(TRUE);

var_dump($protected->getValue($a));
var_dump($protectedStatic->getValue());
var_dump($private->getValue($a));
var_dump($privateStatic->getValue());

$protected->setValue($a, 'e');
$protectedStatic->setValue('f');
$private->setValue($a, 'g');
$privateStatic->setValue('h');

var_dump($protected->getValue($a));
var_dump($protectedStatic->getValue());
var_dump($private->getValue($a));
var_dump($privateStatic->getValue());
?>

Expected result:
----------------
string(44) "Cannot access non-public member A::protected"
string(50) "Cannot access non-public member A::protectedStatic"
string(42) "Cannot access non-public member A::private"
string(48) "Cannot access non-public member A::privateStatic"
string(1) "a"
string(1) "b"
string(1) "c"
string(1) "d"
string(1) "e"
string(1) "f"
string(1) "g"
string(1) "h"

Actual result:
--------------
string(44) "Cannot access non-public member A::protected"
string(50) "Cannot access non-public member A::protectedStatic"
string(42) "Cannot access non-public member A::private"
string(48) "Cannot access non-public member A::privateStatic"
string(1) "a"
string(1) "b"
string(1) "c"
string(1) "d"

ReflectionException: Cannot access non-public member A::protected in /usr/local/src/php/php-5.3/reflectionProperty_setAccessible.php on line 57

Call Stack:
    0.0010     355044   1. {main}() /usr/local/src/php/php-5.3/reflectionProperty_setAccessible.php:0
    0.0294     365972   2. ReflectionProperty->setValue() /usr/local/src/php/php-5.3/reflectionProperty_setAccessible.php:57

Patches

Pull Requests

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2008-11-29 14:49 UTC] sebastian@php.net
Here is a patch that implements the missing functionality in ReflectionProperty::setValue().

Index: php_reflection.c
===================================================================
RCS file: /repository/php-src/ext/reflection/php_reflection.c,v
retrieving revision 1.164.2.33.2.45.2.42
diff -u -B -u -r1.164.2.33.2.45.2.42 php_reflection.c
--- php_reflection.c    27 Nov 2008 19:01:22 -0000      1.164.2.33.2.45.2.42
+++ php_reflection.c    29 Nov 2008 14:44:52 -0000
@@ -4365,7 +4365,7 @@
        METHOD_NOTSTATIC(reflection_property_ptr);
        GET_REFLECTION_OBJECT_PTR(ref);

-       if (!(ref->prop.flags & ZEND_ACC_PUBLIC)) {
+       if (!(ref->prop.flags & ZEND_ACC_PUBLIC) && ref->ignore_visibility == 0) {
                _default_get_entry(getThis(), "name", sizeof("name"), &name TSRMLS_CC);
                zend_throw_exception_ex(reflection_exception_ptr, 0 TSRMLS_CC,
                        "Cannot access non-public member %s::%s", intern->ce->name, Z_STRVAL(name));
@@ -4409,10 +4409,13 @@
                        zend_hash_quick_update(prop_table, ref->prop.name, ref->prop.name_length+1, ref->prop.h, &value, sizeof(zval *), (void **) &foo);
                }
        } else {
+               char *class_name, *prop_name;
+
                if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "oz", &object, &value) == FAILURE) {
                        return;
                }
-               zend_update_property(Z_OBJCE_P(object), object, ref->prop.name, ref->prop.name_length, value TSRMLS_CC);
+               zend_unmangle_property_name(ref->prop.name, ref->prop.name_length, &class_name, &prop_name);
+               zend_update_property(Z_OBJCE_P(object), object, prop_name, strlen(prop_name), value TSRMLS_CC);
        }
 }
 /* }}} */
Index: tests/reflectionProperty_setAccessible.phpt
===================================================================
RCS file: /repository/php-src/ext/reflection/tests/reflectionProperty_setAccessible.phpt,v
retrieving revision 1.1.2.3
diff -u -B -u -r1.1.2.3 reflectionProperty_setAccessible.phpt
--- tests/reflectionProperty_setAccessible.phpt 24 May 2008 13:34:22 -0000      1.1.2.3
+++ tests/reflectionProperty_setAccessible.phpt 29 Nov 2008 14:44:52 -0000
@@ -2,43 +2,82 @@
 Test ReflectionProperty::setAccessible().
 --FILE--
 <?php
-
-class TestClass {
-    public $pub;
-    public $pub2 = 5;
-    static public $stat = "static property";
-    protected $prot = 4;
-    private $priv = "keepOut";
+class A {
+    protected $protected = 'a';
+    protected static $protectedStatic = 'b';
+    private $private = 'c';
+    private static $privateStatic = 'd';
 }

-class AnotherClass {
+$a               = new A;
+$protected       = new ReflectionProperty($a, 'protected');
+$protectedStatic = new ReflectionProperty('A', 'protectedStatic');
+$private         = new ReflectionProperty($a, 'private');
+$privateStatic   = new ReflectionProperty('A', 'privateStatic');
+
+try {
+    var_dump($protected->getValue($a));
 }

-$instance = new TestClass();
+catch (ReflectionException $e) {
+    var_dump($e->getMessage());
+}

-echo "\nProtected property:\n";
-$propInfo = new ReflectionProperty('TestClass', 'prot');
 try {
-    var_dump($propInfo->getValue($instance));
+    var_dump($protectedStatic->getValue());
 }
-catch(Exception $exc) {
-    echo $exc->getMessage(), "\n";
+
+catch (ReflectionException $e) {
+    var_dump($e->getMessage());
+}
+
+try {
+    var_dump($private->getValue($a));
 }

-$propInfo->setAccessible(true);
-var_dump($propInfo->getValue($instance));
+catch (ReflectionException $e) {
+    var_dump($e->getMessage());
+}

-$propInfo->setAccessible(false);
 try {
-    var_dump($propInfo->getValue($instance));
+    var_dump($privateStatic->getValue());
 }
-catch(Exception $exc) {
-    echo $exc->getMessage(), "\n";
+
+catch (ReflectionException $e) {
+    var_dump($e->getMessage());
 }
+
+$protected->setAccessible(TRUE);
+$protectedStatic->setAccessible(TRUE);
+$private->setAccessible(TRUE);
+$privateStatic->setAccessible(TRUE);
+
+var_dump($protected->getValue($a));
+var_dump($protectedStatic->getValue());
+var_dump($private->getValue($a));
+var_dump($privateStatic->getValue());
+
+$protected->setValue($a, 'e');
+$protectedStatic->setValue('f');
+$private->setValue($a, 'g');
+$privateStatic->setValue('h');
+
+var_dump($protected->getValue($a));
+var_dump($protectedStatic->getValue());
+var_dump($private->getValue($a));
+var_dump($privateStatic->getValue());
 ?>
 --EXPECTF--
+string(44) "Cannot access non-public member A::protected"
+string(50) "Cannot access non-public member A::protectedStatic"
+string(42) "Cannot access non-public member A::private"
+string(48) "Cannot access non-public member A::privateStatic"
+string(1) "a"
+string(1) "b"
+string(1) "c"
+string(1) "d"
+string(1) "e"
+string(1) "f"
+string(1) "g"
+string(1) "h"

-Protected property:
-Cannot access non-public member TestClass::prot
-int(4)
-Cannot access non-public member TestClass::prot
 [2008-11-29 15:59 UTC] sebastian@php.net
This bug has been fixed in CVS.

Snapshots of the sources are packaged every three hours; this change
will be in the next snapshot. You can grab the snapshot at
http://snaps.php.net/.
 
Thank you for the report, and for helping us make PHP better.


 
PHP Copyright © 2001-2024 The PHP Group
All rights reserved.
Last updated: Sun Dec 22 06:01:30 2024 UTC