summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDmitry Stogov <dmitry@zend.com>2015-10-09 02:37:51 +0300
committerDmitry Stogov <dmitry@zend.com>2015-10-09 02:37:51 +0300
commit93748bf9ddf971e42917565e35e122af96be85a6 (patch)
tree3d53052b5e581c1e05ad15c0084adce80f68ff8f
parent05bd331c6a86ba157785338b2512e217e40f3312 (diff)
downloadphp-git-93748bf9ddf971e42917565e35e122af96be85a6.tar.gz
Fixed infinity recurion if we create closure on top of other closure.
-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) {