Skip to content

Commit d8b3b28

Browse files
committed
Improve type validation for the Deprecated attribute
1 parent d060a3b commit d8b3b28

File tree

6 files changed

+78
-25
lines changed

6 files changed

+78
-25
lines changed
Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,14 @@
11
--TEST--
2-
#[\Deprecated]: Type validation of $message parameter.
2+
#[\Deprecated]: Type validation of $message parameter with int.
33
--FILE--
44
<?php
55

66
#[\Deprecated(1234)]
77
function test() {
88
}
99

10+
test();
11+
1012
?>
1113
--EXPECTF--
12-
Fatal error: Deprecated::__construct: Argument #1 ($message) must be of type string, int given in %s
14+
Deprecated: Function test() is deprecated, 1234 in %s on line %d
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
--TEST--
2+
#[\Deprecated]: Type validation of $message parameter with native enum case.
3+
--FILE--
4+
<?php
5+
6+
#[\Deprecated(\Random\IntervalBoundary::ClosedOpen)]
7+
function test() {
8+
}
9+
test();
10+
11+
?>
12+
--EXPECTF--
13+
Fatal error: Uncaught TypeError: Deprecated::__construct(): Argument #1 ($message) must be of type ?string, Random\IntervalBoundary given in %s:%d
14+
Stack trace:
15+
#0 %s(%d): Deprecated->__construct(Object(Random\IntervalBoundary))
16+
#1 {main}
17+
thrown in %s on line %d
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
--TEST--
2+
#[\Deprecated]: Type validation of $message parameter with array.
3+
--FILE--
4+
<?php
5+
6+
#[\Deprecated([])]
7+
function test() {
8+
}
9+
test();
10+
11+
?>
12+
--EXPECTF--
13+
Fatal error: Uncaught TypeError: Deprecated::__construct(): Argument #1 ($message) must be of type ?string, array given in %s:%d
14+
Stack trace:
15+
#0 %s(%d): Deprecated->__construct(Array)
16+
#1 {main}
17+
thrown in %s on line %d
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
--TEST--
2+
#[\Deprecated]: Type validation of $message parameter with int and strict types.
3+
--FILE--
4+
<?php
5+
declare(strict_types = 1);
6+
7+
#[\Deprecated(1234)]
8+
function test() {
9+
}
10+
11+
test();
12+
13+
?>
14+
--EXPECTF--
15+
Fatal error: Uncaught TypeError: Deprecated::__construct(): Argument #1 ($message) must be of type ?string, int given in %s:%d
16+
Stack trace:
17+
#0 %s(%d): Deprecated->__construct(1234)
18+
#1 {main}
19+
thrown in %s on line %d

Zend/zend_attributes.c

Lines changed: 0 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -83,28 +83,6 @@ static void validate_allow_dynamic_properties(
8383

8484
void validate_deprecated_attribute(zend_attribute *attr, uint32_t target, zend_class_entry *scope)
8585
{
86-
// TODO: More proper signature validation: Too many args, incorrect arg names.
87-
if (attr->argc == 1) {
88-
zval message;
89-
90-
/* As this is run in the middle of compilation, fetch the attribute value without
91-
* specifying a scope. The class is not fully linked yet, and we may seen an
92-
* inconsistent state. */
93-
if (FAILURE == zend_get_attribute_value(&message, attr, 0, NULL)) {
94-
return;
95-
}
96-
97-
if (Z_TYPE(message) != IS_STRING) {
98-
zval_ptr_dtor(&message);
99-
100-
zend_error_noreturn(E_COMPILE_ERROR,
101-
"Deprecated::__construct: Argument #1 ($message) must be of type string, %s given",
102-
zend_zval_type_name(&message)
103-
);
104-
}
105-
106-
zval_ptr_dtor(&message);
107-
}
10886
}
10987

11088
ZEND_METHOD(Attribute, __construct)

Zend/zend_execute.c

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1734,7 +1734,27 @@ ZEND_API ZEND_COLD void ZEND_FASTCALL zend_deprecated_function(const zend_functi
17341734
zval message;
17351735

17361736
if (FAILURE != zend_get_attribute_value(&message, deprecated, 0, fbc->common.scope)) {
1737-
message_suffix = Z_STR(message);
1737+
zval obj;
1738+
1739+
object_init_ex(&obj, zend_ce_deprecated);
1740+
zend_call_method_with_1_params(Z_OBJ_P(&obj), zend_ce_deprecated, &zend_ce_deprecated->constructor, "__construct", NULL, &message);
1741+
zval_ptr_dtor(&message);
1742+
1743+
if (EG(exception)) {
1744+
zval_ptr_dtor(&obj);
1745+
return;
1746+
}
1747+
1748+
zval *z;
1749+
1750+
if ((z = zend_read_property_ex(zend_ce_deprecated, Z_OBJ_P(&obj), ZSTR_KNOWN(ZEND_STR_MESSAGE), false, NULL)) == NULL) {
1751+
zval_ptr_dtor(&obj);
1752+
return;
1753+
}
1754+
1755+
zval_ptr_dtor(&obj);
1756+
1757+
message_suffix = Z_STR_P(z);
17381758
}
17391759
}
17401760
}

0 commit comments

Comments
 (0)