Преглед изворни кода

wasm loader: Fix pop invalid offset count when stack top is ANY (#3516)

In wasm_loader_pop_frame_offset, when the stack is in polymorphic state
and the stack top operand is VALUE_TYPE_ANY, if we popping I64/F64
operand, we should pop one offset but not two offsets.

The issue was reported in #3513 and #3514.
Wenyong Huang пре 1 година
родитељ
комит
d3e89895be

+ 27 - 22
core/iwasm/interpreter/wasm_loader.c

@@ -9370,42 +9370,41 @@ wasm_loader_pop_frame_offset(WASMLoaderContext *ctx, uint8 type,
                              char *error_buf, uint32 error_buf_size)
                              char *error_buf, uint32 error_buf_size)
 {
 {
     /* if ctx->frame_csp equals ctx->frame_csp_bottom,
     /* if ctx->frame_csp equals ctx->frame_csp_bottom,
-        then current block is the function block */
+       then current block is the function block */
     uint32 depth = ctx->frame_csp > ctx->frame_csp_bottom ? 1 : 0;
     uint32 depth = ctx->frame_csp > ctx->frame_csp_bottom ? 1 : 0;
     BranchBlock *cur_block = ctx->frame_csp - depth;
     BranchBlock *cur_block = ctx->frame_csp - depth;
     int32 available_stack_cell =
     int32 available_stack_cell =
         (int32)(ctx->stack_cell_num - cur_block->stack_cell_num);
         (int32)(ctx->stack_cell_num - cur_block->stack_cell_num);
+    uint32 cell_num_to_pop;
 
 
     /* Directly return success if current block is in stack
     /* Directly return success if current block is in stack
-     * polymorphic state while stack is empty. */
+       polymorphic state while stack is empty. */
     if (available_stack_cell <= 0 && cur_block->is_stack_polymorphic)
     if (available_stack_cell <= 0 && cur_block->is_stack_polymorphic)
         return true;
         return true;
 
 
     if (type == VALUE_TYPE_VOID)
     if (type == VALUE_TYPE_VOID)
         return true;
         return true;
 
 
-    if (is_32bit_type(type)) {
-        /* Check the offset stack bottom to ensure the frame offset
-            stack will not go underflow. But we don't thrown error
-            and return true here, because the error msg should be
-            given in wasm_loader_pop_frame_ref */
-        if (!check_offset_pop(ctx, 1))
-            return true;
+    /* Change type to ANY when the stack top is ANY, so as to avoid
+       popping unneeded offsets, e.g. if type is I64/F64, we may pop
+       two offsets */
+    if (available_stack_cell > 0 && *(ctx->frame_ref - 1) == VALUE_TYPE_ANY)
+        type = VALUE_TYPE_ANY;
 
 
-        ctx->frame_offset -= 1;
-        if ((*(ctx->frame_offset) > ctx->start_dynamic_offset)
-            && (*(ctx->frame_offset) < ctx->max_dynamic_offset))
-            ctx->dynamic_offset -= 1;
-    }
-    else {
-        if (!check_offset_pop(ctx, 2))
-            return true;
+    cell_num_to_pop = wasm_value_type_cell_num(type);
+
+    /* Check the offset stack bottom to ensure the frame offset
+       stack will not go underflow. But we don't thrown error
+       and return true here, because the error msg should be
+       given in wasm_loader_pop_frame_ref */
+    if (!check_offset_pop(ctx, cell_num_to_pop))
+        return true;
+
+    ctx->frame_offset -= cell_num_to_pop;
+    if ((*(ctx->frame_offset) > ctx->start_dynamic_offset)
+        && (*(ctx->frame_offset) < ctx->max_dynamic_offset))
+        ctx->dynamic_offset -= cell_num_to_pop;
 
 
-        ctx->frame_offset -= 2;
-        if ((*(ctx->frame_offset) > ctx->start_dynamic_offset)
-            && (*(ctx->frame_offset) < ctx->max_dynamic_offset))
-            ctx->dynamic_offset -= 2;
-    }
     emit_operand(ctx, *(ctx->frame_offset));
     emit_operand(ctx, *(ctx->frame_offset));
 
 
     (void)error_buf;
     (void)error_buf;
@@ -10893,6 +10892,12 @@ wasm_loader_get_custom_section(WASMModule *module, const char *name,
 }
 }
 #endif
 #endif
 
 
+#if 0
+#define HANDLE_OPCODE(opcode) #opcode
+DEFINE_GOTO_TABLE(const char *, op_mnemonics);
+#undef HANDLE_OPCODE
+#endif
+
 static bool
 static bool
 wasm_loader_prepare_bytecode(WASMModule *module, WASMFunction *func,
 wasm_loader_prepare_bytecode(WASMModule *module, WASMFunction *func,
                              uint32 cur_func_idx, char *error_buf,
                              uint32 cur_func_idx, char *error_buf,

+ 24 - 22
core/iwasm/interpreter/wasm_mini_loader.c

@@ -4924,43 +4924,45 @@ wasm_loader_pop_frame_offset(WASMLoaderContext *ctx, uint8 type,
                              char *error_buf, uint32 error_buf_size)
                              char *error_buf, uint32 error_buf_size)
 {
 {
     /* if ctx->frame_csp equals ctx->frame_csp_bottom,
     /* if ctx->frame_csp equals ctx->frame_csp_bottom,
-        then current block is the function block */
+       then current block is the function block */
     uint32 depth = ctx->frame_csp > ctx->frame_csp_bottom ? 1 : 0;
     uint32 depth = ctx->frame_csp > ctx->frame_csp_bottom ? 1 : 0;
     BranchBlock *cur_block = ctx->frame_csp - depth;
     BranchBlock *cur_block = ctx->frame_csp - depth;
     int32 available_stack_cell =
     int32 available_stack_cell =
         (int32)(ctx->stack_cell_num - cur_block->stack_cell_num);
         (int32)(ctx->stack_cell_num - cur_block->stack_cell_num);
+    uint32 cell_num_to_pop;
 
 
     /* Directly return success if current block is in stack
     /* Directly return success if current block is in stack
-     * polymorphic state while stack is empty. */
+       polymorphic state while stack is empty. */
     if (available_stack_cell <= 0 && cur_block->is_stack_polymorphic)
     if (available_stack_cell <= 0 && cur_block->is_stack_polymorphic)
         return true;
         return true;
 
 
     if (type == VALUE_TYPE_VOID)
     if (type == VALUE_TYPE_VOID)
         return true;
         return true;
 
 
-    if (is_32bit_type(type)) {
-        /* Check the offset stack bottom to ensure the frame offset
-            stack will not go underflow. But we don't thrown error
-            and return true here, because the error msg should be
-            given in wasm_loader_pop_frame_ref */
-        if (!check_offset_pop(ctx, 1))
-            return true;
+    /* Change type to ANY when the stack top is ANY, so as to avoid
+       popping unneeded offsets, e.g. if type is I64/F64, we may pop
+       two offsets */
+    if (available_stack_cell > 0 && *(ctx->frame_ref - 1) == VALUE_TYPE_ANY)
+        type = VALUE_TYPE_ANY;
 
 
-        ctx->frame_offset -= 1;
-        if ((*(ctx->frame_offset) > ctx->start_dynamic_offset)
-            && (*(ctx->frame_offset) < ctx->max_dynamic_offset))
-            ctx->dynamic_offset -= 1;
-    }
-    else {
-        if (!check_offset_pop(ctx, 2))
-            return true;
+    cell_num_to_pop = wasm_value_type_cell_num(type);
+
+    /* Check the offset stack bottom to ensure the frame offset
+       stack will not go underflow. But we don't thrown error
+       and return true here, because the error msg should be
+       given in wasm_loader_pop_frame_ref */
+    if (!check_offset_pop(ctx, cell_num_to_pop))
+        return true;
+
+    ctx->frame_offset -= cell_num_to_pop;
+    if ((*(ctx->frame_offset) > ctx->start_dynamic_offset)
+        && (*(ctx->frame_offset) < ctx->max_dynamic_offset))
+        ctx->dynamic_offset -= cell_num_to_pop;
 
 
-        ctx->frame_offset -= 2;
-        if ((*(ctx->frame_offset) > ctx->start_dynamic_offset)
-            && (*(ctx->frame_offset) < ctx->max_dynamic_offset))
-            ctx->dynamic_offset -= 2;
-    }
     emit_operand(ctx, *(ctx->frame_offset));
     emit_operand(ctx, *(ctx->frame_offset));
+
+    (void)error_buf;
+    (void)error_buf_size;
     return true;
     return true;
 }
 }
 
 

BIN
tests/regression/ba-issues/issues/issue-3513/iwasm_poc_04.wasm


BIN
tests/regression/ba-issues/issues/issue-3514/iwasm_poc_05.wasm


+ 32 - 0
tests/regression/ba-issues/running_config.json

@@ -1722,6 +1722,38 @@
                 "stdout content": "WASM module load failed: data count and data section have inconsistent lengths",
                 "stdout content": "WASM module load failed: data count and data section have inconsistent lengths",
                 "description": "Check data segment count"
                 "description": "Check data segment count"
             }
             }
+        },
+        {
+            "deprecated": false,
+            "ids": [
+                3513
+            ],
+            "runtime": "iwasm-default-wasi-disabled",
+            "file": "iwasm_poc_04.wasm",
+            "mode": "fast-interp",
+            "options": "-f main",
+            "argument": "",
+            "expected return": {
+                "ret code": 0,
+                "stdout content": "",
+                "description": "no sanitizer 'heap-buffer-overflow'"
+            }
+        },
+        {
+            "deprecated": false,
+            "ids": [
+                3514
+            ],
+            "runtime": "iwasm-default-wasi-disabled",
+            "file": "iwasm_poc_05.wasm",
+            "mode": "fast-interp",
+            "options": "-f main",
+            "argument": "",
+            "expected return": {
+                "ret code": 0,
+                "stdout content": "",
+                "description": "no sanitizer 'heap-buffer-overflow'"
+            }
         }
         }
     ]
     ]
 }
 }