浏览代码

Merge branch main into dev/instantiate_linking (#3915)

* Exclude fuzz test python and npm packages in scoreboard scan (#3871)
* Fix out of bounds issues after memory.grow on non-aot non-threads builds (#3872)
* fix(ios): Remove `float-abi` flag (#3889)
* build(deps): bump github/codeql-action from 3.26.13 to 3.27.0 (#3888)
* Refine looking up aot function with index (#3882)
* Bump AOT_CURRENT_VERSION for WAMR 2.x (gc, memory64) (#3880)
* Fix mmap flags for AOT loader on non-Linux SGX platforms (#3890)
* Fix out of bounds issue in is_native_addr_in_shared_heap function (#3886)
* Refactor AOT loader to support compatible versions (#3891)
* Wasm loader enhancement: check code size in code entry  (#3892)
* Fix linked global initialization in multimodule (#3905)
* build(deps): bump github/codeql-action from 3.27.0 to 3.27.1 (#3902)
* GlobalValueSet was moved to IRPartitionLayer recently, but we have a local definition anyway (#3899)
* Fix a leak in wasm_loader_emit_br_info (#3900)
* Correct the table index calculation in aot_instantiation (#3903)
* build(deps): bump github/codeql-action from 3.27.1 to 3.27.4 (#3912)
* Support external toolchain on Windows for aot compiler (#3911)
* Fix CI wamr-ide error (#3913)

Co-authored-by: TianlongLiang <111852609+TianlongLiang@users.noreply.github.com>
Co-authored-by: Maks Litskevich <makslit@amazon.com>
Co-authored-by: Deniz Sokmen <dsokmen@amazon.com>
Co-authored-by: edoardo <48774736+xdoardo@users.noreply.github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: YAMAMOTO Takashi <yamamoto@midokura.com>
Co-authored-by: liang.he <liang.he@intel.com>
Co-authored-by: Fadumina Barre <bafadumi@amazon.com>
Co-authored-by: Marcin Kolny <mkolny@amazon.com>
Co-authored-by: James Ring <sjr@jdns.org>
Wenyong Huang 1 年之前
父节点
当前提交
534c493328

+ 3 - 3
.github/workflows/codeql.yml

@@ -53,7 +53,7 @@ jobs:
 
     # Initializes the CodeQL tools for scanning.
     - name: Initialize CodeQL
-      uses: github/codeql-action/init@v3.26.13
+      uses: github/codeql-action/init@v3.27.4
       with:
         languages: ${{ matrix.language }}
 
@@ -70,7 +70,7 @@ jobs:
     - run: |
         ./.github/scripts/codeql_buildscript.sh
     - name: Perform CodeQL Analysis
-      uses: github/codeql-action/analyze@v3.26.13
+      uses: github/codeql-action/analyze@v3.27.4
       with:
         category: "/language:${{matrix.language}}"
         upload: false
@@ -99,7 +99,7 @@ jobs:
         output: ${{ steps.step1.outputs.sarif-output }}/cpp.sarif
 
     - name: Upload CodeQL results to code scanning
-      uses: github/codeql-action/upload-sarif@v3.26.13
+      uses: github/codeql-action/upload-sarif@v3.27.4
       with:
         sarif_file: ${{ steps.step1.outputs.sarif-output }}
         category: "/language:${{matrix.language}}"

+ 1 - 1
.github/workflows/compilation_on_android_ubuntu.yml

@@ -828,7 +828,7 @@ jobs:
         run: |
           mkdir build
           cd build
-          cmake .. -DWAMR_BUILD_DEBUG_INTERP=1
+          cmake .. -DWAMR_BUILD_DEBUG_INTERP=1 -DWAMR_BUILD_REF_TYPES=1
           make
         working-directory: product-mini/platforms/linux
 

+ 1 - 1
.github/workflows/supply_chain.yml

@@ -60,6 +60,6 @@ jobs:
 
       # Upload the results to GitHub's code scanning dashboard.
       - name: "Upload to code-scanning"
-        uses: github/codeql-action/upload-sarif@af56b044b5d41c317aef5d19920b3183cb4fbbec # v2.2.4
+        uses: github/codeql-action/upload-sarif@a1695c562bbfa68dc5ab58c9b5e9f616b52bf5be # v2.2.4
         with:
           sarif_file: results.sarif

+ 18 - 2
build-scripts/build_llvm.py

@@ -102,12 +102,27 @@ def build_llvm(llvm_dir, platform, backends, projects, use_clang=False, extra_fl
         "default": [],
     }
 
+    experimental_backends = ["ARC", "Xtensa"]
+    normal_backends = [s for s in backends if s not in experimental_backends]
+
     LLVM_TARGETS_TO_BUILD = [
-        '-DLLVM_TARGETS_TO_BUILD:STRING="' + ";".join(backends) + '"'
-        if backends
+        '-DLLVM_TARGETS_TO_BUILD:STRING="' + ";".join(normal_backends) + '"'
+        if normal_backends
         else '-DLLVM_TARGETS_TO_BUILD:STRING="AArch64;ARM;Mips;RISCV;X86"'
     ]
 
+    # if not on ARC platform, but want to add expeirmental backend ARC as target
+    if platform != "ARC" and "ARC" in backends: 
+        LLVM_TARGETS_TO_BUILD.extend(
+            LLVM_EXTRA_COMPILE_OPTIONS["arc"]
+        )
+
+    if platform != "Xtensa" and "Xtensa" in backends:
+        print(
+            "Currently it's not supported to build Xtensa backend on non-Xtensa platform"
+        )
+        return None
+
     LLVM_PROJECTS_TO_BUILD = [
         '-DLLVM_ENABLE_PROJECTS:STRING="' + ";".join(projects) + '"' if projects else ""
     ]
@@ -240,6 +255,7 @@ def main():
             "X86",
             "Xtensa",
         ],
+        default=[],
         help="identify LLVM supported backends, separate by space, like '--arch ARM Mips X86'",
     )
     parser.add_argument(

+ 1 - 0
ci/coding_guidelines_check.py

@@ -180,6 +180,7 @@ def check_file_name(path: Path) -> bool:
         "docker-compose",
         "package-lock",
         "vite-env.d",
+        "osv-scanner",
     ]:
         return True
 

+ 1 - 1
core/config.h

@@ -84,7 +84,7 @@
 #endif
 
 #define AOT_MAGIC_NUMBER 0x746f6100
-#define AOT_CURRENT_VERSION 3
+#define AOT_CURRENT_VERSION 4
 
 #ifndef WASM_ENABLE_JIT
 #define WASM_ENABLE_JIT 0

+ 13 - 2
core/iwasm/aot/aot_loader.c

@@ -304,12 +304,13 @@ loader_mmap(uint32 size, bool prot_exec, char *error_buf, uint32 error_buf_size)
 #if defined(BUILD_TARGET_X86_64) || defined(BUILD_TARGET_AMD_64) \
     || defined(BUILD_TARGET_RISCV64_LP64D)                       \
     || defined(BUILD_TARGET_RISCV64_LP64)
-#ifndef __APPLE__
+#if !defined(__APPLE__) && !defined(BH_PLATFORM_LINUX_SGX)
     /* The mmapped AOT data and code in 64-bit targets had better be in
        range 0 to 2G, or aot loader may fail to apply some relocations,
        e.g., R_X86_64_32/R_X86_64_32S/R_X86_64_PC32/R_RISCV_32.
        We try to mmap with MMAP_MAP_32BIT flag first, and if fails, mmap
        again without the flag. */
+    /* sgx_tprotect_rsrv_mem() and sgx_alloc_rsrv_mem() will ignore flags */
     map_flags = MMAP_MAP_32BIT;
     if ((mem = os_mmap(NULL, size, map_prot, map_flags,
                        os_get_invalid_handle()))) {
@@ -4290,6 +4291,16 @@ fail:
     return false;
 }
 
+static bool
+aot_compatible_version(uint32 version)
+{
+    /*
+     * refer to "AoT-compiled module compatibility among WAMR versions" in
+     * ./doc/biuld_wasm_app.md
+     */
+    return version == 4 || version == 3;
+}
+
 static bool
 load(const uint8 *buf, uint32 size, AOTModule *module,
      bool wasm_binary_freeable, bool no_resolve, char *error_buf,
@@ -4308,7 +4319,7 @@ load(const uint8 *buf, uint32 size, AOTModule *module,
     }
 
     read_uint32(p, p_end, version);
-    if (version != AOT_CURRENT_VERSION) {
+    if (!aot_compatible_version(version)) {
         set_error_buf(error_buf, error_buf_size, "unknown binary version");
         return false;
     }

+ 75 - 11
core/iwasm/aot/aot_runtime.c

@@ -1129,11 +1129,11 @@ aot_get_default_memory(AOTModuleInstance *module_inst)
 }
 
 AOTMemoryInstance *
-aot_get_memory_with_index(AOTModuleInstance *module_inst, uint32 index)
+aot_get_memory_with_idx(AOTModuleInstance *module_inst, uint32 mem_idx)
 {
-    if ((index >= module_inst->memory_count) || !module_inst->memories)
+    if ((mem_idx >= module_inst->memory_count) || !module_inst->memories)
         return NULL;
-    return module_inst->memories[index];
+    return module_inst->memories[mem_idx];
 }
 
 static bool
@@ -1428,21 +1428,78 @@ init_func_ptrs(AOTModuleInstance *module_inst, AOTModule *module,
     return true;
 }
 
+static int
+cmp_export_func_map(const void *a, const void *b)
+{
+    uint32 func_idx1 = ((const ExportFuncMap *)a)->func_idx;
+    uint32 func_idx2 = ((const ExportFuncMap *)b)->func_idx;
+    return func_idx1 < func_idx2 ? -1 : (func_idx1 > func_idx2 ? 1 : 0);
+}
+
 AOTFunctionInstance *
-aot_get_function_instance(AOTModuleInstance *module_inst, uint32 func_idx)
+aot_lookup_function_with_idx(AOTModuleInstance *module_inst, uint32 func_idx)
 {
-    AOTModule *module = (AOTModule *)module_inst->module;
     AOTModuleInstanceExtra *extra = (AOTModuleInstanceExtra *)module_inst->e;
     AOTFunctionInstance *export_funcs =
         (AOTFunctionInstance *)module_inst->export_functions;
+    AOTFunctionInstance *func_inst = NULL;
+    ExportFuncMap *export_func_maps, *export_func_map, key;
+    uint64 size;
     uint32 i;
 
-    /* export functions are pre-instantiated */
-    for (i = 0; i < module_inst->export_func_count; i++) {
-        if (export_funcs[i].func_index == func_idx)
-            return &export_funcs[i];
+    if (module_inst->export_func_count == 0)
+        return NULL;
+
+    exception_lock(module_inst);
+
+    /* create the func_idx to export_idx maps if it hasn't been created */
+    if (!extra->export_func_maps) {
+        size = sizeof(ExportFuncMap) * (uint64)module_inst->export_func_count;
+        if (!(export_func_maps = extra->export_func_maps =
+                  runtime_malloc(size, NULL, 0))) {
+            /* allocate memory failed, lookup the export function one by one */
+            for (i = 0; i < module_inst->export_func_count; i++) {
+                if (export_funcs[i].func_index == func_idx) {
+                    func_inst = &export_funcs[i];
+                    break;
+                }
+            }
+            goto unlock_and_return;
+        }
+
+        for (i = 0; i < module_inst->export_func_count; i++) {
+            export_func_maps[i].func_idx = export_funcs[i].func_index;
+            export_func_maps[i].export_idx = i;
+        }
+
+        qsort(export_func_maps, module_inst->export_func_count,
+              sizeof(ExportFuncMap), cmp_export_func_map);
     }
 
+    /* lookup the map to get the export_idx of the func_idx */
+    key.func_idx = func_idx;
+    export_func_map =
+        bsearch(&key, extra->export_func_maps, module_inst->export_func_count,
+                sizeof(ExportFuncMap), cmp_export_func_map);
+    if (export_func_map)
+        func_inst = &export_funcs[export_func_map->export_idx];
+
+unlock_and_return:
+    exception_unlock(module_inst);
+    return func_inst;
+}
+
+AOTFunctionInstance *
+aot_get_function_instance(AOTModuleInstance *module_inst, uint32 func_idx)
+{
+    AOTModule *module = (AOTModule *)module_inst->module;
+    AOTModuleInstanceExtra *extra = (AOTModuleInstanceExtra *)module_inst->e;
+    AOTFunctionInstance *func_inst;
+
+    /* lookup from export functions first */
+    if ((func_inst = aot_lookup_function_with_idx(module_inst, func_idx)))
+        return func_inst;
+
     exception_lock(module_inst);
 
     /* allocate functions array if needed */
@@ -1891,7 +1948,7 @@ aot_instantiate(AOTModule *module, AOTModuleInstance *parent,
     }
 #endif
 
-    /* Check heap size */
+    /* Align and validate heap size */
     heap_size = align_uint(heap_size, 8);
     if (heap_size > APP_HEAP_SIZE_MAX)
         heap_size = APP_HEAP_SIZE_MAX;
@@ -2118,7 +2175,11 @@ aot_instantiate(AOTModule *module, AOTModuleInstance *parent,
         AOTTableInstance *table_inst;
         table_elem_type_t *table_data;
 
-        table = &module->tables[i];
+        /* bypass imported table since AOTImportTable doesn't have init_expr */
+        if (i < module->import_table_count)
+            continue;
+
+        table = &module->tables[i - module->import_table_count];
         bh_assert(table);
 
         if (table->init_expr.init_expr_type == INIT_EXPR_NONE) {
@@ -2342,6 +2403,9 @@ aot_deinstantiate(AOTModuleInstance *module_inst, bool is_sub_inst)
     if (module_inst->export_functions)
         wasm_runtime_free(module_inst->export_functions);
 
+    if (extra->export_func_maps)
+        wasm_runtime_free(extra->export_func_maps);
+
     if (module_inst->export_globals)
         wasm_runtime_free(module_inst->export_globals);
 

+ 23 - 2
core/iwasm/aot/aot_runtime.h

@@ -109,6 +109,13 @@ typedef struct AOTFunctionInstance {
     } u;
 } AOTFunctionInstance;
 
+/* Map of a function index to the element ith in
+   the export functions array */
+typedef struct ExportFuncMap {
+    uint32 func_idx;
+    uint32 export_idx;
+} ExportFuncMap;
+
 typedef struct AOTModuleInstanceExtra {
     DefPointer(const uint32 *, stack_sizes);
     /*
@@ -120,6 +127,13 @@ typedef struct AOTModuleInstanceExtra {
     MemBound shared_heap_start_off;
 
     WASMModuleInstanceExtraCommon common;
+
+    /**
+     * maps of func indexes to export func indexes, which
+     * is sorted by func index for a quick lookup and is
+     * created only when first time used.
+     */
+    ExportFuncMap *export_func_maps;
     AOTFunctionInstance **functions;
     uint32 function_count;
 #if WASM_ENABLE_MULTI_MODULE != 0
@@ -561,6 +575,13 @@ aot_destroy_memory(AOTMemoryInstance *memory);
 AOTFunctionInstance *
 aot_lookup_function(const AOTModuleInstance *module_inst, const char *name);
 
+/**
+ * Lookup an exported function in the AOT module instance with
+ * the function index.
+ */
+AOTFunctionInstance *
+aot_lookup_function_with_idx(AOTModuleInstance *module_inst, uint32 func_idx);
+
 AOTMemoryInstance *
 aot_lookup_memory(AOTModuleInstance *module_inst, char const *name);
 
@@ -568,7 +589,7 @@ AOTMemoryInstance *
 aot_get_default_memory(AOTModuleInstance *module_inst);
 
 AOTMemoryInstance *
-aot_get_memory_with_index(AOTModuleInstance *module_inst, uint32 index);
+aot_get_memory_with_idx(AOTModuleInstance *module_inst, uint32 mem_idx);
 
 /**
  * Get a function in the AOT module instance.
@@ -579,7 +600,7 @@ aot_get_memory_with_index(AOTModuleInstance *module_inst, uint32 index);
  * @return the function instance found
  */
 AOTFunctionInstance *
-aot_get_function_instance(AOTModuleInstance *module_inst, uint32_t func_idx);
+aot_get_function_instance(AOTModuleInstance *module_inst, uint32 func_idx);
 
 /**
  * Call the given AOT function of a AOT module instance with

+ 2 - 1
core/iwasm/common/wasm_application.c

@@ -105,7 +105,8 @@ execute_main(WASMModuleInstanceCommon *module_inst, int32 argc, char *argv[])
     bool ret, is_import_func = true, is_memory64 = false;
 #if WASM_ENABLE_MEMORY64 != 0
     WASMModuleInstance *wasm_module_inst = (WASMModuleInstance *)module_inst;
-    is_memory64 = wasm_module_inst->memories[0]->is_memory64;
+    if (wasm_module_inst->memory_count > 0)
+        is_memory64 = wasm_module_inst->memories[0]->is_memory64;
 #endif
 
     exec_env = wasm_runtime_get_exec_env_singleton(module_inst);

+ 2 - 14
core/iwasm/common/wasm_c_api.c

@@ -3383,20 +3383,8 @@ wasm_func_call(const wasm_func_t *func, const wasm_val_vec_t *params,
         if (!(func_comm_rt = func->func_comm_rt)) {
             AOTModuleInstance *inst_aot =
                 (AOTModuleInstance *)func->inst_comm_rt;
-            AOTModule *module_aot = (AOTModule *)inst_aot->module;
-            uint32 export_i = 0;
-
-            for (; export_i < module_aot->export_count; ++export_i) {
-                AOTExport *export = module_aot->exports + export_i;
-                if (export->kind == EXPORT_KIND_FUNC) {
-                    if (export->index == func->func_idx_rt) {
-                        func_comm_rt =
-                            aot_lookup_function(inst_aot, export->name);
-                        ((wasm_func_t *)func)->func_comm_rt = func_comm_rt;
-                        break;
-                    }
-                }
-            }
+            func_comm_rt = ((wasm_func_t *)func)->func_comm_rt =
+                aot_lookup_function_with_idx(inst_aot, func->func_idx_rt);
         }
 #endif
     }

+ 24 - 7
core/iwasm/common/wasm_memory.c

@@ -420,13 +420,31 @@ is_native_addr_in_shared_heap(WASMModuleInstanceCommon *module_inst,
                               uint8 *addr, uint32 bytes)
 {
     WASMSharedHeap *heap = get_shared_heap(module_inst);
+    uintptr_t base_addr;
+    uintptr_t addr_int;
+    uintptr_t end_addr;
 
-    if (heap && addr >= heap->base_addr
-        && addr + bytes <= heap->base_addr + heap->size
-        && addr + bytes > addr) {
-        return true;
+    if (!heap) {
+        return false;
     }
-    return false;
+
+    base_addr = (uintptr_t)heap->base_addr;
+    addr_int = (uintptr_t)addr;
+    if (addr_int < base_addr) {
+        return false;
+    }
+
+    end_addr = addr_int + bytes;
+    /* Check for overflow */
+    if (end_addr <= addr_int) {
+        return false;
+    }
+
+    if (end_addr > base_addr + heap->size) {
+        return false;
+    }
+
+    return true;
 }
 
 uint64
@@ -1624,8 +1642,7 @@ wasm_runtime_get_memory(WASMModuleInstanceCommon *module_inst, uint32 index)
 
 #if WASM_ENABLE_AOT != 0
     if (module_inst->module_type == Wasm_Module_AoT)
-        return aot_get_memory_with_index((AOTModuleInstance *)module_inst,
-                                         index);
+        return aot_get_memory_with_idx((AOTModuleInstance *)module_inst, index);
 #endif
 
     return NULL;

+ 4 - 39
core/iwasm/compilation/aot_compiler.c

@@ -4093,39 +4093,6 @@ aot_compile_wasm(AOTCompContext *comp_ctx)
     return true;
 }
 
-#if !(defined(_WIN32) || defined(_WIN32_))
-char *
-aot_generate_tempfile_name(const char *prefix, const char *extension,
-                           char *buffer, uint32 len)
-{
-    int fd, name_len;
-
-    name_len = snprintf(buffer, len, "%s-XXXXXX", prefix);
-
-    if ((fd = mkstemp(buffer)) <= 0) {
-        aot_set_last_error("make temp file failed.");
-        return NULL;
-    }
-
-    /* close and remove temp file */
-    close(fd);
-    unlink(buffer);
-
-    /* Check if buffer length is enough */
-    /* name_len + '.' + extension + '\0' */
-    if (name_len + 1 + strlen(extension) + 1 > len) {
-        aot_set_last_error("temp file name too long.");
-        return NULL;
-    }
-
-    snprintf(buffer + name_len, len - name_len, ".%s", extension);
-    return buffer;
-}
-#else
-
-errno_t
-_mktemp_s(char *nameTemplate, size_t sizeInChars);
-
 char *
 aot_generate_tempfile_name(const char *prefix, const char *extension,
                            char *buffer, uint32 len)
@@ -4134,7 +4101,8 @@ aot_generate_tempfile_name(const char *prefix, const char *extension,
 
     name_len = snprintf(buffer, len, "%s-XXXXXX", prefix);
 
-    if (_mktemp_s(buffer, name_len + 1) != 0) {
+    if (!bh_mkstemp(buffer, name_len + 1)) {
+        aot_set_last_error("make temp file failed.");
         return NULL;
     }
 
@@ -4148,7 +4116,6 @@ aot_generate_tempfile_name(const char *prefix, const char *extension,
     snprintf(buffer + name_len, len - name_len, ".%s", extension);
     return buffer;
 }
-#endif /* end of !(defined(_WIN32) || defined(_WIN32_)) */
 
 bool
 aot_emit_llvm_file(AOTCompContext *comp_ctx, const char *file_name)
@@ -4227,7 +4194,6 @@ aot_emit_object_file(AOTCompContext *comp_ctx, char *file_name)
 
     bh_print_time("Begin to emit object file");
 
-#if !(defined(_WIN32) || defined(_WIN32_))
     if (comp_ctx->external_llc_compiler || comp_ctx->external_asm_compiler) {
         char cmd[1024];
         int ret;
@@ -4270,7 +4236,7 @@ aot_emit_object_file(AOTCompContext *comp_ctx, char *file_name)
                      file_name, bc_file_name);
             LOG_VERBOSE("invoking external LLC compiler:\n\t%s", cmd);
 
-            ret = system(cmd);
+            ret = bh_system(cmd);
             /* remove temp bitcode file */
             unlink(bc_file_name);
 
@@ -4323,7 +4289,7 @@ aot_emit_object_file(AOTCompContext *comp_ctx, char *file_name)
                      file_name, asm_file_name);
             LOG_VERBOSE("invoking external ASM compiler:\n\t%s", cmd);
 
-            ret = system(cmd);
+            ret = bh_system(cmd);
             /* remove temp assembly file */
             unlink(asm_file_name);
 
@@ -4336,7 +4302,6 @@ aot_emit_object_file(AOTCompContext *comp_ctx, char *file_name)
 
         return true;
     }
-#endif /* end of !(defined(_WIN32) || defined(_WIN32_)) */
 
     if (!strncmp(LLVMGetTargetName(target), "arc", 3))
         /* Emit to assembly file instead for arc target

+ 3 - 17
core/iwasm/compilation/aot_emit_aot_file.c

@@ -4398,10 +4398,6 @@ aot_obj_data_create(AOTCompContext *comp_ctx)
 
     bh_print_time("Begin to emit object file");
     if (comp_ctx->external_llc_compiler || comp_ctx->external_asm_compiler) {
-#if defined(_WIN32) || defined(_WIN32_)
-        aot_set_last_error("external toolchain not supported on Windows");
-        goto fail;
-#else
         /* Generate a temp file name */
         int ret;
         char obj_file_name[64];
@@ -4429,27 +4425,18 @@ aot_obj_data_create(AOTCompContext *comp_ctx)
             aot_set_last_error("create mem buffer with file failed.");
             goto fail;
         }
-#endif /* end of defined(_WIN32) || defined(_WIN32_) */
     }
     else if (!strncmp(LLVMGetTargetName(target), "arc", 3)) {
-#if defined(_WIN32) || defined(_WIN32_)
-        aot_set_last_error("emit object file on Windows is unsupported.");
-        goto fail;
-#else
         /* Emit to assembly file instead for arc target
            as it cannot emit to object file */
         char file_name[] = "wasm-XXXXXX", buf[128];
-        int fd, ret;
+        int ret;
 
-        if ((fd = mkstemp(file_name)) <= 0) {
+        if (!bh_mkstemp(file_name, sizeof(file_name))) {
             aot_set_last_error("make temp file failed.");
             goto fail;
         }
 
-        /* close and remove temp file */
-        close(fd);
-        unlink(file_name);
-
         snprintf(buf, sizeof(buf), "%s%s", file_name, ".s");
         if (LLVMTargetMachineEmitToFile(comp_ctx->target_machine,
                                         comp_ctx->module, buf, LLVMAssemblyFile,
@@ -4470,7 +4457,7 @@ aot_obj_data_create(AOTCompContext *comp_ctx)
                  "/opt/zephyr-sdk/arc-zephyr-elf/bin/arc-zephyr-elf-gcc ",
                  "-mcpu=arcem -o ", file_name, ".o -c ", file_name, ".s");
         /* TODO: use try..catch to handle possible exceptions */
-        ret = system(buf);
+        ret = bh_system(buf);
         /* remove temp assembly file */
         snprintf(buf, sizeof(buf), "%s%s", file_name, ".s");
         unlink(buf);
@@ -4497,7 +4484,6 @@ aot_obj_data_create(AOTCompContext *comp_ctx)
             aot_set_last_error("create mem buffer with file failed.");
             goto fail;
         }
-#endif /* end of defined(_WIN32) || defined(_WIN32_) */
     }
     else {
         if (LLVMTargetMachineEmitToMemoryBuffer(

+ 0 - 10
core/iwasm/compilation/aot_llvm.c

@@ -2744,10 +2744,6 @@ aot_create_comp_context(const AOTCompData *comp_data, aot_comp_option_t option)
         /* verify external llc compiler */
         comp_ctx->external_llc_compiler = getenv("WAMRC_LLC_COMPILER");
         if (comp_ctx->external_llc_compiler) {
-#if defined(_WIN32) || defined(_WIN32_)
-            comp_ctx->external_llc_compiler = NULL;
-            LOG_WARNING("External LLC compiler not supported on Windows.");
-#else
             if (access(comp_ctx->external_llc_compiler, X_OK) != 0) {
                 LOG_WARNING("WAMRC_LLC_COMPILER [%s] not found, fallback to "
                             "default pipeline",
@@ -2759,17 +2755,12 @@ aot_create_comp_context(const AOTCompData *comp_data, aot_comp_option_t option)
                 LOG_VERBOSE("Using external LLC compiler [%s]",
                             comp_ctx->external_llc_compiler);
             }
-#endif
         }
 
         /* verify external asm compiler */
         if (!comp_ctx->external_llc_compiler) {
             comp_ctx->external_asm_compiler = getenv("WAMRC_ASM_COMPILER");
             if (comp_ctx->external_asm_compiler) {
-#if defined(_WIN32) || defined(_WIN32_)
-                comp_ctx->external_asm_compiler = NULL;
-                LOG_WARNING("External ASM compiler not supported on Windows.");
-#else
                 if (access(comp_ctx->external_asm_compiler, X_OK) != 0) {
                     LOG_WARNING(
                         "WAMRC_ASM_COMPILER [%s] not found, fallback to "
@@ -2782,7 +2773,6 @@ aot_create_comp_context(const AOTCompData *comp_data, aot_comp_option_t option)
                     LOG_VERBOSE("Using external ASM compiler [%s]",
                                 comp_ctx->external_asm_compiler);
                 }
-#endif
             }
         }
 

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

@@ -37,6 +37,18 @@
 #include "aot_orc_extra.h"
 #include "aot_comp_option.h"
 
+#if defined(_WIN32) || defined(_WIN32_)
+#include <io.h>
+#define access _access
+/* On windows there is no X_OK flag to check for executablity, only check for
+ * existence */
+#ifdef X_OK
+#undef X_OK
+#endif
+#define X_OK 00
+#define unlink _unlink
+#endif
+
 #ifdef __cplusplus
 extern "C" {
 #endif

+ 1 - 1
core/iwasm/compilation/aot_orc_extra.cpp

@@ -177,7 +177,7 @@ LLVMOrcLLLazyJITBuilderSetJITTargetMachineBuilder(
     LLVMOrcDisposeJITTargetMachineBuilder(JTMP);
 }
 
-static Optional<CompileOnDemandLayer::GlobalValueSet>
+static Optional<GlobalValueSet>
 PartitionFunction(GlobalValueSet Requested)
 {
     std::vector<const GlobalValue *> GVsToAdd;

+ 1 - 1
core/iwasm/interpreter/wasm_interp_classic.c

@@ -6727,7 +6727,7 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
     || WASM_CPU_SUPPORTS_UNALIGNED_ADDR_ACCESS == 0 \
     || WASM_ENABLE_BULK_MEMORY != 0
             if (memory)
-                linear_mem_size = get_linear_mem_size();
+                linear_mem_size = GET_LINEAR_MEMORY_SIZE(memory);
 #endif
             if (wasm_copy_exception(module, NULL)) {
 #if WASM_ENABLE_EXCE_HANDLING != 0

+ 1 - 1
core/iwasm/interpreter/wasm_interp_fast.c

@@ -5994,7 +5994,7 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
     || WASM_CPU_SUPPORTS_UNALIGNED_ADDR_ACCESS == 0 \
     || WASM_ENABLE_BULK_MEMORY != 0
             if (memory)
-                linear_mem_size = get_linear_mem_size();
+                linear_mem_size = GET_LINEAR_MEMORY_SIZE(memory);
 #endif
             if (wasm_copy_exception(module, NULL))
                 goto got_exception;

+ 30 - 18
core/iwasm/interpreter/wasm_loader.c

@@ -3610,6 +3610,17 @@ load_function_section(const uint8 *buf, const uint8 *buf_end,
 #endif
             }
 
+            /* Code size in code entry can't be smaller than size of vec(locals)
+             * + expr(at least 1 for opcode end). And expressions are encoded by
+             * their instruction sequence terminated with an explicit 0x0B
+             * opcode for end. */
+            if (p_code_end <= p_code || *(p_code_end - 1) != WASM_OP_END) {
+                set_error_buf(
+                    error_buf, error_buf_size,
+                    "section size mismatch: function body END opcode expected");
+                return false;
+            }
+
             /* Alloc memory, layout: function structure + local types */
             code_size = (uint32)(p_code_end - p_code);
 
@@ -9848,13 +9859,6 @@ fail:
 }
 #endif /* WASM_ENABLE_FAST_INTERP */
 
-#define RESERVE_BLOCK_RET()                                                 \
-    do {                                                                    \
-        if (!reserve_block_ret(loader_ctx, opcode, disable_emit, error_buf, \
-                               error_buf_size))                             \
-            goto fail;                                                      \
-    } while (0)
-
 #define PUSH_TYPE(type)                                               \
     do {                                                              \
         if (!(wasm_loader_push_frame_ref(loader_ctx, type, error_buf, \
@@ -11575,7 +11579,10 @@ re_scan:
 #if WASM_ENABLE_FAST_INTERP != 0
                 /* if the result of if branch is in local or const area, add a
                  * copy op */
-                RESERVE_BLOCK_RET();
+                if (!reserve_block_ret(loader_ctx, opcode, disable_emit,
+                                       error_buf, error_buf_size)) {
+                    goto fail;
+                }
 
                 emit_empty_label_addr_and_frame_ip(PATCH_END);
                 apply_label_patch(loader_ctx, 1, PATCH_ELSE);
@@ -11635,7 +11642,15 @@ re_scan:
 #if WASM_ENABLE_FAST_INTERP != 0
                 skip_label();
                 /* copy the result to the block return address */
-                RESERVE_BLOCK_RET();
+                if (!reserve_block_ret(loader_ctx, opcode, disable_emit,
+                                       error_buf, error_buf_size)) {
+                    /* it could be tmp frame_csp allocated from opcode like
+                     * OP_BR and not counted in loader_ctx->csp_num, it won't
+                     * be freed in wasm_loader_ctx_destroy(loader_ctx) so need
+                     * to free the loader_ctx->frame_csp if fails */
+                    free_label_patch_list(loader_ctx->frame_csp);
+                    goto fail;
+                }
 
                 apply_label_patch(loader_ctx, 0, PATCH_END);
                 free_label_patch_list(loader_ctx->frame_csp);
@@ -15811,15 +15826,12 @@ re_scan:
     }
 
     if (loader_ctx->csp_num > 0) {
-        if (cur_func_idx < module->function_count - 1)
-            /* Function with missing end marker (between two functions) */
-            set_error_buf(error_buf, error_buf_size, "END opcode expected");
-        else
-            /* Function with missing end marker
-               (at EOF or end of code sections) */
-            set_error_buf(error_buf, error_buf_size,
-                          "unexpected end of section or function, "
-                          "or section size mismatch");
+        /* unmatched end opcodes result from unbalanced control flow structures,
+         * for example, br_table with inconsistent target count (1 declared, 2
+         * given), or simply superfluous end opcodes */
+        set_error_buf(
+            error_buf, error_buf_size,
+            "unexpected end opcodes from unbalanced control flow structures");
         goto fail;
     }
 

+ 11 - 9
core/iwasm/interpreter/wasm_mini_loader.c

@@ -1183,6 +1183,8 @@ load_function_section(const uint8 *buf, const uint8 *buf_end,
                 local_count += sub_local_count;
             }
 
+            bh_assert(p_code_end > p_code && *(p_code_end - 1) == WASM_OP_END);
+
             /* Alloc memory, layout: function structure + local types */
             code_size = (uint32)(p_code_end - p_code);
 
@@ -5590,13 +5592,6 @@ fail:
 
 #endif /* WASM_ENABLE_FAST_INTERP */
 
-#define RESERVE_BLOCK_RET()                                                 \
-    do {                                                                    \
-        if (!reserve_block_ret(loader_ctx, opcode, disable_emit, error_buf, \
-                               error_buf_size))                             \
-            goto fail;                                                      \
-    } while (0)
-
 #define PUSH_TYPE(type)                                               \
     do {                                                              \
         if (!(wasm_loader_push_frame_ref(loader_ctx, type, error_buf, \
@@ -6364,7 +6359,10 @@ re_scan:
 #if WASM_ENABLE_FAST_INTERP != 0
                 /* if the result of if branch is in local or const area, add a
                  * copy op */
-                RESERVE_BLOCK_RET();
+                if (!reserve_block_ret(loader_ctx, opcode, disable_emit,
+                                       error_buf, error_buf_size)) {
+                    goto fail;
+                }
 
                 emit_empty_label_addr_and_frame_ip(PATCH_END);
                 apply_label_patch(loader_ctx, 1, PATCH_ELSE);
@@ -6424,7 +6422,11 @@ re_scan:
 #if WASM_ENABLE_FAST_INTERP != 0
                 skip_label();
                 /* copy the result to the block return address */
-                RESERVE_BLOCK_RET();
+                if (!reserve_block_ret(loader_ctx, opcode, disable_emit,
+                                       error_buf, error_buf_size)) {
+                    free_label_patch_list(loader_ctx->frame_csp);
+                    goto fail;
+                }
 
                 apply_label_patch(loader_ctx, 0, PATCH_END);
                 free_label_patch_list(loader_ctx->frame_csp);

+ 1 - 1
core/iwasm/interpreter/wasm_runtime.c

@@ -1336,7 +1336,7 @@ globals_instantiate(WASMModule *module, WASMModuleInstance *module_inst,
             /* The linked global instance has been initialized, we
                just need to copy the value. */
             bh_memcpy_s(&(global->initial_value), sizeof(WASMValue),
-                        &(global_import->import_global_linked->init_expr),
+                        &(global_import->import_global_linked->init_expr.u),
                         sizeof(WASMValue));
         }
         else

+ 2 - 0
core/shared/platform/windows/win_clock.c

@@ -10,9 +10,11 @@
 #define NANOSECONDS_PER_SECOND 1000000000ULL
 #define NANOSECONDS_PER_TICK 100
 
+#if WINAPI_PARTITION_DESKTOP
 extern NTSTATUS
 NtQueryTimerResolution(PULONG MinimumResolution, PULONG MaximumResolution,
                        PULONG CurrentResolution);
+#endif
 
 static __wasi_errno_t
 calculate_monotonic_clock_frequency(uint64 *out_frequency)

+ 50 - 0
core/shared/utils/bh_common.c

@@ -165,3 +165,53 @@ wa_strdup(const char *s)
     }
     return s1;
 }
+
+#if WASM_ENABLE_WAMR_COMPILER != 0 || WASM_ENABLE_JIT != 0
+int
+bh_system(const char *cmd)
+{
+    int ret;
+
+#if !(defined(_WIN32) || defined(_WIN32_))
+    ret = system(cmd);
+#else
+    ret = _spawnlp(_P_WAIT, "cmd.exe", "/c", cmd, NULL);
+#endif
+
+    return ret;
+}
+
+#if defined(_WIN32) || defined(_WIN32_)
+errno_t
+_mktemp_s(char *nameTemplate, size_t sizeInChars);
+#endif
+
+bool
+bh_mkstemp(char *file_name, size_t name_len)
+{
+    int fd;
+
+#if !(defined(_WIN32) || defined(_WIN32_))
+    (void)name_len;
+    /* On Linux, it generates a unique temporary filename from template, creates
+     * and opens the file, and returns an open file descriptor for the file. */
+    if ((fd = mkstemp(file_name)) <= 0) {
+        goto fail;
+    }
+
+    /* close and remove temp file */
+    close(fd);
+    unlink(file_name);
+#else
+    /* On Windows, it generates a unique temporary file name but does not create
+     * or open the file */
+    if (_mktemp_s(file_name, name_len) != 0) {
+        goto fail;
+    }
+#endif
+
+    return true;
+fail:
+    return false;
+}
+#endif /* End of WASM_ENABLE_WAMR_COMPILER != 0 || WASM_ENABLE_JIT != 0 */

+ 10 - 0
core/shared/utils/bh_common.h

@@ -66,6 +66,16 @@ bh_strdup(const char *s);
 char *
 wa_strdup(const char *s);
 
+#if WASM_ENABLE_WAMR_COMPILER != 0 || WASM_ENABLE_JIT != 0
+/* Executes a system command in bash/cmd.exe */
+int
+bh_system(const char *cmd);
+
+/* Tests whether can create a temporary file with the given name */
+bool
+bh_mkstemp(char *filename, size_t name_len);
+#endif
+
 #ifdef __cplusplus
 }
 #endif

+ 11 - 3
doc/build_wasm_app.md

@@ -377,15 +377,23 @@ Examples: wamrc -o test.aot test.wasm
 When making major ABI changes for AoT-compiled modules, we bump
 `AOT_CURRENT_VERSION` constant in `core/config.h` header.
 The runtime rejects to load a module AoT-compiled with wamrc with
-a different `AOT_CURRENT_VERSION`.
+a non-compatible`AOT_CURRENT_VERSION`.
 
 We try our best to maintain our runtime ABI for AoT-compiled modules
-compatible among WAMR versions with the same `AOT_CURRENT_VERSION`
+compatible among WAMR versions with compatible `AOT_CURRENT_VERSION`
 so that combinations of older wamrc and newer runtime usually work.
 However, there might be minor incompatibilities time to time.
-For productions, we recommend to use the exactly same version of
+For productions, we recommend to use compatible versions of
 wamrc and the runtime.
 
+| WAMR version | AOT_CURRENT_VERSION | Compatible AOT version |
+| ------------ | ------------------- | ---------------------- |
+| 1.x          | 3                   | 3                      |
+| 2.0.0        | 3                   | 3                      |
+| 2.1.x        | 3                   | 3                      |
+| 2.2.0        | 3                   | 3                      |
+| next         | 4                   | 3,4                    |
+
 ## AoT compilation with 3rd-party toolchains
 
 `wamrc` uses LLVM to compile wasm bytecode to AoT file, this works for most of the architectures, but there may be circumstances where you want to use 3rd-party toolchains to take over some steps of the compilation pipeline, e.g.

+ 0 - 2
product-mini/platforms/ios/CMakeLists.txt

@@ -3,8 +3,6 @@
 
 cmake_minimum_required (VERSION 3.21)
 
-set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -mfloat-abi=hard")
-
 project (iwasm)
 
 set (WAMR_BUILD_PLATFORM "darwin")

+ 1 - 1
test-tools/aot-analyzer/include/config.h

@@ -15,7 +15,7 @@
 #define WASM_CURRENT_VERSION 1
 
 #define AOT_MAGIC_NUMBER 0x746f6100
-#define AOT_CURRENT_VERSION 3
+#define AOT_CURRENT_VERSION 4
 
 /* Legal values for bin_type */
 #define BIN_TYPE_ELF32L 0 /* 32-bit little endian */

+ 8 - 5
test-tools/wamr-ide/VSCode-Extension/src/test/suite/extension.test.ts

@@ -196,11 +196,14 @@ suite('Inegration Tests', function () {
         );
 
         // Vector
-        assert.equal(
-            namesToVariables['vector'].value,
-            ' (5) vec![1, 2, 3, 4, 12]',
-            'The Vector summary string looks different than expected'
-        );
+        // TODO: The vector format conversion have some problem now, can't see the actual value
+        // - (5) vec![{...}, {...}, {...}, {...}, {...}, ...]
+        // + (5) vec![1, 2, 3, 4, 12]
+        // assert.equal(
+        //     namesToVariables['vector'].value,
+        //     ' (5) vec![1, 2, 3, 4, 12]',
+        //     'The Vector summary string looks different than expected'
+        // );
 
         // Map
         assert.equal(

+ 52 - 0
tests/fuzz/wasm-mutator-fuzz/portal/osv-scanner.toml

@@ -0,0 +1,52 @@
+# GHSA-67hx-6x53-jw92
+[[PackageOverrides]]
+name = "@babel/traverse"
+ecosystem = "npm"
+ignore = true
+reason = "Accepted known vulnerabilities for testing purposes"
+
+# GHSA-67hx-6x53-jw92
+[[PackageOverrides]]
+name = "babel-traverse"
+ecosystem = "npm"
+ignore = true
+reason = "Accepted known vulnerabilities for testing purposes"
+
+# GHSA-9c47-m6qq-7p4h	
+[[PackageOverrides]]
+name = "json5"
+ecosystem = "npm"
+ignore = true
+reason = "Dependency not critical for security"
+
+# GHSA-7fh5-64p2-3v2j
+[[PackageOverrides]]
+name = "postcss"
+ecosystem = "npm"
+ignore = true
+reason = "Vulnerabilities do not affect current use case"
+
+# GHSA-gcx4-mw62-g8wm
+[[PackageOverrides]]
+name = "rollup"
+ecosystem = "npm"
+ignore = true
+reason = "Legacy build tool under controlled environment"
+
+# GHSA-c2qf-rxjj-qqgw
+[[PackageOverrides]]
+name = "semver"
+ecosystem = "npm"
+ignore = true
+reason = "Version parsing is managed securely"
+
+# GHSA-353f-5xf4-qw67
+# GHSA-c24v-8rfc-w8vw
+# GHSA-8jhw-289h-jh2g
+# GHSA-64vr-g452-qvp3
+# GHSA-9cwx-2883-4wfx
+[[PackageOverrides]]
+name = "vite"
+ecosystem = "npm"
+ignore = true
+reason = "Development server not exposed to untrusted networks"

+ 32 - 0
tests/fuzz/wasm-mutator-fuzz/server/osv-scanner.toml

@@ -0,0 +1,32 @@
+# GHSA-m2qf-hxjv-5gpq / PYSEC-2023-62
+[[PackageOverrides]]
+name = "Flask"
+ecosystem = "PyPI"
+ignore = true
+reason = "Accepted known vulnerabilities for testing purposes"
+
+# GHSA-m2qf-hxjv-5gpq / PYSEC-2023-62
+[[PackageOverrides]]
+name = "flask"
+ecosystem = "PyPI"
+ignore = true
+reason = "Accepted known vulnerabilities for testing purposes"
+
+# GHSA-84pr-m4jr-85g5
+# GHSA-hxwh-jpp2-84pm / PYSEC-2024-71
+[[PackageOverrides]]
+name = "flask-cors"
+ecosystem = "PyPI"
+ignore = true
+reason = "Accepted known vulnerabilities for testing purposes"
+
+# GHSA-2g68-c3qc-8985
+# GHSA-hrfv-mqp8-q5rw / PYSEC-2023-221
+# GHSA-px8h-6qxv-m22q / PYSEC-2023-57
+# GHSA-xg9f-g7g7-2323 / PYSEC-2023-58
+# PYSEC-2022-203
+[[PackageOverrides]]
+name = "werkzeug"
+ecosystem = "PyPI"
+ignore = true
+reason = "Accepted known vulnerabilities for testing purposes"