From 2293818e1612247d8d5e2d94e37b1a48792d9841 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tim=20D=C3=BCsterhus?= Date: Mon, 24 Feb 2025 14:49:40 +0100 Subject: [PATCH 1/2] Fix `ReflectionFunction::isDeprecated()` for materialized `__call()` Fixes php/php-src#17913 --- Zend/zend_closures.c | 6 +- ...ctionFunction_isDeprecated_magic_call.phpt | 70 +++++++++++++++++++ 2 files changed, 74 insertions(+), 2 deletions(-) create mode 100644 ext/reflection/tests/ReflectionFunction_isDeprecated_magic_call.phpt diff --git a/Zend/zend_closures.c b/Zend/zend_closures.c index 629aa7d51a84..903e059f2d4f 100644 --- a/Zend/zend_closures.c +++ b/Zend/zend_closures.c @@ -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; diff --git a/ext/reflection/tests/ReflectionFunction_isDeprecated_magic_call.phpt b/ext/reflection/tests/ReflectionFunction_isDeprecated_magic_call.phpt new file mode 100644 index 000000000000..fa63816c44ec --- /dev/null +++ b/ext/reflection/tests/ReflectionFunction_isDeprecated_magic_call.phpt @@ -0,0 +1,70 @@ +--TEST-- +GH-17913: ReflectionClassConstant::isDeprecated() with __call() and __callStatic() +--FILE-- +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) From 4152135bb4c1a5f6acde0f58051e0099a20f8c19 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tim=20D=C3=BCsterhus?= Date: Thu, 27 Feb 2025 12:06:30 +0100 Subject: [PATCH 2/2] NEWS --- NEWS | 2 ++ 1 file changed, 2 insertions(+) diff --git a/NEWS b/NEWS index 285bf4e23a80..dc464b1abeca 100644 --- a/NEWS +++ b/NEWS @@ -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