Skip to content

Commit 5e3ad14

Browse files
committed
Fix closure bound vars in 8.5
1 parent 5d9ad4d commit 5e3ad14

File tree

1 file changed

+26
-9
lines changed

1 file changed

+26
-9
lines changed

src/copy.c

Lines changed: 26 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -787,12 +787,29 @@ zend_result pmmpthread_copy_closure(const pmmpthread_ident_t* owner, zend_closur
787787
);
788788
} else {
789789
HashTable* static_variables = NULL;
790-
if (closure_obj->func.type == ZEND_USER_FUNCTION && closure_obj->func.op_array.static_variables != NULL) {
791-
//if this is a real closure, we need to update the static_variables from the original closure object
792-
//so that the copied closure has the correct use()d variables
793-
//this should not modify the original closure
794-
//these have to be copied before the closure is created, to maintain the original behaviour
795-
static_variables = pmmpthread_copy_statics(owner, closure_obj->func.op_array.static_variables);
790+
#if PHP_VERSION_ID >= 80200
791+
HashTable* static_variables_ptr = NULL;
792+
#endif
793+
if (closure_obj->func.type == ZEND_USER_FUNCTION){
794+
if (closure_obj->func.op_array.static_variables != NULL) {
795+
//if this is a real closure, we need to update the static_variables from the original closure object
796+
//so that the copied closure has the correct use()d variables
797+
//this should not modify the original closure
798+
//these have to be copied before the closure is created, to maintain the original behaviour
799+
static_variables = pmmpthread_copy_statics(owner, closure_obj->func.op_array.static_variables);
800+
}
801+
#if PHP_VERSION_ID >= 80200
802+
//in PHP 8.5, the static_variables field is not overwritten when creating a new closure, so it may be different
803+
//than the static_variables_ptr, which will typically contain bound variables
804+
HashTable *origin_static_variables_ptr = ZEND_MAP_PTR_GET(closure_obj->func.op_array.static_variables_ptr);
805+
if (origin_static_variables_ptr != NULL) {
806+
if (origin_static_variables_ptr != closure_obj->func.op_array.static_variables) {
807+
static_variables_ptr = pmmpthread_copy_statics(owner, origin_static_variables_ptr);
808+
} else {
809+
static_variables_ptr = static_variables;
810+
}
811+
}
812+
#endif
796813
}
797814

798815
//we don't know where the definition for this closure is, so create a definition from this copy of it
@@ -810,15 +827,15 @@ zend_result pmmpthread_copy_closure(const pmmpthread_ident_t* owner, zend_closur
810827
if (static_variables != NULL) {
811828
zend_closure* new_closure = (zend_closure*)Z_OBJ_P(pzval);
812829
ZEND_ASSERT(new_closure->func.type == ZEND_USER_FUNCTION);
813-
if (new_closure->func.op_array.static_variables != NULL) {
830+
if (ZEND_MAP_PTR_GET(new_closure->func.op_array.static_variables_ptr) != NULL) {
814831
//the closure may have static_variables allocated from its original creation by zend_compile.c
815-
zend_array_release(new_closure->func.op_array.static_variables);
832+
zend_array_release(ZEND_MAP_PTR_GET(new_closure->func.op_array.static_variables_ptr));
816833
}
817834
new_closure->func.op_array.static_variables = static_variables;
818835
#if PHP_VERSION_ID >= 80200
819836
ZEND_MAP_PTR_INIT(
820837
new_closure->func.op_array.static_variables_ptr,
821-
new_closure->func.op_array.static_variables
838+
static_variables_ptr
822839
);
823840
#else
824841
//this is not strictly necessary for 8.1, but is here for the sake of completeness

0 commit comments

Comments
 (0)