Skip to content

Commit b00d154

Browse files
committed
Fixes for dynamic properties and magic methods
1 parent 9f587dc commit b00d154

File tree

3 files changed

+55
-36
lines changed

3 files changed

+55
-36
lines changed

ext/reflection/php_reflection.c

Lines changed: 47 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -6692,57 +6692,62 @@ ZEND_METHOD(ReflectionProperty, isReadable)
66926692
ZEND_PARSE_PARAMETERS_END();
66936693

66946694
GET_REFLECTION_OBJECT_PTR(ref);
6695-
zend_property_info *prop = ref->prop;
6696-
if (!prop) {
6697-
if (!obj->properties) {
6698-
RETURN_FALSE;
6699-
}
6700-
RETURN_BOOL(zend_hash_find_ptr(obj->properties, ref->unmangled_name) != NULL);
6701-
}
67026695

6703-
if (obj) {
6696+
zend_property_info *prop = ref->prop;
6697+
if (prop && obj) {
67046698
if (!instanceof_function(obj->ce, prop->ce)) {
67056699
_DO_THROW("Given object is not an instance of the class this property was declared in");
67066700
RETURN_THROWS();
67076701
}
67086702
prop = reflection_property_get_effective_prop(ref, intern->ce, obj);
67096703
}
67106704

6705+
zend_class_entry *ce = obj ? obj->ce : intern->ce;
6706+
if (!prop) {
6707+
if (obj && obj->properties && zend_hash_find_ptr(obj->properties, ref->unmangled_name)) {
6708+
RETURN_TRUE;
6709+
}
6710+
handle_magic_get:
6711+
if (ce->__get) {
6712+
if (obj && ce->__isset) {
6713+
uint32_t *guard = zend_get_property_guard(obj, ref->unmangled_name);
6714+
if (!((*guard) & ZEND_GUARD_PROPERTY_ISSET)) {
6715+
GC_ADDREF(obj);
6716+
*guard |= ZEND_GUARD_PROPERTY_ISSET;
6717+
zval member;
6718+
ZVAL_STR(&member, ref->unmangled_name);
6719+
zend_call_known_instance_method_with_1_params(ce->__isset, obj, return_value, &member);
6720+
*guard &= ~ZEND_GUARD_PROPERTY_ISSET;
6721+
OBJ_RELEASE(obj);
6722+
return;
6723+
}
6724+
}
6725+
RETURN_TRUE;
6726+
}
6727+
RETURN_FALSE;
6728+
}
6729+
67116730
zend_class_entry *scope;
67126731
if (get_ce_from_scope_name(&scope, scope_name, execute_data) == FAILURE) {
67136732
RETURN_THROWS();
67146733
}
67156734

67166735
if (!check_visibility(prop->flags & ZEND_ACC_PPP_MASK, prop->ce, scope)) {
6717-
RETURN_FALSE;
6736+
goto handle_magic_get;
67186737
}
67196738

67206739
if (prop->flags & ZEND_ACC_VIRTUAL) {
67216740
ZEND_ASSERT(prop->hooks);
67226741
if (!prop->hooks[ZEND_PROPERTY_HOOK_GET]) {
67236742
RETURN_FALSE;
67246743
}
6725-
}
6726-
6727-
if (obj && !prop->hooks) {
6744+
} else if (obj && (!prop->hooks || !prop->hooks[ZEND_PROPERTY_HOOK_GET])) {
67286745
zval *prop_val = OBJ_PROP(obj, prop->offset);
6729-
if ( Z_TYPE_P(prop_val) == IS_UNDEF) {
6730-
if (!obj->ce->__get || (Z_PROP_FLAG_P(prop_val) & IS_PROP_UNINIT)) {
6731-
RETURN_FALSE;
6732-
}
6733-
if (obj->ce->__isset) {
6734-
uint32_t *guard = zend_get_property_guard(obj, ref->unmangled_name);
6735-
if (!((*guard) & ZEND_GUARD_PROPERTY_ISSET)) {
6736-
GC_ADDREF(obj);
6737-
*guard |= ZEND_GUARD_PROPERTY_ISSET;
6738-
zval member;
6739-
ZVAL_STR(&member, ref->unmangled_name);
6740-
zend_call_known_instance_method_with_1_params(obj->ce->__isset, obj, return_value, &member);
6741-
*guard &= ~ZEND_GUARD_PROPERTY_ISSET;
6742-
OBJ_RELEASE(obj);
6743-
return;
6744-
}
6746+
if (Z_TYPE_P(prop_val) == IS_UNDEF) {
6747+
if (!(Z_PROP_FLAG_P(prop_val) & IS_PROP_UNINIT)) {
6748+
goto handle_magic_get;
67456749
}
6750+
RETURN_FALSE;
67466751
}
67476752
}
67486753

@@ -6763,27 +6768,33 @@ ZEND_METHOD(ReflectionProperty, isWritable)
67636768
ZEND_PARSE_PARAMETERS_END();
67646769

67656770
GET_REFLECTION_OBJECT_PTR(ref);
6766-
zend_property_info *prop = ref->prop;
6767-
if (!prop) {
6768-
if (obj->ce->ce_flags & ZEND_ACC_NO_DYNAMIC_PROPERTIES) {
6769-
RETURN_FALSE;
6770-
}
6771-
RETURN_TRUE;
6772-
}
67736771

6774-
if (obj) {
6772+
zend_property_info *prop = ref->prop;
6773+
if (prop && obj) {
67756774
if (!instanceof_function(obj->ce, prop->ce)) {
67766775
_DO_THROW("Given object is not an instance of the class this property was declared in");
67776776
RETURN_THROWS();
67786777
}
67796778
prop = reflection_property_get_effective_prop(ref, intern->ce, obj);
67806779
}
67816780

6781+
zend_class_entry *ce = obj ? obj->ce : intern->ce;
6782+
if (!prop) {
6783+
if (!(ce->ce_flags & ZEND_ACC_NO_DYNAMIC_PROPERTIES)) {
6784+
RETURN_TRUE;
6785+
}
6786+
handle_magic_set:
6787+
RETURN_BOOL(ce->__set);
6788+
}
6789+
67826790
zend_class_entry *scope;
67836791
if (get_ce_from_scope_name(&scope, scope_name, execute_data) == FAILURE) {
67846792
RETURN_THROWS();
67856793
}
67866794

6795+
if (!check_visibility(prop->flags & ZEND_ACC_PPP_MASK, prop->ce, scope)) {
6796+
goto handle_magic_set;
6797+
}
67876798
uint32_t set_visibility = prop->flags & ZEND_ACC_PPP_SET_MASK;
67886799
if (!set_visibility) {
67896800
set_visibility = zend_visibility_to_set_visibility(prop->flags & ZEND_ACC_PPP_MASK);

ext/reflection/tests/ReflectionProperty_isReadable_dynamic.phpt

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,11 @@ var_dump($r->isReadable(null, $a));
1818
$a = new A;
1919
var_dump($r->isReadable(null, $a));
2020

21+
var_dump($r->isReadable(null, null));
22+
2123
?>
2224
--EXPECT--
2325
bool(true)
2426
bool(false)
2527
bool(false)
28+
bool(false)

ext/reflection/tests/ReflectionProperty_isWritable_dynamic.phpt

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ $a = new A;
1212

1313
$r = new ReflectionProperty($a, 'a');
1414
var_dump($r->isWritable(null, $a));
15+
var_dump($r->isWritable(null, null));
1516

1617
$a->b = 'b';
1718
$r = new ReflectionProperty($a, 'b');
@@ -20,8 +21,12 @@ var_dump($r->isWritable(null, $a));
2021
$a = new A;
2122
var_dump($r->isWritable(null, $a));
2223

24+
var_dump($r->isWritable(null, null));
25+
2326
?>
2427
--EXPECT--
2528
bool(false)
29+
bool(false)
30+
bool(true)
2631
bool(true)
2732
bool(true)

0 commit comments

Comments
 (0)