diff --git a/core/iwasm/interpreter/wasm_interp_classic.c b/core/iwasm/interpreter/wasm_interp_classic.c index d7c87ec03..3aec3f4c4 100644 --- a/core/iwasm/interpreter/wasm_interp_classic.c +++ b/core/iwasm/interpreter/wasm_interp_classic.c @@ -6352,15 +6352,27 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module, if (cur_func->import_func_inst) { wasm_interp_call_func_import(module, exec_env, cur_func, prev_frame); +#if WASM_ENABLE_TAIL_CALL != 0 || WASM_ENABLE_GC != 0 + if (is_return_call) { + /* the frame was freed before tail calling and + the prev_frame was set as exec_env's cur_frame, + so here we recover context from prev_frame */ + RECOVER_CONTEXT(prev_frame); + } + else +#endif + { + prev_frame = frame->prev_frame; + cur_func = frame->function; + UPDATE_ALL_FROM_FRAME(); + } + #if WASM_ENABLE_EXCE_HANDLING != 0 char uncaught_exception[128] = { 0 }; bool has_exception = wasm_copy_exception(module, uncaught_exception); if (has_exception && strstr(uncaught_exception, "uncaught wasm exception")) { - /* fix framesp */ - UPDATE_ALL_FROM_FRAME(); - uint32 import_exception; /* initialize imported exception index to be invalid */ SET_INVALID_TAGINDEX(import_exception); @@ -6402,19 +6414,20 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module, { wasm_interp_call_func_native(module, exec_env, cur_func, prev_frame); - } - #if WASM_ENABLE_TAIL_CALL != 0 || WASM_ENABLE_GC != 0 - /* Don't restore some variables from frame for tail call, since - they weren't committed into the frame previously and are - available now. Instead, the frame was freed, allocated and - set again, restoring from it may cause unexped behavior. */ - if (!is_return_call) + if (is_return_call) { + /* the frame was freed before tail calling and + the prev_frame was set as exec_env's cur_frame, + so here we recover context from prev_frame */ + RECOVER_CONTEXT(prev_frame); + } + else #endif - { - prev_frame = frame->prev_frame; - cur_func = frame->function; - UPDATE_ALL_FROM_FRAME(); + { + prev_frame = frame->prev_frame; + cur_func = frame->function; + UPDATE_ALL_FROM_FRAME(); + } } /* update memory size, no need to update memory ptr as diff --git a/core/iwasm/interpreter/wasm_interp_fast.c b/core/iwasm/interpreter/wasm_interp_fast.c index 26064272d..5a5a2a141 100644 --- a/core/iwasm/interpreter/wasm_interp_fast.c +++ b/core/iwasm/interpreter/wasm_interp_fast.c @@ -5866,11 +5866,13 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module, } #if WASM_ENABLE_TAIL_CALL != 0 || WASM_ENABLE_GC != 0 - /* Don't restore some variables from frame for tail call, since - they weren't committed into the frame previously and are - available now. Instead, the frame was freed, allocated and - set again, restoring from it may cause unexped behavior. */ - if (!is_return_call) + if (is_return_call) { + /* the frame was freed before tail calling and + the prev_frame was set as exec_env's cur_frame, + so here we recover context from prev_frame */ + RECOVER_CONTEXT(prev_frame); + } + else #endif { prev_frame = frame->prev_frame;