Browse Source

Fix several issues reported by oss-fuzz (#3526)

- possible integer overflow in adjust_table_max_size:
  unsigned integer overflow: 2684354559 * 2 cannot be represented in type 'uint32'
- limit max memory size in wasm_runtime_malloc
- add more checks in aot loader
- adjust compilation options
liang.he 1 year ago
parent
commit
40c41d5110

+ 2 - 4
core/config.h

@@ -667,13 +667,11 @@
 #define WASM_ENABLE_FUZZ_TEST 0
 #endif
 
-#ifndef WASM_MEM_ALLOC_MAX_SIZE
 #if WASM_ENABLE_FUZZ_TEST != 0
+#ifndef WASM_MEM_ALLOC_MAX_SIZE
 /* In oss-fuzz, the maximum RAM is ~2.5G */
 #define WASM_MEM_ALLOC_MAX_SIZE (2U * 1024 * 1024 * 1024)
-#else
-#define WASM_MEM_ALLOC_MAX_SIZE UINT32_MAX
-#endif
 #endif
+#endif /* WASM_ENABLE_FUZZ_TEST != 0 */
 
 #endif /* end of _CONFIG_H_ */

+ 9 - 1
core/iwasm/aot/aot_loader.c

@@ -367,6 +367,8 @@ get_aot_file_target(AOTTargetInfo *target_info, char *target_buf,
             break;
         case E_MACHINE_ARM:
         case E_MACHINE_AARCH64:
+            /* TODO: this will make following `strncmp()` ~L392 unnecessary.
+             * Use const strings here */
             machine_type = target_info->arch;
             break;
         case E_MACHINE_MIPS:
@@ -501,6 +503,11 @@ load_target_info_section(const uint8 *buf, const uint8 *buf_end,
     read_uint64(p, p_end, target_info.reserved);
     read_byte_array(p, p_end, target_info.arch, sizeof(target_info.arch));
 
+    if (target_info.arch[sizeof(target_info.arch) - 1] != '\0') {
+        set_error_buf(error_buf, error_buf_size, "invalid arch string");
+        return false;
+    }
+
     if (p != buf_end) {
         set_error_buf(error_buf, error_buf_size, "invalid section size");
         return false;
@@ -1033,7 +1040,8 @@ load_memory_info(const uint8 **p_buf, const uint8 *buf_end, AOTModule *module,
 
     read_uint32(buf, buf_end, module->import_memory_count);
     /* We don't support import_memory_count > 0 currently */
-    bh_assert(module->import_memory_count == 0);
+    if (module->import_memory_count > 0)
+        return false;
 
     read_uint32(buf, buf_end, module->memory_count);
     total_size = sizeof(AOTMemory) * (uint64)module->memory_count;

+ 7 - 0
core/iwasm/common/wasm_memory.c

@@ -284,6 +284,13 @@ wasm_runtime_malloc(unsigned int size)
 #endif
     }
 
+#if WASM_ENABLE_FUZZ_TEST != 0
+    if (size >= WASM_MEM_ALLOC_MAX_SIZE) {
+        LOG_WARNING("warning: wasm_runtime_malloc with too large size\n");
+        return NULL;
+    }
+#endif
+
     return wasm_runtime_malloc_internal(size);
 }
 

+ 10 - 5
core/iwasm/interpreter/wasm_loader.c

@@ -380,8 +380,7 @@ loader_malloc(uint64 size, char *error_buf, uint32 error_buf_size)
 {
     void *mem;
 
-    if (size >= WASM_MEM_ALLOC_MAX_SIZE
-        || !(mem = wasm_runtime_malloc((uint32)size))) {
+    if (size >= UINT32_MAX || !(mem = wasm_runtime_malloc((uint32)size))) {
         set_error_buf(error_buf, error_buf_size, "allocate memory failed");
         return NULL;
     }
@@ -2255,9 +2254,15 @@ fail:
 static void
 adjust_table_max_size(uint32 init_size, uint32 max_size_flag, uint32 *max_size)
 {
-    uint32 default_max_size = init_size * 2 > WASM_TABLE_MAX_SIZE
-                                  ? init_size * 2
-                                  : WASM_TABLE_MAX_SIZE;
+    uint32 default_max_size;
+
+    if (UINT32_MAX / 2 > init_size)
+        default_max_size = init_size * 2;
+    else
+        default_max_size = UINT32_MAX;
+
+    if (default_max_size < WASM_TABLE_MAX_SIZE)
+        default_max_size = WASM_TABLE_MAX_SIZE;
 
     if (max_size_flag) {
         /* module defines the table limitation */

+ 12 - 1
tests/fuzz/wasm-mutator-fuzz/CMakeLists.txt

@@ -131,9 +131,20 @@ string(FIND "${CFLAGS_ENV}" "-DFUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION" IN_OSS_
 if (IN_OSS_FUZZ EQUAL -1)
   message("[ceith]:Enable ASan and UBSan in non-oss-fuzz environment")
   add_compile_options(
-    -fsanitize=signed-integer-overflow
     -fprofile-instr-generate -fcoverage-mapping
+    -fno-sanitize-recover=all
     -fsanitize=address,undefined
+    # reference: https://clang.llvm.org/docs/UndefinedBehaviorSanitizer.html
+    # -fsanitize=undefined: All of the checks listed above other than float-divide-by-zero,
+    #     unsigned-integer-overflow, implicit-conversion, local-bounds and
+    #     the nullability-* group of checks.
+    #
+    # for now, we disable below from UBSan
+    # -alignment
+    # -implicit-conversion
+    #
+    -fsanitize=float-divide-by-zero,unsigned-integer-overflow,local-bounds,nullability
+    -fno-sanitize=alignment
   )
   add_link_options(-fsanitize=address -fprofile-instr-generate)
 endif ()