Skip to content

Commit ed749ed

Browse files
committed
Fix use-after-free of immediately invoked closure with extra args
1 parent b557265 commit ed749ed

File tree

3 files changed

+21
-2
lines changed

3 files changed

+21
-2
lines changed

Zend/tests/closure_extra_args.phpt

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
--TEST--
2+
Immediately invoked closure with extra args
3+
--FILE--
4+
<?php
5+
6+
(function() {})(new stdClass);
7+
8+
?>
9+
===DONE===
10+
--EXPECT--
11+
===DONE===

Zend/zend_vm_def.h

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2398,6 +2398,11 @@ ZEND_VM_HELPER(zend_leave_helper, ANY, ANY)
23982398
zend_clean_and_cache_symbol_table(EX(symbol_table));
23992399
}
24002400
EG(current_execute_data) = EX(prev_execute_data);
2401+
2402+
/* Free extra args before releasing the closure,
2403+
* as that may free the op_array. */
2404+
zend_vm_stack_free_extra_args_ex(call_info, execute_data);
2405+
24012406
if (UNEXPECTED(call_info & ZEND_CALL_RELEASE_THIS)) {
24022407
zend_object *object = Z_OBJ(execute_data->This);
24032408
#if 0
@@ -2413,7 +2418,6 @@ ZEND_VM_HELPER(zend_leave_helper, ANY, ANY)
24132418
OBJ_RELEASE((zend_object*)execute_data->func->op_array.prototype);
24142419
}
24152420

2416-
zend_vm_stack_free_extra_args_ex(call_info, execute_data);
24172421
old_execute_data = execute_data;
24182422
execute_data = EX(prev_execute_data);
24192423
zend_vm_stack_free_call_frame_ex(call_info, old_execute_data);

Zend/zend_vm_execute.h

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -468,6 +468,11 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_leave_helper_SPEC(ZEND_OPCODE_
468468
zend_clean_and_cache_symbol_table(EX(symbol_table));
469469
}
470470
EG(current_execute_data) = EX(prev_execute_data);
471+
472+
/* Free extra args before releasing the closure,
473+
* as that may free the op_array. */
474+
zend_vm_stack_free_extra_args_ex(call_info, execute_data);
475+
471476
if (UNEXPECTED(call_info & ZEND_CALL_RELEASE_THIS)) {
472477
zend_object *object = Z_OBJ(execute_data->This);
473478
#if 0
@@ -483,7 +488,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_leave_helper_SPEC(ZEND_OPCODE_
483488
OBJ_RELEASE((zend_object*)execute_data->func->op_array.prototype);
484489
}
485490

486-
zend_vm_stack_free_extra_args_ex(call_info, execute_data);
487491
old_execute_data = execute_data;
488492
execute_data = EX(prev_execute_data);
489493
zend_vm_stack_free_call_frame_ex(call_info, old_execute_data);

0 commit comments

Comments
 (0)