@@ -486,6 +486,11 @@ static void zend_closure_free_storage(zend_object *object) /* {{{ */
486486 zend_object_std_dtor (& closure -> std );
487487
488488 if (closure -> func .type == ZEND_USER_FUNCTION ) {
489+ /* We shared static_variables with the original function.
490+ * Unshare now so we don't try to destroy them. */
491+ if (closure -> func .op_array .fn_flags & ZEND_ACC_FAKE_CLOSURE ) {
492+ ZEND_MAP_PTR_INIT (closure -> func .op_array .static_variables_ptr , NULL );
493+ }
489494 destroy_op_array (& closure -> func .op_array );
490495 }
491496
@@ -660,7 +665,7 @@ static ZEND_NAMED_FUNCTION(zend_closure_internal_handler) /* {{{ */
660665}
661666/* }}} */
662667
663- ZEND_API void zend_create_closure (zval * res , zend_function * func , zend_class_entry * scope , zend_class_entry * called_scope , zval * this_ptr ) /* {{{ */
668+ static void zend_create_closure_ex (zval * res , zend_function * func , zend_class_entry * scope , zend_class_entry * called_scope , zval * this_ptr , bool is_fake ) /* {{{ */
664669{
665670 zend_closure * closure ;
666671
@@ -679,12 +684,15 @@ ZEND_API void zend_create_closure(zval *res, zend_function *func, zend_class_ent
679684 closure -> func .common .fn_flags |= ZEND_ACC_CLOSURE ;
680685 closure -> func .common .fn_flags &= ~ZEND_ACC_IMMUTABLE ;
681686
682- if (closure -> func .op_array .static_variables ) {
683- closure -> func .op_array .static_variables =
684- zend_array_dup (closure -> func .op_array .static_variables );
687+ /* For fake closures, we want to reuse the static variables of the original function. */
688+ if (!is_fake ) {
689+ if (closure -> func .op_array .static_variables ) {
690+ closure -> func .op_array .static_variables =
691+ zend_array_dup (closure -> func .op_array .static_variables );
692+ }
693+ ZEND_MAP_PTR_INIT (closure -> func .op_array .static_variables_ptr ,
694+ & closure -> func .op_array .static_variables );
685695 }
686- ZEND_MAP_PTR_INIT (closure -> func .op_array .static_variables_ptr ,
687- & closure -> func .op_array .static_variables );
688696
689697 /* Runtime cache is scope-dependent, so we cannot reuse it if the scope changed */
690698 if (!ZEND_MAP_PTR_GET (closure -> func .op_array .run_time_cache )
@@ -754,11 +762,16 @@ ZEND_API void zend_create_closure(zval *res, zend_function *func, zend_class_ent
754762}
755763/* }}} */
756764
765+ ZEND_API void zend_create_closure (zval * res , zend_function * func , zend_class_entry * scope , zend_class_entry * called_scope , zval * this_ptr )
766+ {
767+ zend_create_closure_ex (res , func , scope , called_scope , this_ptr , /* is_fake */ false);
768+ }
769+
757770ZEND_API void zend_create_fake_closure (zval * res , zend_function * func , zend_class_entry * scope , zend_class_entry * called_scope , zval * this_ptr ) /* {{{ */
758771{
759772 zend_closure * closure ;
760773
761- zend_create_closure (res , func , scope , called_scope , this_ptr );
774+ zend_create_closure_ex (res , func , scope , called_scope , this_ptr , /* is_fake */ true );
762775
763776 closure = (zend_closure * )Z_OBJ_P (res );
764777 closure -> func .common .fn_flags |= ZEND_ACC_FAKE_CLOSURE ;
0 commit comments