Refine aot stack overflow check and enhance wasm loader malformed checks (#248)

And separate global data from wasm memory instance
This commit is contained in:
wenyongh 2020-05-08 12:38:59 +08:00 committed by GitHub
parent d381b0fdec
commit e8e45aeecd
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
16 changed files with 241 additions and 162 deletions

View File

@ -1959,12 +1959,14 @@ aot_load_from_comp_data(AOTCompData *comp_data, AOTCompContext *comp_ctx,
module->start_func_index = comp_data->start_func_index; module->start_func_index = comp_data->start_func_index;
if (comp_data->start_func_index != (uint32)-1) { if (comp_data->start_func_index != (uint32)-1) {
bh_assert(comp_data->start_func_index >= module->import_func_count bh_assert(comp_data->start_func_index < module->import_func_count
&& comp_data->start_func_index < module->import_func_count + module->func_count);
+ module->func_count); /* TODO: fix issue that start func cannot be import func */
module->start_function = if (comp_data->start_func_index >= module->import_func_count) {
module->func_ptrs[comp_data->start_func_index module->start_function =
- module->import_func_count]; module->func_ptrs[comp_data->start_func_index
- module->import_func_count];
}
} }
else { else {
module->start_function = NULL; module->start_function = NULL;

View File

@ -897,6 +897,15 @@ aot_call_indirect(WASMExecEnv *exec_env,
void *attachment = NULL; void *attachment = NULL;
char buf[128]; char buf[128];
/* this function is called from native code, so exec_env->handle and
exec_env->native_stack_boundary must have been set, we don't set
it again */
if ((uint8*)&module_inst < exec_env->native_stack_boundary) {
aot_set_exception_with_id(module_inst, EXCE_NATIVE_STACK_OVERFLOW);
return false;
}
if (table_elem_idx >= table_size) { if (table_elem_idx >= table_size) {
aot_set_exception_with_id(module_inst, EXCE_UNDEFINED_ELEMENT); aot_set_exception_with_id(module_inst, EXCE_UNDEFINED_ELEMENT);
return false; return false;
@ -941,15 +950,6 @@ aot_call_indirect(WASMExecEnv *exec_env,
} }
} }
/* this function is called from native code, so exec_env->handle and
exec_env->native_stack_boundary must have been set, we don't set
it again */
if ((uint8*)&module_inst < exec_env->native_stack_boundary) {
aot_set_exception_with_id(module_inst, EXCE_NATIVE_STACK_OVERFLOW);
return false;
}
return wasm_runtime_invoke_native(exec_env, func_ptr, return wasm_runtime_invoke_native(exec_env, func_ptr,
func_type, signature, attachment, func_type, signature, attachment,
argv, argc, argv); argv, argc, argv);

View File

@ -327,6 +327,8 @@ aot_create_funcs(const WASMModule *module)
/* Resolve local variable info and code info */ /* Resolve local variable info and code info */
funcs[i]->local_count = func->local_count; funcs[i]->local_count = func->local_count;
funcs[i]->local_types = func->local_types; funcs[i]->local_types = func->local_types;
funcs[i]->param_cell_num = func->param_cell_num;
funcs[i]->local_cell_num = func->local_cell_num;
funcs[i]->code = func->code; funcs[i]->code = func->code;
funcs[i]->code_size = func->code_size; funcs[i]->code_size = func->code_size;
} }

View File

@ -98,6 +98,8 @@ typedef struct AOTFunc {
uint32 func_type_index; uint32 func_type_index;
uint32 local_count; uint32 local_count;
uint8 *local_types; uint8 *local_types;
uint16 param_cell_num;
uint16 local_cell_num;
uint32 code_size; uint32 code_size;
uint8 *code; uint8 *code;
} AOTFunc; } AOTFunc;

View File

@ -256,11 +256,25 @@ call_aot_invoke_native_func(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
} }
static bool static bool
check_stack_boundary(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx) check_stack_boundary(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
uint32 callee_cell_num)
{ {
LLVMBasicBlockRef block_curr = LLVMGetInsertBlock(comp_ctx->builder); LLVMBasicBlockRef block_curr = LLVMGetInsertBlock(comp_ctx->builder);
LLVMBasicBlockRef check_stack; LLVMBasicBlockRef check_stack;
LLVMValueRef cmp; LLVMValueRef callee_local_size, stack_bound, cmp;
if (!(callee_local_size = I32_CONST(callee_cell_num * 4))) {
aot_set_last_error("llvm build const failed.");
return false;
}
if (!(stack_bound = LLVMBuildInBoundsGEP(comp_ctx->builder,
func_ctx->native_stack_bound,
&callee_local_size, 1,
"stack_bound"))) {
aot_set_last_error("llvm build inbound gep failed.");
return false;
}
if (!(check_stack = LLVMAppendBasicBlockInContext(comp_ctx->context, if (!(check_stack = LLVMAppendBasicBlockInContext(comp_ctx->context,
func_ctx->func, func_ctx->func,
@ -272,7 +286,7 @@ check_stack_boundary(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx)
LLVMMoveBasicBlockAfter(check_stack, block_curr); LLVMMoveBasicBlockAfter(check_stack, block_curr);
if (!(cmp = LLVMBuildICmp(comp_ctx->builder, LLVMIntULT, if (!(cmp = LLVMBuildICmp(comp_ctx->builder, LLVMIntULT,
func_ctx->last_alloca, func_ctx->native_stack_bound, func_ctx->last_alloca, stack_bound,
"cmp"))) { "cmp"))) {
aot_set_last_error("llvm build icmp failed."); aot_set_last_error("llvm build icmp failed.");
return false; return false;
@ -297,11 +311,13 @@ aot_compile_op_call(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
uint32 func_count = comp_ctx->func_ctx_count, param_cell_num = 0; uint32 func_count = comp_ctx->func_ctx_count, param_cell_num = 0;
AOTFuncContext **func_ctxes = comp_ctx->func_ctxes; AOTFuncContext **func_ctxes = comp_ctx->func_ctxes;
AOTFuncType *func_type; AOTFuncType *func_type;
AOTFunc *aot_func;
LLVMTypeRef *param_types = NULL, ret_type; LLVMTypeRef *param_types = NULL, ret_type;
LLVMValueRef *param_values = NULL, value_ret = NULL, func; LLVMValueRef *param_values = NULL, value_ret = NULL, func;
LLVMValueRef import_func_idx, res; LLVMValueRef import_func_idx, res;
int32 i, j = 0, param_count; int32 i, j = 0, param_count;
uint64 total_size; uint64 total_size;
uint32 callee_cell_num;
uint8 wasm_ret_type; uint8 wasm_ret_type;
bool ret = false; bool ret = false;
@ -379,8 +395,10 @@ aot_compile_op_call(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
} }
else { else {
func = func_ctxes[func_idx - import_func_count]->func; func = func_ctxes[func_idx - import_func_count]->func;
aot_func = func_ctxes[func_idx - import_func_count]->aot_func;
callee_cell_num = aot_func->param_cell_num + aot_func->local_cell_num + 1;
if (!check_stack_boundary(comp_ctx, func_ctx)) if (!check_stack_boundary(comp_ctx, func_ctx, callee_cell_num))
goto fail; goto fail;
/* Call the function */ /* Call the function */

View File

@ -901,7 +901,7 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
uint32 num_bytes_per_page = memory ? memory->num_bytes_per_page : 0; uint32 num_bytes_per_page = memory ? memory->num_bytes_per_page : 0;
uint32 total_mem_size = memory ? num_bytes_per_page * memory->cur_page_count uint32 total_mem_size = memory ? num_bytes_per_page * memory->cur_page_count
- heap_base_offset : 0; - heap_base_offset : 0;
uint8 *global_data = memory ? memory->global_data : NULL; uint8 *global_data = module->global_data;
WASMTableInstance *table = module->default_table; WASMTableInstance *table = module->default_table;
WASMGlobalInstance *globals = module->globals; WASMGlobalInstance *globals = module->globals;
uint8 opcode_IMPDEP = WASM_OP_IMPDEP; uint8 opcode_IMPDEP = WASM_OP_IMPDEP;
@ -1521,7 +1521,6 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
memory = module->default_memory; memory = module->default_memory;
total_mem_size = num_bytes_per_page * memory->cur_page_count total_mem_size = num_bytes_per_page * memory->cur_page_count
- heap_base_offset; - heap_base_offset;
global_data = memory->global_data;
} }
(void)reserved; (void)reserved;

View File

@ -893,7 +893,7 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
uint32 num_bytes_per_page = memory ? memory->num_bytes_per_page : 0; uint32 num_bytes_per_page = memory ? memory->num_bytes_per_page : 0;
uint32 total_mem_size = memory ? num_bytes_per_page * memory->cur_page_count uint32 total_mem_size = memory ? num_bytes_per_page * memory->cur_page_count
- heap_base_offset : 0; - heap_base_offset : 0;
uint8 *global_data = memory ? memory->global_data : NULL; uint8 *global_data = module->global_data;
WASMTableInstance *table = module->default_table; WASMTableInstance *table = module->default_table;
WASMGlobalInstance *globals = module->globals; WASMGlobalInstance *globals = module->globals;
uint8 opcode_IMPDEP = WASM_OP_IMPDEP; uint8 opcode_IMPDEP = WASM_OP_IMPDEP;
@ -1429,7 +1429,6 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
memory = module->default_memory; memory = module->default_memory;
total_mem_size = num_bytes_per_page * memory->cur_page_count total_mem_size = num_bytes_per_page * memory->cur_page_count
- heap_base_offset; - heap_base_offset;
global_data = memory->global_data;
} }
(void)reserved; (void)reserved;

View File

@ -467,6 +467,18 @@ load_type_section(const uint8 *buf, const uint8 *buf_end, WASMModule *module,
return true; return true;
} }
static bool
check_table_max_size(uint32 init_size, uint32 max_size,
char *error_buf, uint32 error_buf_size)
{
if (max_size < init_size) {
set_error_buf(error_buf, error_buf_size,
"size minimum must not be greater than maximum");
return false;
}
return true;
}
static bool static bool
load_table_import(const uint8 **p_buf, const uint8 *buf_end, load_table_import(const uint8 **p_buf, const uint8 *buf_end,
WASMTableImport *table, WASMTableImport *table,
@ -480,8 +492,12 @@ load_table_import(const uint8 **p_buf, const uint8 *buf_end,
bh_assert(table->elem_type == TABLE_ELEM_TYPE_ANY_FUNC); bh_assert(table->elem_type == TABLE_ELEM_TYPE_ANY_FUNC);
read_leb_uint32(p, p_end, table->flags); read_leb_uint32(p, p_end, table->flags);
read_leb_uint32(p, p_end, table->init_size); read_leb_uint32(p, p_end, table->init_size);
if (table->flags & 1) if (table->flags & 1) {
read_leb_uint32(p, p_end, table->max_size); read_leb_uint32(p, p_end, table->max_size);
if (!check_table_max_size(table->init_size, table->max_size,
error_buf, error_buf_size))
return false;
}
else else
table->max_size = 0x10000; table->max_size = 0x10000;
@ -573,8 +589,12 @@ load_table(const uint8 **p_buf, const uint8 *buf_end, WASMTable *table,
bh_assert(table->elem_type == TABLE_ELEM_TYPE_ANY_FUNC); bh_assert(table->elem_type == TABLE_ELEM_TYPE_ANY_FUNC);
read_leb_uint32(p, p_end, table->flags); read_leb_uint32(p, p_end, table->flags);
read_leb_uint32(p, p_end, table->init_size); read_leb_uint32(p, p_end, table->init_size);
if (table->flags & 1) if (table->flags & 1) {
read_leb_uint32(p, p_end, table->max_size); read_leb_uint32(p, p_end, table->max_size);
if (!check_table_max_size(table->init_size, table->max_size,
error_buf, error_buf_size))
return false;
}
else else
table->max_size = 0x10000; table->max_size = 0x10000;
@ -1065,7 +1085,6 @@ load_table_section(const uint8 *buf, const uint8 *buf_end, WASMModule *module,
WASMTable *table; WASMTable *table;
read_leb_uint32(p, p_end, table_count); read_leb_uint32(p, p_end, table_count);
bh_assert(table_count == 1);
if (table_count) { if (table_count) {
if (table_count > 1) { if (table_count > 1) {
@ -2419,6 +2438,7 @@ typedef struct BranchBlock {
uint8 block_type; uint8 block_type;
uint8 return_type; uint8 return_type;
bool is_block_reachable; bool is_block_reachable;
bool skip_else_branch;
uint8 *start_addr; uint8 *start_addr;
uint8 *else_addr; uint8 *else_addr;
uint8 *end_addr; uint8 *end_addr;
@ -2590,10 +2610,13 @@ check_stack_pop(WASMLoaderContext *ctx, uint8 type,
char *error_buf, uint32 error_buf_size, char *error_buf, uint32 error_buf_size,
const char *type_str) const char *type_str)
{ {
uint32 block_stack_cell_num = ctx->stack_cell_num
- (ctx->frame_csp - 1)->stack_cell_num;
if (((type == VALUE_TYPE_I32 || type == VALUE_TYPE_F32) if (((type == VALUE_TYPE_I32 || type == VALUE_TYPE_F32)
&& ctx->stack_cell_num < 1) && block_stack_cell_num < 1)
|| ((type == VALUE_TYPE_I64 || type == VALUE_TYPE_F64) || ((type == VALUE_TYPE_I64 || type == VALUE_TYPE_F64)
&& ctx->stack_cell_num < 2)) { && block_stack_cell_num < 2)) {
set_error_buf(error_buf, error_buf_size, set_error_buf(error_buf, error_buf_size,
"WASM module load failed: " "WASM module load failed: "
"type mismatch: expect data but stack was empty"); "type mismatch: expect data but stack was empty");
@ -2766,7 +2789,17 @@ static bool
wasm_loader_pop_frame_csp(WASMLoaderContext *ctx, wasm_loader_pop_frame_csp(WASMLoaderContext *ctx,
char *error_buf, uint32 error_buf_size) char *error_buf, uint32 error_buf_size)
{ {
uint8 block_return_type;
CHECK_CSP_POP(); CHECK_CSP_POP();
block_return_type = (ctx->frame_csp - 1)->return_type;
if (!wasm_loader_pop_frame_ref(ctx, block_return_type,
error_buf, error_buf_size)
|| !wasm_loader_push_frame_ref(ctx, block_return_type,
error_buf, error_buf_size))
goto fail;
ctx->frame_csp--; ctx->frame_csp--;
ctx->csp_num--; ctx->csp_num--;
return true; return true;
@ -3476,7 +3509,6 @@ fail:
goto fail; \ goto fail; \
} while (0) } while (0)
#define GET_LOCAL_INDEX_TYPE_AND_OFFSET() do { \ #define GET_LOCAL_INDEX_TYPE_AND_OFFSET() do { \
read_leb_uint32(p, p_end, local_idx); \ read_leb_uint32(p, p_end, local_idx); \
if (local_idx >= param_count + local_count) { \ if (local_idx >= param_count + local_count) { \
@ -3515,11 +3547,6 @@ check_memory(WASMModule *module,
goto fail; \ goto fail; \
} while (0) } while (0)
#if WASM_ENABLE_FAST_INTERP != 0
#endif /* WASM_ENABLE_FAST_INTERP */
static bool static bool
is_block_type_valid(uint8 type) is_block_type_valid(uint8 type)
{ {
@ -3538,6 +3565,44 @@ is_block_type_valid(uint8 type)
} \ } \
} while (0) } while (0)
static BranchBlock *
check_branch_block(WASMLoaderContext *loader_ctx,
uint8 **p_buf, uint8 *buf_end,
char *error_buf, uint32 error_buf_size)
{
uint8 *p = *p_buf, *p_end = buf_end;
BranchBlock *frame_csp_tmp;
uint32 depth;
read_leb_uint32(p, p_end, depth);
CHECK_BR(depth);
frame_csp_tmp = loader_ctx->frame_csp - depth - 1;
#if WASM_ENABLE_FAST_INTERP != 0
emit_br_info(frame_csp_tmp);
#endif
*p_buf = p;
return frame_csp_tmp;
fail:
return NULL;
}
static bool
check_branch_block_ret(WASMLoaderContext *loader_ctx,
BranchBlock *frame_csp_tmp,
char *error_buf, uint32 error_buf_size)
{
frame_csp_tmp->is_block_reachable = true;
if (frame_csp_tmp->block_type != BLOCK_TYPE_LOOP) {
uint8 block_return_type = frame_csp_tmp->return_type;
POP_TYPE(block_return_type);
PUSH_TYPE(block_return_type);
}
return true;
fail:
return false;
}
static bool static bool
wasm_loader_prepare_bytecode(WASMModule *module, WASMFunction *func, wasm_loader_prepare_bytecode(WASMModule *module, WASMFunction *func,
BlockAddr *block_addr_cache, BlockAddr *block_addr_cache,
@ -3547,7 +3612,7 @@ wasm_loader_prepare_bytecode(WASMModule *module, WASMFunction *func,
uint32 param_count, local_count, global_count; uint32 param_count, local_count, global_count;
uint8 *param_types, ret_type, *local_types, local_type, global_type; uint8 *param_types, ret_type, *local_types, local_type, global_type;
uint16 *local_offsets, local_offset; uint16 *local_offsets, local_offset;
uint32 count, i, local_idx, global_idx, depth, u32, align, mem_offset; uint32 count, i, local_idx, global_idx, u32, align, mem_offset;
uint32 cache_index, item_index; uint32 cache_index, item_index;
int32 i32, i32_const = 0; int32 i32, i32_const = 0;
int64 i64; int64 i64;
@ -3555,6 +3620,7 @@ wasm_loader_prepare_bytecode(WASMModule *module, WASMFunction *func,
bool return_value = false, is_i32_const = false; bool return_value = false, is_i32_const = false;
BlockAddr *cache_items; BlockAddr *cache_items;
WASMLoaderContext *loader_ctx; WASMLoaderContext *loader_ctx;
BranchBlock *frame_csp_tmp;
#if WASM_ENABLE_FAST_INTERP != 0 #if WASM_ENABLE_FAST_INTERP != 0
uint8 *func_const_end, *func_const; uint8 *func_const_end, *func_const;
int16 operand_offset; int16 operand_offset;
@ -3657,32 +3723,32 @@ re_scan:
if (!is_i32_const) if (!is_i32_const)
(loader_ctx->frame_csp - 1)->is_block_reachable = true; (loader_ctx->frame_csp - 1)->is_block_reachable = true;
else { else {
if (!i32_const) { cache_index = ((uintptr_t)(loader_ctx->frame_csp - 1)->start_addr)
cache_index = ((uintptr_t)(loader_ctx->frame_csp - 1)->start_addr) & (uintptr_t)(BLOCK_ADDR_CACHE_SIZE - 1);
& (uintptr_t)(BLOCK_ADDR_CACHE_SIZE - 1); cache_items = block_addr_cache
cache_items = block_addr_cache + + BLOCK_ADDR_CONFLICT_SIZE * cache_index;
BLOCK_ADDR_CONFLICT_SIZE * cache_index; for (item_index = 0; item_index < BLOCK_ADDR_CONFLICT_SIZE;
for (item_index = 0; item_index < BLOCK_ADDR_CONFLICT_SIZE; item_index++) {
item_index++) { if (cache_items[item_index].start_addr ==
if (cache_items[item_index].start_addr == (loader_ctx->frame_csp - 1)->start_addr) {
(loader_ctx->frame_csp - 1)->start_addr) { (loader_ctx->frame_csp - 1)->else_addr =
(loader_ctx->frame_csp - 1)->else_addr = cache_items[item_index].else_addr;
cache_items[item_index].else_addr; (loader_ctx->frame_csp - 1)->end_addr =
(loader_ctx->frame_csp - 1)->end_addr = cache_items[item_index].end_addr;
cache_items[item_index].end_addr; break;
break;
}
} }
if (item_index == BLOCK_ADDR_CONFLICT_SIZE }
&& !wasm_loader_find_block_addr(block_addr_cache, if (item_index == BLOCK_ADDR_CONFLICT_SIZE
(loader_ctx->frame_csp - 1)->start_addr, && !wasm_loader_find_block_addr(block_addr_cache,
p_end, (loader_ctx->frame_csp - 1)->start_addr,
(loader_ctx->frame_csp - 1)->block_type, p_end,
&(loader_ctx->frame_csp - 1)->else_addr, (loader_ctx->frame_csp - 1)->block_type,
&(loader_ctx->frame_csp - 1)->end_addr, &(loader_ctx->frame_csp - 1)->else_addr,
error_buf, error_buf_size)) &(loader_ctx->frame_csp - 1)->end_addr,
goto fail; error_buf, error_buf_size))
goto fail;
if (!i32_const) {
if ((loader_ctx->frame_csp - 1)->else_addr) { if ((loader_ctx->frame_csp - 1)->else_addr) {
#if WASM_ENABLE_FAST_INTERP != 0 #if WASM_ENABLE_FAST_INTERP != 0
loader_ctx->frame_offset = loader_ctx->frame_offset_bottom + loader_ctx->frame_offset = loader_ctx->frame_offset_bottom +
@ -3698,6 +3764,10 @@ re_scan:
is_i32_const = false; is_i32_const = false;
continue; continue;
} }
else {
/* The else branch cannot be reached, ignored it. */
(loader_ctx->frame_csp - 1)->skip_else_branch = true;
}
} }
break; break;
@ -3710,6 +3780,16 @@ re_scan:
goto fail; goto fail;
} }
if ((loader_ctx->frame_csp - 1)->skip_else_branch) {
/* The else branch is ignored. */
is_i32_const = false;
p = (loader_ctx->frame_csp - 1)->end_addr;
#if WASM_ENABLE_FAST_INTERP != 0
skip_label();
#endif
continue;
}
(loader_ctx->frame_csp - 1)->else_addr = p - 1; (loader_ctx->frame_csp - 1)->else_addr = p - 1;
loader_ctx->stack_cell_num = (loader_ctx->frame_csp - 1)->stack_cell_num; loader_ctx->stack_cell_num = (loader_ctx->frame_csp - 1)->stack_cell_num;
loader_ctx->frame_ref = loader_ctx->frame_ref_bottom + loader_ctx->frame_ref = loader_ctx->frame_ref_bottom +
@ -3748,9 +3828,6 @@ re_scan:
{ {
POP_CSP(); POP_CSP();
POP_TYPE(loader_ctx->frame_csp->return_type);
PUSH_TYPE(loader_ctx->frame_csp->return_type);
#if WASM_ENABLE_FAST_INTERP != 0 #if WASM_ENABLE_FAST_INTERP != 0
skip_label(); skip_label();
// copy the result to the block return address // copy the result to the block return address
@ -3800,16 +3877,13 @@ re_scan:
case WASM_OP_BR: case WASM_OP_BR:
{ {
#if WASM_ENABLE_FAST_INTERP != 0 if (!(frame_csp_tmp = check_branch_block(loader_ctx, &p, p_end,
BranchBlock *frame_csp_tmp; error_buf, error_buf_size)))
#endif goto fail;
read_leb_uint32(p, p_end, depth);
CHECK_BR(depth);
#if WASM_ENABLE_FAST_INTERP != 0 if (!check_branch_block_ret(loader_ctx, frame_csp_tmp,
frame_csp_tmp = loader_ctx->frame_csp - depth - 1; error_buf, error_buf_size))
emit_br_info(frame_csp_tmp); goto fail;
#endif
handle_next_reachable_block: handle_next_reachable_block:
for (i = 1; i <= loader_ctx->csp_num; i++) for (i = 1; i <= loader_ctx->csp_num; i++)
@ -3870,31 +3944,25 @@ handle_next_reachable_block:
case WASM_OP_BR_IF: case WASM_OP_BR_IF:
{ {
#if WASM_ENABLE_FAST_INTERP != 0
BranchBlock *frame_csp_tmp;
#endif
read_leb_uint32(p, p_end, depth);
POP_I32(); POP_I32();
CHECK_BR(depth);
#if WASM_ENABLE_FAST_INTERP != 0 if (!(frame_csp_tmp = check_branch_block(loader_ctx, &p, p_end,
frame_csp_tmp = loader_ctx->frame_csp - depth - 1; error_buf, error_buf_size)))
emit_br_info(frame_csp_tmp); goto fail;
#endif
if (!is_i32_const) if (!is_i32_const || i32_const) {
(loader_ctx->frame_csp - (depth + 1))->is_block_reachable = true; /* The branch can be reached */
else { if (!check_branch_block_ret(loader_ctx, frame_csp_tmp,
if (i32_const) error_buf, error_buf_size))
goto handle_next_reachable_block; goto fail;
} }
if (is_i32_const && i32_const)
goto handle_next_reachable_block;
break; break;
} }
case WASM_OP_BR_TABLE: case WASM_OP_BR_TABLE:
{ {
#if WASM_ENABLE_FAST_INTERP != 0
BranchBlock *frame_csp_tmp;
#endif
read_leb_uint32(p, p_end, count); read_leb_uint32(p, p_end, count);
#if WASM_ENABLE_FAST_INTERP != 0 #if WASM_ENABLE_FAST_INTERP != 0
emit_const(count); emit_const(count);
@ -3903,12 +3971,13 @@ handle_next_reachable_block:
/* TODO: check the const */ /* TODO: check the const */
for (i = 0; i <= count; i++) { for (i = 0; i <= count; i++) {
read_leb_uint32(p, p_end, depth); if (!(frame_csp_tmp = check_branch_block(loader_ctx, &p, p_end,
CHECK_BR(depth); error_buf, error_buf_size)))
#if WASM_ENABLE_FAST_INTERP != 0 goto fail;
frame_csp_tmp = loader_ctx->frame_csp - depth - 1;
emit_br_info(frame_csp_tmp); if (!check_branch_block_ret(loader_ctx, frame_csp_tmp,
#endif error_buf, error_buf_size))
goto fail;
} }
goto handle_next_reachable_block; goto handle_next_reachable_block;
@ -4037,10 +4106,12 @@ handle_next_reachable_block:
case WASM_OP_DROP: case WASM_OP_DROP:
case WASM_OP_DROP_64: case WASM_OP_DROP_64:
{ {
if (loader_ctx->stack_cell_num <= 0) { if (loader_ctx->stack_cell_num
- (loader_ctx->frame_csp - 1)->stack_cell_num <= 0) {
set_error_buf(error_buf, error_buf_size, set_error_buf(error_buf, error_buf_size,
"WASM loader prepare bytecode failed: " "WASM loader prepare bytecode failed: "
"opcode drop was found but stack was empty"); "type mismatch, opcode drop was found "
"but stack was empty");
goto fail; goto fail;
} }
@ -4057,10 +4128,12 @@ handle_next_reachable_block:
#endif #endif
} }
else { else {
if (loader_ctx->stack_cell_num <= 1) { if (loader_ctx->stack_cell_num
- (loader_ctx->frame_csp - 1)->stack_cell_num <= 0) {
set_error_buf(error_buf, error_buf_size, set_error_buf(error_buf, error_buf_size,
"WASM loader prepare bytecode failed: " "WASM loader prepare bytecode failed: "
"opcode drop was found but stack was empty"); "type mismatch, opcode drop was found "
"but stack was empty");
goto fail; goto fail;
} }
loader_ctx->frame_ref -= 2; loader_ctx->frame_ref -= 2;

View File

@ -60,15 +60,13 @@ memories_deinstantiate(WASMMemoryInstance **memories, uint32 count)
static WASMMemoryInstance* static WASMMemoryInstance*
memory_instantiate(uint32 num_bytes_per_page, memory_instantiate(uint32 num_bytes_per_page,
uint32 init_page_count, uint32 max_page_count, uint32 init_page_count, uint32 max_page_count,
uint32 global_data_size,
uint32 heap_size, uint32 heap_size,
char *error_buf, uint32 error_buf_size) char *error_buf, uint32 error_buf_size)
{ {
WASMMemoryInstance *memory; WASMMemoryInstance *memory;
uint64 total_size = offsetof(WASMMemoryInstance, base_addr) + uint64 total_size = offsetof(WASMMemoryInstance, base_addr) +
(uint64)heap_size + (uint64)heap_size +
num_bytes_per_page * (uint64)init_page_count + num_bytes_per_page * (uint64)init_page_count;
global_data_size;
/* Allocate memory space, addr data and global data */ /* Allocate memory space, addr data and global data */
if (total_size >= UINT32_MAX if (total_size >= UINT32_MAX
@ -85,10 +83,8 @@ memory_instantiate(uint32 num_bytes_per_page,
memory->heap_data = memory->base_addr; memory->heap_data = memory->base_addr;
memory->memory_data = memory->heap_data + heap_size; memory->memory_data = memory->heap_data + heap_size;
memory->global_data = memory->memory_data + memory->end_addr = memory->memory_data +
num_bytes_per_page * memory->cur_page_count; num_bytes_per_page * memory->cur_page_count;
memory->global_data_size = global_data_size;
memory->end_addr = memory->global_data + global_data_size;
bh_assert(memory->end_addr - (uint8*)memory == (uint32)total_size); bh_assert(memory->end_addr - (uint8*)memory == (uint32)total_size);
@ -112,7 +108,7 @@ memory_instantiate(uint32 num_bytes_per_page,
*/ */
static WASMMemoryInstance** static WASMMemoryInstance**
memories_instantiate(const WASMModule *module, memories_instantiate(const WASMModule *module,
uint32 global_data_size, uint32 heap_size, uint32 heap_size,
char *error_buf, uint32 error_buf_size) char *error_buf, uint32 error_buf_size)
{ {
WASMImport *import; WASMImport *import;
@ -121,9 +117,6 @@ memories_instantiate(const WASMModule *module,
uint64 total_size; uint64 total_size;
WASMMemoryInstance **memories, *memory; WASMMemoryInstance **memories, *memory;
if (memory_count == 0 && global_data_size > 0)
memory_count = 1;
total_size = sizeof(WASMMemoryInstance*) * (uint64)memory_count; total_size = sizeof(WASMMemoryInstance*) * (uint64)memory_count;
if (total_size >= UINT32_MAX if (total_size >= UINT32_MAX
@ -143,7 +136,6 @@ memories_instantiate(const WASMModule *module,
memory_instantiate(import->u.memory.num_bytes_per_page, memory_instantiate(import->u.memory.num_bytes_per_page,
import->u.memory.init_page_count, import->u.memory.init_page_count,
import->u.memory. max_page_count, import->u.memory. max_page_count,
global_data_size,
heap_size, error_buf, error_buf_size))) { heap_size, error_buf, error_buf_size))) {
set_error_buf(error_buf, error_buf_size, set_error_buf(error_buf, error_buf_size,
"Instantiate memory failed: " "Instantiate memory failed: "
@ -159,7 +151,6 @@ memories_instantiate(const WASMModule *module,
memory_instantiate(module->memories[i].num_bytes_per_page, memory_instantiate(module->memories[i].num_bytes_per_page,
module->memories[i].init_page_count, module->memories[i].init_page_count,
module->memories[i].max_page_count, module->memories[i].max_page_count,
global_data_size,
heap_size, error_buf, error_buf_size))) { heap_size, error_buf, error_buf_size))) {
set_error_buf(error_buf, error_buf_size, set_error_buf(error_buf, error_buf_size,
"Instantiate memory failed: " "Instantiate memory failed: "
@ -172,8 +163,8 @@ memories_instantiate(const WASMModule *module,
if (mem_index == 0) { if (mem_index == 0) {
/* no import memory and define memory, but has global variables */ /* no import memory and define memory, but has global variables */
if (!(memory = memories[mem_index++] = if (!(memory = memories[mem_index++] =
memory_instantiate(0, 0, 0, global_data_size, memory_instantiate(0, 0, 0, heap_size,
heap_size, error_buf, error_buf_size))) { error_buf, error_buf_size))) {
set_error_buf(error_buf, error_buf_size, set_error_buf(error_buf, error_buf_size,
"Instantiate memory failed: " "Instantiate memory failed: "
"allocate memory failed.\n"); "allocate memory failed.\n");
@ -608,11 +599,20 @@ wasm_instantiate(WASMModule *module,
module->import_function_count + module->function_count; module->import_function_count + module->function_count;
module_inst->export_func_count = get_export_function_count(module); module_inst->export_func_count = get_export_function_count(module);
if (global_count > 0) {
if (!(module_inst->global_data =
wasm_runtime_malloc(global_data_size))) {
wasm_deinstantiate(module_inst);
return NULL;
}
memset(module_inst->global_data, 0, global_data_size);
}
/* Instantiate memories/tables/functions */ /* Instantiate memories/tables/functions */
if (((module_inst->memory_count > 0 || global_count > 0) if ((module_inst->memory_count > 0
&& !(module_inst->memories = && !(module_inst->memories =
memories_instantiate(module, global_data_size, memories_instantiate(module, heap_size,
heap_size, error_buf, error_buf_size))) error_buf, error_buf_size)))
|| (module_inst->table_count > 0 || (module_inst->table_count > 0
&& !(module_inst->tables = tables_instantiate(module, && !(module_inst->tables = tables_instantiate(module,
error_buf, error_buf,
@ -629,13 +629,8 @@ wasm_instantiate(WASMModule *module,
return NULL; return NULL;
} }
if (module_inst->memory_count || global_count > 0) { if (global_count > 0) {
WASMMemoryInstance *memory; /* fix globals */
memory = module_inst->default_memory = module_inst->memories[0];
memory_data = module_inst->default_memory->memory_data;
/* fix import memoryBase */
if (!globals_instantiate_fix(globals, module, module_inst, if (!globals_instantiate_fix(globals, module, module_inst,
error_buf, error_buf_size)) { error_buf, error_buf_size)) {
wasm_deinstantiate(module_inst); wasm_deinstantiate(module_inst);
@ -643,7 +638,7 @@ wasm_instantiate(WASMModule *module,
} }
/* Initialize the global data */ /* Initialize the global data */
global_data = memory->global_data; global_data = module_inst->global_data;
global_data_end = global_data + global_data_size; global_data_end = global_data + global_data_size;
global = globals; global = globals;
for (i = 0; i < global_count; i++, global++) { for (i = 0; i < global_count; i++, global++) {
@ -665,8 +660,16 @@ wasm_instantiate(WASMModule *module,
} }
bh_assert(global_data == global_data_end); bh_assert(global_data == global_data_end);
}
if (module_inst->memory_count) {
WASMMemoryInstance *memory;
memory = module_inst->default_memory = module_inst->memories[0];
memory_data = module_inst->default_memory->memory_data;
/* Initialize the memory data with data segment section */ /* Initialize the memory data with data segment section */
if (module_inst->default_memory->cur_page_count > 0) { if (memory->cur_page_count > 0) {
for (i = 0; i < module->data_seg_count; i++) { for (i = 0; i < module->data_seg_count; i++) {
data_seg = module->data_segments[i]; data_seg = module->data_segments[i];
bh_assert(data_seg->memory_index == 0); bh_assert(data_seg->memory_index == 0);
@ -685,8 +688,8 @@ wasm_instantiate(WASMModule *module,
base_offset = (uint32)data_seg->base_offset.u.i32; base_offset = (uint32)data_seg->base_offset.u.i32;
length = data_seg->data_length; length = data_seg->data_length;
memory_size = module_inst->default_memory->num_bytes_per_page memory_size = memory->num_bytes_per_page
* module_inst->default_memory->cur_page_count; * memory->cur_page_count;
if (length > 0 if (length > 0
&& (base_offset >= memory_size && (base_offset >= memory_size
@ -825,6 +828,9 @@ wasm_deinstantiate(WASMModuleInstance *module_inst)
globals_deinstantiate(module_inst->globals); globals_deinstantiate(module_inst->globals);
export_functions_deinstantiate(module_inst->export_functions); export_functions_deinstantiate(module_inst->export_functions);
if (module_inst->global_data)
wasm_runtime_free(module_inst->global_data);
wasm_runtime_free(module_inst); wasm_runtime_free(module_inst);
} }
@ -1057,14 +1063,11 @@ wasm_enlarge_memory(WASMModuleInstance *module, uint32 inc_page_count)
{ {
WASMMemoryInstance *memory = module->default_memory, *new_memory; WASMMemoryInstance *memory = module->default_memory, *new_memory;
uint32 heap_size = memory->memory_data - memory->heap_data; uint32 heap_size = memory->memory_data - memory->heap_data;
uint32 old_page_count = memory->cur_page_count;
uint32 total_size_old = memory->end_addr - (uint8*)memory; uint32 total_size_old = memory->end_addr - (uint8*)memory;
uint32 total_page_count = inc_page_count + memory->cur_page_count; uint32 total_page_count = inc_page_count + memory->cur_page_count;
uint64 total_size = offsetof(WASMMemoryInstance, base_addr) uint64 total_size = offsetof(WASMMemoryInstance, base_addr)
+ (uint64)heap_size + (uint64)heap_size
+ memory->num_bytes_per_page * (uint64)total_page_count + memory->num_bytes_per_page * (uint64)total_page_count;
+ memory->global_data_size;
uint8 *global_data_old;
void *heap_handle_old = memory->heap_handle; void *heap_handle_old = memory->heap_handle;
if (inc_page_count <= 0) if (inc_page_count <= 0)
@ -1111,17 +1114,8 @@ wasm_enlarge_memory(WASMModuleInstance *module, uint32 inc_page_count)
new_memory->cur_page_count = total_page_count; new_memory->cur_page_count = total_page_count;
new_memory->heap_data = new_memory->base_addr; new_memory->heap_data = new_memory->base_addr;
new_memory->memory_data = new_memory->base_addr + heap_size; new_memory->memory_data = new_memory->base_addr + heap_size;
new_memory->global_data = new_memory->memory_data + new_memory->end_addr = new_memory->memory_data +
new_memory->num_bytes_per_page * total_page_count; new_memory->num_bytes_per_page * total_page_count;
new_memory->end_addr = new_memory->global_data + new_memory->global_data_size;
global_data_old = new_memory->memory_data +
new_memory->num_bytes_per_page * old_page_count;
/* Copy global data */
bh_memcpy_s(new_memory->global_data, new_memory->global_data_size,
global_data_old, new_memory->global_data_size);
memset(global_data_old, 0, new_memory->global_data_size);
module->memories[0] = module->default_memory = new_memory; module->memories[0] = module->default_memory = new_memory;
return true; return true;

View File

@ -33,17 +33,12 @@ typedef struct WASMMemoryInstance {
/* Memory data */ /* Memory data */
uint8 *memory_data; uint8 *memory_data;
/* Global data of global instances */
uint8 *global_data;
uint32 global_data_size;
/* End address of memory */ /* End address of memory */
uint8 *end_addr; uint8 *end_addr;
/* Base address, the layout is: /* Base address, the layout is:
heap_data + memory data + global data heap_data + memory data
memory data init size is: num_bytes_per_page * cur_page_count memory data init size is: num_bytes_per_page * cur_page_count
global data size is calculated in module instantiating
Note: when memory is re-allocated, the heap data and memory data Note: when memory is re-allocated, the heap data and memory data
must be copied to new memory also. must be copied to new memory also.
*/ */
@ -127,6 +122,8 @@ typedef struct WASMModuleInstance {
WASMMemoryInstance *default_memory; WASMMemoryInstance *default_memory;
WASMTableInstance *default_table; WASMTableInstance *default_table;
/* Global data of global instances */
uint8 *global_data;
WASMFunctionInstance *start_function; WASMFunctionInstance *start_function;

View File

@ -37,10 +37,8 @@ extern "C" {
#define BH_PLATFORM_ANDROID #define BH_PLATFORM_ANDROID
#endif #endif
#define _STACK_SIZE_ADJUSTMENT (32 * 1024)
/* Stack size of applet threads's native part. */ /* Stack size of applet threads's native part. */
#define BH_APPLET_PRESERVED_STACK_SIZE (32 * 1024 + _STACK_SIZE_ADJUSTMENT) #define BH_APPLET_PRESERVED_STACK_SIZE (32 * 1024)
/* Default thread priority */ /* Default thread priority */
#define BH_THREAD_DEFAULT_PRIORITY 0 #define BH_THREAD_DEFAULT_PRIORITY 0

View File

@ -233,7 +233,8 @@ uint8 *os_thread_get_stack_boundary()
} }
if (addr) if (addr)
return (uint8*)addr + _STACK_SIZE_ADJUSTMENT; /* Reserved 4 KB for safety */
return (uint8*)addr + 4 * 1024;
else else
return NULL; return NULL;
} }

View File

@ -37,10 +37,8 @@ extern "C" {
#define BH_PLATFORM_DARWIN #define BH_PLATFORM_DARWIN
#endif #endif
#define _STACK_SIZE_ADJUSTMENT (32 * 1024)
/* Stack size of applet threads's native part. */ /* Stack size of applet threads's native part. */
#define BH_APPLET_PRESERVED_STACK_SIZE (32 * 1024 + _STACK_SIZE_ADJUSTMENT) #define BH_APPLET_PRESERVED_STACK_SIZE (32 * 1024)
/* Default thread priority */ /* Default thread priority */
#define BH_THREAD_DEFAULT_PRIORITY 0 #define BH_THREAD_DEFAULT_PRIORITY 0

View File

@ -37,10 +37,8 @@ extern "C" {
#define BH_PLATFORM_LINUX #define BH_PLATFORM_LINUX
#endif #endif
#define _STACK_SIZE_ADJUSTMENT (32 * 1024)
/* Stack size of applet threads's native part. */ /* Stack size of applet threads's native part. */
#define BH_APPLET_PRESERVED_STACK_SIZE (32 * 1024 + _STACK_SIZE_ADJUSTMENT) #define BH_APPLET_PRESERVED_STACK_SIZE (32 * 1024)
/* Default thread priority */ /* Default thread priority */
#define BH_THREAD_DEFAULT_PRIORITY 0 #define BH_THREAD_DEFAULT_PRIORITY 0

View File

@ -36,10 +36,8 @@ extern "C" {
#define BH_PLATFORM_VXWORKS #define BH_PLATFORM_VXWORKS
#endif #endif
#define _STACK_SIZE_ADJUSTMENT (32 * 1024)
/* Stack size of applet threads's native part. */ /* Stack size of applet threads's native part. */
#define BH_APPLET_PRESERVED_STACK_SIZE (32 * 1024 + _STACK_SIZE_ADJUSTMENT) #define BH_APPLET_PRESERVED_STACK_SIZE (32 * 1024)
/* Default thread priority */ /* Default thread priority */
#define BH_THREAD_DEFAULT_PRIORITY 0 #define BH_THREAD_DEFAULT_PRIORITY 0

View File

@ -74,7 +74,7 @@ host_interface interface = {
timer_ctx_t timer_ctx; timer_ctx_t timer_ctx;
static char global_heap_buf[370 * 1024] = { 0 }; static char global_heap_buf[368 * 1024] = { 0 };
static NativeSymbol native_symbols[] = { static NativeSymbol native_symbols[] = {
EXPORT_WASM_API_WITH_SIG(display_input_read, "(*)i"), EXPORT_WASM_API_WITH_SIG(display_input_read, "(*)i"),