From 52cef0aad17dd1e9987c1214a7ac44c9cebc9e42 Mon Sep 17 00:00:00 2001 From: Ilija Tovilo Date: Sun, 1 Sep 2024 22:28:19 +0200 Subject: [PATCH] Forbid a-vis on unilateral virtual prop The get-only case is obvious, there is no set operation so specifying its visibility is senseless. The set-only case is also questionable, since there is no operation other than set, so changing the visibility of the entire property is preferable. --- .../virtual_get_only.phpt | 14 ++++++++++++++ .../virtual_set_only.phpt | 14 ++++++++++++++ Zend/zend_inheritance.c | 18 +++++++++++++----- 3 files changed, 41 insertions(+), 5 deletions(-) create mode 100644 Zend/tests/asymmetric_visibility/virtual_get_only.phpt create mode 100644 Zend/tests/asymmetric_visibility/virtual_set_only.phpt diff --git a/Zend/tests/asymmetric_visibility/virtual_get_only.phpt b/Zend/tests/asymmetric_visibility/virtual_get_only.phpt new file mode 100644 index 0000000000000..53a293b021a14 --- /dev/null +++ b/Zend/tests/asymmetric_visibility/virtual_get_only.phpt @@ -0,0 +1,14 @@ +--TEST-- +Get-only virtual property must not specify asymmetric visibility +--FILE-- + 42; + } +} + +?> +--EXPECTF-- +Fatal error: Unilateral virtual property Foo::$bar must not specify asymmetric visibility in %s on line %d diff --git a/Zend/tests/asymmetric_visibility/virtual_set_only.phpt b/Zend/tests/asymmetric_visibility/virtual_set_only.phpt new file mode 100644 index 0000000000000..a9618cb65c2c1 --- /dev/null +++ b/Zend/tests/asymmetric_visibility/virtual_set_only.phpt @@ -0,0 +1,14 @@ +--TEST-- +Set-only virtual property must not specify asymmetric visibility +--FILE-- + +--EXPECTF-- +Fatal error: Unilateral virtual property Foo::$bar must not specify asymmetric visibility in %s on line %d diff --git a/Zend/zend_inheritance.c b/Zend/zend_inheritance.c index 9d7c7f179de7d..e3de40778cb6a 100644 --- a/Zend/zend_inheritance.c +++ b/Zend/zend_inheritance.c @@ -1706,6 +1706,12 @@ ZEND_API void zend_verify_hooked_property(zend_class_entry *ce, zend_property_in zend_error_noreturn(E_COMPILE_ERROR, "Abstract property %s::$%s must specify at least one abstract hook", ZSTR_VAL(ce->name), ZSTR_VAL(prop_name)); } + if ((prop_info->flags & ZEND_ACC_VIRTUAL) + && (prop_info->flags & ZEND_ACC_PPP_SET_MASK) + && (!prop_info->hooks[ZEND_PROPERTY_HOOK_GET] || !prop_info->hooks[ZEND_PROPERTY_HOOK_SET])) { + zend_error_noreturn(E_COMPILE_ERROR, + "Unilateral virtual property %s::$%s must not specify asymmetric visibility", ZSTR_VAL(ce->name), ZSTR_VAL(prop_name)); + } } ZEND_API ZEND_COLD ZEND_NORETURN void zend_hooked_property_variance_error_ex(zend_string *value_param_name, zend_string *class_name, zend_string *prop_name) @@ -1893,11 +1899,13 @@ ZEND_API void zend_do_inheritance_ex(zend_class_entry *ce, zend_class_entry *par } ZEND_HASH_FOREACH_END(); } - ZEND_HASH_MAP_FOREACH_STR_KEY_PTR(&ce->properties_info, key, property_info) { - if (property_info->ce == ce && property_info->hooks) { - zend_verify_hooked_property(ce, property_info, key); - } - } ZEND_HASH_FOREACH_END(); + if (ce->num_hooked_props) { + ZEND_HASH_MAP_FOREACH_STR_KEY_PTR(&ce->properties_info, key, property_info) { + if (property_info->ce == ce && property_info->hooks) { + zend_verify_hooked_property(ce, property_info, key); + } + } ZEND_HASH_FOREACH_END(); + } if (zend_hash_num_elements(&parent_ce->constants_table)) { zend_class_constant *c;