]> granicus.if.org Git - php/commitdiff
Fix #79487: ::getStaticProperties() ignores property modifications
authorChristoph M. Becker <cmbecker69@gmx.de>
Tue, 23 Jun 2020 16:34:07 +0000 (18:34 +0200)
committerChristoph M. Becker <cmbecker69@gmx.de>
Tue, 23 Jun 2020 16:48:54 +0000 (18:48 +0200)
When retrieving the static class properties via reflection, we have to
cater to possible modifications.

NEWS
ext/reflection/php_reflection.c
ext/reflection/tests/bug79487.phpt [new file with mode: 0644]

diff --git a/NEWS b/NEWS
index 61513e9174b3a595601cea9a3f7c1919dedaff60..a2e1aca9537249190d60dbe49036eb37492b3865 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -5,6 +5,10 @@ PHP                                                                        NEWS
 - FTP:
   . Fixed bug #55857 (ftp_size on large files). (cmb)
 
+- Reflection:
+  . Fixed bug #79487 (::getStaticProperties() ignores property modifications).
+    (cmb, Nikita)
+
 ?? ??? 2020, PHP 7.4.8
 
 - Core:
index dbfb67386e9bf2e73ff257b5029e7ff80a3d82af..97066fb13ee37547bf1d9d52289a8c33b0073c82 100644 (file)
@@ -3726,9 +3726,7 @@ static void add_class_vars(zend_class_entry *ce, int statics, zval *return_value
        zend_string *key;
 
        ZEND_HASH_FOREACH_STR_KEY_PTR(&ce->properties_info, key, prop_info) {
-               if (((prop_info->flags & ZEND_ACC_PROTECTED) &&
-                    !zend_check_protected(prop_info->ce, ce)) ||
-                   ((prop_info->flags & ZEND_ACC_PRIVATE) &&
+               if (((prop_info->flags & ZEND_ACC_PRIVATE) &&
                     prop_info->ce != ce)) {
                        continue;
                }
@@ -3766,6 +3764,9 @@ ZEND_METHOD(reflection_class, getStaticProperties)
 {
        reflection_object *intern;
        zend_class_entry *ce;
+       zend_property_info *prop_info;
+       zval *prop;
+       zend_string *key;
 
        if (zend_parse_parameters_none() == FAILURE) {
                return;
@@ -3777,8 +3778,34 @@ ZEND_METHOD(reflection_class, getStaticProperties)
                return;
        }
 
+       if (!CE_STATIC_MEMBERS(ce)) {
+               zend_class_init_statics(ce);
+       }
+
        array_init(return_value);
-       add_class_vars(ce, 1, return_value);
+
+       ZEND_HASH_FOREACH_STR_KEY_PTR(&ce->properties_info, key, prop_info) {
+               if (((prop_info->flags & ZEND_ACC_PRIVATE) &&
+                    prop_info->ce != ce)) {
+                       continue;
+               }
+               if ((prop_info->flags & ZEND_ACC_STATIC) == 0) {
+                       continue;
+               }
+
+               prop = &CE_STATIC_MEMBERS(ce)[prop_info->offset];
+               ZVAL_DEINDIRECT(prop);
+
+               if (prop_info->type && Z_ISUNDEF_P(prop)) {
+                       continue;
+               }
+
+               /* enforce read only access */
+               ZVAL_DEREF(prop);
+               Z_TRY_ADDREF_P(prop);
+
+               zend_hash_update(Z_ARRVAL_P(return_value), key, prop);
+       } ZEND_HASH_FOREACH_END();
 }
 /* }}} */
 
diff --git a/ext/reflection/tests/bug79487.phpt b/ext/reflection/tests/bug79487.phpt
new file mode 100644 (file)
index 0000000..5185c98
--- /dev/null
@@ -0,0 +1,34 @@
+--TEST--
+Bug #79487 (::getStaticProperties() ignores property modifications)
+--FILE--
+<?php
+class Foo {
+    public static $bar = 'orig';
+}
+
+Foo::$bar = 'new';
+$rc = new ReflectionClass('Foo');
+var_dump($rc->getStaticProperties());
+
+class A {
+  public static $a = 'A old';
+}
+class B extends A {
+  public static $b = 'B old';
+}
+
+$rc = new ReflectionClass(B::class);
+A::$a = 'A new';
+var_dump($rc->getStaticProperties());
+?>
+--EXPECT--
+array(1) {
+  ["bar"]=>
+  string(3) "new"
+}
+array(2) {
+  ["b"]=>
+  string(5) "B old"
+  ["a"]=>
+  string(5) "A new"
+}