From 98852cc7114bd80f32419b4710f39e84940569a6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tim=20D=C3=BCsterhus?= Date: Fri, 14 Mar 2025 10:47:09 +0100 Subject: [PATCH 1/2] =?UTF-8?q?zend=5Fget=5Fcallable=5Fname:=20Return=20un?= =?UTF-8?q?derlying=20callable=E2=80=99s=20name=20for=20fake=20closures?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fixes php/php-src#18062 --- Zend/tests/first_class_callable/gh18062.phpt | 32 ++++++++++++++++++++ Zend/zend_API.c | 13 ++++++++ 2 files changed, 45 insertions(+) create mode 100644 Zend/tests/first_class_callable/gh18062.phpt diff --git a/Zend/tests/first_class_callable/gh18062.phpt b/Zend/tests/first_class_callable/gh18062.phpt new file mode 100644 index 000000000000..3865dd77adba --- /dev/null +++ b/Zend/tests/first_class_callable/gh18062.phpt @@ -0,0 +1,32 @@ +--TEST-- +First Class Callable returns correct name from is_callable() +--FILE-- + +--EXPECT-- +string(9) "some_func" +string(13) "Foo::__invoke" +string(8) "Foo::bar" diff --git a/Zend/zend_API.c b/Zend/zend_API.c index 162f9aced147..2be3d428270f 100644 --- a/Zend/zend_API.c +++ b/Zend/zend_API.c @@ -4134,6 +4134,19 @@ ZEND_API zend_string *zend_get_callable_name_ex(zval *callable, zend_object *obj case IS_OBJECT: { zend_class_entry *ce = Z_OBJCE_P(callable); + + if (ce == zend_ce_closure) { + const zend_function *fn = zend_get_closure_method_def(Z_OBJ_P(callable)); + + if (fn->common.fn_flags & ZEND_ACC_FAKE_CLOSURE) { + if (fn->common.scope) { + return zend_create_member_string(fn->common.scope->name, fn->common.function_name); + } else { + return zend_string_copy(fn->common.function_name); + } + } + } + return zend_string_concat2( ZSTR_VAL(ce->name), ZSTR_LEN(ce->name), "::__invoke", sizeof("::__invoke") - 1); From 4d122cf0469f4df586cbade8f11c79af6e0d7b4a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tim=20D=C3=BCsterhus?= Date: Mon, 17 Mar 2025 09:51:50 +0100 Subject: [PATCH 2/2] NEWS / UPGRADING.INTERNALS --- NEWS | 2 ++ UPGRADING.INTERNALS | 2 ++ 2 files changed, 4 insertions(+) diff --git a/NEWS b/NEWS index e498fac1d82e..48e71a0a8063 100644 --- a/NEWS +++ b/NEWS @@ -169,6 +169,8 @@ PHP NEWS - Standard: . Fixed crypt() tests on musl when using --with-external-libcrypt (Michael Orlitzky). + . Fixed bug GH-18062 (is_callable(func(...), callable_name: $name) for first + class callables returns wrong name). (timwolla) - Streams: . Fixed bug GH-16889 (stream_select() timeout useless for pipes on Windows). diff --git a/UPGRADING.INTERNALS b/UPGRADING.INTERNALS index b963ead5cc8d..d2ab4e13fc52 100644 --- a/UPGRADING.INTERNALS +++ b/UPGRADING.INTERNALS @@ -19,6 +19,8 @@ PHP 8.5 INTERNALS UPGRADE NOTES a value to a non-reference zval. . Added zval_ptr_safe_dtor() to safely destroy a zval when a destructor could interfere. + . zend_get_callable_name() now returns the name of the underlying function + for fake closures. ======================== 2. Build system changes