From eda9f5f740550cfb59e94d4f911a42ccc1af1e3c Mon Sep 17 00:00:00 2001 From: Nikita Popov Date: Fri, 27 Aug 2021 11:58:13 +0200 Subject: [PATCH] Fix Closure::call() on internal method closure In this case we should use the original internal handler. Otherwise the trampoline will attempt to free the closure, but the function being used is not actually part of a closure anymore. --- Zend/tests/closure_call_internal.phpt | 10 ++++++++++ Zend/zend_closures.c | 3 +++ 2 files changed, 13 insertions(+) create mode 100644 Zend/tests/closure_call_internal.phpt diff --git a/Zend/tests/closure_call_internal.phpt b/Zend/tests/closure_call_internal.phpt new file mode 100644 index 00000000000..b0d71054256 --- /dev/null +++ b/Zend/tests/closure_call_internal.phpt @@ -0,0 +1,10 @@ +--TEST-- +Closure::call() on internal method +--FILE-- +call(new DateTime('@123'))); + +?> +--EXPECT-- +int(123) diff --git a/Zend/zend_closures.c b/Zend/zend_closures.c index e0e820b6a8d..a003d9f7210 100644 --- a/Zend/zend_closures.c +++ b/Zend/zend_closures.c @@ -152,6 +152,9 @@ ZEND_METHOD(Closure, call) my_function.common.fn_flags &= ~ZEND_ACC_CLOSURE; /* use scope of passed object */ my_function.common.scope = Z_OBJCE_P(newthis); + if (closure->func.type == ZEND_INTERNAL_FUNCTION) { + my_function.internal_function.handler = closure->orig_internal_handler; + } fci_cache.function_handler = &my_function; /* Runtime cache relies on bound scope to be immutable, hence we need a separate rt cache in case scope changed */