diff options
author | Nikita Popov <nikita.ppv@gmail.com> | 2020-03-06 14:57:55 +0100 |
---|---|---|
committer | Nikita Popov <nikita.ppv@gmail.com> | 2020-06-29 15:50:12 +0200 |
commit | 75a04eac978333467ccd98225d7ef21942ce9e91 (patch) | |
tree | ff3ea4cc064bacba90ec19a4d056de348b6d749b /Zend/zend_vm_execute.h | |
parent | d005a8e92becb9993ab0d370e4f5688d09bcaaf2 (diff) | |
download | php-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.h | 14 |
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 */ |