diff options
author | Dmitry Stogov <dmitry@zend.com> | 2015-10-09 02:37:51 +0300 |
---|---|---|
committer | Dmitry Stogov <dmitry@zend.com> | 2015-10-09 02:37:51 +0300 |
commit | 93748bf9ddf971e42917565e35e122af96be85a6 (patch) | |
tree | 3d53052b5e581c1e05ad15c0084adce80f68ff8f | |
parent | 05bd331c6a86ba157785338b2512e217e40f3312 (diff) | |
download | php-git-93748bf9ddf971e42917565e35e122af96be85a6.tar.gz |
Fixed infinity recurion if we create closure on top of other closure.
-rw-r--r-- | Zend/zend_closures.c | 9 |
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) { |