]> granicus.if.org Git - php/commitdiff
Fix #69804: ::getStaticPropertyValue() throws on protected props
authorChristoph M. Becker <cmbecker69@gmx.de>
Wed, 15 Apr 2020 13:15:21 +0000 (15:15 +0200)
committerChristoph M. Becker <cmbecker69@gmx.de>
Wed, 24 Jun 2020 09:17:36 +0000 (11:17 +0200)
`ReflectionClass` allows reading of the values of private and protected
constants, and also to get private and protected static methods.
Therefore getting the values of private and protected static properties
is also permissible, especially since `::getStaticProperties()` already
allows to do so.

We also allow ::setStaticPropertyValue() to modify private and
protected properties, because otherwise this method is useless, as
modifying public properties can be done directly.

NEWS
ext/reflection/php_reflection.c
ext/reflection/tests/006.phpt
ext/reflection/tests/ReflectionClass_getStaticPropertyValue_001.phpt
ext/reflection/tests/ReflectionClass_setStaticPropertyValue_001.phpt

diff --git a/NEWS b/NEWS
index a2e1aca9537249190d60dbe49036eb37492b3865..4cbc98b7e902a845f0e6674c528127e14a946fdb 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -8,6 +8,8 @@ PHP                                                                        NEWS
 - Reflection:
   . Fixed bug #79487 (::getStaticProperties() ignores property modifications).
     (cmb, Nikita)
+  . Fixed bug #69804 ()::getStaticPropertyValue() throws on protected props).
+    (cmb, Nikita)
 
 ?? ??? 2020, PHP 7.4.8
 
index f4d27b580b397885bad29bc975527f742af1ad3c..c3c29d880b5cf2b18c1a621dc1435e051807ef00 100644 (file)
@@ -3814,7 +3814,7 @@ ZEND_METHOD(reflection_class, getStaticProperties)
 ZEND_METHOD(reflection_class, getStaticPropertyValue)
 {
        reflection_object *intern;
-       zend_class_entry *ce;
+       zend_class_entry *ce, *old_scope;
        zend_string *name;
        zval *prop, *def_value = NULL;
 
@@ -3827,7 +3827,12 @@ ZEND_METHOD(reflection_class, getStaticPropertyValue)
        if (UNEXPECTED(zend_update_class_constants(ce) != SUCCESS)) {
                return;
        }
+
+       old_scope = EG(fake_scope);
+       EG(fake_scope) = ce;
        prop = zend_std_get_static_property(ce, name, BP_VAR_IS);
+       EG(fake_scope) = old_scope;
+
        if (!prop) {
                if (def_value) {
                        ZVAL_COPY(return_value, def_value);
@@ -3847,7 +3852,7 @@ ZEND_METHOD(reflection_class, getStaticPropertyValue)
 ZEND_METHOD(reflection_class, setStaticPropertyValue)
 {
        reflection_object *intern;
-       zend_class_entry *ce;
+       zend_class_entry *ce, *old_scope;
        zend_property_info *prop_info;
        zend_string *name;
        zval *variable_ptr, *value;
@@ -3861,7 +3866,10 @@ ZEND_METHOD(reflection_class, setStaticPropertyValue)
        if (UNEXPECTED(zend_update_class_constants(ce) != SUCCESS)) {
                return;
        }
-       variable_ptr = zend_std_get_static_property_with_info(ce, name, BP_VAR_W, &prop_info);
+       old_scope = EG(fake_scope);
+       EG(fake_scope) = ce;
+       variable_ptr =  zend_std_get_static_property_with_info(ce, name, BP_VAR_W, &prop_info);
+       EG(fake_scope) = old_scope;
        if (!variable_ptr) {
                zend_clear_exception();
                zend_throw_exception_ex(reflection_exception_ptr, 0,
index ab22f5c5c976cd380843b5c292ca6499ec710b4f..0e33e0a6a17d4334d8fcb21aaa757047a20e519e 100644 (file)
@@ -88,16 +88,28 @@ TestDerived::testing();
 string(3) "pub"
 string(3) "pub"
 string(7) "updated"
-EXCEPTION
-EXCEPTION
+string(3) "pro"
+string(3) "pro"
+string(7) "updated"
+string(3) "pri"
+string(3) "pri"
+string(7) "updated"
+string(7) "updated"
+string(7) "updated"
+string(7) "updated"
+string(7) "updated"
+string(7) "updated"
+string(7) "updated"
+string(7) "updated"
+string(7) "updated"
+string(7) "updated"
+string(7) "updated"
+string(7) "updated"
+string(7) "updated"
 string(7) "updated"
 string(7) "updated"
 string(7) "updated"
-EXCEPTION
-EXCEPTION
 string(7) "updated"
 string(7) "updated"
 string(7) "updated"
-EXCEPTION
-EXCEPTION
 ===DONE===
index 365ec89ff14a2b44c4fec524e91f4bca1ed0993f..c63ee330d4a8e83367ab462d7617f20a91fd87af 100644 (file)
@@ -19,41 +19,47 @@ class B extends A {
 
 echo "Retrieving static values from A:\n";
 $rcA = new ReflectionClass('A');
-var_dump($rcA->getStaticPropertyValue("privateOverridden", "default value"));
-var_dump($rcA->getStaticPropertyValue("\0A\0privateOverridden"));
-var_dump($rcA->getStaticPropertyValue("protectedOverridden", "default value"));
-var_dump($rcA->getStaticPropertyValue("\0*\0protectedOverridden"));
+var_dump($rcA->getStaticPropertyValue("privateDoesNotExist", "default value"));
+var_dump($rcA->getStaticPropertyValue("privateOverridden"));
+var_dump($rcA->getStaticPropertyValue("protectedDoesNotExist", "default value"));
+var_dump($rcA->getStaticPropertyValue("protectedOverridden"));
 var_dump($rcA->getStaticPropertyValue("publicOverridden"));
 
 echo "\nRetrieving static values from B:\n";
 $rcB = new ReflectionClass('B');
-var_dump($rcB->getStaticPropertyValue("\0A\0privateOverridden"));
-var_dump($rcB->getStaticPropertyValue("\0B\0privateOverridden"));
-var_dump($rcB->getStaticPropertyValue("\0*\0protectedOverridden"));
+var_dump($rcB->getStaticPropertyValue("privateOverridden"));
+var_dump($rcB->getStaticPropertyValue("protectedOverridden"));
 var_dump($rcB->getStaticPropertyValue("publicOverridden"));
 
 echo "\nRetrieving non-existent values from A with no default value:\n";
 try {
-       var_dump($rcA->getStaticPropertyValue("protectedOverridden"));
+       var_dump($rcA->getStaticPropertyValue("protectedDoesNotExist"));
        echo "you should not see this";
 } catch (Exception $e) {
        echo $e->getMessage() . "\n";
 }
 
 try {
-       var_dump($rcA->getStaticPropertyValue("privateOverridden"));
+       var_dump($rcA->getStaticPropertyValue("privateDoesNotExist"));
        echo "you should not see this";
 } catch (Exception $e) {
        echo $e->getMessage() . "\n";
 }
 
 ?>
---EXPECTF--
+--EXPECT--
 Retrieving static values from A:
 string(13) "default value"
+string(16) "original private"
+string(13) "default value"
+string(18) "original protected"
+string(15) "original public"
+
+Retrieving static values from B:
+string(15) "changed private"
+string(17) "changed protected"
+string(14) "changed public"
 
-Fatal error: Uncaught ReflectionException: Class A does not have a property named  in %s:%d
-Stack trace:
-#0 %s(%d): ReflectionClass->getStaticPropertyValue('\x00A\x00privateOverr...')
-#1 {main}
-  thrown in %s on line %d
+Retrieving non-existent values from A with no default value:
+Class A does not have a property named protectedDoesNotExist
+Class A does not have a property named privateDoesNotExist
index bfefce369e00d12c70364d6ce8b9275f3c8de985..41a6482f66d1497428673e39c34ca791a30d55c5 100644 (file)
@@ -19,41 +19,59 @@ class B extends A {
 
 echo "Set static values in A:\n";
 $rcA = new ReflectionClass('A');
-$rcA->setStaticPropertyValue("\0A\0privateOverridden", "new value 1");
-$rcA->setStaticPropertyValue("\0*\0protectedOverridden", "new value 2");
+$rcA->setStaticPropertyValue("privateOverridden", "new value 1");
+$rcA->setStaticPropertyValue("protectedOverridden", "new value 2");
 $rcA->setStaticPropertyValue("publicOverridden", "new value 3");
 print_r($rcA->getStaticProperties());
 
 echo "\nSet static values in B:\n";
 $rcB = new ReflectionClass('B');
-$rcB->setStaticPropertyValue("\0A\0privateOverridden", "new value 4");
-$rcB->setStaticPropertyValue("\0B\0privateOverridden", "new value 5");
-$rcB->setStaticPropertyValue("\0*\0protectedOverridden", "new value 6");
+$rcB->setStaticPropertyValue("privateOverridden", "new value 4");
+$rcB->setStaticPropertyValue("privateOverridden", "new value 5");
+$rcB->setStaticPropertyValue("protectedOverridden", "new value 6");
 $rcB->setStaticPropertyValue("publicOverridden", "new value 7");
 print_r($rcA->getStaticProperties());
 print_r($rcB->getStaticProperties());
 
 echo "\nSet non-existent values from A with no default value:\n";
 try {
-       var_dump($rcA->setStaticPropertyValue("protectedOverridden", "new value 8"));
+       var_dump($rcA->setStaticPropertyValue("protectedDoesNotExist", "new value 8"));
        echo "you should not see this";
 } catch (Exception $e) {
        echo $e->getMessage() . "\n";
 }
 
 try {
-       var_dump($rcA->setStaticPropertyValue("privateOverridden", "new value 9"));
+       var_dump($rcA->setStaticPropertyValue("privateDoesNotExist", "new value 9"));
        echo "you should not see this";
 } catch (Exception $e) {
        echo $e->getMessage() . "\n";
 }
 
 ?>
---EXPECTF--
+--EXPECT--
 Set static values in A:
+Array
+(
+    [privateOverridden] => new value 1
+    [protectedOverridden] => new value 2
+    [publicOverridden] => new value 3
+)
 
-Fatal error: Uncaught ReflectionException: Class A does not have a property named  in %s:%d
-Stack trace:
-#0 %s(%d): ReflectionClass->setStaticPropertyValue('\x00A\x00privateOverr...', 'new value 1')
-#1 {main}
-  thrown in %s on line %d
+Set static values in B:
+Array
+(
+    [privateOverridden] => new value 1
+    [protectedOverridden] => new value 2
+    [publicOverridden] => new value 3
+)
+Array
+(
+    [privateOverridden] => new value 5
+    [protectedOverridden] => new value 6
+    [publicOverridden] => new value 7
+)
+
+Set non-existent values from A with no default value:
+Class A does not have a property named protectedDoesNotExist
+Class A does not have a property named privateDoesNotExist