Skip to content

Commit 35c8058

Browse files
committed
Fixed bug #75186
1 parent e359812 commit 35c8058

File tree

3 files changed

+48
-21
lines changed

3 files changed

+48
-21
lines changed

NEWS

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,9 @@ PHP NEWS
1414
- PDO_MySQL:
1515
. Fixed bug #77944 (Wrong meta pdo_type for bigint on LLP64). (cmb)
1616

17+
- Reflection:
18+
. Fixed bug #75186 (Inconsistent reflection of Closure:::__invoke()). (Nikita)
19+
1720
- Session:
1821
. Fixed bug #77911 (Wrong warning for session.sid_bits_per_character). (cmb)
1922

ext/reflection/php_reflection.c

Lines changed: 20 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -4203,22 +4203,10 @@ ZEND_METHOD(reflection_class, getMethod)
42034203
/* }}} */
42044204

42054205
/* {{{ _addmethod */
4206-
static void _addmethod(zend_function *mptr, zend_class_entry *ce, zval *retval, zend_long filter, zval *obj)
4206+
static void _addmethod(zend_function *mptr, zend_class_entry *ce, zval *retval, zend_long filter)
42074207
{
4208-
zval method;
4209-
size_t len = ZSTR_LEN(mptr->common.function_name);
4210-
zend_function *closure;
42114208
if (mptr->common.fn_flags & filter) {
4212-
if (ce == zend_ce_closure && obj && (len == sizeof(ZEND_INVOKE_FUNC_NAME)-1)
4213-
&& memcmp(ZSTR_VAL(mptr->common.function_name), ZEND_INVOKE_FUNC_NAME, sizeof(ZEND_INVOKE_FUNC_NAME)-1) == 0
4214-
&& (closure = zend_get_closure_invoke_method(Z_OBJ_P(obj))) != NULL)
4215-
{
4216-
_fix_closure_prototype(closure);
4217-
mptr = closure;
4218-
}
4219-
/* don't assign closure_object since we only reflect the invoke handler
4220-
method and not the closure definition itself, even if we have a
4221-
closure */
4209+
zval method;
42224210
reflection_method_factory(ce, mptr, NULL, &method);
42234211
add_next_index_zval(retval, &method);
42244212
}
@@ -4232,9 +4220,8 @@ static int _addmethod_va(zval *el, int num_args, va_list args, zend_hash_key *ha
42324220
zend_class_entry *ce = *va_arg(args, zend_class_entry**);
42334221
zval *retval = va_arg(args, zval*);
42344222
long filter = va_arg(args, long);
4235-
zval *obj = va_arg(args, zval *);
42364223

4237-
_addmethod(mptr, ce, retval, filter, obj);
4224+
_addmethod(mptr, ce, retval, filter);
42384225
return ZEND_HASH_APPLY_KEEP;
42394226
}
42404227
/* }}} */
@@ -4260,13 +4247,25 @@ ZEND_METHOD(reflection_class, getMethods)
42604247
GET_REFLECTION_OBJECT_PTR(ce);
42614248

42624249
array_init(return_value);
4263-
zend_hash_apply_with_arguments(&ce->function_table, (apply_func_args_t) _addmethod_va, 4, &ce, return_value, filter, intern->obj);
4264-
if (Z_TYPE(intern->obj) != IS_UNDEF && instanceof_function(ce, zend_ce_closure)) {
4265-
zend_function *closure = zend_get_closure_invoke_method(Z_OBJ(intern->obj));
4250+
zend_hash_apply_with_arguments(&ce->function_table, (apply_func_args_t) _addmethod_va, 4, &ce, return_value, filter);
4251+
4252+
if (instanceof_function(ce, zend_ce_closure)) {
4253+
zend_bool has_obj = Z_TYPE(intern->obj) != IS_UNDEF;
4254+
zval obj_tmp;
4255+
zend_object *obj;
4256+
if (!has_obj) {
4257+
object_init_ex(&obj_tmp, ce);
4258+
obj = Z_OBJ(obj_tmp);
4259+
} else {
4260+
obj = Z_OBJ(intern->obj);
4261+
}
4262+
zend_function *closure = zend_get_closure_invoke_method(obj);
42664263
if (closure) {
42674264
_fix_closure_prototype(closure);
4268-
_addmethod(closure, ce, return_value, filter, &intern->obj);
4269-
_free_function(closure);
4265+
_addmethod(closure, ce, return_value, filter);
4266+
}
4267+
if (!has_obj) {
4268+
zval_ptr_dtor(&obj_tmp);
42704269
}
42714270
}
42724271
}

ext/reflection/tests/bug75186.phpt

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
--TEST--
2+
Bug #75186: Inconsistent reflection of Closure:::__invoke()
3+
--FILE--
4+
<?php
5+
6+
$rc = new ReflectionClass(Closure::class);
7+
foreach ($rc->getMethods() as $method) {
8+
if ($method->name == '__invoke') {
9+
var_dump($method);
10+
$method->invoke(
11+
function($what) { echo "Hello $what!\n"; },
12+
"World"
13+
);
14+
}
15+
}
16+
17+
?>
18+
--EXPECTF--
19+
object(ReflectionMethod)#%d (2) {
20+
["name"]=>
21+
string(8) "__invoke"
22+
["class"]=>
23+
string(7) "Closure"
24+
}
25+
Hello World!

0 commit comments

Comments
 (0)