Selaa lähdekoodia

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.
liang.he 7 kuukautta sitten
vanhempi
sitoutus
7f9e49213e

+ 1 - 1
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;

+ 42 - 16
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;
                 }
 

+ 6 - 1
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)

+ 1 - 1
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

+ 1 - 1
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

+ 1 - 0
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))