Bladeren bron

Enhance wasm loader checks for opcode br_table (#3352)

Fix the integer overflow issue when checking target branch depth in opcode
br_table, and fix is_32bit_type not check VALUE_TYPE_ANY issue, which may
cause wasm_loader_push_frame_offset push extra unneeded offset.
Wenyong Huang 1 jaar geleden
bovenliggende
commit
e44465d259
2 gewijzigde bestanden met toevoegingen van 34 en 27 verwijderingen
  1. 13 16
      core/iwasm/interpreter/wasm_loader.c
  2. 21 11
      core/iwasm/interpreter/wasm_mini_loader.c

+ 13 - 16
core/iwasm/interpreter/wasm_loader.c

@@ -293,7 +293,10 @@ type2str(uint8 type)
 static bool
 is_32bit_type(uint8 type)
 {
-    if (type == VALUE_TYPE_I32 || type == VALUE_TYPE_F32
+    if (type == VALUE_TYPE_I32
+        || type == VALUE_TYPE_F32
+        /* the operand stack is in polymorphic state */
+        || type == VALUE_TYPE_ANY
 #if WASM_ENABLE_GC != 0
         || (sizeof(uintptr_t) == 4 && wasm_is_type_reftype(type))
 #elif WASM_ENABLE_REF_TYPES != 0
@@ -11533,16 +11536,17 @@ re_scan:
 #endif
                 POP_I32();
 
-                /* Get the default depth and check it */
+                /* Get each depth and check it */
                 p_org = p;
                 for (i = 0; i <= count; i++) {
                     read_leb_uint32(p, p_end, depth);
-                }
-                if (loader_ctx->csp_num < depth + 1) {
-                    set_error_buf(error_buf, error_buf_size,
-                                  "unknown label, "
-                                  "unexpected end of section or function");
-                    goto fail;
+                    bh_assert(loader_ctx->csp_num > 0);
+                    if (loader_ctx->csp_num - 1 < depth) {
+                        set_error_buf(error_buf, error_buf_size,
+                                      "unknown label, "
+                                      "unexpected end of section or function");
+                        goto fail;
+                    }
                 }
                 p = p_org;
 
@@ -11558,12 +11562,6 @@ re_scan:
                 for (i = 0; i <= count; i++) {
                     p_org = p;
                     read_leb_uint32(p, p_end, depth);
-                    if (loader_ctx->csp_num < depth + 1) {
-                        set_error_buf(error_buf, error_buf_size,
-                                      "unknown label, "
-                                      "unexpected end of section or function");
-                        goto fail;
-                    }
                     p = p_org;
 
                     /* Get the target block's arity and check it */
@@ -11965,8 +11963,7 @@ re_scan:
                         loader_ctx->reftype_map_num--;
                     }
 #endif
-                    if (is_32bit_type(*(loader_ctx->frame_ref - 1))
-                        || *(loader_ctx->frame_ref - 1) == VALUE_TYPE_ANY) {
+                    if (is_32bit_type(*(loader_ctx->frame_ref - 1))) {
                         loader_ctx->frame_ref--;
                         loader_ctx->stack_cell_num--;
 #if WASM_ENABLE_FAST_INTERP != 0

+ 21 - 11
core/iwasm/interpreter/wasm_mini_loader.c

@@ -67,7 +67,10 @@ set_error_buf(char *error_buf, uint32 error_buf_size, const char *string)
 static bool
 is_32bit_type(uint8 type)
 {
-    if (type == VALUE_TYPE_I32 || type == VALUE_TYPE_F32
+    if (type == VALUE_TYPE_I32
+        || type == VALUE_TYPE_F32
+        /* the operand stack is in polymorphic state */
+        || type == VALUE_TYPE_ANY
 #if WASM_ENABLE_REF_TYPES != 0
         || type == VALUE_TYPE_FUNCREF || type == VALUE_TYPE_EXTERNREF
 #endif
@@ -4237,7 +4240,7 @@ wasm_loader_pop_frame_ref(WASMLoaderContext *ctx, uint8 type, char *error_buf,
     ctx->frame_ref--;
     ctx->stack_cell_num--;
 
-    if (is_32bit_type(type) || *ctx->frame_ref == VALUE_TYPE_ANY)
+    if (is_32bit_type(type))
         return true;
 
     ctx->frame_ref--;
@@ -6351,13 +6354,11 @@ re_scan:
             case WASM_OP_BR_TABLE:
             {
                 uint8 *ret_types = NULL;
-                uint32 ret_count = 0;
+                uint32 ret_count = 0, depth = 0;
 #if WASM_ENABLE_FAST_INTERP == 0
-                uint8 *p_depth_begin, *p_depth;
-                uint32 depth, j;
                 BrTableCache *br_table_cache = NULL;
-
-                p_org = p - 1;
+                uint8 *p_depth_begin, *p_depth, *p_opcode = p - 1;
+                uint32 j;
 #endif
 
                 read_leb_uint32(p, p_end, count);
@@ -6366,6 +6367,16 @@ re_scan:
 #endif
                 POP_I32();
 
+                /* Get each depth and check it */
+                p_org = p;
+                for (i = 0; i <= count; i++) {
+                    read_leb_uint32(p, p_end, depth);
+                    bh_assert(loader_ctx->csp_num > 0);
+                    bh_assert(loader_ctx->csp_num - 1 >= depth);
+                    (void)depth;
+                }
+                p = p_org;
+
 #if WASM_ENABLE_FAST_INTERP == 0
                 p_depth_begin = p_depth = p;
 #endif
@@ -6391,8 +6402,8 @@ re_scan:
                                       error_buf, error_buf_size))) {
                                 goto fail;
                             }
-                            *p_org = EXT_OP_BR_TABLE_CACHE;
-                            br_table_cache->br_table_op_addr = p_org;
+                            *p_opcode = EXT_OP_BR_TABLE_CACHE;
+                            br_table_cache->br_table_op_addr = p_opcode;
                             br_table_cache->br_count = count;
                             /* Copy previous depths which are one byte */
                             for (j = 0; j < i; j++) {
@@ -6623,8 +6634,7 @@ re_scan:
                             && !cur_block->is_stack_polymorphic));
 
                 if (available_stack_cell > 0) {
-                    if (is_32bit_type(*(loader_ctx->frame_ref - 1))
-                        || *(loader_ctx->frame_ref - 1) == VALUE_TYPE_ANY) {
+                    if (is_32bit_type(*(loader_ctx->frame_ref - 1))) {
                         loader_ctx->frame_ref--;
                         loader_ctx->stack_cell_num--;
 #if WASM_ENABLE_FAST_INTERP != 0