From 226995147a9248f40af5147cc6387cb74f393f88 Mon Sep 17 00:00:00 2001 From: Gina Peter Banyard Date: Mon, 9 Mar 2026 15:27:32 +0000 Subject: [PATCH 1/7] Zend: add interface inheriting enum interface implemented in class test --- ...y_interfaces_error_via_indirect_interface.phpt | 15 +++++++++++++++ 1 file changed, 15 insertions(+) create mode 100644 Zend/tests/inheritance/enum_only_interfaces_error_via_indirect_interface.phpt diff --git a/Zend/tests/inheritance/enum_only_interfaces_error_via_indirect_interface.phpt b/Zend/tests/inheritance/enum_only_interfaces_error_via_indirect_interface.phpt new file mode 100644 index 0000000000000..66a9215320550 --- /dev/null +++ b/Zend/tests/inheritance/enum_only_interfaces_error_via_indirect_interface.phpt @@ -0,0 +1,15 @@ +--TEST-- +Interface that is extended from Enum only interface shouldn't be implementable by non-enum class +--FILE-- + +--EXPECTF-- +Fatal error: Non-enum class C cannot implement interface UnitEnum in %s on line %d From 37eab803fe714ec3841fe273c113454512d2d991 Mon Sep 17 00:00:00 2001 From: Gina Peter Banyard Date: Thu, 22 May 2025 14:13:11 +0100 Subject: [PATCH 2/7] Zend: Inherit interfaces early --- Zend/zend_inheritance.c | 25 +++++++++++++++---------- 1 file changed, 15 insertions(+), 10 deletions(-) diff --git a/Zend/zend_inheritance.c b/Zend/zend_inheritance.c index 9b3b6312cf255..fc2f3bb1ff1fa 100644 --- a/Zend/zend_inheritance.c +++ b/Zend/zend_inheritance.c @@ -1579,17 +1579,21 @@ static void do_inherit_property(zend_property_info *parent_info, zend_string *ke } /* }}} */ -static inline void do_implement_interface(zend_class_entry *ce, zend_class_entry *iface) /* {{{ */ +static inline void do_implement_interface_ex(zend_class_entry *ce, zend_class_entry *inherited_face, zend_class_entry *base_iface) { - if (!(ce->ce_flags & ZEND_ACC_INTERFACE) && iface->interface_gets_implemented && iface->interface_gets_implemented(iface, ce) == FAILURE) { - zend_error_noreturn(E_CORE_ERROR, "%s %s could not implement interface %s", zend_get_object_type_uc(ce), ZSTR_VAL(ce->name), ZSTR_VAL(iface->name)); + if (!(ce->ce_flags & ZEND_ACC_INTERFACE) && inherited_face->interface_gets_implemented && inherited_face->interface_gets_implemented(base_iface, ce) == FAILURE) { + zend_error_noreturn(E_CORE_ERROR, "%s %s could not implement interface %s", zend_get_object_type_uc(ce), ZSTR_VAL(ce->name), ZSTR_VAL(base_iface->name)); } /* This should be prevented by the class lookup logic. */ - ZEND_ASSERT(ce != iface); + ZEND_ASSERT(ce != base_iface); +} + +static inline void do_implement_interface(zend_class_entry *ce, zend_class_entry *iface) +{ + do_implement_interface_ex(ce, iface, iface); } -/* }}} */ -static void zend_do_inherit_interfaces(zend_class_entry *ce, const zend_class_entry *iface) /* {{{ */ +static void zend_do_inherit_interfaces(zend_class_entry *ce, zend_class_entry *iface) /* {{{ */ { /* expects interface to be contained in ce's interface list already */ uint32_t i, ce_num, if_num = iface->num_interfaces; @@ -1618,7 +1622,7 @@ static void zend_do_inherit_interfaces(zend_class_entry *ce, const zend_class_en /* and now call the implementing handlers */ while (ce_num < ce->num_interfaces) { - do_implement_interface(ce, ce->interfaces[ce_num++]); + do_implement_interface_ex(ce, ce->interfaces[ce_num++], iface); } } /* }}} */ @@ -2168,6 +2172,10 @@ static void do_interface_implementation(zend_class_entry *ce, zend_class_entry * zend_class_constant *c; uint32_t flags = ZEND_INHERITANCE_CHECK_PROTO | ZEND_INHERITANCE_CHECK_VISIBILITY; + if (iface->num_interfaces) { + zend_do_inherit_interfaces(ce, iface); + } + if (!(ce->ce_flags & ZEND_ACC_INTERFACE)) { /* We are not setting the prototype of overridden interface methods because of abstract * constructors. See Zend/tests/interface_constructor_prototype_001.phpt. */ @@ -2199,9 +2207,6 @@ static void do_interface_implementation(zend_class_entry *ce, zend_class_entry * } ZEND_HASH_FOREACH_END(); do_implement_interface(ce, iface); - if (iface->num_interfaces) { - zend_do_inherit_interfaces(ce, iface); - } } /* }}} */ From 401291aa15fa1c8c7e1de17d7263d1ccd3b99587 Mon Sep 17 00:00:00 2001 From: Gina Peter Banyard Date: Mon, 9 Mar 2026 15:27:51 +0000 Subject: [PATCH 3/7] fix new test output with new inheritence logic --- .../enum_only_interfaces_error_via_indirect_interface.phpt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Zend/tests/inheritance/enum_only_interfaces_error_via_indirect_interface.phpt b/Zend/tests/inheritance/enum_only_interfaces_error_via_indirect_interface.phpt index 66a9215320550..c3227e5e489b2 100644 --- a/Zend/tests/inheritance/enum_only_interfaces_error_via_indirect_interface.phpt +++ b/Zend/tests/inheritance/enum_only_interfaces_error_via_indirect_interface.phpt @@ -12,4 +12,4 @@ class C implements I { ?> --EXPECTF-- -Fatal error: Non-enum class C cannot implement interface UnitEnum in %s on line %d +Fatal error: Non-enum class C cannot implement interface I in %s on line %d From 8110720db080f8f5a79746fbdde21cc7cdf3fd3c Mon Sep 17 00:00:00 2001 From: Gina Peter Banyard Date: Mon, 9 Mar 2026 15:32:09 +0000 Subject: [PATCH 4/7] nits --- Zend/zend_inheritance.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Zend/zend_inheritance.c b/Zend/zend_inheritance.c index fc2f3bb1ff1fa..22048491f99f7 100644 --- a/Zend/zend_inheritance.c +++ b/Zend/zend_inheritance.c @@ -1579,9 +1579,9 @@ static void do_inherit_property(zend_property_info *parent_info, zend_string *ke } /* }}} */ -static inline void do_implement_interface_ex(zend_class_entry *ce, zend_class_entry *inherited_face, zend_class_entry *base_iface) +static inline void do_implement_interface_ex(zend_class_entry *ce, const zend_class_entry *inherited_iface, zend_class_entry *base_iface) { - if (!(ce->ce_flags & ZEND_ACC_INTERFACE) && inherited_face->interface_gets_implemented && inherited_face->interface_gets_implemented(base_iface, ce) == FAILURE) { + if (!(ce->ce_flags & ZEND_ACC_INTERFACE) && inherited_iface->interface_gets_implemented && inherited_iface->interface_gets_implemented(base_iface, ce) == FAILURE) { zend_error_noreturn(E_CORE_ERROR, "%s %s could not implement interface %s", zend_get_object_type_uc(ce), ZSTR_VAL(ce->name), ZSTR_VAL(base_iface->name)); } /* This should be prevented by the class lookup logic. */ From 7864a62ea321eb9174d8cf302d8513d0a983288e Mon Sep 17 00:00:00 2001 From: Gina Peter Banyard Date: Mon, 9 Mar 2026 15:45:25 +0000 Subject: [PATCH 5/7] No real need to pass base_iface --- ...y_interfaces_error_via_indirect_interface.phpt | 2 +- Zend/zend_inheritance.c | 15 +++++---------- 2 files changed, 6 insertions(+), 11 deletions(-) diff --git a/Zend/tests/inheritance/enum_only_interfaces_error_via_indirect_interface.phpt b/Zend/tests/inheritance/enum_only_interfaces_error_via_indirect_interface.phpt index c3227e5e489b2..66a9215320550 100644 --- a/Zend/tests/inheritance/enum_only_interfaces_error_via_indirect_interface.phpt +++ b/Zend/tests/inheritance/enum_only_interfaces_error_via_indirect_interface.phpt @@ -12,4 +12,4 @@ class C implements I { ?> --EXPECTF-- -Fatal error: Non-enum class C cannot implement interface I in %s on line %d +Fatal error: Non-enum class C cannot implement interface UnitEnum in %s on line %d diff --git a/Zend/zend_inheritance.c b/Zend/zend_inheritance.c index 22048491f99f7..4346cfcbb8930 100644 --- a/Zend/zend_inheritance.c +++ b/Zend/zend_inheritance.c @@ -1579,18 +1579,13 @@ static void do_inherit_property(zend_property_info *parent_info, zend_string *ke } /* }}} */ -static inline void do_implement_interface_ex(zend_class_entry *ce, const zend_class_entry *inherited_iface, zend_class_entry *base_iface) +static inline void do_implement_interface(zend_class_entry *ce, zend_class_entry *iface) { - if (!(ce->ce_flags & ZEND_ACC_INTERFACE) && inherited_iface->interface_gets_implemented && inherited_iface->interface_gets_implemented(base_iface, ce) == FAILURE) { - zend_error_noreturn(E_CORE_ERROR, "%s %s could not implement interface %s", zend_get_object_type_uc(ce), ZSTR_VAL(ce->name), ZSTR_VAL(base_iface->name)); + if (!(ce->ce_flags & ZEND_ACC_INTERFACE) && iface->interface_gets_implemented && iface->interface_gets_implemented(iface, ce) == FAILURE) { + zend_error_noreturn(E_CORE_ERROR, "%s %s could not implement interface %s", zend_get_object_type_uc(ce), ZSTR_VAL(ce->name), ZSTR_VAL(iface->name)); } /* This should be prevented by the class lookup logic. */ - ZEND_ASSERT(ce != base_iface); -} - -static inline void do_implement_interface(zend_class_entry *ce, zend_class_entry *iface) -{ - do_implement_interface_ex(ce, iface, iface); + ZEND_ASSERT(ce != iface); } static void zend_do_inherit_interfaces(zend_class_entry *ce, zend_class_entry *iface) /* {{{ */ @@ -1622,7 +1617,7 @@ static void zend_do_inherit_interfaces(zend_class_entry *ce, zend_class_entry *i /* and now call the implementing handlers */ while (ce_num < ce->num_interfaces) { - do_implement_interface_ex(ce, ce->interfaces[ce_num++], iface); + do_implement_interface(ce, ce->interfaces[ce_num++]); } } /* }}} */ From 27fcd3e812200cb0d9683d710d2d33388c219bd5 Mon Sep 17 00:00:00 2001 From: Gina Peter Banyard Date: Mon, 9 Mar 2026 15:47:03 +0000 Subject: [PATCH 6/7] Nits to reduce diff --- Zend/zend_inheritance.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/Zend/zend_inheritance.c b/Zend/zend_inheritance.c index 4346cfcbb8930..572942c5aa9b7 100644 --- a/Zend/zend_inheritance.c +++ b/Zend/zend_inheritance.c @@ -1579,7 +1579,7 @@ static void do_inherit_property(zend_property_info *parent_info, zend_string *ke } /* }}} */ -static inline void do_implement_interface(zend_class_entry *ce, zend_class_entry *iface) +static inline void do_implement_interface(zend_class_entry *ce, zend_class_entry *iface) /* {{{ */ { if (!(ce->ce_flags & ZEND_ACC_INTERFACE) && iface->interface_gets_implemented && iface->interface_gets_implemented(iface, ce) == FAILURE) { zend_error_noreturn(E_CORE_ERROR, "%s %s could not implement interface %s", zend_get_object_type_uc(ce), ZSTR_VAL(ce->name), ZSTR_VAL(iface->name)); @@ -1587,8 +1587,9 @@ static inline void do_implement_interface(zend_class_entry *ce, zend_class_entry /* This should be prevented by the class lookup logic. */ ZEND_ASSERT(ce != iface); } +/* }}} */ -static void zend_do_inherit_interfaces(zend_class_entry *ce, zend_class_entry *iface) /* {{{ */ +static void zend_do_inherit_interfaces(zend_class_entry *ce, const zend_class_entry *iface) /* {{{ */ { /* expects interface to be contained in ce's interface list already */ uint32_t i, ce_num, if_num = iface->num_interfaces; From 8bad12f64ef6d8d39a4cd8b164d7275ab45aa3cd Mon Sep 17 00:00:00 2001 From: Gina Peter Banyard Date: Mon, 9 Mar 2026 17:23:04 +0000 Subject: [PATCH 7/7] fix BackEnum test --- Zend/tests/enum/no-class-implements-backed-enum.phpt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Zend/tests/enum/no-class-implements-backed-enum.phpt b/Zend/tests/enum/no-class-implements-backed-enum.phpt index f6f37818da5ac..f8d4fd13a4239 100644 --- a/Zend/tests/enum/no-class-implements-backed-enum.phpt +++ b/Zend/tests/enum/no-class-implements-backed-enum.phpt @@ -7,4 +7,4 @@ class Foo implements BackedEnum {} ?> --EXPECTF-- -Fatal error: Non-enum class Foo cannot implement interface BackedEnum in %s on line %d +Fatal error: Non-enum class Foo cannot implement interface UnitEnum in %s on line %d