@@ -486,6 +486,11 @@ static void zend_closure_free_storage(zend_object *object) /* {{{ */
486
486
zend_object_std_dtor (& closure -> std );
487
487
488
488
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
+ }
489
494
destroy_op_array (& closure -> func .op_array );
490
495
}
491
496
@@ -660,7 +665,7 @@ static ZEND_NAMED_FUNCTION(zend_closure_internal_handler) /* {{{ */
660
665
}
661
666
/* }}} */
662
667
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 ) /* {{{ */
664
669
{
665
670
zend_closure * closure ;
666
671
@@ -679,12 +684,15 @@ ZEND_API void zend_create_closure(zval *res, zend_function *func, zend_class_ent
679
684
closure -> func .common .fn_flags |= ZEND_ACC_CLOSURE ;
680
685
closure -> func .common .fn_flags &= ~ZEND_ACC_IMMUTABLE ;
681
686
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 );
685
695
}
686
- ZEND_MAP_PTR_INIT (closure -> func .op_array .static_variables_ptr ,
687
- & closure -> func .op_array .static_variables );
688
696
689
697
/* Runtime cache is scope-dependent, so we cannot reuse it if the scope changed */
690
698
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
754
762
}
755
763
/* }}} */
756
764
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
+
757
770
ZEND_API void zend_create_fake_closure (zval * res , zend_function * func , zend_class_entry * scope , zend_class_entry * called_scope , zval * this_ptr ) /* {{{ */
758
771
{
759
772
zend_closure * closure ;
760
773
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 );
762
775
763
776
closure = (zend_closure * )Z_OBJ_P (res );
764
777
closure -> func .common .fn_flags |= ZEND_ACC_FAKE_CLOSURE ;
0 commit comments