Explorar el Código

Fix memory/table segment checks in memory.init/table.init (#3081)

According to the wasm core spec, the checks for the table segments in
`table.init` opcode are similar to the checks for `memory.init` opcode:
- The size of a passive segment is shrunk to zero after `data.drop`
  (or `elem.drop`) opcode is executed, and the segment can be used to do
  `memory.init` (or `table.init`) again
- The `memory.init` only traps when `s+n > len(data.data)` or `d+n > len(mem.data)`
  and `table.init` only traps when `s+n > len(elem.elem)` or `d+n > len(tab.elem)`
- The active segment can also be used to do `memory.init` (or `table.init`),
  while it behaves like a dropped passive segment

https://github.com/WebAssembly/bulk-memory-operations/blob/master/proposals/bulk-memory-operations/Overview.md
```
Segments can also be shrunk to size zero by using the following new instructions:
- data.drop: discard the data in an data segment
- elem.drop: discard the data in an element segment

An active segment is equivalent to a passive segment, but with an implicit
memory.init followed by a data.drop (or table.init followed by a elem.drop)
that is prepended to the module's start function.
```
ps.
https://webassembly.github.io/spec/core/bikeshed/#-hrefsyntax-instr-memorymathsfmemoryinitx%E2%91%A0
https://webassembly.github.io/spec/core/bikeshed/#-hrefsyntax-instr-tablemathsftableinitxy%E2%91%A0
https://github.com/bytecodealliance/wasm-micro-runtime/issues/3020
Wenyong Huang hace 1 año
padre
commit
313ce8cb61

+ 19 - 14
core/iwasm/aot/aot_runtime.c

@@ -1179,6 +1179,10 @@ aot_instantiate(AOTModule *module, AOTModuleInstance *parent,
                           "failed to allocate bitmaps");
             goto fail;
         }
+        for (i = 0; i < module->mem_init_data_count; i++) {
+            if (!module->mem_init_data_list[i]->is_passive)
+                bh_bitmap_set_bit(common->data_dropped, i);
+        }
     }
 #endif
 #if WASM_ENABLE_REF_TYPES != 0
@@ -1190,6 +1194,10 @@ aot_instantiate(AOTModule *module, AOTModuleInstance *parent,
                           "failed to allocate bitmaps");
             goto fail;
         }
+        for (i = 0; i < module->table_init_data_count; i++) {
+            if (wasm_elem_is_active(module->table_init_data_list[i]->mode))
+                bh_bitmap_set_bit(common->elem_dropped, i);
+        }
     }
 #endif
 
@@ -2621,6 +2629,7 @@ aot_table_init(AOTModuleInstance *module_inst, uint32 tbl_idx,
 {
     AOTTableInstance *tbl_inst;
     AOTTableInitData *tbl_seg;
+    uint32 *tbl_seg_elems = NULL, tbl_seg_len = 0;
     const AOTModule *module = (AOTModule *)module_inst->module;
 
     tbl_inst = module_inst->tables[tbl_idx];
@@ -2629,32 +2638,28 @@ aot_table_init(AOTModuleInstance *module_inst, uint32 tbl_idx,
     tbl_seg = module->table_init_data_list[tbl_seg_idx];
     bh_assert(tbl_seg);
 
-    if (offset_len_out_of_bounds(src_offset, length, tbl_seg->func_index_count)
-        || offset_len_out_of_bounds(dst_offset, length, tbl_inst->cur_size)) {
-        aot_set_exception_with_id(module_inst, EXCE_OUT_OF_BOUNDS_TABLE_ACCESS);
-        return;
-    }
-
-    if (!length) {
-        return;
-    }
-
-    if (bh_bitmap_get_bit(
+    if (!bh_bitmap_get_bit(
             ((AOTModuleInstanceExtra *)module_inst->e)->common.elem_dropped,
             tbl_seg_idx)) {
+        /* table segment isn't dropped */
+        tbl_seg_elems = tbl_seg->func_indexes;
+        tbl_seg_len = tbl_seg->func_index_count;
+    }
+
+    if (offset_len_out_of_bounds(src_offset, length, tbl_seg_len)
+        || offset_len_out_of_bounds(dst_offset, length, tbl_inst->cur_size)) {
         aot_set_exception_with_id(module_inst, EXCE_OUT_OF_BOUNDS_TABLE_ACCESS);
         return;
     }
 
-    if (!wasm_elem_is_passive(tbl_seg->mode)) {
-        aot_set_exception_with_id(module_inst, EXCE_OUT_OF_BOUNDS_TABLE_ACCESS);
+    if (!length) {
         return;
     }
 
     bh_memcpy_s((uint8 *)tbl_inst + offsetof(AOTTableInstance, elems)
                     + dst_offset * sizeof(uint32),
                 (tbl_inst->cur_size - dst_offset) * sizeof(uint32),
-                tbl_seg->func_indexes + src_offset, length * sizeof(uint32));
+                tbl_seg_elems + src_offset, length * sizeof(uint32));
 }
 
 void

+ 11 - 14
core/iwasm/fast-jit/fe/jit_emit_table.c

@@ -88,17 +88,21 @@ fail:
 }
 
 static int
-wasm_init_table(WASMModuleInstance *inst, uint32 tbl_idx, uint32 elem_idx,
+wasm_init_table(WASMModuleInstance *inst, uint32 tbl_idx, uint32 seg_idx,
                 uint32 dst_offset, uint32 len, uint32 src_offset)
 {
     WASMTableInstance *tbl;
     uint32 tbl_sz;
-    WASMTableSeg *elem;
-    uint32 elem_len;
+    WASMTableSeg *tbl_seg = inst->module->table_segments + seg_idx;
+    uint32 *tbl_seg_elems = NULL, tbl_seg_len = 0;
 
-    elem = inst->module->table_segments + elem_idx;
-    elem_len = elem->function_count;
-    if (offset_len_out_of_bounds(src_offset, len, elem_len))
+    if (!bh_bitmap_get_bit(inst->e->common.elem_dropped, seg_idx)) {
+        /* table segment isn't dropped */
+        tbl_seg_elems = tbl_seg->func_indexes;
+        tbl_seg_len = tbl_seg->function_count;
+    }
+
+    if (offset_len_out_of_bounds(src_offset, len, tbl_seg_len))
         goto out_of_bounds;
 
     tbl = inst->tables[tbl_idx];
@@ -109,17 +113,10 @@ wasm_init_table(WASMModuleInstance *inst, uint32 tbl_idx, uint32 elem_idx,
     if (!len)
         return 0;
 
-    if (bh_bitmap_get_bit(inst->e->common.elem_dropped, elem_idx))
-        goto out_of_bounds;
-
-    if (!wasm_elem_is_passive(inst->module->table_segments[elem_idx].mode))
-        goto out_of_bounds;
-
     bh_memcpy_s((uint8 *)tbl + offsetof(WASMTableInstance, elems)
                     + dst_offset * sizeof(uint32),
                 (uint32)((tbl_sz - dst_offset) * sizeof(uint32)),
-                elem->func_indexes + src_offset,
-                (uint32)(len * sizeof(uint32)));
+                tbl_seg_elems + src_offset, (uint32)(len * sizeof(uint32)));
 
     return 0;
 out_of_bounds:

+ 13 - 22
core/iwasm/interpreter/wasm_interp_classic.c

@@ -3262,6 +3262,7 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
                         uint32 tbl_idx, elem_idx;
                         uint32 n, s, d;
                         WASMTableInstance *tbl_inst;
+                        uint32 *tbl_seg_elems = NULL, tbl_seg_len = 0;
 
                         read_leb_uint32(frame_ip, frame_ip_end, elem_idx);
                         bh_assert(elem_idx < module->module->table_seg_count);
@@ -3275,10 +3276,18 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
                         s = (uint32)POP_I32();
                         d = (uint32)POP_I32();
 
-                        if (offset_len_out_of_bounds(
-                                s, n,
+                        if (!bh_bitmap_get_bit(module->e->common.elem_dropped,
+                                               elem_idx)) {
+                            /* table segment isn't dropped */
+                            tbl_seg_elems =
                                 module->module->table_segments[elem_idx]
-                                    .function_count)
+                                    .func_indexes;
+                            tbl_seg_len =
+                                module->module->table_segments[elem_idx]
+                                    .function_count;
+                        }
+
+                        if (offset_len_out_of_bounds(s, n, tbl_seg_len)
                             || offset_len_out_of_bounds(d, n,
                                                         tbl_inst->cur_size)) {
                             wasm_set_exception(module,
@@ -3290,30 +3299,12 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
                             break;
                         }
 
-                        if (bh_bitmap_get_bit(module->e->common.elem_dropped,
-                                              elem_idx)) {
-                            wasm_set_exception(module,
-                                               "out of bounds table access");
-                            goto got_exception;
-                        }
-
-                        if (!wasm_elem_is_passive(
-                                module->module->table_segments[elem_idx]
-                                    .mode)) {
-                            wasm_set_exception(module,
-                                               "out of bounds table access");
-                            goto got_exception;
-                        }
-
                         bh_memcpy_s(
                             (uint8 *)tbl_inst
                                 + offsetof(WASMTableInstance, elems)
                                 + d * sizeof(uint32),
                             (uint32)((tbl_inst->cur_size - d) * sizeof(uint32)),
-                            module->module->table_segments[elem_idx]
-                                    .func_indexes
-                                + s,
-                            (uint32)(n * sizeof(uint32)));
+                            tbl_seg_elems + s, (uint32)(n * sizeof(uint32)));
 
                         break;
                     }

+ 13 - 23
core/iwasm/interpreter/wasm_interp_fast.c

@@ -3023,7 +3023,6 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
                             data = NULL;
                         }
                         else {
-
                             seg_len =
                                 (uint64)module->module->data_segments[segment]
                                     ->data_length;
@@ -3106,6 +3105,7 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
                         uint32 tbl_idx, elem_idx;
                         uint32 n, s, d;
                         WASMTableInstance *tbl_inst;
+                        uint32 *tbl_seg_elems = NULL, tbl_seg_len = 0;
 
                         elem_idx = read_uint32(frame_ip);
                         bh_assert(elem_idx < module->module->table_seg_count);
@@ -3119,10 +3119,18 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
                         s = (uint32)POP_I32();
                         d = (uint32)POP_I32();
 
-                        if (offset_len_out_of_bounds(
-                                s, n,
+                        if (!bh_bitmap_get_bit(module->e->common.elem_dropped,
+                                               elem_idx)) {
+                            /* table segment isn't dropped */
+                            tbl_seg_elems =
+                                module->module->table_segments[elem_idx]
+                                    .func_indexes;
+                            tbl_seg_len =
                                 module->module->table_segments[elem_idx]
-                                    .function_count)
+                                    .function_count;
+                        }
+
+                        if (offset_len_out_of_bounds(s, n, tbl_seg_len)
                             || offset_len_out_of_bounds(d, n,
                                                         tbl_inst->cur_size)) {
                             wasm_set_exception(module,
@@ -3134,30 +3142,12 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
                             break;
                         }
 
-                        if (bh_bitmap_get_bit(module->e->common.elem_dropped,
-                                              elem_idx)) {
-                            wasm_set_exception(module,
-                                               "out of bounds table access");
-                            goto got_exception;
-                        }
-
-                        if (!wasm_elem_is_passive(
-                                module->module->table_segments[elem_idx]
-                                    .mode)) {
-                            wasm_set_exception(module,
-                                               "out of bounds table access");
-                            goto got_exception;
-                        }
-
                         bh_memcpy_s(
                             (uint8 *)tbl_inst
                                 + offsetof(WASMTableInstance, elems)
                                 + d * sizeof(uint32),
                             (uint32)((tbl_inst->cur_size - d) * sizeof(uint32)),
-                            module->module->table_segments[elem_idx]
-                                    .func_indexes
-                                + s,
-                            (uint32)(n * sizeof(uint32)));
+                            tbl_seg_elems + s, (uint32)(n * sizeof(uint32)));
                         break;
                     }
                     case WASM_OP_ELEM_DROP:

+ 17 - 13
core/iwasm/interpreter/wasm_runtime.c

@@ -1670,6 +1670,10 @@ wasm_instantiate(WASMModule *module, WASMModuleInstance *parent,
                           "failed to allocate bitmaps");
             goto fail;
         }
+        for (i = 0; i < module->data_seg_count; i++) {
+            if (!module->data_segments[i]->is_passive)
+                bh_bitmap_set_bit(module_inst->e->common.data_dropped, i);
+        }
     }
 #endif
 #if WASM_ENABLE_REF_TYPES != 0
@@ -1682,6 +1686,10 @@ wasm_instantiate(WASMModule *module, WASMModuleInstance *parent,
                           "failed to allocate bitmaps");
             goto fail;
         }
+        for (i = 0; i < module->table_seg_count; i++) {
+            if (wasm_elem_is_active(module->table_segments[i].mode))
+                bh_bitmap_set_bit(module_inst->e->common.elem_dropped, i);
+        }
     }
 #endif
 
@@ -3278,6 +3286,7 @@ llvm_jit_table_init(WASMModuleInstance *module_inst, uint32 tbl_idx,
 {
     WASMTableInstance *tbl_inst;
     WASMTableSeg *tbl_seg;
+    uint32 *tbl_seg_elems = NULL, tbl_seg_len = 0;
 
     bh_assert(module_inst->module_type == Wasm_Module_Bytecode);
 
@@ -3287,31 +3296,26 @@ llvm_jit_table_init(WASMModuleInstance *module_inst, uint32 tbl_idx,
     bh_assert(tbl_inst);
     bh_assert(tbl_seg);
 
-    if (offset_len_out_of_bounds(src_offset, length, tbl_seg->function_count)
-        || offset_len_out_of_bounds(dst_offset, length, tbl_inst->cur_size)) {
-        jit_set_exception_with_id(module_inst, EXCE_OUT_OF_BOUNDS_TABLE_ACCESS);
-        return;
-    }
-
-    if (!length) {
-        return;
+    if (!bh_bitmap_get_bit(module_inst->e->common.elem_dropped, tbl_seg_idx)) {
+        /* table segment isn't dropped */
+        tbl_seg_elems = tbl_seg->func_indexes;
+        tbl_seg_len = tbl_seg->function_count;
     }
 
-    if (bh_bitmap_get_bit(module_inst->e->common.elem_dropped, tbl_seg_idx)) {
+    if (offset_len_out_of_bounds(src_offset, length, tbl_seg_len)
+        || offset_len_out_of_bounds(dst_offset, length, tbl_inst->cur_size)) {
         jit_set_exception_with_id(module_inst, EXCE_OUT_OF_BOUNDS_TABLE_ACCESS);
         return;
     }
 
-    if (!wasm_elem_is_passive(tbl_seg->mode)) {
-        jit_set_exception_with_id(module_inst, EXCE_OUT_OF_BOUNDS_TABLE_ACCESS);
+    if (!length) {
         return;
     }
 
     bh_memcpy_s((uint8 *)tbl_inst + offsetof(WASMTableInstance, elems)
                     + dst_offset * sizeof(uint32),
                 (uint32)sizeof(uint32) * (tbl_inst->cur_size - dst_offset),
-                tbl_seg->func_indexes + src_offset,
-                (uint32)(length * sizeof(uint32)));
+                tbl_seg_elems + src_offset, (uint32)(length * sizeof(uint32)));
 }
 
 void