From 2c768f08b326347b2033c62e1aa3311e1d123b85 Mon Sep 17 00:00:00 2001 From: Daniel Scherzer Date: Wed, 16 Jul 2025 17:25:02 -0700 Subject: [PATCH 1/2] Add regression tests for current handling --- .../attributes/Attribute/Attribute_on_abstract.phpt | 12 ++++++++++++ .../attributes/Attribute/Attribute_on_enum.phpt | 12 ++++++++++++ .../attributes/Attribute/Attribute_on_interface.phpt | 12 ++++++++++++ .../attributes/Attribute/Attribute_on_trait.phpt | 12 ++++++++++++ 4 files changed, 48 insertions(+) create mode 100644 Zend/tests/attributes/Attribute/Attribute_on_abstract.phpt create mode 100644 Zend/tests/attributes/Attribute/Attribute_on_enum.phpt create mode 100644 Zend/tests/attributes/Attribute/Attribute_on_interface.phpt create mode 100644 Zend/tests/attributes/Attribute/Attribute_on_trait.phpt diff --git a/Zend/tests/attributes/Attribute/Attribute_on_abstract.phpt b/Zend/tests/attributes/Attribute/Attribute_on_abstract.phpt new file mode 100644 index 0000000000000..5764c4bddcb89 --- /dev/null +++ b/Zend/tests/attributes/Attribute/Attribute_on_abstract.phpt @@ -0,0 +1,12 @@ +--TEST-- +#[Attribute] on an abstract class +--FILE-- + +--EXPECT-- +Done diff --git a/Zend/tests/attributes/Attribute/Attribute_on_enum.phpt b/Zend/tests/attributes/Attribute/Attribute_on_enum.phpt new file mode 100644 index 0000000000000..b4403f53a7103 --- /dev/null +++ b/Zend/tests/attributes/Attribute/Attribute_on_enum.phpt @@ -0,0 +1,12 @@ +--TEST-- +#[Attribute] on an enum +--FILE-- + +--EXPECT-- +Done diff --git a/Zend/tests/attributes/Attribute/Attribute_on_interface.phpt b/Zend/tests/attributes/Attribute/Attribute_on_interface.phpt new file mode 100644 index 0000000000000..c923df1b91708 --- /dev/null +++ b/Zend/tests/attributes/Attribute/Attribute_on_interface.phpt @@ -0,0 +1,12 @@ +--TEST-- +#[Attribute] on an interface +--FILE-- + +--EXPECT-- +Done diff --git a/Zend/tests/attributes/Attribute/Attribute_on_trait.phpt b/Zend/tests/attributes/Attribute/Attribute_on_trait.phpt new file mode 100644 index 0000000000000..bfc4e8a83dc3b --- /dev/null +++ b/Zend/tests/attributes/Attribute/Attribute_on_trait.phpt @@ -0,0 +1,12 @@ +--TEST-- +#[Attribute] on a trait +--FILE-- + +--EXPECT-- +Done From 6f57d75da2aefd7861fa578903129bfb1d4bec25 Mon Sep 17 00:00:00 2001 From: Daniel Scherzer Date: Wed, 16 Jul 2025 17:36:48 -0700 Subject: [PATCH 2/2] GH-19153: Validate #[\Attribute] targets Do not allow #[\Attribute] on traits, interfaces, enums, or abstract classes. --- NEWS | 4 ++++ .../Attribute/Attribute_on_abstract.phpt | 4 ++-- .../Attribute/Attribute_on_enum.phpt | 4 ++-- .../Attribute/Attribute_on_interface.phpt | 4 ++-- .../Attribute/Attribute_on_trait.phpt | 4 ++-- Zend/zend_attributes.c | 19 +++++++++++++++++++ 6 files changed, 31 insertions(+), 8 deletions(-) diff --git a/NEWS b/NEWS index 6929e7b2d2f14..4fefdfed301c0 100644 --- a/NEWS +++ b/NEWS @@ -2,6 +2,10 @@ PHP NEWS ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||| ?? ??? ????, PHP 8.5.0alpha3 +- Core: + . Fixed bug GH-19153 (#[\Attribute] validation should error on + trait/interface/enum/abstract class). (DanielEScherzer) + - Sockets: . socket_set_option for multicast context throws a ValueError when the socket family is not of AF_INET/AF_INET6 family. (David Carlier) diff --git a/Zend/tests/attributes/Attribute/Attribute_on_abstract.phpt b/Zend/tests/attributes/Attribute/Attribute_on_abstract.phpt index 5764c4bddcb89..fcd8ec9797989 100644 --- a/Zend/tests/attributes/Attribute/Attribute_on_abstract.phpt +++ b/Zend/tests/attributes/Attribute/Attribute_on_abstract.phpt @@ -8,5 +8,5 @@ abstract class Demo {} echo "Done\n"; ?> ---EXPECT-- -Done +--EXPECTF-- +Fatal error: Cannot apply #[Attribute] to abstract class Demo in %s on line %d diff --git a/Zend/tests/attributes/Attribute/Attribute_on_enum.phpt b/Zend/tests/attributes/Attribute/Attribute_on_enum.phpt index b4403f53a7103..250210c4edb37 100644 --- a/Zend/tests/attributes/Attribute/Attribute_on_enum.phpt +++ b/Zend/tests/attributes/Attribute/Attribute_on_enum.phpt @@ -8,5 +8,5 @@ enum Demo {} echo "Done\n"; ?> ---EXPECT-- -Done +--EXPECTF-- +Fatal error: Cannot apply #[Attribute] to enum Demo in %s on line %d diff --git a/Zend/tests/attributes/Attribute/Attribute_on_interface.phpt b/Zend/tests/attributes/Attribute/Attribute_on_interface.phpt index c923df1b91708..19574fbd589a6 100644 --- a/Zend/tests/attributes/Attribute/Attribute_on_interface.phpt +++ b/Zend/tests/attributes/Attribute/Attribute_on_interface.phpt @@ -8,5 +8,5 @@ interface Demo {} echo "Done\n"; ?> ---EXPECT-- -Done +--EXPECTF-- +Fatal error: Cannot apply #[Attribute] to interface Demo in %s on line %d diff --git a/Zend/tests/attributes/Attribute/Attribute_on_trait.phpt b/Zend/tests/attributes/Attribute/Attribute_on_trait.phpt index bfc4e8a83dc3b..e8666b01240d6 100644 --- a/Zend/tests/attributes/Attribute/Attribute_on_trait.phpt +++ b/Zend/tests/attributes/Attribute/Attribute_on_trait.phpt @@ -8,5 +8,5 @@ trait Demo {} echo "Done\n"; ?> ---EXPECT-- -Done +--EXPECTF-- +Fatal error: Cannot apply #[Attribute] to trait Demo in %s on line %d diff --git a/Zend/zend_attributes.c b/Zend/zend_attributes.c index c3633801be83e..df7c77340cb61 100644 --- a/Zend/zend_attributes.c +++ b/Zend/zend_attributes.c @@ -95,6 +95,24 @@ static void validate_allow_dynamic_properties( scope->ce_flags |= ZEND_ACC_ALLOW_DYNAMIC_PROPERTIES; } +static void validate_attribute( + zend_attribute *attr, uint32_t target, zend_class_entry *scope) +{ + const char *msg = NULL; + if (scope->ce_flags & ZEND_ACC_TRAIT) { + msg = "Cannot apply #[Attribute] to trait %s"; + } else if (scope->ce_flags & ZEND_ACC_INTERFACE) { + msg = "Cannot apply #[Attribute] to interface %s"; + } else if (scope->ce_flags & ZEND_ACC_ENUM) { + msg = "Cannot apply #[Attribute] to enum %s"; + } else if (scope->ce_flags & ZEND_ACC_EXPLICIT_ABSTRACT_CLASS) { + msg = "Cannot apply #[Attribute] to abstract class %s"; + } + if (msg != NULL) { + zend_error_noreturn(E_ERROR, msg, ZSTR_VAL(scope->name)); + } +} + ZEND_METHOD(Attribute, __construct) { zend_long flags = ZEND_ATTRIBUTE_TARGET_ALL; @@ -522,6 +540,7 @@ void zend_register_attribute_ce(void) zend_ce_attribute = register_class_Attribute(); attr = zend_mark_internal_attribute(zend_ce_attribute); + attr->validator = validate_attribute; zend_ce_return_type_will_change_attribute = register_class_ReturnTypeWillChange(); zend_mark_internal_attribute(zend_ce_return_type_will_change_attribute);