diff --git a/Zend/tests/oss_fuzz_438780145.phpt b/Zend/tests/oss_fuzz_438780145.phpt new file mode 100644 index 00000000000..4c6936a69a0 --- /dev/null +++ b/Zend/tests/oss_fuzz_438780145.phpt @@ -0,0 +1,27 @@ +--TEST-- +OSS-Fuzz #438780145: Nested finally with repeated return type check may uaf +--FILE-- + +--EXPECTF-- +Fatal error: Uncaught TypeError: test(): Return value must be of type int, string returned in %s:%d +Stack trace: +#0 %s(%d): test() +#1 {main} + thrown in %s on line %d diff --git a/Zend/zend_vm_def.h b/Zend/zend_vm_def.h index de8a34678c8..9afca6015c5 100644 --- a/Zend/zend_vm_def.h +++ b/Zend/zend_vm_def.h @@ -8624,6 +8624,10 @@ ZEND_VM_HANDLER(159, ZEND_DISCARD_EXCEPTION, ANY, ANY) zval *return_value = EX_VAR(EX(func)->op_array.opcodes[Z_OPLINE_NUM_P(fast_call)].op2.var); zval_ptr_dtor(return_value); + /* Clear return value in case we hit both DISCARD_EXCEPTION and + * zend_dispatch_try_catch_finally_helper, which will free the return + * value again. See OSS-Fuzz #438780145. */ + ZVAL_NULL(return_value); } /* cleanup delayed exception */ diff --git a/Zend/zend_vm_execute.h b/Zend/zend_vm_execute.h index 9105f18ff54..e0c380deedd 100644 --- a/Zend/zend_vm_execute.h +++ b/Zend/zend_vm_execute.h @@ -3498,6 +3498,10 @@ static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_DISCARD_EXCEP zval *return_value = EX_VAR(EX(func)->op_array.opcodes[Z_OPLINE_NUM_P(fast_call)].op2.var); zval_ptr_dtor(return_value); + /* Clear return value in case we hit both DISCARD_EXCEPTION and + * zend_dispatch_try_catch_finally_helper, which will free the return + * value again. See OSS-Fuzz #438780145. */ + ZVAL_NULL(return_value); } /* cleanup delayed exception */ @@ -59153,6 +59157,10 @@ static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_DISCARD_EXCEPTION_ zval *return_value = EX_VAR(EX(func)->op_array.opcodes[Z_OPLINE_NUM_P(fast_call)].op2.var); zval_ptr_dtor(return_value); + /* Clear return value in case we hit both DISCARD_EXCEPTION and + * zend_dispatch_try_catch_finally_helper, which will free the return + * value again. See OSS-Fuzz #438780145. */ + ZVAL_NULL(return_value); } /* cleanup delayed exception */