Skip to content

Commit 2293818

Browse files
committed
Fix ReflectionFunction::isDeprecated() for materialized __call()
Fixes php#17913
1 parent fc73da5 commit 2293818

File tree

2 files changed

+74
-2
lines changed

2 files changed

+74
-2
lines changed

Zend/zend_closures.c

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -361,11 +361,12 @@ static zend_result zend_create_closure_from_callable(zval *return_value, zval *c
361361

362362
memset(&call, 0, sizeof(zend_internal_function));
363363
call.type = ZEND_INTERNAL_FUNCTION;
364-
call.fn_flags = mptr->common.fn_flags & ZEND_ACC_STATIC;
364+
call.fn_flags = mptr->common.fn_flags & (ZEND_ACC_STATIC | ZEND_ACC_DEPRECATED);
365365
call.handler = zend_closure_call_magic;
366366
call.function_name = mptr->common.function_name;
367367
call.scope = mptr->common.scope;
368368
call.doc_comment = NULL;
369+
call.attributes = mptr->common.attributes;
369370

370371
zend_free_trampoline(mptr);
371372
mptr = (zend_function *) &call;
@@ -871,14 +872,15 @@ void zend_closure_from_frame(zval *return_value, zend_execute_data *call) { /* {
871872

872873
memset(&trampoline, 0, sizeof(zend_internal_function));
873874
trampoline.type = ZEND_INTERNAL_FUNCTION;
874-
trampoline.fn_flags = mptr->common.fn_flags & (ZEND_ACC_STATIC | ZEND_ACC_VARIADIC | ZEND_ACC_RETURN_REFERENCE);
875+
trampoline.fn_flags = mptr->common.fn_flags & (ZEND_ACC_STATIC | ZEND_ACC_VARIADIC | ZEND_ACC_RETURN_REFERENCE | ZEND_ACC_DEPRECATED);
875876
trampoline.handler = zend_closure_call_magic;
876877
trampoline.function_name = mptr->common.function_name;
877878
trampoline.scope = mptr->common.scope;
878879
trampoline.doc_comment = NULL;
879880
if (trampoline.fn_flags & ZEND_ACC_VARIADIC) {
880881
trampoline.arg_info = trampoline_arg_info;
881882
}
883+
trampoline.attributes = mptr->common.attributes;
882884

883885
zend_free_trampoline(mptr);
884886
mptr = (zend_function *) &trampoline;
Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
--TEST--
2+
GH-17913: ReflectionClassConstant::isDeprecated() with __call() and __callStatic()
3+
--FILE--
4+
<?php
5+
6+
class Clazz {
7+
#[\Deprecated]
8+
function __call(string $name, array $params) {
9+
}
10+
11+
#[\Deprecated("due to some reason")]
12+
static function __callStatic(string $name, array $params) {
13+
}
14+
}
15+
16+
$foo = new Clazz;
17+
$closure = Closure::fromCallable([$foo, 'test']);
18+
19+
$rc = new ReflectionFunction($closure);
20+
var_dump($rc->getAttributes()[0]->newInstance());
21+
var_dump($rc->isDeprecated());
22+
23+
$closure = $foo->test(...);
24+
25+
$rc = new ReflectionFunction($closure);
26+
var_dump($rc->getAttributes()[0]->newInstance());
27+
var_dump($rc->isDeprecated());
28+
29+
$closure = Closure::fromCallable('Clazz::test');
30+
31+
$rc = new ReflectionFunction($closure);
32+
var_dump($rc->getAttributes()[0]->newInstance());
33+
var_dump($rc->isDeprecated());
34+
35+
$closure = Clazz::test(...);
36+
37+
$rc = new ReflectionFunction($closure);
38+
var_dump($rc->getAttributes()[0]->newInstance());
39+
var_dump($rc->isDeprecated());
40+
41+
?>
42+
--EXPECTF--
43+
object(Deprecated)#%d (2) {
44+
["message"]=>
45+
NULL
46+
["since"]=>
47+
NULL
48+
}
49+
bool(true)
50+
object(Deprecated)#%d (2) {
51+
["message"]=>
52+
NULL
53+
["since"]=>
54+
NULL
55+
}
56+
bool(true)
57+
object(Deprecated)#%d (2) {
58+
["message"]=>
59+
string(18) "due to some reason"
60+
["since"]=>
61+
NULL
62+
}
63+
bool(true)
64+
object(Deprecated)#%d (2) {
65+
["message"]=>
66+
string(18) "due to some reason"
67+
["since"]=>
68+
NULL
69+
}
70+
bool(true)

0 commit comments

Comments
 (0)