]> granicus.if.org Git - php/commitdiff
Fixed infinity recurion if we create closure on top of other closure.
authorDmitry Stogov <dmitry@zend.com>
Thu, 8 Oct 2015 23:37:51 +0000 (02:37 +0300)
committerDmitry Stogov <dmitry@zend.com>
Thu, 8 Oct 2015 23:37:51 +0000 (02:37 +0300)
Zend/zend_closures.c

index b035a4f54a2e5995860d00098724334707859425..a394c91c60b0db7723068777d4d9cbe34ca110d2 100644 (file)
@@ -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) {