Fix data/elem drop (#2747)
Currently, `data.drop` instruction is implemented by directly modifying the underlying module. It breaks use cases where you have multiple instances sharing a single loaded module. `elem.drop` has the same problem too. This PR fixes the issue by keeping track of which data/elem segments have been dropped by using bitmaps for each module instances separately, and add a sample to demonstrate the issue and make the CI run it. Also add a missing check of dropped elements to the fast-jit `table.init`. Fixes: https://github.com/bytecodealliance/wasm-micro-runtime/issues/2735 Fixes: https://github.com/bytecodealliance/wasm-micro-runtime/issues/2772
This commit is contained in:
@ -650,6 +650,7 @@ wasm_init_memory(WASMModuleInstance *inst, uint32 mem_idx, uint32 seg_idx,
|
||||
WASMDataSeg *data_segment;
|
||||
uint32 mem_size;
|
||||
uint8 *mem_addr, *data_addr;
|
||||
uint32 seg_len;
|
||||
|
||||
/* if d + n > the length of mem.data */
|
||||
mem_inst = inst->memories[mem_idx];
|
||||
@ -659,13 +660,19 @@ wasm_init_memory(WASMModuleInstance *inst, uint32 mem_idx, uint32 seg_idx,
|
||||
|
||||
/* if s + n > the length of data.data */
|
||||
bh_assert(seg_idx < inst->module->data_seg_count);
|
||||
data_segment = inst->module->data_segments[seg_idx];
|
||||
if (data_segment->data_length < data_offset
|
||||
|| data_segment->data_length - data_offset < len)
|
||||
if (bh_bitmap_get_bit(inst->e->common.data_dropped, seg_idx)) {
|
||||
seg_len = 0;
|
||||
data_addr = NULL;
|
||||
}
|
||||
else {
|
||||
data_segment = inst->module->data_segments[seg_idx];
|
||||
seg_len = data_segment->data_length;
|
||||
data_addr = data_segment->data + data_offset;
|
||||
}
|
||||
if (seg_len < data_offset || seg_len - data_offset < len)
|
||||
goto out_of_bounds;
|
||||
|
||||
mem_addr = mem_inst->memory_data + mem_offset;
|
||||
data_addr = data_segment->data + data_offset;
|
||||
bh_memcpy_s(mem_addr, mem_size - mem_offset, data_addr, len);
|
||||
|
||||
return 0;
|
||||
@ -706,21 +713,22 @@ fail:
|
||||
return false;
|
||||
}
|
||||
|
||||
static void
|
||||
wasm_data_drop(WASMModuleInstance *inst, uint32 seg_idx)
|
||||
{
|
||||
bh_bitmap_set_bit(inst->e->common.data_dropped, seg_idx);
|
||||
}
|
||||
|
||||
bool
|
||||
jit_compile_op_data_drop(JitCompContext *cc, uint32 seg_idx)
|
||||
{
|
||||
JitReg module = get_module_reg(cc->jit_frame);
|
||||
JitReg data_segments = jit_cc_new_reg_ptr(cc);
|
||||
JitReg data_segment = jit_cc_new_reg_ptr(cc);
|
||||
JitReg args[2] = { 0 };
|
||||
|
||||
GEN_INSN(LDPTR, data_segments, module,
|
||||
NEW_CONST(I32, offsetof(WASMModule, data_segments)));
|
||||
GEN_INSN(LDPTR, data_segment, data_segments,
|
||||
NEW_CONST(I32, seg_idx * sizeof(WASMDataSeg *)));
|
||||
GEN_INSN(STI32, NEW_CONST(I32, 0), data_segment,
|
||||
NEW_CONST(I32, offsetof(WASMDataSeg, data_length)));
|
||||
args[0] = get_module_inst_reg(cc->jit_frame);
|
||||
args[1] = NEW_CONST(I32, seg_idx);
|
||||
|
||||
return true;
|
||||
return jit_emit_callnative(cc, wasm_data_drop, 0, args,
|
||||
sizeof(args) / sizeof(args[0]));
|
||||
}
|
||||
|
||||
static int
|
||||
|
||||
@ -10,21 +10,22 @@
|
||||
#include "../jit_frontend.h"
|
||||
|
||||
#if WASM_ENABLE_REF_TYPES != 0
|
||||
static void
|
||||
wasm_elem_drop(WASMModuleInstance *inst, uint32 tbl_seg_idx)
|
||||
{
|
||||
bh_bitmap_set_bit(inst->e->common.elem_dropped, tbl_seg_idx);
|
||||
}
|
||||
|
||||
bool
|
||||
jit_compile_op_elem_drop(JitCompContext *cc, uint32 tbl_seg_idx)
|
||||
{
|
||||
JitReg module, tbl_segs;
|
||||
JitReg args[2] = { 0 };
|
||||
|
||||
module = get_module_reg(cc->jit_frame);
|
||||
args[0] = get_module_inst_reg(cc->jit_frame);
|
||||
args[1] = NEW_CONST(I32, tbl_seg_idx);
|
||||
|
||||
tbl_segs = jit_cc_new_reg_ptr(cc);
|
||||
GEN_INSN(LDPTR, tbl_segs, module,
|
||||
NEW_CONST(I32, offsetof(WASMModule, table_segments)));
|
||||
|
||||
GEN_INSN(STI32, NEW_CONST(I32, true), tbl_segs,
|
||||
NEW_CONST(I32, tbl_seg_idx * sizeof(WASMTableSeg)
|
||||
+ offsetof(WASMTableSeg, is_dropped)));
|
||||
return true;
|
||||
return jit_emit_callnative(cc, wasm_elem_drop, 0, args,
|
||||
sizeof(args) / sizeof(args[0]));
|
||||
}
|
||||
|
||||
bool
|
||||
@ -105,6 +106,12 @@ wasm_init_table(WASMModuleInstance *inst, uint32 tbl_idx, uint32 elem_idx,
|
||||
if (offset_len_out_of_bounds(dst_offset, len, tbl_sz))
|
||||
goto out_of_bounds;
|
||||
|
||||
if (!len)
|
||||
return 0;
|
||||
|
||||
if (bh_bitmap_get_bit(inst->e->common.elem_dropped, elem_idx))
|
||||
goto out_of_bounds;
|
||||
|
||||
bh_memcpy_s((uint8 *)tbl + offsetof(WASMTableInstance, elems)
|
||||
+ dst_offset * sizeof(uint32),
|
||||
(uint32)((tbl_sz - dst_offset) * sizeof(uint32)),
|
||||
|
||||
Reference in New Issue
Block a user