From d9db446065c47a7c8ae1a9524d9a4687fded1975 Mon Sep 17 00:00:00 2001 From: Ilija Tovilo Date: Wed, 12 Jul 2023 14:02:08 +0200 Subject: [PATCH] Fix iface const visibility variance check --- UPGRADING | 2 ++ .../iface_constant_visibility_variance.phpt | 14 ++++++++++++++ Zend/zend_inheritance.c | 19 +++++++++---------- 3 files changed, 25 insertions(+), 10 deletions(-) create mode 100644 Zend/tests/iface_constant_visibility_variance.phpt diff --git a/UPGRADING b/UPGRADING index 73c400e047f..345947f45f0 100644 --- a/UPGRADING +++ b/UPGRADING @@ -43,6 +43,8 @@ PHP 8.3 UPGRADE NOTES next index is n+1 instead of 0. . Static variable initializers can now contain arbitrary expressions. RFC: https://wiki.php.net/rfc/arbitrary_static_variable_initializers + . Class constant visibility variance is now correctly checked when inherited + from interfaces. - FFI: . C functions that have a return type of void now return null instead of diff --git a/Zend/tests/iface_constant_visibility_variance.phpt b/Zend/tests/iface_constant_visibility_variance.phpt new file mode 100644 index 00000000000..fbd81356923 --- /dev/null +++ b/Zend/tests/iface_constant_visibility_variance.phpt @@ -0,0 +1,14 @@ +--TEST-- +Interface constant visibility should be invariant +--FILE-- + +--EXPECTF-- +Fatal error: Access level to C::FOO must be public (as in interface I) in %s on line %d diff --git a/Zend/zend_inheritance.c b/Zend/zend_inheritance.c index 67b4bebde0f..6bae341727a 100644 --- a/Zend/zend_inheritance.c +++ b/Zend/zend_inheritance.c @@ -1404,16 +1404,6 @@ static void do_inherit_class_constant(zend_string *name, zend_class_constant *pa if (zv != NULL) { c = (zend_class_constant*)Z_PTR_P(zv); - - if (UNEXPECTED((ZEND_CLASS_CONST_FLAGS(c) & ZEND_ACC_PPP_MASK) > (ZEND_CLASS_CONST_FLAGS(parent_const) & ZEND_ACC_PPP_MASK))) { - zend_error_noreturn(E_COMPILE_ERROR, "Access level to %s::%s must be %s (as in class %s)%s", - ZSTR_VAL(ce->name), ZSTR_VAL(name), - zend_visibility_string(ZEND_CLASS_CONST_FLAGS(parent_const)), - ZSTR_VAL(parent_const->ce->name), - (ZEND_CLASS_CONST_FLAGS(parent_const) & ZEND_ACC_PUBLIC) ? "" : " or weaker" - ); - } - bool inherit = do_inherit_constant_check(ce, parent_const, name); ZEND_ASSERT(!inherit); } else if (!(ZEND_CLASS_CONST_FLAGS(parent_const) & ZEND_ACC_PRIVATE)) { @@ -1734,6 +1724,15 @@ static bool do_inherit_constant_check( ZSTR_VAL(parent_constant->ce->name), ZSTR_VAL(name)); } + if (UNEXPECTED((ZEND_CLASS_CONST_FLAGS(child_constant) & ZEND_ACC_PPP_MASK) > (ZEND_CLASS_CONST_FLAGS(parent_constant) & ZEND_ACC_PPP_MASK))) { + zend_error_noreturn(E_COMPILE_ERROR, "Access level to %s::%s must be %s (as in %s %s)%s", + ZSTR_VAL(ce->name), ZSTR_VAL(name), + zend_visibility_string(ZEND_CLASS_CONST_FLAGS(parent_constant)), + zend_get_object_type(parent_constant->ce), + ZSTR_VAL(parent_constant->ce->name), + (ZEND_CLASS_CONST_FLAGS(parent_constant) & ZEND_ACC_PUBLIC) ? "" : " or weaker" + ); + } if (!(ZEND_CLASS_CONST_FLAGS(parent_constant) & ZEND_ACC_PRIVATE) && UNEXPECTED(ZEND_TYPE_IS_SET(parent_constant->type))) { inheritance_status status = class_constant_types_compatible(parent_constant, child_constant);