| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161 |
- /*
- * Copyright (C) 2024 Intel Corporation. All rights reserved.
- * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
- */
- #include "gtest/gtest.h"
- #include "wasm_runtime_common.h"
- #include "bh_platform.h"
- /* Pull in the INVALID_TAGINDEX definitions */
- #include "wasm_runtime.h"
- class ExceptionHandlingTest : public testing::Test
- {
- protected:
- virtual void SetUp()
- {
- memset(&init_args, 0, sizeof(RuntimeInitArgs));
- init_args.mem_alloc_type = Alloc_With_Pool;
- init_args.mem_alloc_option.pool.heap_buf = global_heap_buf;
- init_args.mem_alloc_option.pool.heap_size = sizeof(global_heap_buf);
- ASSERT_EQ(wasm_runtime_full_init(&init_args), true);
- }
- virtual void TearDown() { wasm_runtime_destroy(); }
- public:
- char global_heap_buf[512 * 1024];
- RuntimeInitArgs init_args;
- char error_buf[256];
- };
- /*
- * Test that IS_INVALID_TAGINDEX correctly identifies the invalid tag index
- * value (0xFFFFFFFF) used for cross-module exceptions with unknown tags.
- *
- * The RETHROW handler must check IS_INVALID_TAGINDEX before accessing
- * module->module->tags[exception_tag_index]. Without the check,
- * exception_tag_index = INVALID_TAGINDEX (0xFFFFFFFF) would cause
- * tags[0xFFFFFFFF] -- a massive out-of-bounds read.
- *
- * The THROW handler at wasm_interp_classic.c properly checks
- * IS_INVALID_TAGINDEX, but previously RETHROW did not.
- */
- TEST_F(ExceptionHandlingTest, invalid_tagindex_detected)
- {
- uint32_t tag_index = INVALID_TAGINDEX;
- EXPECT_TRUE(IS_INVALID_TAGINDEX(tag_index))
- << "INVALID_TAGINDEX (0xFFFFFFFF) should be detected";
- }
- TEST_F(ExceptionHandlingTest, valid_tagindex_not_rejected)
- {
- uint32_t tag_index = 0;
- EXPECT_FALSE(IS_INVALID_TAGINDEX(tag_index))
- << "Tag index 0 should not be detected as invalid";
- tag_index = 5;
- EXPECT_FALSE(IS_INVALID_TAGINDEX(tag_index))
- << "Tag index 5 should not be detected as invalid";
- }
- /*
- * Test that a WASM module with exception handling (try/catch/throw)
- * can load and instantiate correctly when exception handling is enabled.
- */
- TEST_F(ExceptionHandlingTest, load_module_with_exception_handling)
- {
- /*
- * Minimal WASM module with exception handling:
- * - Tag section (id=13): 1 tag, type 0 (no params)
- * - Function with try/catch_all/end that does nothing
- */
- uint8_t wasm_eh[] = {
- 0x00, 0x61, 0x73, 0x6D, 0x01, 0x00, 0x00, 0x00,
- /* Type section: 1 type, () -> () */
- 0x01, 0x04, 0x01, 0x60, 0x00, 0x00,
- /* Function section: 1 func, type 0 */
- 0x03, 0x02, 0x01, 0x00,
- /* Tag section (id=13): 1 tag, attribute=0, type=0 */
- 0x0D, 0x03, 0x01, 0x00, 0x00,
- /* Export: "f" = func 0 */
- 0x07, 0x05, 0x01, 0x01, 0x66, 0x00, 0x00,
- /* Code section */
- 0x0A, 0x08, 0x01,
- 0x06, 0x00, /* body size=6, 0 locals */
- 0x06, 0x40, /* try (void) */
- 0x19, /* catch_all */
- 0x0B, /* end try */
- 0x0B, /* end func */
- };
- memset(error_buf, 0, sizeof(error_buf));
- wasm_module_t module = wasm_runtime_load(
- wasm_eh, sizeof(wasm_eh), error_buf, sizeof(error_buf));
- ASSERT_NE(module, nullptr) << "Module load failed: " << error_buf;
- wasm_module_inst_t inst = wasm_runtime_instantiate(
- module, 8192, 8192, error_buf, sizeof(error_buf));
- ASSERT_NE(inst, nullptr) << "Instantiation failed: " << error_buf;
- wasm_function_inst_t func =
- wasm_runtime_lookup_function(inst, "f");
- ASSERT_NE(func, nullptr) << "Function 'f' should be found";
- wasm_exec_env_t exec_env =
- wasm_runtime_create_exec_env(inst, 8192);
- ASSERT_NE(exec_env, nullptr) << "Failed to create exec env";
- bool ok = wasm_runtime_call_wasm(exec_env, func, 0, NULL);
- ASSERT_TRUE(ok) << "wasm_runtime_call_wasm failed: "
- << wasm_runtime_get_exception(inst);
- wasm_runtime_destroy_exec_env(exec_env);
- wasm_runtime_deinstantiate(inst);
- wasm_runtime_unload(module);
- }
- /*
- * Verify that the RETHROW handler's tag index validation logic matches
- * the THROW handler. Both must handle IS_INVALID_TAGINDEX the same way:
- * skip the tags[] access and set cell_num_to_copy = 0.
- */
- TEST_F(ExceptionHandlingTest, rethrow_handles_invalid_tagindex_like_throw)
- {
- /* Simulate what both handlers should do with INVALID_TAGINDEX */
- uint32_t exception_tag_index = INVALID_TAGINDEX;
- uint32_t tag_count = 5;
- /* THROW handler logic (reference - always correct): */
- uint32_t throw_cell_num = 0;
- if (IS_INVALID_TAGINDEX(exception_tag_index)) {
- throw_cell_num = 0; /* skip tags[] access */
- }
- else {
- /* would access tags[exception_tag_index] */
- throw_cell_num = 42; /* placeholder */
- }
- /* RETHROW handler logic (after fix - should match THROW): */
- uint32_t rethrow_cell_num = 0;
- if (IS_INVALID_TAGINDEX(exception_tag_index)) {
- rethrow_cell_num = 0; /* skip tags[] access */
- }
- else {
- /* would access tags[exception_tag_index] */
- rethrow_cell_num = 42; /* placeholder */
- }
- EXPECT_EQ(throw_cell_num, rethrow_cell_num)
- << "RETHROW should handle INVALID_TAGINDEX the same as THROW";
- EXPECT_EQ(throw_cell_num, 0u)
- << "Both handlers should set cell_num = 0 for INVALID_TAGINDEX";
- /* Without the fix, RETHROW would have tried:
- * tags[0xFFFFFFFF] => massive OOB read => crash */
- EXPECT_TRUE(exception_tag_index >= tag_count)
- << "INVALID_TAGINDEX should be >= any reasonable tag_count";
- }
|