Skip to content

Commit

Permalink
Fix data/elem drop (#2747)
Browse files Browse the repository at this point in the history
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: #2735
Fixes: #2772
  • Loading branch information
yamt authored Nov 18, 2023
1 parent 08c0ec7 commit 562a5dd
Show file tree
Hide file tree
Showing 26 changed files with 745 additions and 72 deletions.
6 changes: 6 additions & 0 deletions .github/workflows/compilation_on_android_ubuntu.yml
Original file line number Diff line number Diff line change
Expand Up @@ -444,6 +444,12 @@ jobs:
cmake --build . --config Release --parallel 4
./iwasm wasm-apps/no_pthread.wasm
- name: Build Sample [shared-module]
run: |
cd samples/shared-module
./build.sh
./run.sh
test:
needs:
[
Expand Down
6 changes: 6 additions & 0 deletions .github/workflows/compilation_on_macos.yml
Original file line number Diff line number Diff line change
Expand Up @@ -327,3 +327,9 @@ jobs:
cmake ..
cmake --build . --config Release --parallel 4
./iwasm wasm-apps/no_pthread.wasm
- name: Build Sample [shared-module]
run: |
cd samples/shared-module
./build.sh
./run.sh
6 changes: 6 additions & 0 deletions .github/workflows/nightly_run.yml
Original file line number Diff line number Diff line change
Expand Up @@ -501,6 +501,12 @@ jobs:
cmake ..
cmake --build . --config Release --parallel 4
./iwasm wasm-apps/no_pthread.wasm
- name: Build Sample [shared-module]
run: |
cd samples/shared-module
./build.sh
./run.sh
test:
needs:
[
Expand Down
1 change: 0 additions & 1 deletion core/iwasm/aot/aot_loader.c
Original file line number Diff line number Diff line change
Expand Up @@ -1095,7 +1095,6 @@ load_table_init_data_list(const uint8 **p_buf, const uint8 *buf_end,

data_list[i]->mode = mode;
data_list[i]->elem_type = elem_type;
data_list[i]->is_dropped = false;
data_list[i]->table_index = table_index;
data_list[i]->offset.init_expr_type = (uint8)init_expr_type;
data_list[i]->offset.u.i64 = (int64)init_expr_value;
Expand Down
74 changes: 61 additions & 13 deletions core/iwasm/aot/aot_runtime.c
Original file line number Diff line number Diff line change
Expand Up @@ -1098,6 +1098,9 @@ aot_instantiate(AOTModule *module, AOTModuleInstance *parent,
char *error_buf, uint32 error_buf_size)
{
AOTModuleInstance *module_inst;
#if WASM_ENABLE_BULK_MEMORY != 0 || WASM_ENABLE_REF_TYPES != 0
WASMModuleInstanceExtraCommon *common;
#endif
const uint32 module_inst_struct_size =
offsetof(AOTModuleInstance, global_table_data.bytes);
const uint64 module_inst_mem_inst_size =
Expand Down Expand Up @@ -1164,6 +1167,32 @@ aot_instantiate(AOTModule *module, AOTModuleInstance *parent,
}
#endif

#if WASM_ENABLE_BULK_MEMORY != 0 || WASM_ENABLE_REF_TYPES != 0
common = &((AOTModuleInstanceExtra *)module_inst->e)->common;
#endif
#if WASM_ENABLE_BULK_MEMORY != 0
if (module->mem_init_data_count > 0) {
common->data_dropped = bh_bitmap_new(0, module->mem_init_data_count);
if (common->data_dropped == NULL) {
LOG_DEBUG("failed to allocate bitmaps");
set_error_buf(error_buf, error_buf_size,
"failed to allocate bitmaps");
goto fail;
}
}
#endif
#if WASM_ENABLE_REF_TYPES != 0
if (module->table_init_data_count > 0) {
common->elem_dropped = bh_bitmap_new(0, module->table_init_data_count);
if (common->elem_dropped == NULL) {
LOG_DEBUG("failed to allocate bitmaps");
set_error_buf(error_buf, error_buf_size,
"failed to allocate bitmaps");
goto fail;
}
}
#endif

/* Initialize global info */
p = (uint8 *)module_inst + module_inst_struct_size
+ module_inst_mem_inst_size;
Expand Down Expand Up @@ -1264,6 +1293,8 @@ aot_instantiate(AOTModule *module, AOTModuleInstance *parent,
void
aot_deinstantiate(AOTModuleInstance *module_inst, bool is_sub_inst)
{
WASMModuleInstanceExtraCommon *common =
&((AOTModuleInstanceExtra *)module_inst->e)->common;
if (module_inst->exec_env_singleton) {
/* wasm_exec_env_destroy will call
wasm_cluster_wait_for_all_except_self to wait for other
Expand Down Expand Up @@ -1306,7 +1337,7 @@ aot_deinstantiate(AOTModuleInstance *module_inst, bool is_sub_inst)
if (module_inst->func_type_indexes)
wasm_runtime_free(module_inst->func_type_indexes);

if (((AOTModuleInstanceExtra *)module_inst->e)->common.c_api_func_imports)
if (common->c_api_func_imports)
wasm_runtime_free(((AOTModuleInstanceExtra *)module_inst->e)
->common.c_api_func_imports);

Expand All @@ -1317,6 +1348,13 @@ aot_deinstantiate(AOTModuleInstance *module_inst, bool is_sub_inst)
wasm_native_call_context_dtors((WASMModuleInstanceCommon *)module_inst);
}

#if WASM_ENABLE_BULK_MEMORY != 0
bh_bitmap_delete(common->data_dropped);
#endif
#if WASM_ENABLE_REF_TYPES != 0
bh_bitmap_delete(common->elem_dropped);
#endif

wasm_runtime_free(module_inst);
}

Expand Down Expand Up @@ -2302,13 +2340,21 @@ aot_memory_init(AOTModuleInstance *module_inst, uint32 seg_index, uint32 offset,
{
AOTMemoryInstance *memory_inst = aot_get_default_memory(module_inst);
AOTModule *aot_module;
uint8 *data = NULL;
uint8 *data;
uint8 *maddr;
uint64 seg_len = 0;
uint64 seg_len;

aot_module = (AOTModule *)module_inst->module;
seg_len = aot_module->mem_init_data_list[seg_index]->byte_count;
data = aot_module->mem_init_data_list[seg_index]->bytes;
if (bh_bitmap_get_bit(
((AOTModuleInstanceExtra *)module_inst->e)->common.data_dropped,
seg_index)) {
seg_len = 0;
data = NULL;
}
else {
aot_module = (AOTModule *)module_inst->module;
seg_len = aot_module->mem_init_data_list[seg_index]->byte_count;
data = aot_module->mem_init_data_list[seg_index]->bytes;
}

if (!wasm_runtime_validate_app_addr((WASMModuleInstanceCommon *)module_inst,
dst, len))
Expand All @@ -2331,9 +2377,9 @@ aot_memory_init(AOTModuleInstance *module_inst, uint32 seg_index, uint32 offset,
bool
aot_data_drop(AOTModuleInstance *module_inst, uint32 seg_index)
{
AOTModule *aot_module = (AOTModule *)module_inst->module;

aot_module->mem_init_data_list[seg_index]->byte_count = 0;
bh_bitmap_set_bit(
((AOTModuleInstanceExtra *)module_inst->e)->common.data_dropped,
seg_index);
/* Currently we can't free the dropped data segment
as the mem_init_data_count is a continuous array */
return true;
Expand Down Expand Up @@ -2546,9 +2592,9 @@ aot_get_module_inst_mem_consumption(const AOTModuleInstance *module_inst,
void
aot_drop_table_seg(AOTModuleInstance *module_inst, uint32 tbl_seg_idx)
{
AOTModule *module = (AOTModule *)module_inst->module;
AOTTableInitData *tbl_seg = module->table_init_data_list[tbl_seg_idx];
tbl_seg->is_dropped = true;
bh_bitmap_set_bit(
((AOTModuleInstanceExtra *)module_inst->e)->common.elem_dropped,
tbl_seg_idx);
}

void
Expand Down Expand Up @@ -2576,7 +2622,9 @@ aot_table_init(AOTModuleInstance *module_inst, uint32 tbl_idx,
return;
}

if (tbl_seg->is_dropped) {
if (bh_bitmap_get_bit(
((AOTModuleInstanceExtra *)module_inst->e)->common.elem_dropped,
tbl_seg_idx)) {
aot_set_exception_with_id(module_inst, EXCE_OUT_OF_BOUNDS_TABLE_ACCESS);
return;
}
Expand Down
1 change: 0 additions & 1 deletion core/iwasm/compilation/aot.c
Original file line number Diff line number Diff line change
Expand Up @@ -129,7 +129,6 @@ aot_create_table_init_data_list(const WASMModule *module)
data_list[i]->mode = module->table_segments[i].mode;
data_list[i]->elem_type = module->table_segments[i].elem_type;
/* runtime control it */
data_list[i]->is_dropped = false;
data_list[i]->table_index = module->table_segments[i].table_index;
bh_memcpy_s(&data_list[i]->offset, sizeof(AOTInitExpr),
&module->table_segments[i].base_offset,
Expand Down
1 change: 0 additions & 1 deletion core/iwasm/compilation/aot.h
Original file line number Diff line number Diff line change
Expand Up @@ -143,7 +143,6 @@ typedef struct AOTTableInitData {
uint32 mode;
/* funcref or externref, elemkind will be considered as funcref */
uint32 elem_type;
bool is_dropped;
/* optional, only for active */
uint32 table_index;
/* Start address of init data */
Expand Down
2 changes: 1 addition & 1 deletion core/iwasm/compilation/aot_emit_aot_file.c
Original file line number Diff line number Diff line change
Expand Up @@ -269,7 +269,7 @@ static uint32
get_table_init_data_size(AOTTableInitData *table_init_data)
{
/*
* mode (4 bytes), elem_type (4 bytes), do not need is_dropped field
* mode (4 bytes), elem_type (4 bytes)
*
* table_index(4 bytes) + init expr type (4 bytes) + init expr value (8
* bytes)
Expand Down
36 changes: 22 additions & 14 deletions core/iwasm/fast-jit/fe/jit_emit_memory.c
Original file line number Diff line number Diff line change
Expand Up @@ -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];
Expand All @@ -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;
Expand Down Expand Up @@ -706,21 +713,22 @@ jit_compile_op_memory_init(JitCompContext *cc, uint32 mem_idx, uint32 seg_idx)
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
Expand Down
27 changes: 17 additions & 10 deletions core/iwasm/fast-jit/fe/jit_emit_table.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);

tbl_segs = jit_cc_new_reg_ptr(cc);
GEN_INSN(LDPTR, tbl_segs, module,
NEW_CONST(I32, offsetof(WASMModule, table_segments)));
args[0] = get_module_inst_reg(cc->jit_frame);
args[1] = NEW_CONST(I32, tbl_seg_idx);

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
Expand Down Expand Up @@ -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)),
Expand Down
1 change: 0 additions & 1 deletion core/iwasm/interpreter/wasm.h
Original file line number Diff line number Diff line change
Expand Up @@ -311,7 +311,6 @@ typedef struct WASMTableSeg {
uint32 mode;
/* funcref or externref, elemkind will be considered as funcref */
uint32 elem_type;
bool is_dropped;
/* optional, only for active */
uint32 table_index;
InitializerExpression base_offset;
Expand Down
25 changes: 17 additions & 8 deletions core/iwasm/interpreter/wasm_interp_classic.c
Original file line number Diff line number Diff line change
Expand Up @@ -3160,9 +3160,17 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
maddr = memory->memory_data + (uint32)addr;
#endif

seg_len = (uint64)module->module->data_segments[segment]
->data_length;
data = module->module->data_segments[segment]->data;
if (bh_bitmap_get_bit(module->e->common.data_dropped,
segment)) {
seg_len = 0;
data = NULL;
}
else {
seg_len =
(uint64)module->module->data_segments[segment]
->data_length;
data = module->module->data_segments[segment]->data;
}
if (offset + bytes > seg_len)
goto out_of_bounds;

Expand All @@ -3175,7 +3183,8 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
uint32 segment;

read_leb_uint32(frame_ip, frame_ip_end, segment);
module->module->data_segments[segment]->data_length = 0;
bh_bitmap_set_bit(module->e->common.data_dropped,
segment);
break;
}
case WASM_OP_MEMORY_COPY:
Expand Down Expand Up @@ -3270,8 +3279,8 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
break;
}

if (module->module->table_segments[elem_idx]
.is_dropped) {
if (bh_bitmap_get_bit(module->e->common.elem_dropped,
elem_idx)) {
wasm_set_exception(module,
"out of bounds table access");
goto got_exception;
Expand Down Expand Up @@ -3303,8 +3312,8 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
read_leb_uint32(frame_ip, frame_ip_end, elem_idx);
bh_assert(elem_idx < module->module->table_seg_count);

module->module->table_segments[elem_idx].is_dropped =
true;
bh_bitmap_set_bit(module->e->common.elem_dropped,
elem_idx);
break;
}
case WASM_OP_TABLE_COPY:
Expand Down
Loading

0 comments on commit 562a5dd

Please sign in to comment.