From 7f9e49213e2dd1839cb85c04e5a1dbf6fc6b4475 Mon Sep 17 00:00:00 2001 From: "liang.he" Date: Wed, 28 May 2025 20:29:09 +0800 Subject: [PATCH] Enhance type checking for function types in loader and improve error handling (#4294) Especially when GC is enabled, a valid item of `module->types` needs additional checks before casting to WASMFuncType. Also, avoid overflowing if reftype_map_count is 0. Additionally, correctly set IN_OSS_FUZZ based on CFLAGS_ENV for sanitizer configuration. Update ASan and UBSan messages for clarity in non-oss-fuzz environments. --- core/iwasm/interpreter/wasm.h | 2 +- core/iwasm/interpreter/wasm_loader.c | 58 ++++++++++++++----- tests/fuzz/wasm-mutator-fuzz/CMakeLists.txt | 7 ++- .../aot-compiler/CMakeLists.txt | 2 +- .../wasm-mutator/CMakeLists.txt | 2 +- wamr-compiler/CMakeLists.txt | 1 + 6 files changed, 52 insertions(+), 20 deletions(-) diff --git a/core/iwasm/interpreter/wasm.h b/core/iwasm/interpreter/wasm.h index 6023b0702..ddc0b15b4 100644 --- a/core/iwasm/interpreter/wasm.h +++ b/core/iwasm/interpreter/wasm.h @@ -1243,7 +1243,7 @@ wasm_value_type_size_internal(uint8 value_type, uint8 pointer_size) return sizeof(int16); #endif else { - bh_assert(0); + bh_assert(0 && "Unknown value type. It should be handled ahead."); } #if WASM_ENABLE_GC == 0 (void)pointer_size; diff --git a/core/iwasm/interpreter/wasm_loader.c b/core/iwasm/interpreter/wasm_loader.c index db9afb0f2..6ef1ff5bf 100644 --- a/core/iwasm/interpreter/wasm_loader.c +++ b/core/iwasm/interpreter/wasm_loader.c @@ -379,7 +379,6 @@ memory_realloc(void *mem_old, uint32 size_old, uint32 size_new, char *error_buf, mem = mem_new; \ } while (0) -#if WASM_ENABLE_GC != 0 static bool check_type_index(const WASMModule *module, uint32 type_count, uint32 type_index, char *error_buf, uint32 error_buf_size) @@ -392,6 +391,7 @@ check_type_index(const WASMModule *module, uint32 type_count, uint32 type_index, return true; } +#if WASM_ENABLE_GC != 0 static bool check_array_type(const WASMModule *module, uint32 type_index, char *error_buf, uint32 error_buf_size) @@ -409,6 +409,29 @@ check_array_type(const WASMModule *module, uint32 type_index, char *error_buf, } #endif +/* + * if no GC is enabled, an valid type is always a function type. + * but if GC is enabled, we need to check the type flag + */ +static bool +check_function_type(const WASMModule *module, uint32 type_index, + char *error_buf, uint32 error_buf_size) +{ + if (!check_type_index(module, module->type_count, type_index, error_buf, + error_buf_size)) { + return false; + } + +#if WASM_ENABLE_GC != 0 + if (module->types[type_index]->type_flag != WASM_TYPE_FUNC) { + set_error_buf(error_buf, error_buf_size, "unknown function type"); + return false; + } +#endif + + return true; +} + static bool check_function_index(const WASMModule *module, uint32 function_index, char *error_buf, uint32 error_buf_size) @@ -2479,8 +2502,8 @@ load_function_import(const uint8 **p_buf, const uint8 *buf_end, read_leb_uint32(p, p_end, declare_type_index); *p_buf = p; - if (declare_type_index >= parent_module->type_count) { - set_error_buf(error_buf, error_buf_size, "unknown type"); + if (!check_function_type(parent_module, declare_type_index, error_buf, + error_buf_size)) { return false; } @@ -2893,8 +2916,8 @@ load_tag_import(const uint8 **p_buf, const uint8 *buf_end, /* get type */ read_leb_uint32(p, p_end, declare_type_index); /* compare against module->types */ - if (declare_type_index >= parent_module->type_count) { - set_error_buf(error_buf, error_buf_size, "unknown tag type"); + if (!check_function_type(parent_module, declare_type_index, error_buf, + error_buf_size)) { goto fail; } @@ -3563,8 +3586,9 @@ load_function_section(const uint8 *buf, const uint8 *buf_end, for (i = 0; i < func_count; i++) { /* Resolve function type */ read_leb_uint32(p, p_end, type_index); - if (type_index >= module->type_count) { - set_error_buf(error_buf, error_buf_size, "unknown type"); + + if (!check_function_type(module, type_index, error_buf, + error_buf_size)) { return false; } @@ -4970,8 +4994,8 @@ load_tag_section(const uint8 *buf, const uint8 *buf_end, const uint8 *buf_code, /* get type */ read_leb_uint32(p, p_end, tag_type); /* compare against module->types */ - if (tag_type >= module->type_count) { - set_error_buf(error_buf, error_buf_size, "unknown type"); + if (!check_function_type(module, tag_type, error_buf, + error_buf_size)) { return false; } @@ -10477,7 +10501,7 @@ wasm_loader_check_br(WASMLoaderContext *loader_ctx, uint32 depth, uint8 opcode, * match block type. */ if (cur_block->is_stack_polymorphic) { #if WASM_ENABLE_GC != 0 - int32 j = reftype_map_count - 1; + int32 j = (int32)reftype_map_count - 1; #endif for (i = (int32)arity - 1; i >= 0; i--) { #if WASM_ENABLE_GC != 0 @@ -10780,7 +10804,7 @@ check_block_stack(WASMLoaderContext *loader_ctx, BranchBlock *block, * match block type. */ if (block->is_stack_polymorphic) { #if WASM_ENABLE_GC != 0 - int32 j = return_reftype_map_count - 1; + int32 j = (int32)return_reftype_map_count - 1; #endif for (i = (int32)return_count - 1; i >= 0; i--) { #if WASM_ENABLE_GC != 0 @@ -11549,15 +11573,17 @@ re_scan: } else { int32 type_index; + /* Resolve the leb128 encoded type index as block type */ p--; p_org = p - 1; pb_read_leb_int32(p, p_end, type_index); - if ((uint32)type_index >= module->type_count) { - set_error_buf(error_buf, error_buf_size, - "unknown type"); + + if (!check_function_type(module, type_index, error_buf, + error_buf_size)) { goto fail; } + block_type.is_value_type = false; block_type.u.type = (WASMFuncType *)module->types[type_index]; @@ -12607,8 +12633,8 @@ re_scan: /* skip elem idx */ POP_TBL_ELEM_IDX(); - if (type_idx >= module->type_count) { - set_error_buf(error_buf, error_buf_size, "unknown type"); + if (!check_function_type(module, type_idx, error_buf, + error_buf_size)) { goto fail; } diff --git a/tests/fuzz/wasm-mutator-fuzz/CMakeLists.txt b/tests/fuzz/wasm-mutator-fuzz/CMakeLists.txt index a6ff12d64..500ad8fe3 100644 --- a/tests/fuzz/wasm-mutator-fuzz/CMakeLists.txt +++ b/tests/fuzz/wasm-mutator-fuzz/CMakeLists.txt @@ -181,7 +181,12 @@ add_link_options(-fsanitize=fuzzer -fno-sanitize=vptr) # Enable sanitizers if not in oss-fuzz environment set(CFLAGS_ENV $ENV{CFLAGS}) -string(FIND "${CFLAGS_ENV}" "-DFUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION" IN_OSS_FUZZ) +string(FIND "${CFLAGS_ENV}" "-DFUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION" FUZZ_POS) +if (FUZZ_POS GREATER -1) + set(IN_OSS_FUZZ 1) +else() + set(IN_OSS_FUZZ 0) +endif() add_subdirectory(aot-compiler) add_subdirectory(wasm-mutator) diff --git a/tests/fuzz/wasm-mutator-fuzz/aot-compiler/CMakeLists.txt b/tests/fuzz/wasm-mutator-fuzz/aot-compiler/CMakeLists.txt index a613ea4e2..5ca33906a 100644 --- a/tests/fuzz/wasm-mutator-fuzz/aot-compiler/CMakeLists.txt +++ b/tests/fuzz/wasm-mutator-fuzz/aot-compiler/CMakeLists.txt @@ -68,7 +68,7 @@ target_link_directories(aotclib PUBLIC ${LLVM_LIBRARY_DIR}) target_link_libraries(aotclib PUBLIC ${REQUIRED_LLVM_LIBS}) if(NOT IN_OSS_FUZZ) - message(STATUS "Enable ASan and UBSan in non-oss-fuzz environment") + message(STATUS "Enable ASan and UBSan in non-oss-fuzz environment for aotclib") target_compile_options(aotclib PUBLIC -fprofile-instr-generate -fcoverage-mapping -fno-sanitize-recover=all diff --git a/tests/fuzz/wasm-mutator-fuzz/wasm-mutator/CMakeLists.txt b/tests/fuzz/wasm-mutator-fuzz/wasm-mutator/CMakeLists.txt index 4d6ae0fa4..b501baecf 100644 --- a/tests/fuzz/wasm-mutator-fuzz/wasm-mutator/CMakeLists.txt +++ b/tests/fuzz/wasm-mutator-fuzz/wasm-mutator/CMakeLists.txt @@ -58,7 +58,7 @@ add_executable(wasm_mutator_fuzz wasm_mutator_fuzz.cc) target_link_libraries(wasm_mutator_fuzz PRIVATE vmlib m) if(NOT IN_OSS_FUZZ) - message(STATUS "Enable ASan and UBSan in non-oss-fuzz environment") + message(STATUS "Enable ASan and UBSan in non-oss-fuzz environment for vmlib") target_compile_options(vmlib PUBLIC -fprofile-instr-generate -fcoverage-mapping -fno-sanitize-recover=all diff --git a/wamr-compiler/CMakeLists.txt b/wamr-compiler/CMakeLists.txt index bbe83cc64..0ce647394 100644 --- a/wamr-compiler/CMakeLists.txt +++ b/wamr-compiler/CMakeLists.txt @@ -315,6 +315,7 @@ if (WAMR_BUILD_LIB_WASI_THREADS EQUAL 1) include (${IWASM_DIR}/libraries/lib-wasi-threads/lib_wasi_threads.cmake) endif () +#TODO: sync up WAMR_BUILD_SANITIZER in config_common.cmake # set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wconversion -Wsign-conversion") if (WAMR_BUILD_TARGET MATCHES "X86_.*" OR WAMR_BUILD_TARGET STREQUAL "AMD_64") if (NOT (CMAKE_C_COMPILER MATCHES ".*clang.*" OR CMAKE_C_COMPILER_ID MATCHES ".*Clang" OR MSVC))