Skip to content

Commit

Permalink
Fix memory/table segment checks in memory.init/table.init (#3081)
Browse files Browse the repository at this point in the history
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
#3020
  • Loading branch information
wenyongh committed Jan 26, 2024
1 parent 6daaf6d commit 313ce8c
Show file tree
Hide file tree
Showing 5 changed files with 73 additions and 86 deletions.
33 changes: 19 additions & 14 deletions core/iwasm/aot/aot_runtime.c
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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

Expand Down Expand Up @@ -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];
Expand All @@ -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
Expand Down
25 changes: 11 additions & 14 deletions core/iwasm/fast-jit/fe/jit_emit_table.c
Original file line number Diff line number Diff line change
Expand Up @@ -88,17 +88,21 @@ jit_compile_op_table_set(JitCompContext *cc, uint32 tbl_idx)
}

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];
Expand All @@ -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:
Expand Down
35 changes: 13 additions & 22 deletions core/iwasm/interpreter/wasm_interp_classic.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand All @@ -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,
Expand All @@ -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;
}
Expand Down
36 changes: 13 additions & 23 deletions core/iwasm/interpreter/wasm_interp_fast.c
Original file line number Diff line number Diff line change
Expand Up @@ -3023,7 +3023,6 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
data = NULL;
}
else {

seg_len =
(uint64)module->module->data_segments[segment]
->data_length;
Expand Down Expand Up @@ -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);
Expand All @@ -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,
Expand All @@ -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:
Expand Down
30 changes: 17 additions & 13 deletions core/iwasm/interpreter/wasm_runtime.c
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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

Expand Down Expand Up @@ -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);

Expand All @@ -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
Expand Down

0 comments on commit 313ce8c

Please sign in to comment.