summaryrefslogtreecommitdiff
path: root/Zend/zend_vm_execute.h
diff options
context:
space:
mode:
authorNikita Popov <nikita.ppv@gmail.com>2020-03-06 14:57:55 +0100
committerNikita Popov <nikita.ppv@gmail.com>2020-06-29 15:50:12 +0200
commit75a04eac978333467ccd98225d7ef21942ce9e91 (patch)
treeff3ea4cc064bacba90ec19a4d056de348b6d749b /Zend/zend_vm_execute.h
parentd005a8e92becb9993ab0d370e4f5688d09bcaaf2 (diff)
downloadphp-git-75a04eac978333467ccd98225d7ef21942ce9e91.tar.gz
Make exit() unwind properly
exit() is now internally implemented by throwing an exception, performing a normal stack unwind and a clean shutdown. This ensures that no persistent resource leaks occur. The exception is internal, cannot be caught and does not result in the execution of finally blocks. This may be relaxed in the future. Closes GH-5768.
Diffstat (limited to 'Zend/zend_vm_execute.h')
-rw-r--r--Zend/zend_vm_execute.h14
1 files changed, 9 insertions, 5 deletions
diff --git a/Zend/zend_vm_execute.h b/Zend/zend_vm_execute.h
index a6f2ed827e..c1975fd0b9 100644
--- a/Zend/zend_vm_execute.h
+++ b/Zend/zend_vm_execute.h
@@ -2322,8 +2322,8 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_EXIT_SPEC_HANDLER
} while (0);
FREE_OP(opline->op1_type, opline->op1.var);
}
- zend_bailout();
- ZEND_VM_NEXT_OPCODE(); /* Never reached */
+ zend_throw_unwind_exit();
+ HANDLE_EXCEPTION();
}
static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_BEGIN_SILENCE_SPEC_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
@@ -2476,9 +2476,10 @@ static zend_never_inline ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_dispatch_try
{
/* May be NULL during generator closing (only finally blocks are executed) */
zend_object *ex = EG(exception);
+ zend_bool is_unwind_exit = ex && zend_is_unwind_exit(ex);
/* Walk try/catch/finally structures upwards, performing the necessary actions */
- while (try_catch_offset != (uint32_t) -1) {
+ for (; try_catch_offset != (uint32_t) -1; try_catch_offset--) {
zend_try_catch_element *try_catch =
&EX(func)->op_array.try_catch_array[try_catch_offset];
@@ -2488,6 +2489,11 @@ static zend_never_inline ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_dispatch_try
ZEND_VM_JMP_EX(&EX(func)->op_array.opcodes[try_catch->catch_op], 0);
} else if (op_num < try_catch->finally_op) {
+ if (is_unwind_exit) {
+ /* Don't execute finally blocks on exit (for now) */
+ continue;
+ }
+
/* Go to finally block */
zval *fast_call = EX_VAR(EX(func)->op_array.opcodes[try_catch->finally_end].op1.var);
cleanup_live_vars(execute_data, op_num, try_catch->finally_op);
@@ -2517,8 +2523,6 @@ static zend_never_inline ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_dispatch_try
ex = Z_OBJ_P(fast_call);
}
}
-
- try_catch_offset--;
}
/* Uncaught exception */