]> granicus.if.org Git - php/commitdiff
Fix ReflectionProperty::get/setValue() on internal static property
authorNikita Popov <nikita.ppv@gmail.com>
Thu, 28 Jun 2018 20:45:26 +0000 (22:45 +0200)
committerNikita Popov <nikita.ppv@gmail.com>
Thu, 28 Jun 2018 20:45:26 +0000 (22:45 +0200)
This was broken by 6dc0cd868d972885249ce40f2d64097cd0ba6c1f, which
moved static property initialization outside of constant updating.

Instead of replicating logic, use zend_get_static_property() API
in the reflection implementation, just like we're using
read_property for non-static proprety access.

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

index 861ee16e3e54be1ee5250d70e0f3ef130a9663dc..6300e4a4e51ae30ddca3b0ae174faa3bb479093d 100644 (file)
@@ -5495,18 +5495,16 @@ ZEND_METHOD(reflection_property, getValue)
                return;
        }
 
-       if ((ref->prop.flags & ZEND_ACC_STATIC)) {
-               if (UNEXPECTED(zend_update_class_constants(intern->ce) != SUCCESS)) {
-                       return;
-               }
-               if (Z_TYPE(CE_STATIC_MEMBERS(intern->ce)[ref->prop.offset]) == IS_UNDEF) {
-                       zend_throw_error(NULL, "Internal error: Could not find the property %s::%s", ZSTR_VAL(intern->ce->name), ZSTR_VAL(ref->prop.name));
-                       return;
+       if (ref->prop.flags & ZEND_ACC_STATIC) {
+               zend_class_entry *old_scope = EG(fake_scope);
+               EG(fake_scope) = ref->ce;
+               member_p = zend_std_get_static_property(ref->ce, ref->unmangled_name, 0);
+               EG(fake_scope) = old_scope;
+
+               if (member_p) {
+                       ZVAL_DEREF(member_p);
+                       ZVAL_COPY(return_value, member_p);
                }
-               member_p = &CE_STATIC_MEMBERS(intern->ce)[ref->prop.offset];
-               ZVAL_DEINDIRECT(member_p);
-               ZVAL_DEREF(member_p);
-               ZVAL_COPY(return_value, member_p);
        } else {
                zval rv;
 
@@ -5554,34 +5552,27 @@ ZEND_METHOD(reflection_property, setValue)
                return;
        }
 
-       if ((ref->prop.flags & ZEND_ACC_STATIC)) {
+       if (ref->prop.flags & ZEND_ACC_STATIC) {
+               zend_class_entry *old_scope;
+               zval garbage;
+
                if (zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET, ZEND_NUM_ARGS(), "z", &value) == FAILURE) {
                        if (zend_parse_parameters(ZEND_NUM_ARGS(), "zz", &tmp, &value) == FAILURE) {
                                return;
                        }
                }
-               if (UNEXPECTED(zend_update_class_constants(intern->ce) != SUCCESS)) {
-                       return;
-               }
 
-               if (Z_TYPE(CE_STATIC_MEMBERS(intern->ce)[ref->prop.offset]) == IS_UNDEF) {
-                       zend_throw_error(NULL, "Internal error: Could not find the property %s::%s", ZSTR_VAL(intern->ce->name), ZSTR_VAL(ref->prop.name));
-                       return;
-               }
-               variable_ptr = &CE_STATIC_MEMBERS(intern->ce)[ref->prop.offset];
-               ZVAL_DEINDIRECT(variable_ptr);
-               if (variable_ptr != value) {
-                       zval garbage;
+               old_scope = EG(fake_scope);
+               EG(fake_scope) = ref->ce;
+               variable_ptr = zend_std_get_static_property(ref->ce, ref->unmangled_name, 0);
+               EG(fake_scope) = old_scope;
 
-                       ZVAL_DEREF(variable_ptr);
-                       ZVAL_DEREF(value);
+               ZVAL_DEREF(variable_ptr);
+               ZVAL_DEREF(value);
 
-                       ZVAL_COPY_VALUE(&garbage, variable_ptr);
-
-                       ZVAL_COPY(variable_ptr, value);
-
-                       zval_ptr_dtor(&garbage);
-               }
+               ZVAL_COPY_VALUE(&garbage, variable_ptr);
+               ZVAL_COPY(variable_ptr, value);
+               zval_ptr_dtor(&garbage);
        } else {
                if (zend_parse_parameters(ZEND_NUM_ARGS(), "oz", &object, &value) == FAILURE) {
                        return;
diff --git a/ext/reflection/tests/internal_static_property.phpt b/ext/reflection/tests/internal_static_property.phpt
new file mode 100644 (file)
index 0000000..79ba666
--- /dev/null
@@ -0,0 +1,16 @@
+--TEST--
+ReflectionProperty::get/setValue() on internal static property
+--SKIPIF--
+<?php
+if (!class_exists('_ZendTestClass')) die('skip zend_test extension required');
+?>
+--FILE--
+<?php
+
+$rp = new ReflectionProperty('_ZendTestClass', '_StaticProp');
+$rp->setValue(42);
+var_dump($rp->getValue());
+
+?>
+--EXPECT--
+int(42)