diff --git a/CMakeLists.txt b/CMakeLists.txt index 5f0b246..296d4ef 100755 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -168,10 +168,14 @@ set(WASM2C_RUNTIME_SOURCE_DIR "${mod_wasm2c_SOURCE_DIR}/wasm2c/") set(WASM2C_RUNTIME_DIR "${mod_wasm2c_SOURCE_DIR}/build_${WASM2C_BUILD_DIR_SUFFIX}/") set(C_SOURCE_FILES "${CMAKE_SOURCE_DIR}/c_src/wasm2c_sandbox_wrapper.c") -set(GLUE_LIB_WASM_DIR "${CMAKE_BINARY_DIR}/wasm/") -set(GLUE_LIB_WASM "${GLUE_LIB_WASM_DIR}/glue_lib_wasm2c.wasm") -set(GLUE_LIB_H "${GLUE_LIB_WASM_DIR}/glue_lib_wasm2c.h") -set(GLUE_LIB_C "${GLUE_LIB_WASM_DIR}/glue_lib_wasm2c.c") +set(GLUE_LIB_WASM_IMPORTED_DIR "${CMAKE_BINARY_DIR}/wasm_imported/") +set(GLUE_LIB_IMPORTED_WASM "${GLUE_LIB_WASM_IMPORTED_DIR}/glue_lib_wasm2c.wasm") +set(GLUE_LIB_IMPORTED_H "${GLUE_LIB_WASM_IMPORTED_DIR}/glue_lib_wasm2c.h") +set(GLUE_LIB_IMPORTED_C "${GLUE_LIB_WASM_IMPORTED_DIR}/glue_lib_wasm2c.c") +set(GLUE_LIB_WASM_EXPORTED_DIR "${CMAKE_BINARY_DIR}/wasm_exported/") +set(GLUE_LIB_EXPORTED_WASM "${GLUE_LIB_WASM_EXPORTED_DIR}/glue_lib_wasm2c.wasm") +set(GLUE_LIB_EXPORTED_H "${GLUE_LIB_WASM_EXPORTED_DIR}/glue_lib_wasm2c.h") +set(GLUE_LIB_EXPORTED_C "${GLUE_LIB_WASM_EXPORTED_DIR}/glue_lib_wasm2c.c") if(MSVC) set(WASM2C_PATH ${WASM2C_RUNTIME_DIR}/${WASM2C_BUILD_TYPE}/wasm2c.exe) @@ -179,8 +183,7 @@ else() set(WASM2C_PATH ${WASM2C_RUNTIME_DIR}/wasm2c) endif() -add_custom_command(OUTPUT "${GLUE_LIB_H}" "${GLUE_LIB_C}" "${GLUE_LIB_WASM}" - DEPENDS ${C_SOURCE_FILES} +add_custom_command(OUTPUT "${WASM2C_PATH}" WORKING_DIRECTORY "${mod_wasm2c_SOURCE_DIR}" COMMAND ${CMAKE_COMMAND} -DCMAKE_BUILD_TYPE=${WASM2C_BUILD_TYPE} @@ -193,18 +196,37 @@ add_custom_command(OUTPUT "${GLUE_LIB_H}" "${GLUE_LIB_C}" "${GLUE_LIB_WASM}" --build ${WASM2C_RUNTIME_DIR} --config ${WASM2C_BUILD_TYPE} --parallel - COMMAND ${CMAKE_COMMAND} -E make_directory ${GLUE_LIB_WASM_DIR} + COMMENT "Building wasm2c compiler and runtime") + +add_custom_command(OUTPUT "${GLUE_LIB_IMPORTED_H}" "${GLUE_LIB_IMPORTED_C}" "${GLUE_LIB_IMPORTED_WASM}" + DEPENDS ${C_SOURCE_FILES} ${WASM2C_PATH} + COMMAND ${CMAKE_COMMAND} -E make_directory ${GLUE_LIB_WASM_IMPORTED_DIR} COMMAND ${wasiclang_SOURCE_DIR}/bin/clang --sysroot ${wasiclang_SOURCE_DIR}/share/wasi-sysroot/ -O3 -Wl,--export-all -Wl,--no-entry -Wl,--growable-table -Wl,--stack-first -Wl,-z,stack-size=1048576 -Wl,--import-memory -Wl,--import-table - -o ${GLUE_LIB_WASM} + -o ${GLUE_LIB_IMPORTED_WASM} + ${CMAKE_SOURCE_DIR}/c_src/wasm2c_sandbox_wrapper.c + ${rlbox_SOURCE_DIR}/code/tests/rlbox_glue/lib/libtest.c + COMMAND ${WASM2C_PATH} + -o ${GLUE_LIB_IMPORTED_C} + ${GLUE_LIB_IMPORTED_WASM} + COMMENT "Building wasm sandboxed library with imported memory and imported table") + +add_custom_command(OUTPUT "${GLUE_LIB_EXPORTED_H}" "${GLUE_LIB_EXPORTED_C}" "${GLUE_LIB_EXPORTED_WASM}" + DEPENDS ${C_SOURCE_FILES} ${WASM2C_PATH} + COMMAND ${CMAKE_COMMAND} -E make_directory ${GLUE_LIB_WASM_EXPORTED_DIR} + COMMAND ${wasiclang_SOURCE_DIR}/bin/clang + --sysroot ${wasiclang_SOURCE_DIR}/share/wasi-sysroot/ + -O3 + -Wl,--export-all -Wl,--no-entry -Wl,--growable-table -Wl,--stack-first -Wl,-z,stack-size=1048576 -Wl,--export-table + -o ${GLUE_LIB_EXPORTED_WASM} ${CMAKE_SOURCE_DIR}/c_src/wasm2c_sandbox_wrapper.c ${rlbox_SOURCE_DIR}/code/tests/rlbox_glue/lib/libtest.c COMMAND ${WASM2C_PATH} - -o ${GLUE_LIB_C} - ${GLUE_LIB_WASM} - COMMENT "Building wasm2c compiler, runtime and wasm sandboxed library") + -o ${GLUE_LIB_EXPORTED_C} + ${GLUE_LIB_EXPORTED_WASM} + COMMENT "Building wasm sandboxed library with exported memory and exported table") # Tests ################### @@ -218,14 +240,26 @@ set(WASM2C_RUNTIME_CODE ${WASM2C_RUNTIME_SOURCE_DIR}/wasm-rt-impl.c ${CMAKE_SOURCE_DIR}/src/wasm2c_rt_minwasi.c ${CMAKE_SOURCE_DIR}/src/wasm2c_rt_mem.c) -add_library(glue_lib STATIC ${GLUE_LIB_C} ${WASM2C_RUNTIME_CODE}) -target_include_directories(glue_lib PRIVATE ${mod_wasm2c_SOURCE_DIR}/wasm2c - PUBLIC ${mod_wasm2c_SOURCE_DIR}/third_party/simde - PRIVATE ${CMAKE_SOURCE_DIR}/include) +add_library(glue_lib_imported STATIC ${GLUE_LIB_IMPORTED_C} ${WASM2C_RUNTIME_CODE}) +target_include_directories(glue_lib_imported PRIVATE ${mod_wasm2c_SOURCE_DIR}/wasm2c + PUBLIC ${mod_wasm2c_SOURCE_DIR}/third_party/simde + PRIVATE ${CMAKE_SOURCE_DIR}/include) + +target_compile_definitions(glue_lib_imported PUBLIC WASM_RT_USE_MMAP=1 + PUBLIC WASM_RT_SKIP_SIGNAL_RECOVERY=1 + PUBLIC WASM_RT_NONCONFORMING_UNCHECKED_STACK_EXHAUSTION=1) + +add_library(glue_lib_exported STATIC ${GLUE_LIB_EXPORTED_C} ${WASM2C_RUNTIME_CODE}) +target_include_directories(glue_lib_exported PRIVATE ${mod_wasm2c_SOURCE_DIR}/wasm2c + PUBLIC ${mod_wasm2c_SOURCE_DIR}/third_party/simde + PRIVATE ${CMAKE_SOURCE_DIR}/include) -target_compile_definitions(glue_lib PUBLIC WASM_RT_USE_MMAP=1 - PUBLIC WASM_RT_SKIP_SIGNAL_RECOVERY=1 - PUBLIC WASM_RT_NONCONFORMING_UNCHECKED_STACK_EXHAUSTION=1) +target_compile_definitions(glue_lib_exported PUBLIC WASM_RT_USE_MMAP=1 + PUBLIC WASM_RT_SKIP_SIGNAL_RECOVERY=1 + PUBLIC WASM_RT_NONCONFORMING_UNCHECKED_STACK_EXHAUSTION=1) + +# Hack to avoid multiple concurrent calls to the custom command that builds wasm2c +add_dependencies(glue_lib_imported glue_lib_exported) include(CTest) include(Catch) @@ -241,12 +275,12 @@ target_include_directories(test_rlbox_glue PUBLIC ${CMAKE_SOURCE_DIR}/include PUBLIC ${rlbox_SOURCE_DIR}/code/tests/rlbox_glue PUBLIC ${rlbox_SOURCE_DIR}/code/tests/rlbox_glue/lib PUBLIC ${mod_wasm2c_SOURCE_DIR}/wasm2c - PUBLIC ${GLUE_LIB_WASM_DIR} + PUBLIC ${GLUE_LIB_WASM_IMPORTED_DIR} ) target_link_libraries(test_rlbox_glue Catch2::Catch2 ${CMAKE_THREAD_LIBS_INIT} ${CMAKE_DL_LIBS} - glue_lib + glue_lib_imported ) if(UNIX AND NOT (${CMAKE_SYSTEM_NAME} MATCHES "Darwin")) @@ -256,6 +290,28 @@ catch_discover_tests(test_rlbox_glue) #### +add_executable(test_rlbox_glue_exported test/test_wasm2c_sandbox_glue_main.cpp + test/test_wasm2c_sandbox_glue.cpp) +target_include_directories(test_rlbox_glue_exported PUBLIC ${CMAKE_SOURCE_DIR}/include + PUBLIC ${rlbox_SOURCE_DIR}/code/include + PUBLIC ${rlbox_SOURCE_DIR}/code/tests/rlbox_glue + PUBLIC ${rlbox_SOURCE_DIR}/code/tests/rlbox_glue/lib + PUBLIC ${mod_wasm2c_SOURCE_DIR}/wasm2c + PUBLIC ${GLUE_LIB_WASM_EXPORTED_DIR} + ) +target_link_libraries(test_rlbox_glue_exported Catch2::Catch2 + ${CMAKE_THREAD_LIBS_INIT} + ${CMAKE_DL_LIBS} + glue_lib_exported +) + +if(UNIX AND NOT (${CMAKE_SYSTEM_NAME} MATCHES "Darwin")) + target_link_libraries(test_rlbox_glue_exported rt) +endif() +catch_discover_tests(test_rlbox_glue_exported) + +#### + add_executable(test_rlbox_glue_smallheap test/test_wasm2c_sandbox_glue_main.cpp test/test_wasm2c_sandbox_glue_smallheap.cpp) target_include_directories(test_rlbox_glue_smallheap PUBLIC ${CMAKE_SOURCE_DIR}/include @@ -263,12 +319,12 @@ target_include_directories(test_rlbox_glue_smallheap PUBLIC ${CMAKE_SOURCE_DIR}/ PUBLIC ${rlbox_SOURCE_DIR}/code/tests/rlbox_glue PUBLIC ${rlbox_SOURCE_DIR}/code/tests/rlbox_glue/lib PUBLIC ${mod_wasm2c_SOURCE_DIR}/wasm2c - PUBLIC ${GLUE_LIB_WASM_DIR} + PUBLIC ${GLUE_LIB_WASM_IMPORTED_DIR} ) target_link_libraries(test_rlbox_glue_smallheap Catch2::Catch2 ${CMAKE_THREAD_LIBS_INIT} ${CMAKE_DL_LIBS} - glue_lib + glue_lib_imported ) if(UNIX AND NOT (${CMAKE_SYSTEM_NAME} MATCHES "Darwin")) @@ -285,12 +341,12 @@ target_include_directories(test_rlbox_glue_embed PUBLIC ${CMAKE_SOURCE_DIR}/incl PUBLIC ${rlbox_SOURCE_DIR}/code/tests/rlbox_glue PUBLIC ${rlbox_SOURCE_DIR}/code/tests/rlbox_glue/lib PUBLIC ${mod_wasm2c_SOURCE_DIR}/wasm2c - PUBLIC ${GLUE_LIB_WASM_DIR} + PUBLIC ${GLUE_LIB_WASM_IMPORTED_DIR} ) target_link_libraries(test_rlbox_glue_embed Catch2::Catch2 ${CMAKE_THREAD_LIBS_INIT} ${CMAKE_DL_LIBS} - glue_lib + glue_lib_imported ) if(UNIX AND NOT (${CMAKE_SYSTEM_NAME} MATCHES "Darwin")) @@ -302,6 +358,7 @@ catch_discover_tests(test_rlbox_glue_embed) add_custom_target(check COMMAND ${CMAKE_CTEST_COMMAND} -V) add_dependencies(check test_rlbox_glue) +add_dependencies(check test_rlbox_glue_exported) add_dependencies(check test_rlbox_glue_smallheap) add_dependencies(check test_rlbox_glue_embed) diff --git a/include/rlbox_wasm2c_sandbox.hpp b/include/rlbox_wasm2c_sandbox.hpp index b6ed0e2..10f3750 100644 --- a/include/rlbox_wasm2c_sandbox.hpp +++ b/include/rlbox_wasm2c_sandbox.hpp @@ -52,45 +52,60 @@ # endif #endif -#define DEFINE_RLBOX_WASM2C_MODULE_TYPE(modname) \ - struct rlbox_wasm2c_module_type_##modname \ - { \ - using instance_t = w2c_##modname; \ - \ - using create_instance_t = void (*)(instance_t*, \ - struct w2c_env*, \ - struct w2c_wasi__snapshot__preview1*); \ - static constexpr create_instance_t create_instance = \ - &wasm2c_##modname##_instantiate; \ - \ - using free_instance_t = void (*)(instance_t*); \ - static constexpr free_instance_t free_instance = &wasm2c_##modname##_free; \ - \ - using get_func_type_t = wasm_rt_func_type_t (*)(uint32_t, uint32_t, ...); \ - static constexpr get_func_type_t get_func_type = \ - &wasm2c_##modname##_get_func_type; \ - \ - static constexpr const uint64_t* initial_memory_pages = \ - &wasm2c_##modname##_min_env_memory; \ - static constexpr const uint8_t* is_memory_64 = \ - &wasm2c_##modname##_is64_env_memory; \ - static constexpr const uint32_t* initial_func_elements = \ - &wasm2c_##modname##_min_env_0x5F_indirect_function_table; \ - \ - static constexpr const char* prefix = #modname; \ - \ - /* A function that returns the address of the func specified as a \ - * constexpr string */ \ - /* Unfortunately, there is no way to implement the below in C++. */ \ - /* Implement this to fully support multiple static modules. */ \ - /* static constexpr void* dlsym_in_w2c_module(const char* func_name) { */ \ - /* return &w2c_##modname##_%func%; */ \ - /* } */ \ - \ - static constexpr auto malloc_address = &w2c_##modname##_malloc; \ - static constexpr auto free_address = &w2c_##modname##_free; \ +#define DEFINE_RLBOX_WASM2C_MODULE_TYPE(modname) \ + struct rlbox_wasm2c_module_type_##modname \ + { \ + using instance_t = w2c_##modname; \ + \ + using create_instance_imported_t = void (*)(instance_t*, \ + struct w2c_env*, \ + struct w2c_wasi__snapshot__preview1*); \ + using create_instance_exported_t = void (*)(instance_t*, \ + struct w2c_wasi__snapshot__preview1*); \ + static constexpr auto create_instance = \ + &wasm2c_##modname##_instantiate; \ + \ + using free_instance_t = void (*)(instance_t*); \ + static constexpr free_instance_t free_instance = &wasm2c_##modname##_free; \ + \ + using get_func_type_t = wasm_rt_func_type_t (*)(uint32_t, uint32_t, ...); \ + static constexpr get_func_type_t get_func_type = \ + &wasm2c_##modname##_get_func_type; \ + \ + static constexpr const char* prefix = #modname; \ + \ + /* A function that returns the address of the func specified as a \ + * constexpr string */ \ + /* Unfortunately, there is no way to implement the below in C++. */ \ + /* Implement this to fully support multiple static modules. */ \ + /* static constexpr void* dlsym_in_w2c_module(const char* func_name) { */ \ + /* return &w2c_##modname##_%func%; */ \ + /* } */ \ + \ + static constexpr auto malloc_address = &w2c_##modname##_malloc; \ + static constexpr auto free_address = &w2c_##modname##_free; \ + \ + }; \ + extern "C" { \ + /* Declarations for imported memory and tables */ \ + extern const uint64_t wasm2c_##modname##_min_env_memory; \ + extern const uint8_t wasm2c_##modname##_is64_env_memory; \ + extern const uint32_t wasm2c_##modname##_min_env_0x5F_indirect_function_table; \ + /* Declarations for exported memory and tables */ \ + extern wasm_rt_memory_t* w2c_##modname##_memory(w2c_##modname*); \ + extern wasm_rt_funcref_table_t* w2c_##modname##_0x5F_indirect_function_table( \ + w2c_##modname*); \ } +#define DEFINE_RLBOX_WASM2C_IMPORTED_MODULE_ATTRIBS(modname) \ + constexpr const uint64_t* initial_memory_pages = &wasm2c_##modname##_min_env_memory; \ + constexpr const uint8_t* is_memory_64 = &wasm2c_##modname##_is64_env_memory; \ + constexpr const uint32_t* initial_func_elements = &wasm2c_##modname##_min_env_0x5F_indirect_function_table; + +#define DEFINE_RLBOX_WASM2C_EXPORTED_MODULE_ATTRIBS(modname) \ + constexpr const auto get_exported_memory = &w2c_##modname##_memory; \ + constexpr const auto get_exported_table = &w2c_##modname##_0x5F_indirect_function_table; \ + // wasm_module_name module name used when compiling with wasm2c #ifndef RLBOX_WASM2C_MODULE_NAME # error "Expected definition for RLBOX_WASM2C_MODULE_NAME" @@ -100,6 +115,13 @@ #define INVOKE_DEFINE_RLBOX_WASM2C_MODULE_TYPE(modname) \ DEFINE_RLBOX_WASM2C_MODULE_TYPE(modname) +#define INVOKE_DEFINE_RLBOX_WASM2C_IMPORTED_MODULE_ATTRIBS(modname) \ + DEFINE_RLBOX_WASM2C_IMPORTED_MODULE_ATTRIBS(modname) + +#define INVOKE_DEFINE_RLBOX_WASM2C_EXPORTED_MODULE_ATTRIBS(modname) \ + DEFINE_RLBOX_WASM2C_EXPORTED_MODULE_ATTRIBS(modname) + +// Define the base wasm2c module type INVOKE_DEFINE_RLBOX_WASM2C_MODULE_TYPE(RLBOX_WASM2C_MODULE_NAME); // Concat after macro expansion @@ -307,8 +329,14 @@ class rlbox_wasm2c_sandbox struct w2c_env sandbox_memory_env{ 0 }; struct w2c_wasi__snapshot__preview1 wasi_env{ 0 }; bool instance_initialized = false; - wasm_rt_memory_t sandbox_memory_info{ 0 }; - mutable wasm_rt_funcref_table_t sandbox_callback_table{ 0 }; + // Only used if memory and tables are imported + wasm_rt_memory_t local_sandbox_memory_info{ 0 }; + mutable wasm_rt_funcref_table_t local_sandbox_callback_table{ 0 }; + // Pointers to actual memory and table. This points to + // local_sandbox_memory_info and local_sandbox_callback_table if the Wasm + // module imports the memory and table. + wasm_rt_memory_t* sandbox_memory_info{ 0 }; + mutable wasm_rt_funcref_table_t* sandbox_callback_table{ 0 }; uintptr_t heap_base = 0; size_t return_slot_size = 0; T_PointerType return_slot = 0; @@ -468,6 +496,10 @@ class rlbox_wasm2c_sandbox return nullptr; } + using create_instance_t = std::remove_cv_t; + static constexpr bool is_imported_memory_and_table = std::is_same_v; + static constexpr bool is_exported_memory_and_table = std::is_same_v; + public: #define FALLIBLE_DYNAMIC_CHECK(infallible, cond, msg) \ if (infallible) { \ @@ -514,34 +546,54 @@ class rlbox_wasm2c_sandbox infallible, custom_capacity->is_valid, "Invalid capacity"); } - sandbox_memory_info = create_wasm2c_memory( - *RLBOX_WASM_MODULE_TYPE_CURR::initial_memory_pages, custom_capacity); - FALLIBLE_DYNAMIC_CHECK(infallible, - sandbox_memory_info.data != nullptr, - "Could not allocate a heap for the wasm2c sandbox"); + static_assert(is_imported_memory_and_table || is_exported_memory_and_table, + "Wasm modules memories and tables must either be imported or exported"); + + if constexpr (is_imported_memory_and_table) { + sandbox_memory_info = &local_sandbox_memory_info; + sandbox_callback_table = &local_sandbox_callback_table; + + INVOKE_DEFINE_RLBOX_WASM2C_IMPORTED_MODULE_ATTRIBS(RLBOX_WASM2C_MODULE_NAME); + + *sandbox_memory_info = create_wasm2c_memory( + *initial_memory_pages, custom_capacity); + FALLIBLE_DYNAMIC_CHECK(infallible, + sandbox_memory_info->data != nullptr, + "Could not allocate a heap for the wasm2c sandbox"); + + FALLIBLE_DYNAMIC_CHECK(infallible, + *is_memory_64 == 0, + "Does not support Wasm with memory64"); + + const uint32_t max_table_size = 0xffffffffu; /* this means unlimited */ + wasm_rt_allocate_funcref_table( + sandbox_callback_table, + *initial_func_elements, + max_table_size); - FALLIBLE_DYNAMIC_CHECK(infallible, - *RLBOX_WASM_MODULE_TYPE_CURR::is_memory_64 == 0, - "Does not support Wasm with memory64"); + sandbox_memory_env.sandbox_memory_info = sandbox_memory_info; + sandbox_memory_env.sandbox_callback_table = sandbox_callback_table; + wasi_env.instance_memory = sandbox_memory_info; - const uint32_t max_table_size = 0xffffffffu; /* this means unlimited */ - wasm_rt_allocate_funcref_table( - &sandbox_callback_table, - *RLBOX_WASM_MODULE_TYPE_CURR::initial_func_elements, - max_table_size); + auto create_instance_func = (RLBOX_WASM_MODULE_TYPE_CURR::create_instance_imported_t) RLBOX_WASM_MODULE_TYPE_CURR::create_instance; + create_instance_func(&wasm2c_instance, &sandbox_memory_env, &wasi_env); + } else { + INVOKE_DEFINE_RLBOX_WASM2C_EXPORTED_MODULE_ATTRIBS(RLBOX_WASM2C_MODULE_NAME); + sandbox_memory_info = get_exported_memory(&wasm2c_instance); + sandbox_callback_table = get_exported_table(&wasm2c_instance); + + wasi_env.instance_memory = sandbox_memory_info; - sandbox_memory_env.sandbox_memory_info = &sandbox_memory_info; - sandbox_memory_env.sandbox_callback_table = &sandbox_callback_table; - wasi_env.instance_memory = &sandbox_memory_info; - RLBOX_WASM_MODULE_TYPE_CURR::create_instance( - &wasm2c_instance, &sandbox_memory_env, &wasi_env); + auto create_instance_func = (RLBOX_WASM_MODULE_TYPE_CURR::create_instance_exported_t) RLBOX_WASM_MODULE_TYPE_CURR::create_instance; + create_instance_func(&wasm2c_instance, &wasi_env); + } heap_base = reinterpret_cast(impl_get_memory_location()); - if constexpr (sizeof(uintptr_t) != sizeof(uint32_t)) { - // On larger platforms, check that the heap is aligned to the pointer size - // i.e. 32-bit pointer => aligned to 4GB. The implementations of - // impl_get_unsandboxed_pointer_no_ctx and + if constexpr (is_imported_memory_and_table && sizeof(uintptr_t) != sizeof(uint32_t)) { + // On larger platforms, with imported memory check that the heap is + // aligned to the pointer size i.e. 32-bit pointer => aligned to 4GB. The + // implementations of impl_get_unsandboxed_pointer_no_ctx and // impl_get_sandboxed_pointer_no_ctx below rely on this. uintptr_t heap_offset_mask = std::numeric_limits::max(); FALLIBLE_DYNAMIC_CHECK(infallible, @@ -567,8 +619,10 @@ class rlbox_wasm2c_sandbox RLBOX_WASM_MODULE_TYPE_CURR::free_instance(&wasm2c_instance); } - destroy_wasm2c_memory(&sandbox_memory_info); - wasm_rt_free_funcref_table(&sandbox_callback_table); + if constexpr (is_imported_memory_and_table) { + destroy_wasm2c_memory(sandbox_memory_info); + wasm_rt_free_funcref_table(sandbox_callback_table); + } minwasi_cleanup_instance(&wasi_env); } @@ -608,17 +662,19 @@ class rlbox_wasm2c_sandbox reinterpret_cast(const_cast(p)); func_val.module_instance = &wasm2c_instance; - sandbox_callback_table.data[slot_number] = func_val; + sandbox_callback_table->data[slot_number] = func_val; internal_callbacks[p] = slot_number; slot_assignments[slot_number] = p; } return static_cast(slot_number); } else { - if constexpr (sizeof(uintptr_t) == sizeof(uint32_t)) { + // if imported memory on a 64-bit platform, we can assume that the heap is + // aligned and let integer truncation handle the conversion + if constexpr (is_imported_memory_and_table && sizeof(uintptr_t) != sizeof(uint32_t)) { + return static_cast(reinterpret_cast(p)); + } else { return static_cast(reinterpret_cast(p) - heap_base); - } else { - return static_cast(reinterpret_cast(p)); } } } @@ -630,11 +686,9 @@ class rlbox_wasm2c_sandbox rlbox_wasm2c_sandbox* (*expensive_sandbox_finder)( const void* example_unsandboxed_ptr)) { - // on 32-bit platforms we don't assume the heap is aligned - if constexpr (sizeof(uintptr_t) == sizeof(uint32_t)) { - auto sandbox = expensive_sandbox_finder(example_unsandboxed_ptr); - return sandbox->template impl_get_unsandboxed_pointer(p); - } else { + // if imported memory on a 64-bit platform, we can assume that the heap is + // aligned + if constexpr (is_imported_memory_and_table && sizeof(uintptr_t) != sizeof(uint32_t)) { if constexpr (std::is_function_v>) { // swizzling function pointers needs access to the function pointer // tables and thus cannot be done without context @@ -650,6 +704,9 @@ class rlbox_wasm2c_sandbox uintptr_t ret = computed_heap_base | p; return reinterpret_cast(ret); } + } else { + auto sandbox = expensive_sandbox_finder(example_unsandboxed_ptr); + return sandbox->template impl_get_unsandboxed_pointer(p); } } @@ -660,11 +717,9 @@ class rlbox_wasm2c_sandbox rlbox_wasm2c_sandbox* (*expensive_sandbox_finder)( const void* example_unsandboxed_ptr)) { - // on 32-bit platforms we don't assume the heap is aligned - if constexpr (sizeof(uintptr_t) == sizeof(uint32_t)) { - auto sandbox = expensive_sandbox_finder(example_unsandboxed_ptr); - return sandbox->template impl_get_sandboxed_pointer(p); - } else { + // if imported memory on a 64-bit platform, we can assume that the heap is + // aligned + if constexpr (is_imported_memory_and_table && sizeof(uintptr_t) != sizeof(uint32_t)) { if constexpr (std::is_function_v>) { // swizzling function pointers needs access to the function pointer // tables and thus cannot be done without context @@ -677,6 +732,9 @@ class rlbox_wasm2c_sandbox std::numeric_limits::max(); return static_cast(ret); } + } else { + auto sandbox = expensive_sandbox_finder(example_unsandboxed_ptr); + return sandbox->template impl_get_sandboxed_pointer(p); } } @@ -700,11 +758,11 @@ class rlbox_wasm2c_sandbox return !(impl_is_pointer_in_sandbox_memory(p)); } - inline size_t impl_get_total_memory() { return sandbox_memory_info.size; } + inline size_t impl_get_total_memory() { return sandbox_memory_info->size; } inline void* impl_get_memory_location() const { - return sandbox_memory_info.data; + return sandbox_memory_info->data; } template @@ -846,10 +904,10 @@ class rlbox_wasm2c_sandbox return ret; } - const uint32_t curr_size = sandbox_callback_table.size; + const uint32_t curr_size = sandbox_callback_table->size; detail::dynamic_check( - curr_size < sandbox_callback_table.max_size, + curr_size < sandbox_callback_table->max_size, "Could not find an empty row in Wasm instance table. This would " "happen if you have registered too many callbacks, or unsandboxed " "too many function pointers."); @@ -857,7 +915,7 @@ class rlbox_wasm2c_sandbox wasm_rt_funcref_t func_val{ 0 }; // on success, this returns the previous number of elements in the table const uint32_t ret = - wasm_rt_grow_funcref_table(&sandbox_callback_table, 1, func_val); + wasm_rt_grow_funcref_table(sandbox_callback_table, 1, func_val); detail::dynamic_check( ret != 0 && ret != (uint32_t)-1, @@ -917,7 +975,7 @@ class rlbox_wasm2c_sandbox func_val.module_instance = &wasm2c_instance; const uint32_t slot_number = new_callback_slot(); - sandbox_callback_table.data[slot_number] = func_val; + sandbox_callback_table->data[slot_number] = func_val; callback_unique_keys[found_loc] = key; callbacks[found_loc] = callback; @@ -950,7 +1008,7 @@ class rlbox_wasm2c_sandbox if (callback_unique_keys[i] == key) { const uint32_t slot_number = callback_slot_assignment[i]; wasm_rt_funcref_t func_val{ 0 }; - sandbox_callback_table.data[slot_number] = func_val; + sandbox_callback_table->data[slot_number] = func_val; callback_unique_keys[i] = nullptr; callbacks[i] = nullptr;