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
This commit is contained in:
Wenyong Huang
2024-01-26 09:45:59 +08:00
committed by GitHub
parent 6daaf6d27a
commit 313ce8cb61
5 changed files with 73 additions and 86 deletions

View File

@ -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]
.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,
@ -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: