Add checks to avoid wasm_runtime_malloc memory with size 0 (#507)
In some platforms, allocating memory with size 0 may return NULL but not an empty memory block, which causes runtime load, instantiate or execute wasm/aot file failed. We add checks to try to avoid allocating memory in runtime if the size is 0. And in wasm_runtime_malloc/free, output warning if allocate memory with size 0 and free memory with NULL ptr. Also fix some coding style issues, fix handle riscv32 ilp32d issue, and fix several wasm-c-api issues. Signed-off-by: Wenyong Huang <wenyong.huang@intel.com>
This commit is contained in:
@ -234,7 +234,7 @@ aot_set_last_error(const char *error);
|
||||
void
|
||||
aot_set_last_error_v(const char *format, ...);
|
||||
|
||||
#if BH_DEBUG == 1
|
||||
#if BH_DEBUG != 0
|
||||
#define HANDLE_FAILURE(callee) do { \
|
||||
aot_set_last_error_v("call %s failed in %s:%d", (callee),\
|
||||
__FUNCTION__, __LINE__); \
|
||||
|
||||
@ -1751,16 +1751,18 @@ aot_resolve_functions(AOTCompContext *comp_ctx, AOTObjectData *obj_data)
|
||||
AOTObjectFunc *func;
|
||||
LLVMSymbolIteratorRef sym_itr;
|
||||
char *name, *prefix = AOT_FUNC_PREFIX;
|
||||
uint32 func_index;
|
||||
uint32 func_index, total_size;
|
||||
|
||||
/* allocate memory for aot function */
|
||||
obj_data->func_count = comp_ctx->comp_data->func_count;
|
||||
if (!(obj_data->funcs
|
||||
= wasm_runtime_malloc((uint32)sizeof(AOTObjectFunc) * obj_data->func_count))) {
|
||||
aot_set_last_error("allocate memory for functions failed.");
|
||||
return false;
|
||||
if (obj_data->func_count) {
|
||||
total_size = (uint32)sizeof(AOTObjectFunc) * obj_data->func_count;
|
||||
if (!(obj_data->funcs = wasm_runtime_malloc(total_size))) {
|
||||
aot_set_last_error("allocate memory for functions failed.");
|
||||
return false;
|
||||
}
|
||||
memset(obj_data->funcs, 0, total_size);
|
||||
}
|
||||
memset(obj_data->funcs, 0, sizeof(AOTObjectFunc) * obj_data->func_count);
|
||||
|
||||
if (!(sym_itr = LLVMObjectFileCopySymbolIterator(obj_data->binary))) {
|
||||
aot_set_last_error("llvm get symbol iterator failed.");
|
||||
|
||||
@ -792,7 +792,7 @@ aot_compile_op_call_indirect(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
|
||||
uint8 wasm_ret_type, *wasm_ret_types;
|
||||
uint64 total_size;
|
||||
char buf[32];
|
||||
bool ret;
|
||||
bool ret = false;
|
||||
|
||||
/* Check function type index */
|
||||
if (type_idx >= comp_ctx->comp_data->func_type_count) {
|
||||
@ -1105,13 +1105,15 @@ aot_compile_op_call_indirect(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
|
||||
LLVMPositionBuilderAtEnd(comp_ctx->builder, block_call_import);
|
||||
|
||||
/* Allocate memory for result values */
|
||||
total_size = sizeof(LLVMValueRef) * (uint64)func_result_count;
|
||||
if (total_size >= UINT32_MAX
|
||||
|| !(value_rets = wasm_runtime_malloc((uint32)total_size))) {
|
||||
aot_set_last_error("allocate memory failed.");
|
||||
goto fail;
|
||||
if (func_result_count > 0) {
|
||||
total_size = sizeof(LLVMValueRef) * (uint64)func_result_count;
|
||||
if (total_size >= UINT32_MAX
|
||||
|| !(value_rets = wasm_runtime_malloc((uint32)total_size))) {
|
||||
aot_set_last_error("allocate memory failed.");
|
||||
goto fail;
|
||||
}
|
||||
memset(value_rets, 0, (uint32)total_size);
|
||||
}
|
||||
memset(value_rets, 0, total_size);
|
||||
|
||||
param_cell_num = func_type->param_cell_num;
|
||||
wasm_ret_types = func_type->types + func_type->param_count;
|
||||
|
||||
@ -74,7 +74,7 @@ get_memory_check_bound(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
|
||||
}
|
||||
|
||||
static LLVMValueRef
|
||||
get_memory_size(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx);
|
||||
get_memory_curr_page_count(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx);
|
||||
|
||||
LLVMValueRef
|
||||
aot_check_memory_overflow(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
|
||||
@ -171,7 +171,7 @@ aot_check_memory_overflow(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
|
||||
if (init_page_count == 0) {
|
||||
LLVMValueRef mem_size;
|
||||
|
||||
if (!(mem_size = get_memory_size(comp_ctx, func_ctx))) {
|
||||
if (!(mem_size = get_memory_curr_page_count(comp_ctx, func_ctx))) {
|
||||
goto fail;
|
||||
}
|
||||
BUILD_ICMP(LLVMIntEQ, mem_size, I32_ZERO, cmp, "is_zero");
|
||||
@ -611,7 +611,7 @@ fail:
|
||||
}
|
||||
|
||||
static LLVMValueRef
|
||||
get_memory_size(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx)
|
||||
get_memory_curr_page_count(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx)
|
||||
{
|
||||
LLVMValueRef mem_size;
|
||||
|
||||
@ -636,7 +636,7 @@ fail:
|
||||
bool
|
||||
aot_compile_op_memory_size(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx)
|
||||
{
|
||||
LLVMValueRef mem_size = get_memory_size(comp_ctx, func_ctx);
|
||||
LLVMValueRef mem_size = get_memory_curr_page_count(comp_ctx, func_ctx);
|
||||
|
||||
if (mem_size)
|
||||
PUSH_I32(mem_size);
|
||||
@ -648,7 +648,7 @@ fail:
|
||||
bool
|
||||
aot_compile_op_memory_grow(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx)
|
||||
{
|
||||
LLVMValueRef mem_size = get_memory_size(comp_ctx, func_ctx);
|
||||
LLVMValueRef mem_size = get_memory_curr_page_count(comp_ctx, func_ctx);
|
||||
LLVMValueRef delta, param_values[2], ret_value, func, value;
|
||||
LLVMTypeRef param_types[2], ret_type, func_type, func_ptr_type;
|
||||
|
||||
@ -801,9 +801,17 @@ check_bulk_memory_overflow(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
|
||||
}
|
||||
}
|
||||
|
||||
/* mem_size_offset = aot_inst + off */
|
||||
if (!(mem_size = get_memory_size(comp_ctx, func_ctx))) {
|
||||
goto fail;
|
||||
if (func_ctx->mem_space_unchanged) {
|
||||
mem_size = func_ctx->mem_info[0].mem_data_size_addr;
|
||||
}
|
||||
else {
|
||||
if (!(mem_size =
|
||||
LLVMBuildLoad(comp_ctx->builder,
|
||||
func_ctx->mem_info[0].mem_data_size_addr,
|
||||
"mem_size"))) {
|
||||
aot_set_last_error("llvm build load failed.");
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
|
||||
ADD_BASIC_BLOCK(check_succ, "check_succ");
|
||||
|
||||
@ -262,6 +262,13 @@ create_memory_info(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
|
||||
aot_set_last_error("llvm build in bounds gep failed");
|
||||
return false;
|
||||
}
|
||||
offset = I32_CONST(offsetof(AOTMemoryInstance, memory_data_size));
|
||||
if (!(func_ctx->mem_info[0].mem_data_size_addr =
|
||||
LLVMBuildInBoundsGEP(comp_ctx->builder, shared_mem_addr,
|
||||
&offset, 1, "mem_data_size_offset"))) {
|
||||
aot_set_last_error("llvm build in bounds gep failed");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else
|
||||
#endif
|
||||
@ -282,6 +289,14 @@ create_memory_info(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
|
||||
aot_set_last_error("llvm build in bounds gep failed");
|
||||
return false;
|
||||
}
|
||||
offset = I32_CONST(offsetof(AOTModuleInstance, global_table_data)
|
||||
+ offsetof(AOTMemoryInstance, memory_data_size));
|
||||
if (!(func_ctx->mem_info[0].mem_data_size_addr =
|
||||
LLVMBuildInBoundsGEP(comp_ctx->builder, func_ctx->aot_inst,
|
||||
&offset, 1, "mem_data_size_offset"))) {
|
||||
aot_set_last_error("llvm build in bounds gep failed");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
/* Store mem info base address before cast */
|
||||
mem_info_base = func_ctx->mem_info[0].mem_base_addr;
|
||||
@ -300,6 +315,13 @@ create_memory_info(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
|
||||
aot_set_last_error("llvm build bit cast failed");
|
||||
return false;
|
||||
}
|
||||
if (!(func_ctx->mem_info[0].mem_data_size_addr =
|
||||
LLVMBuildBitCast(comp_ctx->builder,
|
||||
func_ctx->mem_info[0].mem_data_size_addr,
|
||||
INT32_PTR_TYPE, "mem_data_size_ptr"))) {
|
||||
aot_set_last_error("llvm build bit cast failed");
|
||||
return false;
|
||||
}
|
||||
if (mem_space_unchanged) {
|
||||
if (!(func_ctx->mem_info[0].mem_base_addr =
|
||||
LLVMBuildLoad(comp_ctx->builder,
|
||||
@ -311,7 +333,14 @@ create_memory_info(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
|
||||
if (!(func_ctx->mem_info[0].mem_cur_page_count_addr =
|
||||
LLVMBuildLoad(comp_ctx->builder,
|
||||
func_ctx->mem_info[0].mem_cur_page_count_addr,
|
||||
"mem_cur_page_count_addr"))) {
|
||||
"mem_cur_page_count"))) {
|
||||
aot_set_last_error("llvm build load failed");
|
||||
return false;
|
||||
}
|
||||
if (!(func_ctx->mem_info[0].mem_data_size_addr =
|
||||
LLVMBuildLoad(comp_ctx->builder,
|
||||
func_ctx->mem_info[0].mem_data_size_addr,
|
||||
"mem_data_size"))) {
|
||||
aot_set_last_error("llvm build load failed");
|
||||
return false;
|
||||
}
|
||||
@ -1476,7 +1505,9 @@ aot_create_comp_context(AOTCompData *comp_data,
|
||||
|
||||
/* Create function context for each function */
|
||||
comp_ctx->func_ctx_count = comp_data->func_count;
|
||||
if (!(comp_ctx->func_ctxes = aot_create_func_contexts(comp_data, comp_ctx)))
|
||||
if (comp_data->func_count > 0
|
||||
&& !(comp_ctx->func_ctxes =
|
||||
aot_create_func_contexts(comp_data, comp_ctx)))
|
||||
goto fail;
|
||||
|
||||
ret = comp_ctx;
|
||||
@ -1521,7 +1552,8 @@ aot_destroy_comp_context(AOTCompContext *comp_ctx)
|
||||
LLVMContextDispose(comp_ctx->context);
|
||||
|
||||
if (comp_ctx->func_ctxes)
|
||||
aot_destroy_func_contexts(comp_ctx->func_ctxes, comp_ctx->func_ctx_count);
|
||||
aot_destroy_func_contexts(comp_ctx->func_ctxes,
|
||||
comp_ctx->func_ctx_count);
|
||||
|
||||
wasm_runtime_free(comp_ctx);
|
||||
}
|
||||
|
||||
@ -103,6 +103,7 @@ typedef struct AOTCheckedAddr {
|
||||
|
||||
typedef struct AOTMemInfo {
|
||||
LLVMValueRef mem_base_addr;
|
||||
LLVMValueRef mem_data_size_addr;
|
||||
LLVMValueRef mem_cur_page_count_addr;
|
||||
LLVMValueRef mem_bound_check_1byte;
|
||||
LLVMValueRef mem_bound_check_2bytes;
|
||||
|
||||
@ -83,7 +83,7 @@ fail:
|
||||
return false;
|
||||
}
|
||||
|
||||
// TODO: instructions for other CPUs
|
||||
/* TODO: instructions for other CPUs */
|
||||
/* shufflevector is not an option, since it requires *mask as a const */
|
||||
bool
|
||||
aot_compile_simd_swizzle(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx)
|
||||
|
||||
Reference in New Issue
Block a user