Skip to content

Commit 8bb387e

Browse files
committed
handle private/protected types in properties
1 parent 9f5f2a4 commit 8bb387e

File tree

3 files changed

+39
-2
lines changed

3 files changed

+39
-2
lines changed

Zend/zend_execute.c

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1045,8 +1045,45 @@ static zend_always_inline bool i_zend_check_property_type(const zend_property_in
10451045
return zend_verify_scalar_type_hint(type_mask, property, strict, 0);
10461046
}
10471047

1048+
static zend_result zend_check_type_visibility(const zend_class_entry *ce, const zend_property_info *info, uint32_t current_visibility)
1049+
{
1050+
/* public classes are always visible */
1051+
if (!ce->required_scope) {
1052+
return SUCCESS;
1053+
}
1054+
1055+
/* a protected class is visible if it is a subclass of the lexical scope
1056+
* and the current visibility is protected or private */
1057+
if (!ce->required_scope_absolute && instanceof_function(info->ce, ce->required_scope)) {
1058+
if (current_visibility & ZEND_ACC_PUBLIC) {
1059+
zend_type_error("Cannot declare protected class %s to a public property in %s::%s", ZSTR_VAL(ce->name), ZSTR_VAL(info->ce->name), zend_get_unmangled_property_name(info->name));
1060+
return FAILURE;
1061+
}
1062+
1063+
return SUCCESS;
1064+
}
1065+
1066+
/* a private class is visible if it is the same class as the lexical scope and the current visibility is private */
1067+
if (ce->required_scope_absolute && ce->required_scope == info->ce) {
1068+
if (current_visibility < ZEND_ACC_PRIVATE) {
1069+
zend_type_error("Cannot declare private class %s to a %s property in %s::%s", ZSTR_VAL(ce->name), zend_visibility_string(current_visibility), ZSTR_VAL(info->ce->name), zend_get_unmangled_property_name(info->name));
1070+
return FAILURE;
1071+
}
1072+
1073+
return SUCCESS;
1074+
}
1075+
1076+
zend_type_error("Cannot declare %s to weaker visible property %s::%s", ZSTR_VAL(ce->name), ZSTR_VAL(info->ce->name), zend_get_unmangled_property_name(info->name));
1077+
return FAILURE;
1078+
}
1079+
10481080
static zend_always_inline bool i_zend_verify_property_type(const zend_property_info *info, zval *property, bool strict)
10491081
{
1082+
if (Z_TYPE_P(property) == IS_OBJECT && zend_check_type_visibility(Z_OBJCE_P(property), info, info->flags)) {
1083+
zend_verify_property_type_error(info, property);
1084+
return 0;
1085+
}
1086+
10501087
if (i_zend_check_property_type(info, property, strict)) {
10511088
return 1;
10521089
}

tests/classes/inner_classes/visibility_001.phpt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ $x->test();
1818
var_dump($x);
1919
?>
2020
--EXPECTF--
21-
Fatal error: Uncaught TypeError: Cannot assign private Outer\Inner to higher visibile property Outer::illegal in %s:%d
21+
Fatal error: Uncaught TypeError: Cannot declare private class Outer\Inner to a public property in Outer::illegal in %s:%d
2222
Stack trace:
2323
#0 %s(%d): Outer->test()
2424
#1 {main}

tests/classes/inner_classes/visibility_004.phpt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ $x->test();
1818
var_dump($x);
1919
?>
2020
--EXPECTF--
21-
Fatal error: Uncaught TypeError: Cannot assign protected Outer\Inner to higher visibile property Outer::illegal in %s:%d
21+
Fatal error: Uncaught TypeError: Cannot declare protected class Outer\Inner to a public property in Outer::illegal in %s:%d
2222
Stack trace:
2323
#0 %s(%d): Outer->test()
2424
#1 {main}

0 commit comments

Comments
 (0)