summaryrefslogtreecommitdiff
path: root/Zend/zend_closures.c
diff options
context:
space:
mode:
Diffstat (limited to 'Zend/zend_closures.c')
-rw-r--r--Zend/zend_closures.c9
1 files changed, 8 insertions, 1 deletions
diff --git a/Zend/zend_closures.c b/Zend/zend_closures.c
index b035a4f54a..a394c91c60 100644
--- a/Zend/zend_closures.c
+++ b/Zend/zend_closures.c
@@ -564,7 +564,14 @@ ZEND_API void zend_create_closure(zval *res, zend_function *func, zend_class_ent
closure->func.common.prototype = (zend_function*)closure;
closure->func.common.fn_flags |= ZEND_ACC_CLOSURE;
/* wrap internal function handler to avoid memory leak */
- closure->orig_internal_handler = closure->func.internal_function.handler;
+ if (UNEXPECTED(closure->func.internal_function.handler == zend_closure_internal_handler)) {
+ /* avoid infinity recursion, by taking handler from nested closure */
+ zend_closure *nested = (zend_closure*)((char*)func - XtOffsetOf(zend_closure, func));
+ ZEND_ASSERT(nested->std.ce == zend_ce_closure);
+ closure->orig_internal_handler = nested->orig_internal_handler;
+ } else {
+ closure->orig_internal_handler = closure->func.internal_function.handler;
+ }
closure->func.internal_function.handler = zend_closure_internal_handler;
/* verify that we aren't binding internal function to a wrong scope */
if(func->common.scope != NULL) {