Просмотр исходного кода

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>
Wenyong Huang 5 лет назад
Родитель
Сommit
a5188f5574

+ 16 - 10
core/iwasm/aot/aot_loader.c

@@ -1117,8 +1117,9 @@ load_function_section(const uint8 *buf, const uint8 *buf_end,
     uint64 size, text_offset;
 
     size = sizeof(void*) * (uint64)module->func_count;
-    if (!(module->func_ptrs = loader_malloc
-                (size, error_buf, error_buf_size))) {
+    if (size > 0
+        && !(module->func_ptrs = loader_malloc
+                    (size, error_buf, error_buf_size))) {
         return false;
     }
 
@@ -1158,8 +1159,9 @@ load_function_section(const uint8 *buf, const uint8 *buf_end,
     }
 
     size = sizeof(uint32) * (uint64)module->func_count;
-    if (!(module->func_type_indexes = loader_malloc
-                (size, error_buf, error_buf_size))) {
+    if (size > 0
+        && !(module->func_type_indexes = loader_malloc
+                    (size, error_buf, error_buf_size))) {
         return false;
     }
 
@@ -1498,7 +1500,8 @@ load_relocation_section(const uint8 *buf, const uint8 *buf_end,
 
     /* Allocate memory for relocation groups */
     size = sizeof(AOTRelocationGroup) * (uint64)group_count;
-    if (!(groups = loader_malloc(size, error_buf, error_buf_size))) {
+    if (size > 0
+        && !(groups = loader_malloc(size, error_buf, error_buf_size))) {
         goto fail;
     }
 
@@ -2065,8 +2068,9 @@ aot_load_from_comp_data(AOTCompData *comp_data, AOTCompContext *comp_ctx,
 
     /* Allocate memory for function pointers */
     size = (uint64)module->func_count * sizeof(void *);
-    if (!(module->func_ptrs =
-            loader_malloc(size, error_buf, error_buf_size))) {
+    if (size > 0
+        && !(module->func_ptrs =
+                loader_malloc(size, error_buf, error_buf_size))) {
         goto fail2;
     }
 
@@ -2085,8 +2089,9 @@ aot_load_from_comp_data(AOTCompData *comp_data, AOTCompContext *comp_ctx,
 
     /* Allocation memory for function type indexes */
     size = (uint64)module->func_count * sizeof(uint32);
-    if (!(module->func_type_indexes =
-            loader_malloc(size, error_buf, error_buf_size))) {
+    if (size > 0
+        && !(module->func_type_indexes =
+                loader_malloc(size, error_buf, error_buf_size))) {
         goto fail3;
     }
     for (i = 0; i < comp_data->func_count; i++)
@@ -2135,7 +2140,8 @@ aot_load_from_comp_data(AOTCompData *comp_data, AOTCompContext *comp_ctx,
     return module;
 
 fail3:
-    wasm_runtime_free(module->func_ptrs);
+    if (module->func_ptrs)
+        wasm_runtime_free(module->func_ptrs);
 fail2:
     if (module->memory_count > 0)
         wasm_runtime_free(module->memories);

+ 28 - 15
core/iwasm/aot/aot_runtime.c

@@ -176,7 +176,7 @@ memories_deinstantiate(AOTModuleInstance *module_inst)
                 wasm_runtime_free(memory_inst->heap_handle.ptr);
             }
 
-            if (memory_inst->heap_data.ptr) {
+            if (memory_inst->memory_data.ptr) {
 #ifndef OS_ENABLE_HW_BOUND_CHECK
                 wasm_runtime_free(memory_inst->memory_data.ptr);
 #else
@@ -202,7 +202,7 @@ memory_instantiate(AOTModuleInstance *module_inst, AOTModule *module,
     uint32 bytes_of_last_page, bytes_to_page_end;
     uint32 heap_offset = num_bytes_per_page *init_page_count;
     uint64 total_size;
-    uint8 *p, *global_addr;
+    uint8 *p = NULL, *global_addr;
 #ifdef OS_ENABLE_HW_BOUND_CHECK
     uint8 *mapped_mem;
     uint64 map_size = 8 * (uint64)BH_GB;
@@ -321,7 +321,8 @@ memory_instantiate(AOTModuleInstance *module_inst, AOTModule *module,
 
 #ifndef OS_ENABLE_HW_BOUND_CHECK
     /* Allocate memory */
-    if (!(p = runtime_malloc(total_size, error_buf, error_buf_size))) {
+    if (total_size > 0
+        && !(p = runtime_malloc(total_size, error_buf, error_buf_size))) {
         return NULL;
     }
 #else
@@ -420,7 +421,8 @@ fail2:
         wasm_runtime_free(memory_inst->heap_handle.ptr);
 fail1:
 #ifndef OS_ENABLE_HW_BOUND_CHECK
-    wasm_runtime_free(memory_inst->memory_data.ptr);
+    if (memory_inst->memory_data.ptr)
+        wasm_runtime_free(memory_inst->memory_data.ptr);
 #else
     os_munmap(mapped_mem, map_size);
 #endif
@@ -504,7 +506,8 @@ memories_instantiate(AOTModuleInstance *module_inst, AOTModule *module,
         }
 
         /* Copy memory data */
-        bh_assert(memory_inst->memory_data.ptr);
+        bh_assert(memory_inst->memory_data.ptr
+                  || memory_inst->memory_data_size == 0);
 
         /* Check memory data */
         /* check offset since length might negative */
@@ -526,9 +529,11 @@ memories_instantiate(AOTModuleInstance *module_inst, AOTModule *module,
             return false;
         }
 
-        bh_memcpy_s((uint8*)memory_inst->memory_data.ptr + base_offset,
-                    memory_inst->memory_data_size - base_offset,
-                    data_seg->bytes, length);
+        if (memory_inst->memory_data.ptr) {
+            bh_memcpy_s((uint8*)memory_inst->memory_data.ptr + base_offset,
+                        memory_inst->memory_data_size - base_offset,
+                        data_seg->bytes, length);
+        }
     }
 
     return true;
@@ -543,6 +548,9 @@ init_func_ptrs(AOTModuleInstance *module_inst, AOTModule *module,
     uint64 total_size =
         ((uint64)module->import_func_count + module->func_count) * sizeof(void*);
 
+    if (module->import_func_count + module->func_count == 0)
+        return true;
+
     /* Allocate memory */
     if (!(module_inst->func_ptrs.ptr = runtime_malloc
                 (total_size, error_buf, error_buf_size))) {
@@ -562,7 +570,8 @@ init_func_ptrs(AOTModuleInstance *module_inst, AOTModule *module,
     }
 
     /* Set defined function pointers */
-    memcpy(func_ptrs, module->func_ptrs, module->func_count * sizeof(void*));
+    bh_memcpy_s(func_ptrs, sizeof(void*) * module->func_count,
+                module->func_ptrs, sizeof(void*) * module->func_count);
     return true;
 }
 
@@ -575,6 +584,9 @@ init_func_type_indexes(AOTModuleInstance *module_inst, AOTModule *module,
     uint64 total_size =
         ((uint64)module->import_func_count + module->func_count) * sizeof(uint32);
 
+    if (module->import_func_count + module->func_count == 0)
+        return true;
+
     /* Allocate memory */
     if (!(module_inst->func_type_indexes.ptr =
                 runtime_malloc(total_size, error_buf, error_buf_size))) {
@@ -586,9 +598,8 @@ init_func_type_indexes(AOTModuleInstance *module_inst, AOTModule *module,
     for (i = 0; i < module->import_func_count; i++, func_type_index++)
         *func_type_index = module->import_funcs[i].func_type_index;
 
-    memcpy(func_type_index, module->func_type_indexes,
-           module->func_count * sizeof(uint32));
-
+    bh_memcpy_s(func_type_index, sizeof(uint32) * module->func_count,
+                module->func_type_indexes, sizeof(uint32) * module->func_count);
     return true;
 }
 
@@ -1688,9 +1699,11 @@ aot_enlarge_memory(AOTModuleInstance *module_inst, uint32 inc_page_count)
         if (!(memory_data = wasm_runtime_malloc((uint32)total_size))) {
             return false;
         }
-        bh_memcpy_s(memory_data, (uint32)total_size,
-                    memory_data_old, total_size_old);
-        wasm_runtime_free(memory_data_old);
+        if (memory_data_old) {
+            bh_memcpy_s(memory_data, (uint32)total_size,
+                        memory_data_old, total_size_old);
+            wasm_runtime_free(memory_data_old);
+        }
     }
 
     memset(memory_data + total_size_old,

+ 55 - 45
core/iwasm/common/wasm_c_api.c

@@ -23,7 +23,7 @@ void
 wasm_instance_delete_internal(wasm_instance_t *);
 
 static void *
-malloc_internal(size_t size)
+malloc_internal(uint64 size)
 {
     void *mem = NULL;
 
@@ -47,8 +47,7 @@ malloc_internal(size_t size)
 /* Vectors */
 #define INIT_VEC(vector_p, func_prefix, size)                                 \
     do {                                                                      \
-        vector_p = malloc_internal(sizeof(*(vector_p)));                      \
-        if (!vector_p) {                                                      \
+        if (!(vector_p = malloc_internal(sizeof(*(vector_p))))) {             \
             goto failed;                                                      \
         }                                                                     \
         func_prefix##_new_uninitialized(vector_p, size);                      \
@@ -75,7 +74,8 @@ malloc_internal(size_t size)
 static inline void
 generic_vec_init_data(Vector *out, size_t num_of_elems, size_t size_of_elem)
 {
-    if (!bh_vector_init(out, num_of_elems, size_of_elem)) {
+    /* size 0 is meaningless for a elemment */
+    if (!size_of_elem || !bh_vector_init(out, num_of_elems, size_of_elem)) {
         out->data = NULL;
         out->max_elems = 0;
         out->num_elems = 0;
@@ -99,7 +99,7 @@ wasm_byte_vec_copy(wasm_byte_vec_t *out, const wasm_byte_vec_t *src)
 
     bh_assert(out && src);
 
-    generic_vec_init_data((Vector *)out, src->size, src->size_of_elem);
+    generic_vec_init_data((Vector *)out, src->size, sizeof(wasm_byte_t));
     if (!out->data) {
         goto failed;
     }
@@ -187,7 +187,7 @@ wasm_engine_new_internal(mem_alloc_type_t type,
         goto failed;
     }
 
-#if BH_DEBUG == 1
+#if BH_DEBUG != 0
     bh_log_set_verbose_level(5);
 #else
     bh_log_set_verbose_level(3);
@@ -459,7 +459,7 @@ wasm_valtype_vec_copy(wasm_valtype_vec_t *out, const wasm_valtype_vec_t *src)
 
     bh_assert(out && src);
 
-    generic_vec_init_data((Vector *)out, src->size, src->size_of_elem);
+    generic_vec_init_data((Vector *)out, src->size, sizeof(wasm_valtype_t *));
     if (!out->data) {
         goto failed;
     }
@@ -1116,33 +1116,41 @@ failed:
 static void
 native_func_trampoline(wasm_exec_env_t exec_env, uint64 *argv)
 {
-    wasm_val_t *params = NULL;
-    wasm_val_t *results = NULL;
+    wasm_val_t *params = NULL, *results = NULL;
     uint32 argc = 0;
     const wasm_func_t *func = NULL;
     wasm_trap_t *trap = NULL;
-
-    bh_assert(argv);
+    size_t param_count, result_count;
 
     func = wasm_runtime_get_function_attachment(exec_env);
     bh_assert(func);
 
-    params = malloc_internal(wasm_func_param_arity(func) * sizeof(wasm_val_t));
-    if (!params) {
-        goto failed;
-    }
+    param_count = wasm_func_param_arity(func);
+    if (param_count) {
+        if (!argv) {
+            goto failed;
+        }
 
-    results =
-      malloc_internal(wasm_func_result_arity(func) * sizeof(wasm_val_t));
-    if (!results) {
-        goto failed;
+        if (!(params = malloc_internal(param_count * sizeof(wasm_val_t)))) {
+            goto failed;
+        }
+
+        /* argv -> const wasm_val_t params[] */
+        if (!(argc = argv_to_params(
+                argv, wasm_functype_params(wasm_func_type(func)), params))) {
+            goto failed;
+        }
     }
 
-    /* argv -> const wasm_val_t params[] */
-    argc =
-      argv_to_params(argv, wasm_functype_params(wasm_func_type(func)), params);
-    if (wasm_func_param_arity(func) && !argc) {
-        goto failed;
+    result_count = wasm_func_result_arity(func);
+    if (result_count) {
+        if (!argv) {
+            goto failed;
+        }
+
+        if (!(results = malloc_internal(result_count * sizeof(wasm_val_t)))) {
+            goto failed;
+        }
     }
 
     if (func->with_env) {
@@ -1164,16 +1172,17 @@ native_func_trampoline(wasm_exec_env_t exec_env, uint64 *argv)
         }
     }
 
-    /* there is no result or there is an exception */
-    if (trap || !wasm_func_result_arity(func)) {
+    if (argv) {
         memset(argv, 0, wasm_func_param_arity(func) * sizeof(uint64));
     }
 
-    /* wasm_val_t results[] -> argv */
-    argc = results_to_argv(results,
-                           wasm_functype_results(wasm_func_type(func)), argv);
-    if (wasm_func_result_arity(func) && !argc) {
-        goto failed;
+    /* there is no trap and there is return values */
+    if (!trap && result_count) {
+        /* wasm_val_t results[] -> argv */
+        if (!(argc = results_to_argv(
+                results, wasm_functype_results(wasm_func_type(func)), argv))) {
+            goto failed;
+        }
     }
 
 failed:
@@ -1503,8 +1512,7 @@ wasm_func_call(const wasm_func_t *func,
     /* a parameter list and a return value list */
     uint32 *argv = NULL;
     WASMFunctionInstanceCommon *func_comm_rt = NULL;
-    size_t param_count = 0;
-    size_t result_count = 0;
+    size_t param_count, result_count, alloc_count;
 
     bh_assert(func && func->func_type && func->inst_comm_rt);
 
@@ -1527,17 +1535,18 @@ wasm_func_call(const wasm_func_t *func,
 
     param_count = wasm_func_param_arity(func);
     result_count = wasm_func_result_arity(func);
-    argv = malloc_internal(
-      sizeof(uint64)
-      * (param_count > result_count ? param_count : result_count));
-    if (!argv) {
-        goto failed;
+    alloc_count = (param_count > result_count) ? param_count : result_count;
+    if (alloc_count) {
+        if (!(argv = malloc_internal(sizeof(uint64) * alloc_count))) {
+            goto failed;
+        }
     }
 
     /* copy parametes */
-    argc = params_to_argv(params, wasm_functype_params(wasm_func_type(func)),
-                          wasm_func_param_arity(func), argv);
-    if (wasm_func_param_arity(func) && !argc) {
+    if (param_count
+        && !(argc = params_to_argv(params,
+                                   wasm_functype_params(wasm_func_type(func)),
+                                   wasm_func_param_arity(func), argv))) {
         goto failed;
     }
 
@@ -1548,9 +1557,10 @@ wasm_func_call(const wasm_func_t *func,
     }
 
     /* copy results */
-    argc = argv_to_results(argv, wasm_functype_results(wasm_func_type(func)),
-                           wasm_func_result_arity(func), results);
-    if (wasm_func_result_arity(func) && !argc) {
+    if (result_count
+        && !(argc = argv_to_results(
+               argv, wasm_functype_results(wasm_func_type(func)),
+               wasm_func_result_arity(func), results))) {
         goto failed;
     }
 
@@ -2734,7 +2744,7 @@ wasm_extern_vec_copy(wasm_extern_vec_t *out, const wasm_extern_vec_t *src)
     size_t i = 0;
     bh_assert(out && src);
 
-    generic_vec_init_data((Vector *)out, src->size, src->size_of_elem);
+    generic_vec_init_data((Vector *)out, src->size, sizeof(wasm_extern_t *));
     if (!out->data) {
         goto failed;
     }

+ 13 - 1
core/iwasm/common/wasm_memory.c

@@ -161,8 +161,14 @@ wasm_runtime_realloc_internal(void *ptr, unsigned int size)
 static inline void
 wasm_runtime_free_internal(void *ptr)
 {
+    if (!ptr) {
+        LOG_WARNING("warning: wasm_runtime_free with NULL pointer\n");
+        return;
+    }
+
     if (memory_mode == MEMORY_MODE_UNKNOWN) {
-        LOG_WARNING("wasm_runtime_free failed: memory hasn't been initialize.\n");
+        LOG_WARNING("warning: wasm_runtime_free failed: "
+                    "memory hasn't been initialize.\n");
     }
     else if (memory_mode == MEMORY_MODE_POOL) {
         mem_allocator_free(pool_allocator, ptr);
@@ -175,6 +181,12 @@ wasm_runtime_free_internal(void *ptr)
 void *
 wasm_runtime_malloc(unsigned int size)
 {
+    if (size == 0) {
+        LOG_WARNING("warning: wasm_runtime_malloc with size zero\n");
+        /* At lease alloc 1 byte to avoid malloc failed */
+        size = 1;
+    }
+
     return wasm_runtime_malloc_internal(size);
 }
 

+ 10 - 5
core/iwasm/common/wasm_runtime_common.c

@@ -1712,9 +1712,11 @@ wasm_runtime_init_wasi(WASMModuleInstanceCommon *module_inst,
 
     total_size = sizeof(char *) * (uint64)argc;
     if (total_size >= UINT32_MAX
-        || !(argv_list = wasm_runtime_malloc((uint32)total_size))
+        || (total_size > 0 &&
+            !(argv_list = wasm_runtime_malloc((uint32)total_size)))
         || argv_buf_size >= UINT32_MAX
-        || !(argv_buf = wasm_runtime_malloc((uint32)argv_buf_size))) {
+        || (argv_buf_size > 0 &&
+            !(argv_buf = wasm_runtime_malloc((uint32)argv_buf_size)))) {
         set_error_buf(error_buf, error_buf_size,
                       "Init wasi environment failed: allocate memory failed");
         goto fail;
@@ -1730,11 +1732,13 @@ wasm_runtime_init_wasi(WASMModuleInstanceCommon *module_inst,
     for (i = 0; i < env_count; i++)
         env_buf_size += strlen(env[i]) + 1;
 
-    total_size = sizeof(char *) * (uint64)argc;
+    total_size = sizeof(char *) * (uint64)env_count;
     if (total_size >= UINT32_MAX
-        || !(env_list = wasm_runtime_malloc((uint32)total_size))
+        || (total_size > 0
+            && !(env_list = wasm_runtime_malloc((uint32)total_size)))
         || env_buf_size >= UINT32_MAX
-        || !(env_buf = wasm_runtime_malloc((uint32)env_buf_size))) {
+        || (env_buf_size > 0
+            && !(env_buf = wasm_runtime_malloc((uint32)env_buf_size)))) {
         set_error_buf(error_buf, error_buf_size,
                       "Init wasi environment failed: allocate memory failed");
         goto fail;
@@ -2842,6 +2846,7 @@ wasm_runtime_invoke_native(WASMExecEnv *exec_env, void *func_ptr,
                         n_stacks++;
                     n_stacks += 2;
                 }
+                break;
 #endif /* BUILD_TARGET_RISCV32_ILP32D */
             default:
                 bh_assert(0);

+ 1 - 1
core/iwasm/compilation/aot.h

@@ -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__);            \

+ 8 - 6
core/iwasm/compilation/aot_emit_aot_file.c

@@ -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.");

+ 9 - 7
core/iwasm/compilation/aot_emit_function.c

@@ -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;

+ 16 - 8
core/iwasm/compilation/aot_emit_memory.c

@@ -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");

+ 35 - 3
core/iwasm/compilation/aot_llvm.c

@@ -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);
 }

+ 1 - 0
core/iwasm/compilation/aot_llvm.h

@@ -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;

+ 1 - 1
core/iwasm/compilation/simd/simd_access_lanes.c

@@ -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)

+ 6 - 4
core/iwasm/interpreter/wasm_loader.c

@@ -2148,7 +2148,8 @@ load_table_segment_section(const uint8 *buf, const uint8 *buf_end, WASMModule *m
             read_leb_uint32(p, p_end, function_count);
             table_segment->function_count = function_count;
             total_size = sizeof(uint32) * (uint64)function_count;
-            if (!(table_segment->func_indexes = (uint32 *)
+            if (total_size > 0
+                && !(table_segment->func_indexes = (uint32 *)
                     loader_malloc(total_size, error_buf, error_buf_size))) {
                 return false;
             }
@@ -2444,7 +2445,7 @@ handle_name_section(const uint8 *buf, const uint8 *buf_end,
                         previous_func_index = func_index;
                         read_leb_uint32(p, p_end, func_name_len);
                         CHECK_BUF(p, p_end, func_name_len);
-                        // Skip the import functions
+                        /* Skip the import functions */
                         if (func_index >= module->import_count) {
                             func_index -= module->import_count;
                             if (func_index >= module->function_count) {
@@ -5697,7 +5698,7 @@ wasm_loader_prepare_bytecode(WASMModule *module, WASMFunction *func,
     uint32 segment_index;
 #endif
 #if WASM_ENABLE_FAST_INTERP != 0
-    uint8 *func_const_end, *func_const;
+    uint8 *func_const_end, *func_const = NULL;
     int16 operand_offset;
     uint8 last_op = 0;
     bool disable_emit, preserve_local = false;
@@ -7710,7 +7711,8 @@ fail_data_cnt_sec_require:
         goto re_scan;
 
     func->const_cell_num = loader_ctx->const_cell_num;
-    if (!(func->consts = func_const =
+    if (func->const_cell_num > 0
+        && !(func->consts = func_const =
                 loader_malloc(func->const_cell_num * 4,
                               error_buf, error_buf_size))) {
         goto fail;

+ 6 - 4
core/iwasm/interpreter/wasm_mini_loader.c

@@ -1167,7 +1167,8 @@ load_table_segment_section(const uint8 *buf, const uint8 *buf_end, WASMModule *m
             read_leb_uint32(p, p_end, function_count);
             table_segment->function_count = function_count;
             total_size = sizeof(uint32) * (uint64)function_count;
-            if (!(table_segment->func_indexes = (uint32 *)
+            if (total_size > 0
+                && !(table_segment->func_indexes = (uint32 *)
                     loader_malloc(total_size, error_buf, error_buf_size))) {
                 return false;
             }
@@ -1391,7 +1392,7 @@ handle_name_section(const uint8 *buf, const uint8 *buf_end,
                         previous_func_index = func_index;
                         read_leb_uint32(p, p_end, func_name_len);
                         CHECK_BUF(p, p_end, func_name_len);
-                        // Skip the import functions
+                        /* Skip the import functions */
                         if (func_index >= module->import_count) {
                             func_index -= module->import_count;
                             bh_assert(func_index < module->function_count);
@@ -4257,7 +4258,7 @@ wasm_loader_prepare_bytecode(WASMModule *module, WASMFunction *func,
     uint32 segment_index;
 #endif
 #if WASM_ENABLE_FAST_INTERP != 0
-    uint8 *func_const_end, *func_const;
+    uint8 *func_const_end, *func_const = NULL;
     int16 operand_offset;
     uint8 last_op = 0;
     bool disable_emit, preserve_local = false;
@@ -5733,7 +5734,8 @@ handle_op_block_and_loop:
         goto re_scan;
 
     func->const_cell_num = loader_ctx->const_cell_num;
-    if (!(func->consts = func_const =
+    if (func->const_cell_num > 0
+        && !(func->consts = func_const =
                 loader_malloc(func->const_cell_num * 4,
                               error_buf, error_buf_size))) {
         goto fail;

+ 18 - 11
core/iwasm/interpreter/wasm_runtime.c

@@ -110,7 +110,8 @@ memories_deinstantiate(WASMModuleInstance *module_inst,
                     wasm_runtime_free(memories[i]->heap_handle);
                     memories[i]->heap_handle = NULL;
                 }
-                wasm_runtime_free(memories[i]->memory_data);
+                if (memories[i]->memory_data)
+                    wasm_runtime_free(memories[i]->memory_data);
                 wasm_runtime_free(memories[i]);
             }
         }
@@ -248,8 +249,10 @@ memory_instantiate(WASMModuleInstance *module_inst,
         return NULL;
     }
 
-    if (!(memory->memory_data =
-        runtime_malloc(memory_data_size, error_buf, error_buf_size))) {
+    if (memory_data_size > 0
+        && !(memory->memory_data =
+                    runtime_malloc(memory_data_size,
+                                   error_buf, error_buf_size))) {
         goto fail1;
     }
 
@@ -307,7 +310,8 @@ fail3:
     if (heap_size > 0)
         wasm_runtime_free(memory->heap_handle);
 fail2:
-    wasm_runtime_free(memory->memory_data);
+    if (memory->memory_data)
+        wasm_runtime_free(memory->memory_data);
 fail1:
     wasm_runtime_free(memory);
     return NULL;
@@ -1293,9 +1297,8 @@ wasm_instantiate(WASMModule *module, bool is_sub_inst,
         bh_assert(memory);
 
         memory_data = memory->memory_data;
-        bh_assert(memory_data);
-
         memory_size = memory->num_bytes_per_page * memory->cur_page_count;
+        bh_assert(memory_data || memory_size == 0);
 
         bh_assert(data_seg->base_offset.init_expr_type
                     == INIT_EXPR_TYPE_I32_CONST
@@ -1337,8 +1340,10 @@ wasm_instantiate(WASMModule *module, bool is_sub_inst,
             goto fail;
         }
 
-        bh_memcpy_s(memory_data + base_offset, memory_size - base_offset,
-                    data_seg->data, length);
+        if (memory_data) {
+            bh_memcpy_s(memory_data + base_offset, memory_size - base_offset,
+                        data_seg->data, length);
+        }
     }
 
     /* Initialize the table data with table segment section */
@@ -1970,9 +1975,11 @@ wasm_enlarge_memory(WASMModuleInstance *module, uint32 inc_page_count)
         if (!(new_memory_data = wasm_runtime_malloc((uint32)total_size))) {
             return false;
         }
-        bh_memcpy_s(new_memory_data, (uint32)total_size,
-                    memory_data, total_size_old);
-        wasm_runtime_free(memory_data);
+        if (memory_data) {
+            bh_memcpy_s(new_memory_data, (uint32)total_size,
+                        memory_data, total_size_old);
+            wasm_runtime_free(memory_data);
+        }
     }
 
     memset(new_memory_data + total_size_old,

+ 2 - 1
core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/src/posix.c

@@ -1652,7 +1652,8 @@ static __wasi_errno_t path_get_nofollow(
 static void path_put(
     struct path_access *pa
 ) UNLOCKS(pa->fd_object->refcount) {
-  wasm_runtime_free(pa->path_start);
+  if (pa->path_start)
+    wasm_runtime_free(pa->path_start);
   if (fd_number(pa->fd_object) != pa->fd)
     close(pa->fd);
   fd_object_release(pa->fd_object);

+ 2 - 2
core/shared/utils/bh_log.h

@@ -51,7 +51,7 @@ bh_log(LogLevel log_level, const char *file, int line, const char *fmt, ...);
 
 #endif
 
-#if BH_DEBUG == 1
+#if BH_DEBUG != 0
 #define LOG_FATAL(...)   bh_log(BH_LOG_LEVEL_FATAL, __FILE__, __LINE__, __VA_ARGS__)
 #else
 #define LOG_FATAL(...)   bh_log(BH_LOG_LEVEL_FATAL, __FUNCTION__, __LINE__, __VA_ARGS__)
@@ -61,7 +61,7 @@ bh_log(LogLevel log_level, const char *file, int line, const char *fmt, ...);
 #define LOG_WARNING(...) bh_log(BH_LOG_LEVEL_WARNING, NULL, 0, __VA_ARGS__)
 #define LOG_VERBOSE(...) bh_log(BH_LOG_LEVEL_VERBOSE, NULL, 0, __VA_ARGS__)
 
-#if BH_DEBUG == 1
+#if BH_DEBUG != 0
 #define LOG_DEBUG(...)   bh_log(BH_LOG_LEVEL_DEBUG, __FILE__, __LINE__, __VA_ARGS__)
 #else
 #define LOG_DEBUG(...)   (void)0

+ 10 - 4
core/shared/utils/uncommon/bh_read_file.c

@@ -14,7 +14,7 @@ bh_read_file_to_buffer(const char *filename, uint32 *ret_size)
 {
     char *buffer;
     int file;
-    uint32 file_size, read_size;
+    uint32 file_size, buf_size, read_size;
     struct stat stat_buf;
 
     if (!filename || !ret_size) {
@@ -36,7 +36,10 @@ bh_read_file_to_buffer(const char *filename, uint32 *ret_size)
     }
     file_size = (uint32)stat_buf.st_size;
 
-    if (!(buffer = (char *)BH_MALLOC(file_size))) {
+    /* At lease alloc 1 byte to avoid malloc failed */
+    buf_size = file_size > 0 ? file_size : 1;
+
+    if (!(buffer = (char *)BH_MALLOC(buf_size))) {
         printf("Read file to buffer failed: alloc memory failed.\n");
         _close(file);
         return NULL;
@@ -63,7 +66,7 @@ bh_read_file_to_buffer(const char *filename, uint32 *ret_size)
 {
     char *buffer;
     int file;
-    uint32 file_size, read_size;
+    uint32 file_size, buf_size, read_size;
     struct stat stat_buf;
 
     if (!filename || !ret_size) {
@@ -86,7 +89,10 @@ bh_read_file_to_buffer(const char *filename, uint32 *ret_size)
 
     file_size = (uint32)stat_buf.st_size;
 
-    if (!(buffer = BH_MALLOC(file_size))) {
+    /* At lease alloc 1 byte to avoid malloc failed */
+    buf_size = file_size > 0 ? file_size : 1;
+
+    if (!(buffer = BH_MALLOC(buf_size))) {
         printf("Read file to buffer failed: alloc memory failed.\n");
         close(file);
         return NULL;

+ 1 - 1
samples/wasm-c-api/CMakeLists.txt

@@ -74,7 +74,7 @@ endif()
 ## locate wat2wasm
 find_program(WAT2WASM
   wat2wasm
-  PATHS /opt/wabt/bin /opt/wabt-1.0.18/bin
+  PATHS /opt/wabt/bin
   REQUIRED
 )
 

+ 2 - 2
samples/workload/meshoptimizer/codecbench.patch

@@ -1,5 +1,5 @@
 diff --git a/CMakeLists.txt b/CMakeLists.txt
-index ffdb4da..536a5c8 100644
+index ffdb4da..a397427 100644
 --- a/CMakeLists.txt
 +++ b/CMakeLists.txt
 @@ -127,3 +127,43 @@ install(FILES
@@ -24,7 +24,7 @@ index ffdb4da..536a5c8 100644
 +
 +target_link_options(codecbench
 +  PUBLIC
-+    LINKER:-allow-undefined,--demangle
++    LINKER:-allow-undefined,--demangle,--export=malloc,--export=free
 +)
 +
 +find_program(WASM_OPT