Skip to content

Commit 6962540

Browse files
authored
zend_get_callable_name: Return underlying callable’s name for fake closures (#18063)
Fixes #18062
1 parent 81ef122 commit 6962540

File tree

4 files changed

+49
-0
lines changed

4 files changed

+49
-0
lines changed

NEWS

+2
Original file line numberDiff line numberDiff line change
@@ -169,6 +169,8 @@ PHP NEWS
169169
- Standard:
170170
. Fixed crypt() tests on musl when using --with-external-libcrypt
171171
(Michael Orlitzky).
172+
. Fixed bug GH-18062 (is_callable(func(...), callable_name: $name) for first
173+
class callables returns wrong name). (timwolla)
172174

173175
- Streams:
174176
. Fixed bug GH-16889 (stream_select() timeout useless for pipes on Windows).

UPGRADING.INTERNALS

+2
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,8 @@ PHP 8.5 INTERNALS UPGRADE NOTES
1919
a value to a non-reference zval.
2020
. Added zval_ptr_safe_dtor() to safely destroy a zval when a destructor
2121
could interfere.
22+
. zend_get_callable_name() now returns the name of the underlying function
23+
for fake closures.
2224

2325
========================
2426
2. Build system changes
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
--TEST--
2+
First Class Callable returns correct name from is_callable()
3+
--FILE--
4+
<?php
5+
6+
class Foo {
7+
public function __invoke() {
8+
9+
}
10+
11+
public static function bar() {
12+
13+
}
14+
}
15+
16+
function some_func() {
17+
18+
}
19+
20+
is_callable(some_func(...), callable_name: $name);
21+
var_dump($name);
22+
23+
is_callable((new Foo())(...), callable_name: $name);
24+
var_dump($name);
25+
26+
is_callable(Foo::bar(...), callable_name: $name);
27+
var_dump($name);
28+
?>
29+
--EXPECT--
30+
string(9) "some_func"
31+
string(13) "Foo::__invoke"
32+
string(8) "Foo::bar"

Zend/zend_API.c

+13
Original file line numberDiff line numberDiff line change
@@ -4134,6 +4134,19 @@ ZEND_API zend_string *zend_get_callable_name_ex(zval *callable, zend_object *obj
41344134
case IS_OBJECT:
41354135
{
41364136
zend_class_entry *ce = Z_OBJCE_P(callable);
4137+
4138+
if (ce == zend_ce_closure) {
4139+
const zend_function *fn = zend_get_closure_method_def(Z_OBJ_P(callable));
4140+
4141+
if (fn->common.fn_flags & ZEND_ACC_FAKE_CLOSURE) {
4142+
if (fn->common.scope) {
4143+
return zend_create_member_string(fn->common.scope->name, fn->common.function_name);
4144+
} else {
4145+
return zend_string_copy(fn->common.function_name);
4146+
}
4147+
}
4148+
}
4149+
41374150
return zend_string_concat2(
41384151
ZSTR_VAL(ce->name), ZSTR_LEN(ce->name),
41394152
"::__invoke", sizeof("::__invoke") - 1);

0 commit comments

Comments
 (0)