Skip to content

Commit ef3babc

Browse files
authored
interp: Restore context from prev_frame after tail calling a native function (#3283)
The current frame was freed before tail calling to an import or native function and the prev_frame was set as exec_env's cur_frame, so after the tail calling, we should recover context from prev_frame but not current frame. Found in #3279.
1 parent b11dbcb commit ef3babc

File tree

2 files changed

+63
-10
lines changed

2 files changed

+63
-10
lines changed

core/iwasm/interpreter/wasm_interp_classic.c

+39-7
Original file line numberDiff line numberDiff line change
@@ -1509,6 +1509,9 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
15091509
WASMStringviewIterObjectRef stringview_iter_obj;
15101510
#endif
15111511
#endif
1512+
#if WASM_ENABLE_TAIL_CALL != 0 || WASM_ENABLE_GC != 0
1513+
bool is_return_call = false;
1514+
#endif
15121515
#if WASM_ENABLE_MEMORY64 != 0
15131516
/* TODO: multi-memories for now assuming the memory idx type is consistent
15141517
* across multi-memories */
@@ -6227,6 +6230,9 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
62276230
frame_ip = frame->ip;
62286231
frame_sp = frame->sp;
62296232
frame_csp = frame->csp;
6233+
#if WASM_ENABLE_TAIL_CALL != 0 || WASM_ENABLE_GC != 0
6234+
is_return_call = false;
6235+
#endif
62306236
goto call_func_from_entry;
62316237
}
62326238

@@ -6320,6 +6326,7 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
63206326
}
63216327
FREE_FRAME(exec_env, frame);
63226328
wasm_exec_env_set_cur_frame(exec_env, prev_frame);
6329+
is_return_call = true;
63236330
goto call_func_from_entry;
63246331
}
63256332
#endif
@@ -6333,6 +6340,9 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
63336340
}
63346341
SYNC_ALL_TO_FRAME();
63356342
prev_frame = frame;
6343+
#if WASM_ENABLE_TAIL_CALL != 0 || WASM_ENABLE_GC != 0
6344+
is_return_call = false;
6345+
#endif
63366346
}
63376347

63386348
call_func_from_entry:
@@ -6342,15 +6352,27 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
63426352
if (cur_func->import_func_inst) {
63436353
wasm_interp_call_func_import(module, exec_env, cur_func,
63446354
prev_frame);
6355+
#if WASM_ENABLE_TAIL_CALL != 0 || WASM_ENABLE_GC != 0
6356+
if (is_return_call) {
6357+
/* the frame was freed before tail calling and
6358+
the prev_frame was set as exec_env's cur_frame,
6359+
so here we recover context from prev_frame */
6360+
RECOVER_CONTEXT(prev_frame);
6361+
}
6362+
else
6363+
#endif
6364+
{
6365+
prev_frame = frame->prev_frame;
6366+
cur_func = frame->function;
6367+
UPDATE_ALL_FROM_FRAME();
6368+
}
6369+
63456370
#if WASM_ENABLE_EXCE_HANDLING != 0
63466371
char uncaught_exception[128] = { 0 };
63476372
bool has_exception =
63486373
wasm_copy_exception(module, uncaught_exception);
63496374
if (has_exception
63506375
&& strstr(uncaught_exception, "uncaught wasm exception")) {
6351-
/* fix framesp */
6352-
UPDATE_ALL_FROM_FRAME();
6353-
63546376
uint32 import_exception;
63556377
/* initialize imported exception index to be invalid */
63566378
SET_INVALID_TAGINDEX(import_exception);
@@ -6392,12 +6414,22 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
63926414
{
63936415
wasm_interp_call_func_native(module, exec_env, cur_func,
63946416
prev_frame);
6417+
#if WASM_ENABLE_TAIL_CALL != 0 || WASM_ENABLE_GC != 0
6418+
if (is_return_call) {
6419+
/* the frame was freed before tail calling and
6420+
the prev_frame was set as exec_env's cur_frame,
6421+
so here we recover context from prev_frame */
6422+
RECOVER_CONTEXT(prev_frame);
6423+
}
6424+
else
6425+
#endif
6426+
{
6427+
prev_frame = frame->prev_frame;
6428+
cur_func = frame->function;
6429+
UPDATE_ALL_FROM_FRAME();
6430+
}
63956431
}
63966432

6397-
prev_frame = frame->prev_frame;
6398-
cur_func = frame->function;
6399-
UPDATE_ALL_FROM_FRAME();
6400-
64016433
/* update memory size, no need to update memory ptr as
64026434
it isn't changed in wasm_enlarge_memory */
64036435
#if !defined(OS_ENABLE_HW_BOUND_CHECK) \

core/iwasm/interpreter/wasm_interp_fast.c

+24-3
Original file line numberDiff line numberDiff line change
@@ -1501,6 +1501,9 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
15011501
WASMStringviewIterObjectRef stringview_iter_obj;
15021502
#endif
15031503
#endif
1504+
#if WASM_ENABLE_TAIL_CALL != 0 || WASM_ENABLE_GC != 0
1505+
bool is_return_call = false;
1506+
#endif
15041507

15051508
#if WASM_ENABLE_LABELS_AS_VALUES != 0
15061509
#define HANDLE_OPCODE(op) &&HANDLE_##op
@@ -5618,6 +5621,9 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
56185621
{
56195622
frame = prev_frame;
56205623
frame_ip = frame->ip;
5624+
#if WASM_ENABLE_TAIL_CALL != 0 || WASM_ENABLE_GC != 0
5625+
is_return_call = false;
5626+
#endif
56215627
goto call_func_from_entry;
56225628
}
56235629

@@ -5766,6 +5772,7 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
57665772
FREE_FRAME(exec_env, frame);
57675773
frame_ip += cur_func->param_count * sizeof(int16);
57685774
wasm_exec_env_set_cur_frame(exec_env, (WASMRuntimeFrame *)prev_frame);
5775+
is_return_call = true;
57695776
goto call_func_from_entry;
57705777
}
57715778
#endif /* WASM_ENABLE_TAIL_CALL != 0 || WASM_ENABLE_GC != 0 */
@@ -5838,6 +5845,9 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
58385845
}
58395846
SYNC_ALL_TO_FRAME();
58405847
prev_frame = frame;
5848+
#if WASM_ENABLE_TAIL_CALL != 0 || WASM_ENABLE_GC != 0
5849+
is_return_call = false;
5850+
#endif
58415851
}
58425852

58435853
call_func_from_entry:
@@ -5855,9 +5865,20 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
58555865
prev_frame);
58565866
}
58575867

5858-
prev_frame = frame->prev_frame;
5859-
cur_func = frame->function;
5860-
UPDATE_ALL_FROM_FRAME();
5868+
#if WASM_ENABLE_TAIL_CALL != 0 || WASM_ENABLE_GC != 0
5869+
if (is_return_call) {
5870+
/* the frame was freed before tail calling and
5871+
the prev_frame was set as exec_env's cur_frame,
5872+
so here we recover context from prev_frame */
5873+
RECOVER_CONTEXT(prev_frame);
5874+
}
5875+
else
5876+
#endif
5877+
{
5878+
prev_frame = frame->prev_frame;
5879+
cur_func = frame->function;
5880+
UPDATE_ALL_FROM_FRAME();
5881+
}
58615882

58625883
/* update memory size, no need to update memory ptr as
58635884
it isn't changed in wasm_enlarge_memory */

0 commit comments

Comments
 (0)