Skip to content

Commit 3e13275

Browse files
committed
Fix refcounting
1 parent d73829e commit 3e13275

File tree

4 files changed

+21
-3
lines changed

4 files changed

+21
-3
lines changed

Zend/zend_partial.c

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -917,6 +917,9 @@ zend_result zend_partial_init_call(zend_execute_data *call)
917917
uint32_t orig_call_info = ZEND_CALL_INFO(call);
918918
uint32_t call_info = orig_call_info & (ZEND_CALL_NESTED | ZEND_CALL_TOP | ZEND_CALL_ALLOCATED | ZEND_CALL_FREE_EXTRA_ARGS | ZEND_CALL_HAS_EXTRA_NAMED_PARAMS);
919919
void *object_or_called_scope;
920+
if (!ZEND_PARTIAL_FUNC_FLAG(&partial->func, ZEND_ACC_CALL_VIA_TRAMPOLINE)) {
921+
call_info |= ZEND_CALL_FAKE_CLOSURE;
922+
}
920923
if (Z_TYPE(partial->This) == IS_OBJECT) {
921924
object_or_called_scope = Z_OBJ(partial->This);
922925
ZEND_ADD_CALL_FLAG_EX(call_info, ZEND_CALL_HAS_THIS);
@@ -960,10 +963,9 @@ zend_result zend_partial_init_call(zend_execute_data *call)
960963

961964
if (ZEND_PARTIAL_FUNC_FLAG(&partial->func, ZEND_ACC_CALL_VIA_TRAMPOLINE)) {
962965
zend_string_addref(partial->func.common.function_name);
966+
OBJ_RELEASE(&partial->std);
963967
}
964968

965-
OBJ_RELEASE(&partial->std);
966-
967969
return SUCCESS;
968970
}
969971

@@ -975,6 +977,8 @@ void zend_partial_create(zval *result, uint32_t info, zval *this_ptr, zend_funct
975977

976978
zend_partial *applied, *partial = (zend_partial*) Z_OBJ_P(result);
977979

980+
ZEND_ASSERT(ZEND_PARTIAL_OBJECT(&partial->func) == &partial->std);
981+
978982
if ((applied = zend_partial_fetch(this_ptr))) {
979983
ZEND_ADD_CALL_FLAG(partial, ZEND_CALL_INFO(applied) & ~ZEND_APPLY_VARIADIC);
980984

Zend/zend_partial.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,10 @@
2323

2424
BEGIN_EXTERN_C()
2525

26+
/* This macro depends on zend_closure structure layout */
27+
#define ZEND_PARTIAL_OBJECT(func) \
28+
((zend_object*)((char*)(func) - XtOffsetOf(struct{uint32_t a; zend_function b;}, b) - sizeof(zval) - sizeof(zend_function) - sizeof(zend_object)))
29+
2630
typedef struct _zend_partial zend_partial;
2731

2832
void zend_partial_startup(void);

Zend/zend_vm_def.h

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2978,6 +2978,8 @@ ZEND_VM_HOT_HELPER(zend_leave_helper, ANY, ANY)
29782978
OBJ_RELEASE(Z_OBJ(execute_data->This));
29792979
} else if (UNEXPECTED(call_info & ZEND_CALL_CLOSURE)) {
29802980
OBJ_RELEASE(ZEND_CLOSURE_OBJECT(EX(func)));
2981+
} else if (UNEXPECTED(call_info & ZEND_CALL_FAKE_CLOSURE)) {
2982+
OBJ_RELEASE(ZEND_PARTIAL_OBJECT(EX(func)));
29812983
}
29822984
EG(vm_stack_top) = (zval*)execute_data;
29832985
execute_data = EX(prev_execute_data);
@@ -3012,6 +3014,8 @@ ZEND_VM_HOT_HELPER(zend_leave_helper, ANY, ANY)
30123014
OBJ_RELEASE(Z_OBJ(execute_data->This));
30133015
} else if (UNEXPECTED(call_info & ZEND_CALL_CLOSURE)) {
30143016
OBJ_RELEASE(ZEND_CLOSURE_OBJECT(EX(func)));
3017+
} else if (UNEXPECTED(call_info & ZEND_CALL_FAKE_CLOSURE)) {
3018+
OBJ_RELEASE(ZEND_PARTIAL_OBJECT(EX(func)));
30153019
}
30163020

30173021
old_execute_data = execute_data;
@@ -3069,6 +3073,8 @@ ZEND_VM_HOT_HELPER(zend_leave_helper, ANY, ANY)
30693073
}
30703074
if (UNEXPECTED(call_info & ZEND_CALL_CLOSURE)) {
30713075
OBJ_RELEASE(ZEND_CLOSURE_OBJECT(EX(func)));
3076+
} else if (UNEXPECTED(call_info & ZEND_CALL_FAKE_CLOSURE)) {
3077+
OBJ_RELEASE(ZEND_PARTIAL_OBJECT(EX(func)));
30723078
}
30733079
ZEND_VM_RETURN();
30743080
} else /* if (call_kind == ZEND_CALL_TOP_CODE) */ {
@@ -9328,6 +9334,10 @@ ZEND_VM_HANDLER(214, ZEND_CALL_PARTIAL, ANY, ANY, SPEC(OBSERVER))
93289334
if (ret == &retval) {
93299335
zval_ptr_dtor(ret);
93309336
}
9337+
9338+
if (UNEXPECTED(ZEND_CALL_INFO(call) & ZEND_CALL_FAKE_CLOSURE)) {
9339+
OBJ_RELEASE(ZEND_PARTIAL_OBJECT(fbc));
9340+
}
93319341
}
93329342

93339343
execute_data = EG(current_execute_data);

ext/reflection/php_reflection.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -902,7 +902,7 @@ static void _function_string(smart_str *str, zend_function *fptr, zend_class_ent
902902

903903
smart_str_appendl(str, indent, strlen(indent));
904904
const char *prefix = "Function [ ";
905-
if (fptr->common.fn_flags & ZEND_ACC_CLOSURE) {
905+
if (fptr->common.fn_flags & (ZEND_ACC_CLOSURE|ZEND_ACC_FAKE_CLOSURE)) {
906906
if (zend_is_partial_function(fptr)) {
907907
prefix = "Partial [ ";
908908
} else {

0 commit comments

Comments
 (0)