1
0
mirror of https://github.com/php/php-src.git synced 2026-03-24 00:02:20 +01:00

Fix ReflectionFunction::isDeprecated() for materialized __call() (#17914)

* Fix `ReflectionFunction::isDeprecated()` for materialized `__call()`

Fixes php/php-src#17913

* NEWS
This commit is contained in:
Tim Düsterhus
2025-02-27 14:48:08 +01:00
committed by GitHub
parent 8be263d2a1
commit 2e999bad34
3 changed files with 76 additions and 2 deletions

2
NEWS
View File

@@ -9,6 +9,8 @@ PHP NEWS
(ilutov)
. Fixed bug GH-17376 (Broken JIT polymorphism for property hooks added to
child class). (ilutov)
. Fixed bug GH-17913 (ReflectionFunction::isDeprecated() returns incorrect
results for closures created from magic __call()). (timwolla)
27 Feb 2025, PHP 8.4.5

View File

@@ -361,11 +361,12 @@ static zend_result zend_create_closure_from_callable(zval *return_value, zval *c
memset(&call, 0, sizeof(zend_internal_function));
call.type = ZEND_INTERNAL_FUNCTION;
call.fn_flags = mptr->common.fn_flags & ZEND_ACC_STATIC;
call.fn_flags = mptr->common.fn_flags & (ZEND_ACC_STATIC | ZEND_ACC_DEPRECATED);
call.handler = zend_closure_call_magic;
call.function_name = mptr->common.function_name;
call.scope = mptr->common.scope;
call.doc_comment = NULL;
call.attributes = mptr->common.attributes;
zend_free_trampoline(mptr);
mptr = (zend_function *) &call;
@@ -871,7 +872,7 @@ void zend_closure_from_frame(zval *return_value, zend_execute_data *call) { /* {
memset(&trampoline, 0, sizeof(zend_internal_function));
trampoline.type = ZEND_INTERNAL_FUNCTION;
trampoline.fn_flags = mptr->common.fn_flags & (ZEND_ACC_STATIC | ZEND_ACC_VARIADIC | ZEND_ACC_RETURN_REFERENCE);
trampoline.fn_flags = mptr->common.fn_flags & (ZEND_ACC_STATIC | ZEND_ACC_VARIADIC | ZEND_ACC_RETURN_REFERENCE | ZEND_ACC_DEPRECATED);
trampoline.handler = zend_closure_call_magic;
trampoline.function_name = mptr->common.function_name;
trampoline.scope = mptr->common.scope;
@@ -879,6 +880,7 @@ void zend_closure_from_frame(zval *return_value, zend_execute_data *call) { /* {
if (trampoline.fn_flags & ZEND_ACC_VARIADIC) {
trampoline.arg_info = trampoline_arg_info;
}
trampoline.attributes = mptr->common.attributes;
zend_free_trampoline(mptr);
mptr = (zend_function *) &trampoline;

View File

@@ -0,0 +1,70 @@
--TEST--
GH-17913: ReflectionClassConstant::isDeprecated() with __call() and __callStatic()
--FILE--
<?php
class Clazz {
#[\Deprecated]
function __call(string $name, array $params) {
}
#[\Deprecated("due to some reason")]
static function __callStatic(string $name, array $params) {
}
}
$foo = new Clazz;
$closure = Closure::fromCallable([$foo, 'test']);
$rc = new ReflectionFunction($closure);
var_dump($rc->getAttributes()[0]->newInstance());
var_dump($rc->isDeprecated());
$closure = $foo->test(...);
$rc = new ReflectionFunction($closure);
var_dump($rc->getAttributes()[0]->newInstance());
var_dump($rc->isDeprecated());
$closure = Closure::fromCallable('Clazz::test');
$rc = new ReflectionFunction($closure);
var_dump($rc->getAttributes()[0]->newInstance());
var_dump($rc->isDeprecated());
$closure = Clazz::test(...);
$rc = new ReflectionFunction($closure);
var_dump($rc->getAttributes()[0]->newInstance());
var_dump($rc->isDeprecated());
?>
--EXPECTF--
object(Deprecated)#%d (2) {
["message"]=>
NULL
["since"]=>
NULL
}
bool(true)
object(Deprecated)#%d (2) {
["message"]=>
NULL
["since"]=>
NULL
}
bool(true)
object(Deprecated)#%d (2) {
["message"]=>
string(18) "due to some reason"
["since"]=>
NULL
}
bool(true)
object(Deprecated)#%d (2) {
["message"]=>
string(18) "due to some reason"
["since"]=>
NULL
}
bool(true)