Skip to content

Commit c416191

Browse files
GH-19153: Validate #[\Attribute] targets (#19154)
Do not allow #[\Attribute] on traits, interfaces, enums, or abstract classes.
1 parent 5f8d648 commit c416191

File tree

6 files changed

+69
-0
lines changed

6 files changed

+69
-0
lines changed

NEWS

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,8 @@ PHP NEWS
6262
. The socket_set_timeout() alias function has been deprecated. (timwolla)
6363
. Passing null to to readdir(), rewinddir(), and closedir() to use the last
6464
opened directory has been deprecated. (Girgias)
65+
. Fixed bug GH-19153 (#[\Attribute] validation should error on
66+
trait/interface/enum/abstract class). (DanielEScherzer)
6567

6668
31 Jul 2025, PHP 8.5.0alpha4
6769

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
--TEST--
2+
#[Attribute] on an abstract class
3+
--FILE--
4+
<?php
5+
6+
#[Attribute]
7+
abstract class Demo {}
8+
9+
echo "Done\n";
10+
?>
11+
--EXPECTF--
12+
Fatal error: Cannot apply #[\Attribute] to abstract class Demo in %s on line %d
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
--TEST--
2+
#[Attribute] on an enum
3+
--FILE--
4+
<?php
5+
6+
#[Attribute]
7+
enum Demo {}
8+
9+
echo "Done\n";
10+
?>
11+
--EXPECTF--
12+
Fatal error: Cannot apply #[\Attribute] to enum Demo in %s on line %d
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
--TEST--
2+
#[Attribute] on an interface
3+
--FILE--
4+
<?php
5+
6+
#[Attribute]
7+
interface Demo {}
8+
9+
echo "Done\n";
10+
?>
11+
--EXPECTF--
12+
Fatal error: Cannot apply #[\Attribute] to interface Demo in %s on line %d
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
--TEST--
2+
#[Attribute] on a trait
3+
--FILE--
4+
<?php
5+
6+
#[Attribute]
7+
trait Demo {}
8+
9+
echo "Done\n";
10+
?>
11+
--EXPECTF--
12+
Fatal error: Cannot apply #[\Attribute] to trait Demo in %s on line %d

Zend/zend_attributes.c

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,24 @@ static void validate_allow_dynamic_properties(
9595
scope->ce_flags |= ZEND_ACC_ALLOW_DYNAMIC_PROPERTIES;
9696
}
9797

98+
static void validate_attribute(
99+
zend_attribute *attr, uint32_t target, zend_class_entry *scope)
100+
{
101+
const char *msg = NULL;
102+
if (scope->ce_flags & ZEND_ACC_TRAIT) {
103+
msg = "Cannot apply #[\\Attribute] to trait %s";
104+
} else if (scope->ce_flags & ZEND_ACC_INTERFACE) {
105+
msg = "Cannot apply #[\\Attribute] to interface %s";
106+
} else if (scope->ce_flags & ZEND_ACC_ENUM) {
107+
msg = "Cannot apply #[\\Attribute] to enum %s";
108+
} else if (scope->ce_flags & ZEND_ACC_EXPLICIT_ABSTRACT_CLASS) {
109+
msg = "Cannot apply #[\\Attribute] to abstract class %s";
110+
}
111+
if (msg != NULL) {
112+
zend_error_noreturn(E_ERROR, msg, ZSTR_VAL(scope->name));
113+
}
114+
}
115+
98116
ZEND_METHOD(Attribute, __construct)
99117
{
100118
zend_long flags = ZEND_ATTRIBUTE_TARGET_ALL;
@@ -522,6 +540,7 @@ void zend_register_attribute_ce(void)
522540

523541
zend_ce_attribute = register_class_Attribute();
524542
attr = zend_mark_internal_attribute(zend_ce_attribute);
543+
attr->validator = validate_attribute;
525544

526545
zend_ce_return_type_will_change_attribute = register_class_ReturnTypeWillChange();
527546
zend_mark_internal_attribute(zend_ce_return_type_will_change_attribute);

0 commit comments

Comments
 (0)