From f72e84811474991db5dcb48c7069de583e281fe9 Mon Sep 17 00:00:00 2001 From: wenyongh Date: Wed, 22 Apr 2020 18:43:50 +0800 Subject: [PATCH 1/2] Refine aot memory boundary check, add more llvm passes (#236) Fix issue of some error info mismatch with spec cases --- core/iwasm/compilation/aot_emit_control.c | 5 ++ core/iwasm/compilation/aot_emit_memory.c | 47 +++++++----- core/iwasm/compilation/aot_emit_variable.c | 7 ++ core/iwasm/compilation/aot_llvm.c | 84 ++++++++++++++++++++- core/iwasm/compilation/aot_llvm.h | 24 ++++++ core/iwasm/interpreter/wasm_loader.c | 86 +++++++++++++++++----- core/iwasm/interpreter/wasm_runtime.c | 2 +- 7 files changed, 216 insertions(+), 39 deletions(-) diff --git a/core/iwasm/compilation/aot_emit_control.c b/core/iwasm/compilation/aot_emit_control.c index d2a321fa19..4dbaabb065 100644 --- a/core/iwasm/compilation/aot_emit_control.c +++ b/core/iwasm/compilation/aot_emit_control.c @@ -127,6 +127,8 @@ handle_next_reachable_block(AOTCompContext *comp_ctx, AOTBlock *block_prev; uint8 *frame_ip; + aot_checked_addr_list_destroy(func_ctx); + if (block->block_type == BLOCK_TYPE_IF && block->llvm_else_block && !block->skip_wasm_code_else @@ -233,6 +235,8 @@ aot_compile_op_block(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, /* Start to translate the block */ SET_BUILDER_POS(block->llvm_entry_block); aot_block_stack_push(&func_ctx->block_stack, block); + if (block_type == BLOCK_TYPE_LOOP) + aot_checked_addr_list_destroy(func_ctx); } else if (block_type == BLOCK_TYPE_IF) { POP_COND(value); @@ -373,6 +377,7 @@ aot_compile_op_else(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, /* Clear value stack and start to translate else branch */ aot_value_stack_destroy(&block->value_stack); SET_BUILDER_POS(block->llvm_else_block); + aot_checked_addr_list_destroy(func_ctx); return true; } diff --git a/core/iwasm/compilation/aot_emit_memory.c b/core/iwasm/compilation/aot_emit_memory.c index cdabe6b924..674d2eb1a3 100644 --- a/core/iwasm/compilation/aot_emit_memory.c +++ b/core/iwasm/compilation/aot_emit_memory.c @@ -82,6 +82,7 @@ check_memory_overflow(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, LLVMValueRef mem_base_addr, mem_check_bound, total_mem_size; LLVMBasicBlockRef block_curr = LLVMGetInsertBlock(comp_ctx->builder); LLVMBasicBlockRef check_succ, check_mem_space; + AOTValue *aot_value; CHECK_LLVM_CONST(offset_const); CHECK_LLVM_CONST(bytes_const); @@ -100,6 +101,8 @@ check_memory_overflow(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, } } + aot_value = func_ctx->block_stack.block_list_end->value_stack.value_list_end; + POP_I32(addr); /* offset1 = offset + addr; */ BUILD_OP(Add, offset_const, addr, offset1, "offset1"); @@ -152,27 +155,37 @@ check_memory_overflow(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, SET_BUILD_POS(check_mem_space); } - /* offset2 = offset1 - heap_base_offset; */ - BUILD_OP(Sub, offset1, heap_base_offset, offset2, "offset2"); + if (!(aot_value->is_local + && aot_checked_addr_list_find(func_ctx, aot_value->local_idx, + offset, bytes))) { + /* offset2 = offset1 - heap_base_offset; */ + BUILD_OP(Sub, offset1, heap_base_offset, offset2, "offset2"); - if (!(mem_check_bound = - get_memory_check_bound(comp_ctx, func_ctx, bytes))) { - goto fail; - } + if (!(mem_check_bound = + get_memory_check_bound(comp_ctx, func_ctx, bytes))) { + goto fail; + } - /* Add basic blocks */ - ADD_BASIC_BLOCK(check_succ, "check_succ"); - LLVMMoveBasicBlockAfter(check_succ, block_curr); + /* Add basic blocks */ + ADD_BASIC_BLOCK(check_succ, "check_succ"); + LLVMMoveBasicBlockAfter(check_succ, block_curr); - /* offset2 > bound ? */ - BUILD_ICMP(LLVMIntUGT, offset2, mem_check_bound, cmp, "cmp"); - if (!aot_emit_exception(comp_ctx, func_ctx, - EXCE_OUT_OF_BOUNDS_MEMORY_ACCESS, - true, cmp, check_succ)) { - goto fail; - } + /* offset2 > bound ? */ + BUILD_ICMP(LLVMIntUGT, offset2, mem_check_bound, cmp, "cmp"); + if (!aot_emit_exception(comp_ctx, func_ctx, + EXCE_OUT_OF_BOUNDS_MEMORY_ACCESS, + true, cmp, check_succ)) { + goto fail; + } + + SET_BUILD_POS(check_succ); - SET_BUILD_POS(check_succ); + if (aot_value->is_local) { + if (!aot_checked_addr_list_add(func_ctx, aot_value->local_idx, + offset, bytes)) + goto fail; + } + } /* maddr = mem_base_addr + offset1 */ if (!(maddr = LLVMBuildInBoundsGEP(comp_ctx->builder, mem_base_addr, diff --git a/core/iwasm/compilation/aot_emit_variable.c b/core/iwasm/compilation/aot_emit_variable.c index 97ca8da005..4f5e63f18d 100644 --- a/core/iwasm/compilation/aot_emit_variable.c +++ b/core/iwasm/compilation/aot_emit_variable.c @@ -30,6 +30,7 @@ aot_compile_op_get_local(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, { char name[32]; LLVMValueRef value; + AOTValue *aot_value; CHECK_LOCAL(local_idx); @@ -42,6 +43,10 @@ aot_compile_op_get_local(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, } PUSH(value, get_local_type(func_ctx, local_idx)); + + aot_value = func_ctx->block_stack.block_list_end->value_stack.value_list_end; + aot_value->is_local = true; + aot_value->local_idx = local_idx; return true; fail: @@ -65,6 +70,7 @@ aot_compile_op_set_local(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, return false; } + aot_checked_addr_list_del(func_ctx, local_idx); return true; fail: @@ -92,6 +98,7 @@ aot_compile_op_tee_local(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, } PUSH(value, type); + aot_checked_addr_list_del(func_ctx, local_idx); return true; fail: diff --git a/core/iwasm/compilation/aot_llvm.c b/core/iwasm/compilation/aot_llvm.c index 5e3da9c437..f1776d1243 100644 --- a/core/iwasm/compilation/aot_llvm.c +++ b/core/iwasm/compilation/aot_llvm.c @@ -629,6 +629,7 @@ aot_destroy_func_contexts(AOTFuncContext **func_ctxes, uint32 count) if (func_ctxes[i]->exception_blocks) wasm_runtime_free(func_ctxes[i]->exception_blocks); aot_block_stack_destroy(&func_ctxes[i]->block_stack); + aot_checked_addr_list_destroy(func_ctxes[i]); wasm_runtime_free(func_ctxes[i]); } wasm_runtime_free(func_ctxes); @@ -1119,11 +1120,15 @@ aot_create_comp_context(AOTCompData *comp_data, aot_set_last_error("create LLVM pass manager failed."); goto fail; } + + LLVMAddBasicAliasAnalysisPass(comp_ctx->pass_mgr); LLVMAddPromoteMemoryToRegisterPass(comp_ctx->pass_mgr); LLVMAddInstructionCombiningPass(comp_ctx->pass_mgr); - LLVMAddCFGSimplificationPass(comp_ctx->pass_mgr); LLVMAddJumpThreadingPass(comp_ctx->pass_mgr); LLVMAddConstantPropagationPass(comp_ctx->pass_mgr); + LLVMAddReassociatePass(comp_ctx->pass_mgr); + LLVMAddGVNPass(comp_ctx->pass_mgr); + LLVMAddCFGSimplificationPass(comp_ctx->pass_mgr); /* Create metadata for llvm float experimental constrained intrinsics */ if (!(comp_ctx->fp_rounding_mode = @@ -1298,3 +1303,80 @@ aot_block_destroy(AOTBlock *block) aot_value_stack_destroy(&block->value_stack); wasm_runtime_free(block); } + +bool +aot_checked_addr_list_add(AOTFuncContext *func_ctx, + uint32 local_idx, uint32 offset, uint32 bytes) +{ + AOTCheckedAddr *node = func_ctx->checked_addr_list; + + if (!(node = wasm_runtime_malloc(sizeof(AOTCheckedAddr)))) { + aot_set_last_error("allocate memory failed."); + return false; + } + + node->local_idx = local_idx; + node->offset = offset; + node->bytes = bytes; + + node->next = func_ctx->checked_addr_list; + func_ctx->checked_addr_list = node; + return true; +} + +void +aot_checked_addr_list_del(AOTFuncContext *func_ctx, uint32 local_idx) +{ + AOTCheckedAddr *node = func_ctx->checked_addr_list; + AOTCheckedAddr *node_prev = NULL, *node_next; + + while (node) { + node_next = node->next; + + if (node->local_idx == local_idx) { + if (!node_prev) + func_ctx->checked_addr_list = node_next; + else + node_prev->next = node_next; + wasm_runtime_free(node); + } + else { + node_prev = node; + } + + node = node_next; + } +} + +bool +aot_checked_addr_list_find(AOTFuncContext *func_ctx, + uint32 local_idx, uint32 offset, uint32 bytes) +{ + AOTCheckedAddr *node = func_ctx->checked_addr_list; + + while (node) { + if (node->local_idx == local_idx + && node->offset == offset + && node->bytes >= bytes) { + return true; + } + node = node->next; + } + + return false; +} + +void +aot_checked_addr_list_destroy(AOTFuncContext *func_ctx) +{ + AOTCheckedAddr *node = func_ctx->checked_addr_list, *node_next; + + while (node) { + node_next = node->next; + wasm_runtime_free(node); + node = node_next; + } + + func_ctx->checked_addr_list = NULL; +} + diff --git a/core/iwasm/compilation/aot_llvm.h b/core/iwasm/compilation/aot_llvm.h index 6cbf119952..c97cd48554 100644 --- a/core/iwasm/compilation/aot_llvm.h +++ b/core/iwasm/compilation/aot_llvm.h @@ -30,6 +30,8 @@ typedef struct AOTValue { LLVMValueRef value; /* VALUE_TYPE_I32/I64/F32/F64/VOID */ uint8 type; + bool is_local; + uint32 local_idx; } AOTValue; /** @@ -84,6 +86,13 @@ typedef struct AOTBlockStack { uint32 block_index[3]; } AOTBlockStack; +typedef struct AOTCheckedAddr { + struct AOTCheckedAddr *next; + uint32 local_idx; + uint32 offset; + uint32 bytes; +} AOTCheckedAddr, *AOTCheckedAddrList; + typedef struct AOTFuncContext { AOTFunc *aot_func; LLVMValueRef func; @@ -105,6 +114,7 @@ typedef struct AOTFuncContext { LLVMValueRef cur_exception; bool mem_space_unchanged; + AOTCheckedAddrList checked_addr_list; LLVMBasicBlockRef *exception_blocks; LLVMBasicBlockRef got_exception_block; @@ -258,6 +268,20 @@ aot_block_destroy(AOTBlock *block); LLVMTypeRef wasm_type_to_llvm_type(AOTLLVMTypes *llvm_types, uint8 wasm_type); +bool +aot_checked_addr_list_add(AOTFuncContext *func_ctx, + uint32 local_idx, uint32 offset, uint32 bytes); + +void +aot_checked_addr_list_del(AOTFuncContext *func_ctx, uint32 local_idx); + +bool +aot_checked_addr_list_find(AOTFuncContext *func_ctx, + uint32 local_idx, uint32 offset, uint32 bytes); + +void +aot_checked_addr_list_destroy(AOTFuncContext *func_ctx); + #ifdef __cplusplus } /* end of extern "C" */ #endif diff --git a/core/iwasm/interpreter/wasm_loader.c b/core/iwasm/interpreter/wasm_loader.c index 12f7c79bd2..d24babbf9a 100644 --- a/core/iwasm/interpreter/wasm_loader.c +++ b/core/iwasm/interpreter/wasm_loader.c @@ -419,7 +419,7 @@ load_type_section(const uint8 *buf, const uint8 *buf_end, WASMModule *module, read_leb_uint32(p, p_end, result_count); if (result_count > 1) { set_error_buf(error_buf, error_buf_size, - "Load type section failed: invalid result count."); + "Load type section failed: invalid result arity."); return false; } CHECK_BUF(p, p_end, result_count); @@ -485,6 +485,36 @@ load_table_import(const uint8 **p_buf, const uint8 *buf_end, unsigned wasm_runtime_memory_pool_size(); +static bool +check_memory_init_size(uint32 init_size, + char *error_buf, uint32 error_buf_size) +{ + if (init_size > 65536) { + set_error_buf(error_buf, error_buf_size, + "memory size must be at most 65536 pages (4GiB)"); + return false; + } + return true; +} + +static bool +check_memory_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; + } + + if (max_size > 65536) { + set_error_buf(error_buf, error_buf_size, + "memory size must be at most 65536 pages (4GiB)"); + return false; + } + return true; +} + static bool load_memory_import(const uint8 **p_buf, const uint8 *buf_end, WASMMemoryImport *memory, @@ -501,8 +531,16 @@ load_memory_import(const uint8 **p_buf, const uint8 *buf_end, read_leb_uint32(p, p_end, memory->flags); read_leb_uint32(p, p_end, memory->init_page_count); + if (!check_memory_init_size(memory->init_page_count, + error_buf, error_buf_size)) + return false; + if (memory->flags & 1) { read_leb_uint32(p, p_end, memory->max_page_count); + if (!check_memory_max_size(memory->init_page_count, + memory->max_page_count, + error_buf, error_buf_size)) + return false; if (memory->max_page_count > max_page_count) memory->max_page_count = max_page_count; } @@ -552,8 +590,16 @@ load_memory(const uint8 **p_buf, const uint8 *buf_end, WASMMemory *memory, read_leb_uint32(p, p_end, memory->flags); read_leb_uint32(p, p_end, memory->init_page_count); + if (!check_memory_init_size(memory->init_page_count, + error_buf, error_buf_size)) + return false; + if (memory->flags & 1) { read_leb_uint32(p, p_end, memory->max_page_count); + if (!check_memory_max_size(memory->init_page_count, + memory->max_page_count, + error_buf, error_buf_size)) + return false; if (memory->max_page_count > max_page_count) memory->max_page_count = max_page_count; } @@ -715,7 +761,7 @@ load_import_section(const uint8 *buf, const uint8 *buf_end, WASMModule *module, if (type_index >= module->type_count) { set_error_buf(error_buf, error_buf_size, "Load import section failed: " - "function type index out of range."); + "unknown type."); return false; } import->u.function.func_type = module->types[type_index]; @@ -898,7 +944,7 @@ load_function_section(const uint8 *buf, const uint8 *buf_end, if (type_index >= module->type_count) { set_error_buf(error_buf, error_buf_size, "Load function section failed: " - "function type index out of range."); + "unknown type."); return false; } @@ -1017,7 +1063,7 @@ load_table_section(const uint8 *buf, const uint8 *buf_end, WASMModule *module, if (table_count) { if (table_count > 1) { set_error_buf(error_buf, error_buf_size, - "Load table section failed: multiple memories"); + "Load table section failed: multiple tables"); return false; } module->table_count = table_count; @@ -1194,7 +1240,7 @@ load_export_section(const uint8 *buf, const uint8 *buf_end, WASMModule *module, if (index >= module->function_count + module->import_function_count) { set_error_buf(error_buf, error_buf_size, "Load export section failed: " - "function index out of range."); + "unknown function."); return false; } break; @@ -1203,7 +1249,7 @@ load_export_section(const uint8 *buf, const uint8 *buf_end, WASMModule *module, if (index >= module->table_count + module->import_table_count) { set_error_buf(error_buf, error_buf_size, "Load export section failed: " - "table index out of range."); + "unknown table."); return false; } break; @@ -1212,7 +1258,7 @@ load_export_section(const uint8 *buf, const uint8 *buf_end, WASMModule *module, if (index >= module->memory_count + module->import_memory_count) { set_error_buf(error_buf, error_buf_size, "Load export section failed: " - "memory index out of range."); + "unknown memory."); return false; } break; @@ -1221,7 +1267,7 @@ load_export_section(const uint8 *buf, const uint8 *buf_end, WASMModule *module, if (index >= module->global_count + module->import_global_count) { set_error_buf(error_buf, error_buf_size, "Load export section failed: " - "global index out of range."); + "unknown global."); return false; } break; @@ -1273,7 +1319,7 @@ load_table_segment_section(const uint8 *buf, const uint8 *buf_end, WASMModule *m if (p >= p_end) { set_error_buf(error_buf, error_buf_size, "Load table segment section failed: " - "invalid value type"); + "unexpected end"); return false; } read_leb_uint32(p, p_end, table_index); @@ -1417,7 +1463,7 @@ load_start_section(const uint8 *buf, const uint8 *buf_end, WASMModule *module, if (start_function >= module->function_count + module->import_function_count) { set_error_buf(error_buf, error_buf_size, "Load start section failed: " - "function index out of range."); + "unknown function."); return false; } module->start_function = start_function; @@ -2703,7 +2749,7 @@ wasm_loader_check_br(WASMLoaderContext *ctx, uint32 depth, { if (ctx->csp_num < depth + 1) { set_error_buf(error_buf, error_buf_size, - "WASM module load failed: type mismatch: " + "WASM module load failed: unknown label, " "unexpected end of section or function"); return false; } @@ -3405,7 +3451,7 @@ wasm_loader_get_const_offset(WASMLoaderContext *ctx, uint8 type, if (local_idx >= param_count + local_count) { \ set_error_buf(error_buf, error_buf_size, \ "WASM module load failed: " \ - "local index out of range"); \ + "unknown local."); \ goto fail; \ } \ local_type = local_idx < param_count \ @@ -3427,8 +3473,7 @@ check_memory(WASMModule *module, if (module->memory_count == 0 && module->import_memory_count == 0) { set_error_buf(error_buf, error_buf_size, - "WASM module load failed: " - "load or store in module without default memory"); + "WASM module load failed: unknown memory"); return false; } return true; @@ -3848,7 +3893,7 @@ wasm_loader_prepare_bytecode(WASMModule *module, WASMFunction *func, if (func_idx >= module->import_function_count + module->function_count) { set_error_buf(error_buf, error_buf_size, "WASM loader prepare bytecode failed: " - "function index out of range"); + "unknown function."); goto fail; } @@ -3888,7 +3933,7 @@ wasm_loader_prepare_bytecode(WASMModule *module, WASMFunction *func, && module->import_table_count == 0) { set_error_buf(error_buf, error_buf_size, "WASM loader prepare bytecode failed: " - "call indirect without default table"); + "call indirect with unknown table"); goto fail; } @@ -3911,7 +3956,7 @@ wasm_loader_prepare_bytecode(WASMModule *module, WASMFunction *func, if (type_idx >= module->type_count) { set_error_buf(error_buf, error_buf_size, "WASM loader prepare bytecode failed: " - "function index out of range"); + "unknown type"); goto fail; } @@ -3992,7 +4037,8 @@ wasm_loader_prepare_bytecode(WASMModule *module, WASMFunction *func, if (loader_ctx->stack_cell_num <= 0) { set_error_buf(error_buf, error_buf_size, "WASM loader prepare bytecode failed: " - "opcode select was found but stack was empty"); + "type mismatch, opcode select was found " + "but stack was empty"); goto fail; } @@ -4175,7 +4221,7 @@ wasm_loader_prepare_bytecode(WASMModule *module, WASMFunction *func, if (global_idx >= global_count) { set_error_buf(error_buf, error_buf_size, "WASM loader prepare bytecode failed: " - "global index out of range"); + "unknown global."); goto fail; } @@ -4197,7 +4243,7 @@ wasm_loader_prepare_bytecode(WASMModule *module, WASMFunction *func, if (global_idx >= global_count) { set_error_buf(error_buf, error_buf_size, "WASM loader prepare bytecode failed: " - "global index out of range"); + "unknown global."); goto fail; } diff --git a/core/iwasm/interpreter/wasm_runtime.c b/core/iwasm/interpreter/wasm_runtime.c index 06f4f8966c..789340871b 100644 --- a/core/iwasm/interpreter/wasm_runtime.c +++ b/core/iwasm/interpreter/wasm_runtime.c @@ -753,7 +753,7 @@ wasm_instantiate(WASMModule *module, for (j = 0; j < length; j++) { if (table_seg->func_indexes[j] >= module_inst->function_count) { set_error_buf(error_buf, error_buf_size, - "function index is overflow"); + "WASM instantiate failed: unknown function"); wasm_deinstantiate(module_inst); return NULL; } From eab5e4085398a6c187bcd0a20b4fff9e26a4117d Mon Sep 17 00:00:00 2001 From: Wang Xin Date: Wed, 22 Apr 2020 19:07:44 +0800 Subject: [PATCH 2/2] sample gui update (#237) --- wamr-sdk/build_sdk.sh | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/wamr-sdk/build_sdk.sh b/wamr-sdk/build_sdk.sh index 02f43e1839..0b819c5dbf 100755 --- a/wamr-sdk/build_sdk.sh +++ b/wamr-sdk/build_sdk.sh @@ -159,9 +159,6 @@ fi echo -e "\n\n" echo "############## Start to build wasm app sdk ###############" -cd ${sdk_root}/app -rm -fr build && mkdir build -cd build # If wgl module is selected, check if the extra SDK include dir is passed by the args, prompt user to input if not. app_all_selected=`cat ${wamr_config_cmake_file} | grep WAMR_APP_BUILD_ALL` @@ -178,8 +175,15 @@ if [[ -n "${app_wgl_selected}" ]] || [[ -n "${app_all_selected}" ]]; then CM_DEXTRA_SDK_INCLUDE_PATH="-DEXTRA_SDK_INCLUDE_PATH=${extra_file_path}" fi fi + + cd ${wamr_root_dir}/core/app-framework/wgl/app + ./prepare_headers.sh fi +cd ${sdk_root}/app +rm -fr build && mkdir build +cd build + out=`grep WAMR_BUILD_LIBC_WASI ${wamr_config_cmake_file} |grep 1` if [ -n "$out" ]; then LIBC_SUPPORT="WASI"