From db7ead0768076da486a9c98264061113233deb7f Mon Sep 17 00:00:00 2001 From: Nikita Popov Date: Thu, 28 Jun 2018 22:45:26 +0200 Subject: [PATCH] Fix ReflectionProperty::get/setValue() on internal static property 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 | 53 ++++++++----------- .../tests/internal_static_property.phpt | 16 ++++++ 2 files changed, 38 insertions(+), 31 deletions(-) create mode 100644 ext/reflection/tests/internal_static_property.phpt diff --git a/ext/reflection/php_reflection.c b/ext/reflection/php_reflection.c index 861ee16e3e..6300e4a4e5 100644 --- a/ext/reflection/php_reflection.c +++ b/ext/reflection/php_reflection.c @@ -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 index 0000000000..79ba666720 --- /dev/null +++ b/ext/reflection/tests/internal_static_property.phpt @@ -0,0 +1,16 @@ +--TEST-- +ReflectionProperty::get/setValue() on internal static property +--SKIPIF-- + +--FILE-- +setValue(42); +var_dump($rp->getValue()); + +?> +--EXPECT-- +int(42) -- 2.40.0