From 1a2fb90bf459f2ab918e02dff63c803f24a354a9 Mon Sep 17 00:00:00 2001 From: Nikita Popov Date: Mon, 1 Nov 2021 11:42:36 +0100 Subject: [PATCH] Fix finally exception chaining on recursion In this case zend_exception_set_previous() would destroy the fast_call exception and further accesses on ex would be invalid. We should only update ex if we update EG(exception). Fixes oss-fuzz #40464. --- .../try/try_finally_recursive_previous.phpt | 18 ++++++++++++++++++ Zend/zend_vm_def.h | 3 +-- Zend/zend_vm_execute.h | 3 +-- 3 files changed, 20 insertions(+), 4 deletions(-) create mode 100644 Zend/tests/try/try_finally_recursive_previous.phpt diff --git a/Zend/tests/try/try_finally_recursive_previous.phpt b/Zend/tests/try/try_finally_recursive_previous.phpt new file mode 100644 index 00000000000..85d90d44d54 --- /dev/null +++ b/Zend/tests/try/try_finally_recursive_previous.phpt @@ -0,0 +1,18 @@ +--TEST-- +Test case where the implicit previous finally exception would result in recursion +--FILE-- + +--EXPECTF-- +Fatal error: Uncaught Exception: M1 in %s:%d +Stack trace: +#0 {main} + thrown in %s on line %d diff --git a/Zend/zend_vm_def.h b/Zend/zend_vm_def.h index c39cbdbf1bb..786a8f2db4b 100644 --- a/Zend/zend_vm_def.h +++ b/Zend/zend_vm_def.h @@ -7714,9 +7714,8 @@ ZEND_VM_HELPER(zend_dispatch_try_catch_finally_helper, ANY, ANY, uint32_t try_ca if (ex) { zend_exception_set_previous(ex, Z_OBJ_P(fast_call)); } else { - EG(exception) = Z_OBJ_P(fast_call); + ex = EG(exception) = Z_OBJ_P(fast_call); } - ex = Z_OBJ_P(fast_call); } } } diff --git a/Zend/zend_vm_execute.h b/Zend/zend_vm_execute.h index 0e12ede5bd3..90551512ef4 100644 --- a/Zend/zend_vm_execute.h +++ b/Zend/zend_vm_execute.h @@ -2905,9 +2905,8 @@ static zend_never_inline ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_dispatch_try if (ex) { zend_exception_set_previous(ex, Z_OBJ_P(fast_call)); } else { - EG(exception) = Z_OBJ_P(fast_call); + ex = EG(exception) = Z_OBJ_P(fast_call); } - ex = Z_OBJ_P(fast_call); } } }