diff --git a/core/iwasm/compilation/aot_compiler.c b/core/iwasm/compilation/aot_compiler.c index 5c66e0fe..96ed8fac 100644 --- a/core/iwasm/compilation/aot_compiler.c +++ b/core/iwasm/compilation/aot_compiler.c @@ -1028,7 +1028,9 @@ aot_compile_func(AOTCompContext *comp_ctx, uint32 func_index) } else { frame_ip--; - read_leb_uint32(frame_ip, frame_ip_end, type_index); + read_leb_int32(frame_ip, frame_ip_end, type_index); + /* type index was checked in wasm loader */ + bh_assert(type_index < comp_ctx->comp_data->type_count); func_type = (AOTFuncType *)comp_ctx->comp_data->types[type_index]; param_count = func_type->param_count; @@ -1048,7 +1050,9 @@ aot_compile_func(AOTCompContext *comp_ctx, uint32 func_index) case EXT_OP_LOOP: case EXT_OP_IF: { - read_leb_uint32(frame_ip, frame_ip_end, type_index); + read_leb_int32(frame_ip, frame_ip_end, type_index); + /* type index was checked in wasm loader */ + bh_assert(type_index < comp_ctx->comp_data->type_count); func_type = (AOTFuncType *)comp_ctx->comp_data->types[type_index]; param_count = func_type->param_count; diff --git a/core/iwasm/fast-jit/jit_frontend.c b/core/iwasm/fast-jit/jit_frontend.c index 092f9c0c..17c33230 100644 --- a/core/iwasm/fast-jit/jit_frontend.c +++ b/core/iwasm/fast-jit/jit_frontend.c @@ -1510,7 +1510,9 @@ jit_compile_func(JitCompContext *cc) case EXT_OP_LOOP: case EXT_OP_IF: { - read_leb_uint32(frame_ip, frame_ip_end, type_idx); + read_leb_int32(frame_ip, frame_ip_end, type_idx); + /* type index was checked in wasm loader */ + bh_assert(type_idx < cc->cur_wasm_module->type_count); func_type = cc->cur_wasm_module->types[type_idx]; param_count = func_type->param_count; param_types = func_type->types; diff --git a/core/iwasm/interpreter/wasm_loader.c b/core/iwasm/interpreter/wasm_loader.c index f4911d6e..b5185b92 100644 --- a/core/iwasm/interpreter/wasm_loader.c +++ b/core/iwasm/interpreter/wasm_loader.c @@ -7086,7 +7086,8 @@ wasm_loader_find_block_addr(WASMExecEnv *exec_env, BlockAddr *block_addr_cache, } else { p--; - skip_leb_uint32(p, p_end); + /* block type */ + skip_leb_int32(p, p_end); } if (block_nested_depth < sizeof(block_stack) / sizeof(BlockAddr)) { @@ -7101,7 +7102,7 @@ wasm_loader_find_block_addr(WASMExecEnv *exec_env, BlockAddr *block_addr_cache, case EXT_OP_LOOP: case EXT_OP_IF: /* block type */ - skip_leb_uint32(p, p_end); + skip_leb_int32(p, p_end); if (block_nested_depth < sizeof(block_stack) / sizeof(BlockAddr)) { block_stack[block_nested_depth].start_addr = p; @@ -7850,7 +7851,11 @@ typedef struct BranchBlock { BranchBlockPatch *patch_list; /* This is used to save params frame_offset of of if block */ int16 *param_frame_offsets; - /* This is used to recover dynamic offset for else branch */ + /* This is used to recover the dynamic offset for else branch, + * and also to remember the start offset of dynamic space which + * stores the block arguments for loop block, so we can use it + * to copy the stack operands to the loop block's arguments in + * wasm_loader_emit_br_info for opcode br. */ uint16 start_dynamic_offset; #endif @@ -8001,13 +8006,26 @@ static void free_all_label_patch_lists(BranchBlock *frame_csp, uint32 csp_num) { BranchBlock *tmp_csp = frame_csp; + uint32 i; - for (uint32 i = 0; i < csp_num; i++) { + for (i = 0; i < csp_num; i++) { free_label_patch_list(tmp_csp); tmp_csp++; } } +static void +free_all_label_param_frame_offsets(BranchBlock *frame_csp, uint32 csp_num) +{ + BranchBlock *tmp_csp = frame_csp; + uint32 i; + + for (i = 0; i < csp_num; i++) { + if (tmp_csp->param_frame_offsets) + wasm_runtime_free(tmp_csp->param_frame_offsets); + tmp_csp++; + } +} #endif /* end of WASM_ENABLE_FAST_INTERP */ #if WASM_ENABLE_GC != 0 @@ -8126,6 +8144,8 @@ wasm_loader_ctx_destroy(WASMLoaderContext *ctx) if (ctx->frame_csp_bottom) { #if WASM_ENABLE_FAST_INTERP != 0 free_all_label_patch_lists(ctx->frame_csp_bottom, ctx->csp_num); + free_all_label_param_frame_offsets(ctx->frame_csp_bottom, + ctx->csp_num); #endif #if WASM_ENABLE_GC != 0 wasm_loader_clean_all_local_use_masks(ctx); @@ -9238,8 +9258,14 @@ wasm_loader_emit_br_info(WASMLoaderContext *ctx, BranchBlock *frame_csp, emit_operand(ctx, *(int16 *)(frame_offset)); } /* Part e */ - dynamic_offset = - frame_csp->dynamic_offset + wasm_get_cell_num(types, arity); + if (frame_csp->label_type == LABEL_TYPE_LOOP) + /* Use start_dynamic_offset which was set in + copy_params_to_dynamic_space */ + dynamic_offset = frame_csp->start_dynamic_offset + + wasm_get_cell_num(types, arity); + else + dynamic_offset = + frame_csp->dynamic_offset + wasm_get_cell_num(types, arity); if (is_br) ctx->dynamic_offset = dynamic_offset; for (i = (int32)arity - 1; i >= 0; i--) { @@ -10623,8 +10649,8 @@ fail: * Part e: each param's dst offset */ static bool -copy_params_to_dynamic_space(WASMLoaderContext *loader_ctx, bool is_if_block, - char *error_buf, uint32 error_buf_size) +copy_params_to_dynamic_space(WASMLoaderContext *loader_ctx, char *error_buf, + uint32 error_buf_size) { bool ret = false; int16 *frame_offset = NULL; @@ -10638,6 +10664,7 @@ copy_params_to_dynamic_space(WASMLoaderContext *loader_ctx, bool is_if_block, uint32 param_count = block_type->u.type->param_count; int16 condition_offset = 0; bool disable_emit = false; + bool is_if_block = (block->label_type == LABEL_TYPE_IF ? true : false); int16 operand_offset = 0; uint64 size = (uint64)param_count * (sizeof(*cells) + sizeof(*src_offsets)); @@ -10690,6 +10717,14 @@ copy_params_to_dynamic_space(WASMLoaderContext *loader_ctx, bool is_if_block, if (is_if_block) emit_operand(loader_ctx, condition_offset); + /* Since the start offset to save the block's params and + * the start offset to save the block's results may be + * different, we remember the dynamic offset for loop block + * so that we can use it to copy the stack operands to the + * loop block's params in wasm_loader_emit_br_info. */ + if (block->label_type == LABEL_TYPE_LOOP) + block->start_dynamic_offset = loader_ctx->dynamic_offset; + /* Part e) */ /* Push to dynamic space. The push will emit the dst offset. */ for (i = 0; i < param_count; i++) @@ -11062,12 +11097,12 @@ re_scan: #endif /* end of WASM_ENABLE_GC != 0 */ } else { - uint32 type_index; + int32 type_index; /* Resolve the leb128 encoded type index as block type */ p--; p_org = p - 1; - read_leb_uint32(p, p_end, type_index); - if (type_index >= module->type_count) { + read_leb_int32(p, p_end, type_index); + if ((uint32)type_index >= module->type_count) { set_error_buf(error_buf, error_buf_size, "unknown type"); goto fail; @@ -11171,8 +11206,8 @@ re_scan: if (BLOCK_HAS_PARAM(block_type)) { /* Make sure params are in dynamic space */ - if (!copy_params_to_dynamic_space( - loader_ctx, false, error_buf, error_buf_size)) + if (!copy_params_to_dynamic_space(loader_ctx, error_buf, + error_buf_size)) goto fail; } @@ -11218,8 +11253,8 @@ re_scan: /* skip the if label */ skip_label(); /* Emit a copy instruction */ - if (!copy_params_to_dynamic_space( - loader_ctx, true, error_buf, error_buf_size)) + if (!copy_params_to_dynamic_space(loader_ctx, error_buf, + error_buf_size)) goto fail; /* Emit the if instruction */ diff --git a/core/iwasm/interpreter/wasm_mini_loader.c b/core/iwasm/interpreter/wasm_mini_loader.c index b9cd91fd..15e55925 100644 --- a/core/iwasm/interpreter/wasm_mini_loader.c +++ b/core/iwasm/interpreter/wasm_mini_loader.c @@ -3451,7 +3451,7 @@ wasm_loader_find_block_addr(WASMExecEnv *exec_env, BlockAddr *block_addr_cache, case EXT_OP_LOOP: case EXT_OP_IF: /* block type */ - skip_leb_uint32(p, p_end); + skip_leb_int32(p, p_end); if (block_nested_depth < sizeof(block_stack) / sizeof(BlockAddr)) { block_stack[block_nested_depth].start_addr = p; @@ -3921,7 +3921,11 @@ typedef struct BranchBlock { /* This is used to store available param num for if/else branch, so the else * opcode can know how many parameters should be copied to the stack */ uint32 available_param_num; - /* This is used to recover dynamic offset for else branch */ + /* This is used to recover the dynamic offset for else branch, + * and also to remember the start offset of dynamic space which + * stores the block arguments for loop block, so we can use it + * to copy the stack operands to the loop block's arguments in + * wasm_loader_emit_br_info for opcode br. */ uint16 start_dynamic_offset; #endif @@ -4050,13 +4054,26 @@ static void free_all_label_patch_lists(BranchBlock *frame_csp, uint32 csp_num) { BranchBlock *tmp_csp = frame_csp; + uint32 i; - for (uint32 i = 0; i < csp_num; i++) { + for (i = 0; i < csp_num; i++) { free_label_patch_list(tmp_csp); tmp_csp++; } } +static void +free_all_label_param_frame_offsets(BranchBlock *frame_csp, uint32 csp_num) +{ + BranchBlock *tmp_csp = frame_csp; + uint32 i; + + for (i = 0; i < csp_num; i++) { + if (tmp_csp->param_frame_offsets) + wasm_runtime_free(tmp_csp->param_frame_offsets); + tmp_csp++; + } +} #endif static bool @@ -4120,6 +4137,8 @@ wasm_loader_ctx_destroy(WASMLoaderContext *ctx) if (ctx->frame_csp_bottom) { #if WASM_ENABLE_FAST_INTERP != 0 free_all_label_patch_lists(ctx->frame_csp_bottom, ctx->csp_num); + free_all_label_param_frame_offsets(ctx->frame_csp_bottom, + ctx->csp_num); #endif wasm_runtime_free(ctx->frame_csp_bottom); } @@ -4798,8 +4817,14 @@ wasm_loader_emit_br_info(WASMLoaderContext *ctx, BranchBlock *frame_csp, emit_operand(ctx, *(int16 *)(frame_offset)); } /* Part e */ - dynamic_offset = - frame_csp->dynamic_offset + wasm_get_cell_num(types, arity); + if (frame_csp->label_type == LABEL_TYPE_LOOP) + /* Use start_dynamic_offset which was set in + copy_params_to_dynamic_space */ + dynamic_offset = frame_csp->start_dynamic_offset + + wasm_get_cell_num(types, arity); + else + dynamic_offset = + frame_csp->dynamic_offset + wasm_get_cell_num(types, arity); if (is_br) ctx->dynamic_offset = dynamic_offset; for (i = (int32)arity - 1; i >= 0; i--) { @@ -5778,8 +5803,8 @@ fail: * Part e: each param's dst offset */ static bool -copy_params_to_dynamic_space(WASMLoaderContext *loader_ctx, bool is_if_block, - char *error_buf, uint32 error_buf_size) +copy_params_to_dynamic_space(WASMLoaderContext *loader_ctx, char *error_buf, + uint32 error_buf_size) { bool ret = false; int16 *frame_offset = NULL; @@ -5793,6 +5818,7 @@ copy_params_to_dynamic_space(WASMLoaderContext *loader_ctx, bool is_if_block, uint32 param_count = block_type->u.type->param_count; int16 condition_offset = 0; bool disable_emit = false; + bool is_if_block = (block->label_type == LABEL_TYPE_IF ? true : false); int16 operand_offset = 0; uint64 size = (uint64)param_count * (sizeof(*cells) + sizeof(*src_offsets)); @@ -5845,6 +5871,14 @@ copy_params_to_dynamic_space(WASMLoaderContext *loader_ctx, bool is_if_block, if (is_if_block) emit_operand(loader_ctx, condition_offset); + /* Since the start offset to save the block's params and + * the start offset to save the block's results may be + * different, we remember the dynamic offset for loop block + * so that we can use it to copy the stack operands to the + * loop block's params in wasm_loader_emit_br_info. */ + if (block->label_type == LABEL_TYPE_LOOP) + block->start_dynamic_offset = loader_ctx->dynamic_offset; + /* Part e) */ /* Push to dynamic space. The push will emit the dst offset. */ for (i = 0; i < param_count; i++) @@ -6043,11 +6077,11 @@ re_scan: block_type.u.value_type.type = value_type; } else { - uint32 type_index; + int32 type_index; /* Resolve the leb128 encoded type index as block type */ p--; - read_leb_uint32(p, p_end, type_index); - bh_assert(type_index < module->type_count); + read_leb_int32(p, p_end, type_index); + bh_assert((uint32)type_index < module->type_count); block_type.is_value_type = false; block_type.u.type = module->types[type_index]; #if WASM_ENABLE_FAST_INTERP == 0 @@ -6134,8 +6168,8 @@ re_scan: skip_label(); if (BLOCK_HAS_PARAM(block_type)) { /* Make sure params are in dynamic space */ - if (!copy_params_to_dynamic_space( - loader_ctx, false, error_buf, error_buf_size)) + if (!copy_params_to_dynamic_space(loader_ctx, error_buf, + error_buf_size)) goto fail; } if (opcode == WASM_OP_LOOP) { @@ -6175,8 +6209,8 @@ re_scan: /* skip the if label */ skip_label(); /* Emit a copy instruction */ - if (!copy_params_to_dynamic_space( - loader_ctx, true, error_buf, error_buf_size)) + if (!copy_params_to_dynamic_space(loader_ctx, error_buf, + error_buf_size)) goto fail; /* Emit the if instruction */ diff --git a/tests/regression/ba-issues/issues/issue-3467/tt_unreachable.wasm b/tests/regression/ba-issues/issues/issue-3467/tt_unreachable.wasm new file mode 100644 index 00000000..9f56fb5e Binary files /dev/null and b/tests/regression/ba-issues/issues/issue-3467/tt_unreachable.wasm differ diff --git a/tests/regression/ba-issues/issues/issue-3468/i64.add.wasm b/tests/regression/ba-issues/issues/issue-3468/i64.add.wasm new file mode 100644 index 00000000..ea40df17 Binary files /dev/null and b/tests/regression/ba-issues/issues/issue-3468/i64.add.wasm differ diff --git a/tests/regression/ba-issues/running_config.json b/tests/regression/ba-issues/running_config.json index 7ec213e4..b7e35cad 100644 --- a/tests/regression/ba-issues/running_config.json +++ b/tests/regression/ba-issues/running_config.json @@ -1674,6 +1674,38 @@ "stdout content": "Hello from Kotlin via WASI\nCurrent 'realtime' timestamp is:", "description": "no 'type mismatch: expect (ref null ht) but got other1 unknown type'" } + }, + { + "deprecated": false, + "ids": [ + 3467 + ], + "runtime": "iwasm-default-wasi-disabled", + "file": "tt_unreachable.wasm", + "mode": "fast-interp", + "options": "--heap-size=0 -f to_test", + "argument": "", + "expected return": { + "ret code": 1, + "stdout content": "Exception: unreachable", + "description": "no '-1.861157e+19:f32'" + } + }, + { + "deprecated": false, + "ids": [ + 3468 + ], + "runtime": "iwasm-default-wasi-disabled", + "file": "i64.add.wasm", + "mode": "fast-interp", + "options": "--heap-size=0 -f to_test", + "argument": "", + "expected return": { + "ret code": 255, + "stdout content": "WASM module load failed: unknown type", + "description": "no '0x0:i64'" + } } ] }