wasm_exec_env_test.cc 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135
  1. /*
  2. * Copyright (C) 2019 Intel Corporation. All rights reserved.
  3. * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
  4. */
  5. #include "test_helper.h"
  6. #include "gtest/gtest.h"
  7. #include "wasm_exec_env.h"
  8. #include "wasm_runtime_common.h"
  9. class wasm_exec_env_test_suite : public testing::Test
  10. {
  11. protected:
  12. // You should make the members protected s.t. they can be
  13. // accessed from sub-classes.
  14. // virtual void SetUp() will be called before each test is run. You
  15. // should define it if you need to initialize the variables.
  16. // Otherwise, this can be skipped.
  17. virtual void SetUp() {}
  18. // virtual void TearDown() will be called after each test is run.
  19. // You should define it if there is cleanup work to do. Otherwise,
  20. // you don't have to provide it.
  21. //
  22. virtual void TearDown() {}
  23. };
  24. TEST_F(wasm_exec_env_test_suite, wasm_exec_env_create)
  25. {
  26. EXPECT_EQ(nullptr, wasm_exec_env_create(nullptr, 0));
  27. }
  28. TEST_F(wasm_exec_env_test_suite, wasm_exec_env_create_internal)
  29. {
  30. EXPECT_EQ(nullptr, wasm_exec_env_create_internal(nullptr, UINT32_MAX));
  31. }
  32. TEST_F(wasm_exec_env_test_suite, wasm_exec_env_pop_jmpbuf)
  33. {
  34. WASMExecEnv exec_env;
  35. exec_env.jmpbuf_stack_top = nullptr;
  36. EXPECT_EQ(nullptr, wasm_exec_env_pop_jmpbuf(&exec_env));
  37. }
  38. /*
  39. * Test: exec_env_tls is cleared on early return from native stack overflow
  40. *
  41. * This test verifies that when wasm_runtime_call_wasm fails early due to
  42. * native stack overflow check, exec_env_tls is properly cleared. Without
  43. * this fix, subsequent calls with a different exec_env would fail with
  44. * "invalid exec env" error.
  45. *
  46. * Bug scenario:
  47. * 1. Call WASM with exec_env_A, TLS set to exec_env_A
  48. * 2. Native stack overflow check fails, early return
  49. * 3. TLS still points to exec_env_A (BUG: not cleared)
  50. * 4. Destroy exec_env_A
  51. * 5. Create exec_env_B, call WASM
  52. * 6. Fails with "invalid exec env" because TLS != exec_env_B
  53. */
  54. #ifdef OS_ENABLE_HW_BOUND_CHECK
  55. /* Minimal WASM module: (module (func (export "test") (result i32) i32.const
  56. * 42)) */
  57. static uint8_t test_wasm[] = { 0x00, 0x61, 0x73, 0x6d, 0x01, 0x00, 0x00, 0x00,
  58. 0x01, 0x05, 0x01, 0x60, 0x00, 0x01, 0x7f, 0x03,
  59. 0x02, 0x01, 0x00, 0x07, 0x08, 0x01, 0x04, 0x74,
  60. 0x65, 0x73, 0x74, 0x00, 0x00, 0x0a, 0x06, 0x01,
  61. 0x04, 0x00, 0x41, 0x2a, 0x0b };
  62. TEST_F(wasm_exec_env_test_suite, exec_env_tls_cleared_on_stack_overflow)
  63. {
  64. WAMRRuntimeRAII<512 * 1024> runtime;
  65. /* Load and instantiate module */
  66. wasm_module_t module =
  67. wasm_runtime_load(test_wasm, sizeof(test_wasm), nullptr, 0);
  68. ASSERT_NE(module, nullptr);
  69. wasm_module_inst_t inst_a =
  70. wasm_runtime_instantiate(module, 8192, 8192, nullptr, 0);
  71. ASSERT_NE(inst_a, nullptr);
  72. wasm_exec_env_t exec_env_a =
  73. wasm_runtime_create_exec_env(inst_a, 8192);
  74. ASSERT_NE(exec_env_a, nullptr);
  75. /* Set native stack boundary high to trigger overflow check failure */
  76. uint8_t stack_var;
  77. uint8_t *high_boundary = &stack_var + 0x100000;
  78. wasm_runtime_set_native_stack_boundary(exec_env_a, high_boundary);
  79. /* Call should fail with native stack overflow */
  80. wasm_function_inst_t func =
  81. wasm_runtime_lookup_function(inst_a, "test");
  82. ASSERT_NE(func, nullptr);
  83. uint32_t argv[1] = { 0 };
  84. bool result = wasm_runtime_call_wasm(exec_env_a, func, 0, argv);
  85. EXPECT_FALSE(result);
  86. /* Verify TLS is cleared after failed call (this is the fix) */
  87. WASMExecEnv *tls = wasm_runtime_get_exec_env_tls();
  88. EXPECT_EQ(tls, nullptr);
  89. /* Clean up first instance */
  90. wasm_runtime_destroy_exec_env(exec_env_a);
  91. wasm_runtime_deinstantiate(inst_a);
  92. /* Create second instance and exec_env */
  93. wasm_module_inst_t inst_b =
  94. wasm_runtime_instantiate(module, 8192, 8192, nullptr, 0);
  95. ASSERT_NE(inst_b, nullptr);
  96. wasm_exec_env_t exec_env_b =
  97. wasm_runtime_create_exec_env(inst_b, 8192);
  98. ASSERT_NE(exec_env_b, nullptr);
  99. /* This call should succeed (would fail without the fix) */
  100. func = wasm_runtime_lookup_function(inst_b, "test");
  101. ASSERT_NE(func, nullptr);
  102. argv[0] = 0;
  103. result = wasm_runtime_call_wasm(exec_env_b, func, 0, argv);
  104. EXPECT_TRUE(result);
  105. EXPECT_EQ(argv[0], 42u);
  106. /* Clean up */
  107. wasm_runtime_destroy_exec_env(exec_env_b);
  108. wasm_runtime_deinstantiate(inst_b);
  109. wasm_runtime_unload(module);
  110. }
  111. #endif /* OS_ENABLE_HW_BOUND_CHECK */