Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions core/iwasm/aot/aot_runtime.c
Original file line number Diff line number Diff line change
Expand Up @@ -2485,6 +2485,7 @@ invoke_native_with_hw_bound_check(WASMExecEnv *exec_env, void *func_ptr,
native stack to run the following codes before actually calling
the aot function in invokeNative function. */
if (!wasm_runtime_detect_native_stack_overflow(exec_env)) {
wasm_runtime_set_exec_env_tls(NULL);
return false;
}

Expand Down
1 change: 1 addition & 0 deletions core/iwasm/interpreter/wasm_runtime.c
Original file line number Diff line number Diff line change
Expand Up @@ -3618,6 +3618,7 @@ call_wasm_with_hw_bound_check(WASMModuleInstance *module_inst,
native stack to run the following codes before actually calling
the aot function in invokeNative function. */
if (!wasm_runtime_detect_native_stack_overflow(exec_env)) {
wasm_runtime_set_exec_env_tls(NULL);
return;
}

Expand Down
90 changes: 90 additions & 0 deletions tests/unit/runtime-common/wasm_exec_env_test.cc
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
#include "gtest/gtest.h"

#include "wasm_exec_env.h"
#include "wasm_runtime_common.h"

class wasm_exec_env_test_suite : public testing::Test
{
Expand Down Expand Up @@ -43,3 +44,92 @@ TEST_F(wasm_exec_env_test_suite, wasm_exec_env_pop_jmpbuf)
exec_env.jmpbuf_stack_top = nullptr;
EXPECT_EQ(nullptr, wasm_exec_env_pop_jmpbuf(&exec_env));
}

/*
* Test: exec_env_tls is cleared on early return from native stack overflow
*
* This test verifies that when wasm_runtime_call_wasm fails early due to
* native stack overflow check, exec_env_tls is properly cleared. Without
* this fix, subsequent calls with a different exec_env would fail with
* "invalid exec env" error.
*
* Bug scenario:
* 1. Call WASM with exec_env_A, TLS set to exec_env_A
* 2. Native stack overflow check fails, early return
* 3. TLS still points to exec_env_A (BUG: not cleared)
* 4. Destroy exec_env_A
* 5. Create exec_env_B, call WASM
* 6. Fails with "invalid exec env" because TLS != exec_env_B
*/
#ifdef OS_ENABLE_HW_BOUND_CHECK
/* Minimal WASM module: (module (func (export "test") (result i32) i32.const
* 42)) */
static uint8_t test_wasm[] = { 0x00, 0x61, 0x73, 0x6d, 0x01, 0x00, 0x00, 0x00,
0x01, 0x05, 0x01, 0x60, 0x00, 0x01, 0x7f, 0x03,
0x02, 0x01, 0x00, 0x07, 0x08, 0x01, 0x04, 0x74,
0x65, 0x73, 0x74, 0x00, 0x00, 0x0a, 0x06, 0x01,
0x04, 0x00, 0x41, 0x2a, 0x0b };

TEST_F(wasm_exec_env_test_suite, exec_env_tls_cleared_on_stack_overflow)
{
WAMRRuntimeRAII<512 * 1024> runtime;

/* Load and instantiate module */
wasm_module_t module =
wasm_runtime_load(test_wasm, sizeof(test_wasm), nullptr, 0);
ASSERT_NE(module, nullptr);

wasm_module_inst_t inst_a =
wasm_runtime_instantiate(module, 8192, 8192, nullptr, 0);
ASSERT_NE(inst_a, nullptr);

wasm_exec_env_t exec_env_a =
wasm_runtime_create_exec_env(inst_a, 8192);
ASSERT_NE(exec_env_a, nullptr);

/* Set native stack boundary high to trigger overflow check failure */
uint8_t stack_var;
uint8_t *high_boundary = &stack_var + 0x100000;
wasm_runtime_set_native_stack_boundary(exec_env_a, high_boundary);

/* Call should fail with native stack overflow */
wasm_function_inst_t func =
wasm_runtime_lookup_function(inst_a, "test");
ASSERT_NE(func, nullptr);

uint32_t argv[1] = { 0 };
bool result = wasm_runtime_call_wasm(exec_env_a, func, 0, argv);
EXPECT_FALSE(result);

/* Verify TLS is cleared after failed call (this is the fix) */
WASMExecEnv *tls = wasm_runtime_get_exec_env_tls();
EXPECT_EQ(tls, nullptr);

/* Clean up first instance */
wasm_runtime_destroy_exec_env(exec_env_a);
wasm_runtime_deinstantiate(inst_a);

/* Create second instance and exec_env */
wasm_module_inst_t inst_b =
wasm_runtime_instantiate(module, 8192, 8192, nullptr, 0);
ASSERT_NE(inst_b, nullptr);

wasm_exec_env_t exec_env_b =
wasm_runtime_create_exec_env(inst_b, 8192);
ASSERT_NE(exec_env_b, nullptr);

/* This call should succeed (would fail without the fix) */
func = wasm_runtime_lookup_function(inst_b, "test");
ASSERT_NE(func, nullptr);

argv[0] = 0;
result = wasm_runtime_call_wasm(exec_env_b, func, 0, argv);
EXPECT_TRUE(result);
EXPECT_EQ(argv[0], 42u);

/* Clean up */
wasm_runtime_destroy_exec_env(exec_env_b);
wasm_runtime_deinstantiate(inst_b);
wasm_runtime_unload(module);
}
#endif /* OS_ENABLE_HW_BOUND_CHECK */
Loading