Răsfoiți Sursa

Validate func type in aot loader (#3535)

Fix issue reported by Oss-fuzz test (#69629).
liang.he 1 an în urmă
părinte
comite
c19bc95391

+ 6 - 0
core/iwasm/aot/aot_loader.c

@@ -1684,6 +1684,9 @@ load_types(const uint8 **p_buf, const uint8 *buf_end, AOTModule *module,
 
             func_type->ref_type_map_count = ref_type_map_count;
 
+            if (!is_valid_func_type(func_type))
+                goto fail;
+
             param_cell_num = wasm_get_cell_num(func_type->types, param_count);
             ret_cell_num =
                 wasm_get_cell_num(func_type->types + param_count, result_count);
@@ -1988,6 +1991,9 @@ load_types(const uint8 **p_buf, const uint8 *buf_end, AOTModule *module,
         func_types[i]->result_count = (uint16)result_count;
         read_byte_array(buf, buf_end, func_types[i]->types, (uint32)size1);
 
+        if (!is_valid_func_type(func_types[i]))
+            goto fail;
+
         param_cell_num = wasm_get_cell_num(func_types[i]->types, param_count);
         ret_cell_num =
             wasm_get_cell_num(func_types[i]->types + param_count, result_count);

+ 41 - 1
core/iwasm/common/wasm_loader_common.c

@@ -4,7 +4,9 @@
  */
 #include "wasm_loader_common.h"
 #include "bh_log.h"
-#include "../interpreter/wasm.h"
+#if WASM_ENABLE_GC != 0
+#include "../common/gc/gc_type.h"
+#endif
 
 static void
 set_error_buf(char *error_buf, uint32 error_buf_size, const char *string,
@@ -56,3 +58,41 @@ wasm_memory_check_flags(const uint8 mem_flag, char *error_buf,
 
     return true;
 }
+
+/*
+ * compare with a bigger type set in `wasm_value_type_size_internal()`,
+ * this function will only cover global value type, function's param
+ * value type and function's result value type.
+ *
+ * please feel free to add more if there are more requirements
+ */
+bool
+is_valid_value_type(uint8 type)
+{
+    if (/* I32/I64/F32/F64, 0x7C to 0x7F */
+        (type >= VALUE_TYPE_F64 && type <= VALUE_TYPE_I32)
+#if WASM_ENABLE_GC != 0
+        /* reference types, 0x65 to 0x70 */
+        || wasm_is_type_reftype(type)
+#elif WASM_ENABLE_REF_TYPES != 0
+        || (type == VALUE_TYPE_FUNCREF || type == VALUE_TYPE_EXTERNREF)
+#endif
+#if WASM_ENABLE_SIMD != 0
+        || type == VALUE_TYPE_V128 /* 0x7B */
+#endif
+    )
+        return true;
+    return false;
+}
+
+bool
+is_valid_func_type(const WASMFuncType *func_type)
+{
+    unsigned i;
+    for (i = 0; i < func_type->param_count + func_type->result_count; i++) {
+        if (!is_valid_value_type(func_type->types[i]))
+            return false;
+    }
+
+    return true;
+}

+ 7 - 0
core/iwasm/common/wasm_loader_common.h

@@ -7,6 +7,7 @@
 #define _WASM_LOADER_COMMON_H
 
 #include "platform_common.h"
+#include "../interpreter/wasm.h"
 
 #ifdef __cplusplus
 extern "C" {
@@ -16,6 +17,12 @@ bool
 wasm_memory_check_flags(const uint8 mem_flag, char *error_buf,
                         uint32 error_buf_size, bool is_aot);
 
+bool
+is_valid_value_type(uint8 value_tpye);
+
+bool
+is_valid_func_type(const WASMFuncType *func_type);
+
 #ifdef __cplusplus
 }
 #endif

+ 8 - 28
core/iwasm/interpreter/wasm_loader.c

@@ -323,27 +323,6 @@ is_64bit_type(uint8 type)
     return false;
 }
 
-static bool
-is_value_type(uint8 type)
-{
-    if (/* I32/I64/F32/F64, 0x7C to 0x7F */
-        (type >= VALUE_TYPE_F64 && type <= VALUE_TYPE_I32)
-#if WASM_ENABLE_GC != 0
-        /* reference types, 0x65 to 0x70 */
-        || wasm_is_type_reftype(type)
-#elif WASM_ENABLE_REF_TYPES != 0
-        || (type == VALUE_TYPE_FUNCREF || type == VALUE_TYPE_EXTERNREF)
-#endif
-#if WASM_ENABLE_SIMD != 0
-#if (WASM_ENABLE_WAMR_COMPILER != 0) || (WASM_ENABLE_JIT != 0)
-        || type == VALUE_TYPE_V128 /* 0x7B */
-#endif
-#endif
-    )
-        return true;
-    return false;
-}
-
 #if WASM_ENABLE_GC != 0
 static bool
 is_packed_type(uint8 type)
@@ -355,7 +334,8 @@ is_packed_type(uint8 type)
 static bool
 is_byte_a_type(uint8 type)
 {
-    return (is_value_type(type) || (type == VALUE_TYPE_VOID)) ? true : false;
+    return (is_valid_value_type(type) || (type == VALUE_TYPE_VOID)) ? true
+                                                                    : false;
 }
 
 #if WASM_ENABLE_SIMD != 0
@@ -1462,7 +1442,7 @@ resolve_value_type(const uint8 **p_buf, const uint8 *buf_end,
     }
     else {
         /* type which can be represented by one byte */
-        if (!is_value_type(type)
+        if (!is_valid_value_type(type)
             && !(allow_packed_type && is_packed_type(type))) {
             set_error_buf(error_buf, error_buf_size, "type mismatch");
             return false;
@@ -1972,7 +1952,7 @@ load_type_section(const uint8 *buf, const uint8 *buf_end, WASMModule *module,
                 type->types[param_count + j] = read_uint8(p);
             }
             for (j = 0; j < param_count + result_count; j++) {
-                if (!is_value_type(type->types[j])) {
+                if (!is_valid_value_type(type->types[j])) {
                     set_error_buf(error_buf, error_buf_size,
                                   "unknown value type");
                     return false;
@@ -3061,7 +3041,7 @@ load_global_import(const uint8 **p_buf, const uint8 *buf_end,
     CHECK_BUF(p, p_end, 2);
     /* global type */
     declare_type = read_uint8(p);
-    if (!is_value_type(declare_type)) {
+    if (!is_valid_value_type(declare_type)) {
         set_error_buf(error_buf, error_buf_size, "type mismatch");
         return false;
     }
@@ -3773,7 +3753,7 @@ load_function_section(const uint8 *buf, const uint8 *buf_end,
                 CHECK_BUF(p_code, buf_code_end, 1);
                 /* 0x7F/0x7E/0x7D/0x7C */
                 type = read_uint8(p_code);
-                if (!is_value_type(type)) {
+                if (!is_valid_value_type(type)) {
                     if (type == VALUE_TYPE_V128)
                         set_error_buf(error_buf, error_buf_size,
                                       "v128 value type requires simd feature");
@@ -4048,7 +4028,7 @@ load_global_section(const uint8 *buf, const uint8 *buf_end, WASMModule *module,
             CHECK_BUF(p, p_end, 2);
             /* global type */
             global->type.val_type = read_uint8(p);
-            if (!is_value_type(global->type.val_type)) {
+            if (!is_valid_value_type(global->type.val_type)) {
                 set_error_buf(error_buf, error_buf_size, "type mismatch");
                 return false;
             }
@@ -12322,7 +12302,7 @@ re_scan:
 #if WASM_ENABLE_GC == 0
                 CHECK_BUF(p, p_end, 1);
                 type = read_uint8(p);
-                if (!is_value_type(type)) {
+                if (!is_valid_value_type(type)) {
                     set_error_buf(error_buf, error_buf_size,
                                   "unknown value type");
                     goto fail;

+ 4 - 17
core/iwasm/interpreter/wasm_mini_loader.c

@@ -88,23 +88,10 @@ is_64bit_type(uint8 type)
     return false;
 }
 
-static bool
-is_value_type(uint8 type)
-{
-    if (type == VALUE_TYPE_I32 || type == VALUE_TYPE_I64
-        || type == VALUE_TYPE_F32 || type == VALUE_TYPE_F64
-#if WASM_ENABLE_REF_TYPES != 0
-        || type == VALUE_TYPE_FUNCREF || type == VALUE_TYPE_EXTERNREF
-#endif
-    )
-        return true;
-    return false;
-}
-
 static bool
 is_byte_a_type(uint8 type)
 {
-    return is_value_type(type) || (type == VALUE_TYPE_VOID);
+    return is_valid_value_type(type) || (type == VALUE_TYPE_VOID);
 }
 
 static void
@@ -581,7 +568,7 @@ load_type_section(const uint8 *buf, const uint8 *buf_end, WASMModule *module,
                 type->types[param_count + j] = read_uint8(p);
             }
             for (j = 0; j < param_count + result_count; j++) {
-                bh_assert(is_value_type(type->types[j]));
+                bh_assert(is_valid_value_type(type->types[j]));
             }
 
             param_cell_num = wasm_get_cell_num(type->types, param_count);
@@ -1228,7 +1215,7 @@ load_function_section(const uint8 *buf, const uint8 *buf_end,
                 CHECK_BUF(p_code, buf_code_end, 1);
                 /* 0x7F/0x7E/0x7D/0x7C */
                 type = read_uint8(p_code);
-                bh_assert(is_value_type(type));
+                bh_assert(is_valid_value_type(type));
                 for (k = 0; k < sub_local_count; k++) {
                     func->local_types[local_type_index++] = type;
                 }
@@ -6829,7 +6816,7 @@ re_scan:
 
                 CHECK_BUF(p, p_end, 1);
                 ref_type = read_uint8(p);
-                if (!is_value_type(ref_type)) {
+                if (!is_valid_value_type(ref_type)) {
                     set_error_buf(error_buf, error_buf_size,
                                   "unknown value type");
                     goto fail;