Skip to content

Commit 5b037b3

Browse files
committed
php_reflection: Simplify the Closure::__invoke() check
1 parent a794fc9 commit 5b037b3

File tree

1 file changed

+15
-13
lines changed

1 file changed

+15
-13
lines changed

ext/reflection/php_reflection.c

Lines changed: 15 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -3445,24 +3445,26 @@ static void reflection_method_invoke(INTERNAL_FUNCTION_PARAMETERS, int variadic)
34453445
}
34463446

34473447
/* For Closure::__invoke(), closures from different source locations have
3448-
* different signatures, so we must reject those. However, closures created
3449-
* from the same source (e.g. in a loop) share the same op_array and should
3450-
* be allowed. For user closures compare op_array.opcodes, for internal
3451-
* closures (e.g. var_dump(...)) compare function_name and scope since
3452-
* zend_get_closure_method_def() returns a per-object embedded copy. */
3448+
* different signatures, so we must reject those. */
34533449
if (obj_ce == zend_ce_closure && !Z_ISUNDEF(intern->obj)
34543450
&& Z_OBJ_P(object) != Z_OBJ(intern->obj)) {
34553451
const zend_function *orig_func = zend_get_closure_method_def(Z_OBJ(intern->obj));
34563452
const zend_function *given_func = zend_get_closure_method_def(Z_OBJ_P(object));
3457-
bool same_closure;
3458-
if (orig_func->type == ZEND_USER_FUNCTION && given_func->type == ZEND_USER_FUNCTION) {
3459-
same_closure = orig_func->op_array.opcodes == given_func->op_array.opcodes;
3460-
} else if (orig_func->type == ZEND_INTERNAL_FUNCTION && given_func->type == ZEND_INTERNAL_FUNCTION) {
3461-
same_closure = orig_func->common.function_name == given_func->common.function_name
3462-
&& orig_func->common.scope == given_func->common.scope;
3463-
} else {
3464-
same_closure = false;
3453+
3454+
bool same_closure = false;
3455+
/* Check if they are either both fake closures or they both are not. */
3456+
if ((orig_func->common.fn_flags & ZEND_ACC_FAKE_CLOSURE) == (given_func->common.fn_flags & ZEND_ACC_FAKE_CLOSURE)) {
3457+
if (orig_func->common.fn_flags & ZEND_ACC_FAKE_CLOSURE) {
3458+
/* For fake closures, scope and name must match. */
3459+
same_closure = orig_func->common.scope == given_func->common.scope
3460+
&& orig_func->common.function_name == given_func->common.function_name;
3461+
} else {
3462+
/* Otherwise the opcode structure must be identical. */
3463+
ZEND_ASSERT(orig_func->type == ZEND_USER_FUNCTION);
3464+
same_closure = orig_func->op_array.opcodes == given_func->op_array.opcodes;
3465+
}
34653466
}
3467+
34663468
if (!same_closure) {
34673469
if (!variadic) {
34683470
efree(params);

0 commit comments

Comments
 (0)