Jelajahi Sumber

Enhance wasm loader and update build app document (#147)

wenyongh 6 tahun lalu
induk
melakukan
1c81ad6da5

+ 19 - 18
core/iwasm/lib/native/libc/libc_builtin_wrapper.c

@@ -80,15 +80,17 @@ _printf_hex_uint(out_func_t out, void *ctx,
                  enum pad_type padding,
                  int min_width)
 {
-    int size = sizeof(num) * (is_u64 ? 2 : 1);
+    int shift = sizeof(num) * 8;
     int found_largest_digit = 0;
-    int remaining = 8; /* 8 digits max */
+    int remaining = 16; /* 16 digits max */
     int digits = 0;
+    char nibble;
 
-    for (; size; size--) {
-        char nibble = (num >> ((size - 1) << 2) & 0xf);
+     while (shift >= 4) {
+         shift -= 4;
+         nibble = (num >> shift) & 0xf;
 
-        if (nibble || found_largest_digit || size == 1) {
+        if (nibble || found_largest_digit || shift == 0) {
             found_largest_digit = 1;
             nibble = (char)(nibble + (nibble > 9 ? 87 : 48));
             out((int) nibble, ctx);
@@ -1153,17 +1155,13 @@ __cxa_throw_wrapper(wasm_module_inst_t module_inst,
     wasm_runtime_set_exception(module_inst, buf);
 }
 
-/*#define ENABLE_SPEC_TEST 1*/
-
-#ifdef ENABLE_SPEC_TEST
-static void
-print_i32_wrapper(wasm_module_inst_t module_inst, int i32)
-{
-    bh_printf("%d\n", i32);
-}
+#ifndef ENABLE_SPEC_TEST
+#define ENABLE_SPEC_TEST 0
+#endif
 
+#if ENABLE_SPEC_TEST != 0
 static void
-print_wrapper(wasm_module_inst_t module_inst, int i32)
+print_i32_wrapper(wasm_module_inst_t module_inst, int32 i32)
 {
     bh_printf("%d\n", i32);
 }
@@ -1180,9 +1178,8 @@ typedef struct WASMNativeFuncDef {
 } WASMNativeFuncDef;
 
 static WASMNativeFuncDef native_func_defs[] = {
-#ifdef ENABLE_SPEC_TEST
+#if ENABLE_SPEC_TEST != 0
     REG_NATIVE_FUNC(spectest, print_i32),
-    REG_NATIVE_FUNC(spectest, print),
 #endif
     REG_NATIVE_FUNC(env, _printf),
     REG_NATIVE_FUNC(env, _sprintf),
@@ -1284,8 +1281,12 @@ typedef struct WASMNativeGlobalDef {
 } WASMNativeGlobalDef;
 
 static WASMNativeGlobalDef native_global_defs[] = {
-#ifdef ENABLE_SPEC_TEST
-    { "spectest", "global_i32", .global_data.u32 = 0 },
+#if ENABLE_SPEC_TEST != 0
+    { "spectest", "global_i32", .global_data.i32 = 666 },
+    { "spectest", "global_f32", .global_data.f32 = 0 },
+    { "spectest", "global_f64", .global_data.f64 = 0 },
+    { "test", "global-i32", .global_data.i32 = 0 },
+    { "test", "global-f32", .global_data.f32 = 0 },
 #endif
     { "env", "STACKTOP", .global_data.u32 = 0 },
     { "env", "STACK_MAX", .global_data.u32 = 0 },

+ 2 - 2
core/iwasm/lib/native/libc/wasmtime-wasi-c/sandboxed-system-primitives/src/posix.c

@@ -846,7 +846,7 @@ __wasi_errno_t wasmtime_ssp_fd_pread(
 
   struct fd_object *fo;
   __wasi_errno_t error = fd_object_get(curfds,
-      &fo, fd, __WASI_RIGHT_FD_READ | __WASI_RIGHT_FD_SEEK, 0);
+      &fo, fd, __WASI_RIGHT_FD_READ, 0);
   if (error != 0)
     return error;
 
@@ -918,7 +918,7 @@ __wasi_errno_t wasmtime_ssp_fd_pwrite(
 
   struct fd_object *fo;
   __wasi_errno_t error = fd_object_get(curfds,
-      &fo, fd, __WASI_RIGHT_FD_WRITE | __WASI_RIGHT_FD_SEEK, 0);
+      &fo, fd, __WASI_RIGHT_FD_WRITE, 0);
   if (error != 0)
     return error;
 

+ 0 - 5
core/iwasm/runtime/vmcore-wasm/wasm.h

@@ -68,9 +68,6 @@ extern "C" {
 #define BLOCK_TYPE_IF 2
 #define BLOCK_TYPE_FUNCTION 3
 
-#define CALL_TYPE_WRAPPER 0
-#define CALL_TYPE_C_INTRINSIC 1
-
 typedef union WASMValue {
     int32 i32;
     uint32 u32;
@@ -140,8 +137,6 @@ typedef struct WASMFunctionImport {
     char *field_name;
     /* function type */
     WASMType *func_type;
-    /* c intrinsic function or wrapper function */
-    uint32 call_type;
     /* function pointer after linked */
     void *func_ptr_linked;
 } WASMFunctionImport;

+ 16 - 3
core/iwasm/runtime/vmcore-wasm/wasm_interp.c

@@ -612,6 +612,16 @@ wasm_interp_call_func_native(WASMThread *self,
 
     wasm_thread_set_cur_frame (self, frame);
 
+    if (!cur_func->u.func_import->func_ptr_linked) {
+        char buf[128];
+        snprintf(buf,
+                 sizeof(buf), "fail to call unlinked import function (%s, %s)",
+                 cur_func->u.func_import->module_name,
+                 cur_func->u.func_import->field_name);
+        wasm_runtime_set_exception(self->module_inst, buf);
+        return;
+    }
+
     ret = wasm_runtime_invoke_native(cur_func->u.func_import->func_ptr_linked,
                                      cur_func->u.func_import->func_type,
                                      self->module_inst,
@@ -840,7 +850,7 @@ wasm_interp_call_func_bytecode(WASMThread *self,
       HANDLE_OP (WASM_OP_CALL_INDIRECT):
         {
           WASMType *cur_type, *cur_func_type;
-          /* TODO: test */
+
           read_leb_uint32(frame_ip, frame_ip_end, tidx);
           if (tidx >= module->module->type_count) {
             wasm_runtime_set_exception(module, "type index is overflow");
@@ -858,8 +868,11 @@ wasm_interp_call_func_bytecode(WASMThread *self,
           }
 
           fidx = ((uint32*)table->base_addr)[val];
-          /* Skip function index check, it has been checked
-             in wasm module instantiate */
+          if (fidx == (uint32)-1) {
+            wasm_runtime_set_exception(module, "uninitialized element");
+            goto got_exception;
+          }
+
           cur_func = module->functions + fidx;
 
           if (cur_func->is_import_func)

+ 232 - 96
core/iwasm/runtime/vmcore-wasm/wasm_loader.c

@@ -26,11 +26,21 @@ set_error_buf(char *error_buf, uint32 error_buf_size, const char *string)
         snprintf(error_buf, error_buf_size, "%s", string);
 }
 
-#define CHECK_BUF(buf, buf_end, length) do {                    \
-  if (buf + length > buf_end) {                                 \
-    set_error_buf(error_buf, error_buf_size, "unexpected end"); \
-    return false;                                               \
-  }                                                             \
+#define CHECK_BUF(buf, buf_end, length) do {                \
+  if (buf + length > buf_end) {                             \
+    set_error_buf(error_buf, error_buf_size,                \
+                  "WASM module load failed: "               \
+                  "unexpected end of section or function"); \
+    return false;                                           \
+  }                                                         \
+} while (0)
+
+#define CHECK_BUF1(buf, buf_end, length) do {               \
+  if (buf + length > buf_end) {                             \
+    set_error_buf(error_buf, error_buf_size,                \
+                  "WASM module load failed: unexpected end");\
+    return false;                                           \
+  }                                                         \
 } while (0)
 
 static bool
@@ -57,6 +67,7 @@ read_leb(const uint8 *buf, const uint8 *buf_end,
     }
     if (bcnt > (maxbits + 7 - 1) / 7) {
         set_error_buf(error_buf, error_buf_size,
+                      "WASM module load failed: "
                       "integer representation too long");
         return false;
     }
@@ -122,14 +133,56 @@ read_leb(const uint8 *buf, const uint8 *buf_end,
   res = (uint8)res64;                               \
 } while (0)
 
+static bool
+check_utf8_str(const uint8* str, uint32 len)
+{
+    const uint8 *p = str, *p_end = str + len, *p_end1;
+    uint8 chr, n_bytes;
+
+    while (p < p_end) {
+        chr = *p++;
+        if (chr >= 0x80) {
+            /* Calculate the byte count: the first byte must be
+               110XXXXX, 1110XXXX, 11110XXX, 111110XX, or 1111110X,
+               the count of leading '1' denotes the total byte count */
+            n_bytes = 0;
+            while ((chr & 0x80) != 0) {
+                chr <<= 1;
+                n_bytes++;
+            }
+
+            /* Check byte count */
+            if (n_bytes < 2 || n_bytes > 6
+                || p + n_bytes - 1 > p_end)
+                return false;
+
+            /* Check the following bytes, which must be 10XXXXXX */
+            p_end1 = p + n_bytes - 1;
+            while (p < p_end1) {
+                if (!(*p & 0x80) || (*p | 0x40))
+                    return false;
+                p++;
+            }
+        }
+    }
+    return true;
+}
+
 static char*
 const_str_set_insert(const uint8 *str, uint32 len, WASMModule *module,
                      char* error_buf, uint32 error_buf_size)
 {
     HashMap *set = module->const_str_set;
-    char *c_str = wasm_malloc(len + 1), *value;
+    char *c_str, *value;
 
-    if (!c_str) {
+    if (!check_utf8_str(str, len)) {
+        set_error_buf(error_buf, error_buf_size,
+                      "WASM module load failed: "
+                      "invalid UTF-8 encoding");
+        return NULL;
+    }
+
+    if (!(c_str = wasm_malloc(len + 1))) {
         set_error_buf(error_buf, error_buf_size,
                       "WASM module load failed: "
                       "allocate memory failed.");
@@ -196,13 +249,16 @@ load_init_expr(const uint8 **p_buf, const uint8 *buf_end,
             read_leb_uint32(p, p_end, init_expr->u.global_index);
             break;
         default:
-            set_error_buf(error_buf, error_buf_size, "type mismatch");
+            set_error_buf(error_buf, error_buf_size,
+                          "WASM module load failed: type mismatch");
             return false;
     }
     CHECK_BUF(p, p_end, 1);
     end_byte = read_uint8(p);
     if (end_byte != 0x0b) {
-        set_error_buf(error_buf, error_buf_size, "unexpected end");
+        set_error_buf(error_buf, error_buf_size,
+                      "WASM module load failed: "
+                      "unexpected end of section or function");
         return false;
     }
     *p_buf = p;
@@ -284,7 +340,7 @@ load_type_section(const uint8 *buf, const uint8 *buf_end, WASMModule *module,
 
     if (p != p_end) {
         set_error_buf(error_buf, error_buf_size,
-                      "Load type section failed: invalid section size.");
+                      "Load type section failed: section size mismatch");
         return false;
     }
 
@@ -455,7 +511,8 @@ load_import_section(const uint8 *buf, const uint8 *buf_end, WASMModule *module,
                         read_leb_uint32(p, p_end, u32);
                     module->import_table_count++;
                     if (module->import_table_count > 1) {
-                        set_error_buf(error_buf, error_buf_size, "multiple tables");
+                        set_error_buf(error_buf, error_buf_size,
+                                      "Load import section failed: multiple tables");
                         return false;
                     }
                     break;
@@ -467,14 +524,15 @@ load_import_section(const uint8 *buf, const uint8 *buf_end, WASMModule *module,
                         read_leb_uint32(p, p_end, u32);
                     module->import_memory_count++;
                     if (module->import_memory_count > 1) {
-                        set_error_buf(error_buf, error_buf_size, "multiple memories");
+                        set_error_buf(error_buf, error_buf_size,
+                                      "Load import section failed: multiple memories");
                         return false;
                     }
                     break;
 
                 case IMPORT_KIND_GLOBAL: /* import global */
-                    read_leb_uint8(p, p_end, u8);
-                    read_leb_uint8(p, p_end, u8);
+                    CHECK_BUF(p, p_end, 2);
+                    p += 2;
                     module->import_global_count++;
                     break;
 
@@ -529,27 +587,18 @@ 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: "
-                                      "invalid function type index.");
+                                      "function type index out of range.");
                         return false;
                     }
                     import->u.function.func_type = module->types[type_index];
 
-                    if (!(import->u.function.func_ptr_linked = wasm_native_func_lookup
-                                (module_name, field_name))) {
-                        if (!(import->u.function.func_ptr_linked =
-                                    resolve_sym(module_name, field_name))) {
-                            if (error_buf != NULL)
-                                snprintf(error_buf, error_buf_size,
-                                         "Load import section failed: "
-                                         "resolve import function (%s, %s) failed.",
-                                         module_name, field_name);
-                            return false;
-
-                        }
-                        import->u.function.call_type = CALL_TYPE_C_INTRINSIC;
-                        break;
+                    if (!(import->u.function.func_ptr_linked =
+                                wasm_native_func_lookup(module_name, field_name))
+                        && !(import->u.function.func_ptr_linked =
+                                resolve_sym(module_name, field_name))) {
+                        LOG_WARNING("warning: fail to link import function (%s, %s)\n",
+                                    module_name, field_name);
                     }
-                    import->u.function.call_type = CALL_TYPE_WRAPPER;
                     break;
 
                 case IMPORT_KIND_TABLE: /* import table */
@@ -571,7 +620,8 @@ load_import_section(const uint8 *buf, const uint8 *buf_end, WASMModule *module,
                                 error_buf, error_buf_size))
                         return false;
                     if (module->import_table_count > 1) {
-                        set_error_buf(error_buf, error_buf_size, "multiple memories");
+                        set_error_buf(error_buf, error_buf_size,
+                                      "Load import section failed: multiple memories");
                         return false;
                     }
                     break;
@@ -579,8 +629,15 @@ load_import_section(const uint8 *buf, const uint8 *buf_end, WASMModule *module,
                 case IMPORT_KIND_GLOBAL: /* import global */
                     wasm_assert(import_globals);
                     import = import_globals++;
-                    read_leb_uint8(p, p_end, import->u.global.type);
-                    read_leb_uint8(p, p_end, mutable);
+                    CHECK_BUF(p, p_end, 2);
+                    import->u.global.type = read_uint8(p);
+                    mutable = read_uint8(p);
+                    if (mutable >= 2) {
+                        set_error_buf(error_buf, error_buf_size,
+                                      "Load import section failed: "
+                                      "invalid mutability");
+                        return false;
+                    }
                     import->u.global.is_mutable = mutable & 1 ? true : false;
                     if (!(wasm_native_global_lookup(module_name, field_name,
                                                     &import->u.global))) {
@@ -617,8 +674,7 @@ load_import_section(const uint8 *buf, const uint8 *buf_end, WASMModule *module,
 
     if (p != p_end) {
         set_error_buf(error_buf, error_buf_size,
-                      "Load import section failed: "
-                      "invalid section size.");
+                      "Load import section failed: section size mismatch");
         return false;
     }
 
@@ -650,6 +706,7 @@ load_function_section(const uint8 *buf, const uint8 *buf_end,
 
     if (func_count != code_count) {
         set_error_buf(error_buf, error_buf_size,
+                      "Load function section failed: "
                       "function and code section have inconsistent lengths");
         return false;
     }
@@ -672,7 +729,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: "
-                              "invalid function type index.");
+                              "function type index out of range.");
                 return false;
             }
 
@@ -696,6 +753,7 @@ load_function_section(const uint8 *buf, const uint8 *buf_end,
                 read_leb_uint32(p_code, buf_code_end, sub_local_count);
                 if (sub_local_count > UINT32_MAX - local_count) {
                     set_error_buf(error_buf, error_buf_size,
+                                  "Load function section failed: "
                                   "too many locals");
                     return false;
                 }
@@ -753,8 +811,7 @@ load_function_section(const uint8 *buf, const uint8 *buf_end,
 
     if (p != p_end) {
         set_error_buf(error_buf, error_buf_size,
-                      "Load function section failed: "
-                      "invalid section size.");
+                      "Load function section failed: section size mismatch");
         return false;
     }
 
@@ -776,7 +833,8 @@ 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, "multiple memories");
+            set_error_buf(error_buf, error_buf_size,
+                          "Load table section failed: multiple memories");
             return false;
         }
         module->table_count = table_count;
@@ -784,8 +842,7 @@ load_table_section(const uint8 *buf, const uint8 *buf_end, WASMModule *module,
         if (total_size >= UINT32_MAX
             || !(module->tables = wasm_malloc((uint32)total_size))) {
             set_error_buf(error_buf, error_buf_size,
-                          "Load table section failed: "
-                          "allocate memory failed.");
+                          "Load table section failed: allocate memory failed.");
             return false;
         }
 
@@ -800,7 +857,7 @@ load_table_section(const uint8 *buf, const uint8 *buf_end, WASMModule *module,
 
     if (p != p_end) {
         set_error_buf(error_buf, error_buf_size,
-                      "Load table section failed: invalid section size.");
+                      "Load table section failed: section size mismatch");
         return false;
     }
 
@@ -822,7 +879,8 @@ load_memory_section(const uint8 *buf, const uint8 *buf_end, WASMModule *module,
 
     if (memory_count) {
         if (memory_count > 1) {
-            set_error_buf(error_buf, error_buf_size, "multiple memories");
+            set_error_buf(error_buf, error_buf_size,
+                          "Load memory section failed: multiple memories");
             return false;
         }
         module->memory_count = memory_count;
@@ -830,8 +888,7 @@ load_memory_section(const uint8 *buf, const uint8 *buf_end, WASMModule *module,
         if (total_size >= UINT32_MAX
             || !(module->memories = wasm_malloc((uint32)total_size))) {
             set_error_buf(error_buf, error_buf_size,
-                         "Load memory section failed: "
-                         "allocate memory failed.");
+                         "Load memory section failed: allocate memory failed.");
             return false;
         }
 
@@ -846,7 +903,7 @@ load_memory_section(const uint8 *buf, const uint8 *buf_end, WASMModule *module,
 
     if (p != p_end) {
         set_error_buf(error_buf, error_buf_size,
-                      "Load memory section failed: invalid section size.");
+                      "Load memory section failed: section size mismatch");
         return false;
     }
 
@@ -862,6 +919,7 @@ load_global_section(const uint8 *buf, const uint8 *buf_end, WASMModule *module,
     uint32 global_count, i;
     uint64 total_size;
     WASMGlobal *global;
+    uint8 mutable;
 
     read_leb_uint32(p, p_end, global_count);
 
@@ -881,10 +939,16 @@ load_global_section(const uint8 *buf, const uint8 *buf_end, WASMModule *module,
         global = module->globals;
 
         for(i = 0; i < global_count; i++, global++) {
-            CHECK_BUF(p, p_end, 1);
+            CHECK_BUF(p, p_end, 2);
             global->type = read_uint8(p);
-            CHECK_BUF(p, p_end, 1);
-            global->is_mutable = read_bool(p);
+            mutable = read_uint8(p);
+            if (mutable >= 2) {
+                set_error_buf(error_buf, error_buf_size,
+                              "Load import section failed: "
+                              "invalid mutability");
+                return false;
+            }
+            global->is_mutable = mutable ? true : false;
 
             /* initialize expression */
             if (!load_init_expr(&p, p_end, &(global->init_expr), error_buf, error_buf_size))
@@ -894,7 +958,7 @@ load_global_section(const uint8 *buf, const uint8 *buf_end, WASMModule *module,
 
     if (p != p_end) {
         set_error_buf(error_buf, error_buf_size,
-                      "Load global section failed: invalid section size.");
+                      "Load global section failed: section size mismatch");
         return false;
     }
 
@@ -947,7 +1011,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 is out of range.");
+                                      "function index out of range.");
                         return false;
                     }
                     break;
@@ -956,7 +1020,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 is out of range.");
+                                      "table index out of range.");
                         return false;
                     }
                     break;
@@ -965,7 +1029,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 is out of range.");
+                                      "memory index out of range.");
                         return false;
                     }
                     break;
@@ -974,14 +1038,14 @@ 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 is out of range.");
+                                      "global index out of range.");
                         return false;
                     }
                     break;
                 default:
                     set_error_buf(error_buf, error_buf_size,
                                   "Load export section failed: "
-                                  "kind flag is unexpected.");
+                                  "invalid export kind.");
                     return false;
             }
         }
@@ -989,8 +1053,7 @@ load_export_section(const uint8 *buf, const uint8 *buf_end, WASMModule *module,
 
     if (p != p_end) {
         set_error_buf(error_buf, error_buf_size,
-                      "Load export section failed: "
-                      "invalid section size.");
+                      "Load export section failed: section size mismatch");
         return false;
     }
 
@@ -1024,6 +1087,12 @@ load_table_segment_section(const uint8 *buf, const uint8 *buf_end, WASMModule *m
 
         table_segment = module->table_segments;
         for (i = 0; i < table_segment_count; i++, table_segment++) {
+            if (p >= p_end) {
+                set_error_buf(error_buf, error_buf_size,
+                              "Load table segment section failed: "
+                              "invalid value type");
+                return false;
+            }
             read_leb_uint32(p, p_end, table_index);
             table_segment->table_index = table_index;
 
@@ -1052,8 +1121,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 section size.");
+                     "Load table segment section failed: section size mismatch");
         return false;
     }
 
@@ -1116,8 +1184,7 @@ load_data_segment_section(const uint8 *buf, const uint8 *buf_end,
 
     if (p != p_end) {
         set_error_buf(error_buf, error_buf_size,
-                      "Load data segment section failed, "
-                      "invalid section size.");
+                      "Load data segment section failed: section size mismatch");
         return false;
     }
 
@@ -1145,6 +1212,7 @@ load_code_section(const uint8 *buf, const uint8 *buf_end,
 
     if (func_count != code_count) {
         set_error_buf(error_buf, error_buf_size,
+                      "Load code section failed: "
                       "function and code section have inconsistent lengths");
         return false;
     }
@@ -1166,7 +1234,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 is out of range.");
+                          "function index out of range.");
             return false;
         }
         module->start_function = start_function;
@@ -1174,8 +1242,7 @@ load_start_section(const uint8 *buf, const uint8 *buf_end, WASMModule *module,
 
     if (p != p_end) {
         set_error_buf(error_buf, error_buf_size,
-                      "Load start section failed: "
-                      "invalid section size.");
+                      "Load start section failed: section size mismatch");
         return false;
     }
 
@@ -1183,6 +1250,40 @@ load_start_section(const uint8 *buf, const uint8 *buf_end, WASMModule *module,
     return true;
 }
 
+static bool
+load_user_section(const uint8 *buf, const uint8 *buf_end, WASMModule *module,
+                  char *error_buf, uint32 error_buf_size)
+{
+    const uint8 *p = buf, *p_end = buf_end;
+    uint32 name_len;
+
+    if (p >= p_end) {
+        set_error_buf(error_buf, error_buf_size,
+                      "Load custom section failed: unexpected end");
+        return false;
+    }
+
+    read_leb_uint32(p, p_end, name_len);
+
+    if (name_len == 0
+        || p + name_len > p_end) {
+        set_error_buf(error_buf, error_buf_size,
+                      "Load custom section failed: unexpected end");
+        return false;
+    }
+
+    if (!check_utf8_str(p, name_len)) {
+        set_error_buf(error_buf, error_buf_size,
+                      "WASM module load failed: "
+                      "invalid UTF-8 encoding");
+        return false;
+    }
+
+    LOG_VERBOSE("Load custom section success.\n");
+    return true;
+}
+
+
 static bool
 wasm_loader_prepare_bytecode(WASMModule *module, WASMFunction *func,
                              char *error_buf, uint32 error_buf_size);
@@ -1216,8 +1317,8 @@ load_from_sections(WASMModule *module, WASMSection *sections,
         switch (section->section_type) {
             case SECTION_TYPE_USER:
                 /* unsupported user section, ignore it. */
-                /* add a check to pass spec test case */
-                CHECK_BUF(buf, buf_end, 1);
+                if (!load_user_section(buf, buf_end, module, error_buf, error_buf_size))
+                    return false;
                 break;
             case SECTION_TYPE_TYPE:
                 if (!load_type_section(buf, buf_end, module, error_buf, error_buf_size))
@@ -1266,7 +1367,8 @@ load_from_sections(WASMModule *module, WASMSection *sections,
                     return false;
                 break;
             default:
-                set_error_buf(error_buf, error_buf_size, "invalid section id");
+                set_error_buf(error_buf, error_buf_size,
+                              "WASM module load failed: invalid section id");
                 return false;
         }
 
@@ -1386,7 +1488,7 @@ create_sections(const uint8 *buf, uint32 size,
 {
     WASMSection *section_list_end = NULL, *section;
     const uint8 *p = buf, *p_end = buf + size/*, *section_body*/;
-    uint8 section_type;
+    uint8 section_type, last_section_type = (uint8)-1;
     uint32 section_size;
 
     wasm_assert(!*p_section_list);
@@ -1396,8 +1498,22 @@ create_sections(const uint8 *buf, uint32 size,
         CHECK_BUF(p, p_end, 1);
         section_type = read_uint8(p);
         if (section_type <= SECTION_TYPE_DATA) {
+            if (section_type != SECTION_TYPE_USER) {
+                /* Custom sections may be inserted at any place,
+                   while other sections must occur at most once
+                   and in prescribed order. */
+                if (last_section_type != (uint8)-1
+                    && section_type <= last_section_type) {
+                    set_error_buf(error_buf, error_buf_size,
+                                  "WASM module load failed: "
+                                  "junk after last section");
+                    return false;
+                }
+                last_section_type = section_type;
+            }
+            CHECK_BUF1(p, p_end, 1);
             read_leb_uint32(p, p_end, section_size);
-            CHECK_BUF(p, p_end, section_size);
+            CHECK_BUF1(p, p_end, section_size);
 
             if (!(section = wasm_malloc(sizeof(WASMSection)))) {
                 set_error_buf(error_buf, error_buf_size,
@@ -1421,7 +1537,8 @@ create_sections(const uint8 *buf, uint32 size,
             p += section_size;
         }
         else {
-            set_error_buf(error_buf, error_buf_size, "invalid section id");
+            set_error_buf(error_buf, error_buf_size,
+                          "WASM module load failed: invalid section id");
             return false;
         }
     }
@@ -1457,23 +1574,25 @@ load(const uint8 *buf, uint32 size, WASMModule *module,
     uint32 magic_number, version;
     WASMSection *section_list = NULL;
 
-    CHECK_BUF(p, p_end, sizeof(uint32));
+    CHECK_BUF1(p, p_end, sizeof(uint32));
     magic_number = read_uint32(p);
     if (!is_little_endian())
         exchange32((uint8*)&magic_number);
 
     if (magic_number != WASM_MAGIC_NUMBER) {
-        set_error_buf(error_buf, error_buf_size, "magic header not detected");
+        set_error_buf(error_buf, error_buf_size,
+                      "WASM module load failed: magic header not detected");
         return false;
     }
 
-    CHECK_BUF(p, p_end, sizeof(uint32));
+    CHECK_BUF1(p, p_end, sizeof(uint32));
     version = read_uint32(p);
     if (!is_little_endian())
         exchange32((uint8*)&version);
 
     if (version != WASM_CURRENT_VERSION) {
-        set_error_buf(error_buf, error_buf_size, "unknown binary version");
+        set_error_buf(error_buf, error_buf_size,
+                      "WASM module load failed: unknown binary version");
         return false;
     }
 
@@ -2059,7 +2178,8 @@ check_stack_pop(uint8 type, uint8 *frame_ref, uint32 stack_cell_num,
         || ((type == VALUE_TYPE_I64 || type == VALUE_TYPE_F64)
             && stack_cell_num < 2)) {
         set_error_buf(error_buf, error_buf_size,
-                      "type mismatch: expected data but stack was empty");
+                      "WASM module load failed: "
+                      "type mismatch: expect data but stack was empty");
         return false;
     }
 
@@ -2071,7 +2191,8 @@ check_stack_pop(uint8 type, uint8 *frame_ref, uint32 stack_cell_num,
             && (*(frame_ref - 2) != REF_F64_1 || *(frame_ref - 1) != REF_F64_2))) {
         if (error_buf != NULL)
             snprintf(error_buf, error_buf_size, "%s%s%s",
-                     "type mismatch: expected ", type_str, " but got other");
+                     "WASM module load failed: type mismatch: expect ",
+                     type_str, " but got other");
         return false;
     }
     return true;
@@ -2251,7 +2372,8 @@ pop_type(uint8 type, uint8 **p_frame_ref, uint32 *p_stack_cell_num,
 #define CHECK_CSP_POP() do {                                \
     if (csp_num < 1) {                                      \
       set_error_buf(error_buf, error_buf_size,              \
-      "type mismatch: expected data but block stack was empty");\
+                  "WASM module load failed: type mismatch: "\
+                  "expect data but block stack was empty"); \
       goto fail;                                            \
     }                                                       \
   } while (0)
@@ -2281,7 +2403,8 @@ pop_type(uint8 type, uint8 **p_frame_ref, uint32 *p_stack_cell_num,
     read_leb_uint32(p, p_end, local_idx);           \
     if (local_idx >= param_count + local_count) {   \
       set_error_buf(error_buf, error_buf_size,      \
-        "invalid index: local index out of range"); \
+                    "WASM module load failed: "     \
+                    "local index out of range"); \
       goto fail;                                    \
     }                                               \
     local_type = local_idx < param_count            \
@@ -2291,8 +2414,9 @@ pop_type(uint8 type, uint8 **p_frame_ref, uint32 *p_stack_cell_num,
 
 #define CHECK_BR(depth) do {                                        \
     if (csp_num < depth + 1) {                                      \
-      set_error_buf(error_buf, error_buf_size, "type mismatch: "    \
-                    "expected data but block stack was empty");     \
+      set_error_buf(error_buf, error_buf_size,                      \
+                    "WASM module load failed: type mismatch: "      \
+                    "unexpected end of section or function");       \
       goto fail;                                                    \
     }                                                               \
     if ((frame_csp - (depth + 1))->block_type != BLOCK_TYPE_LOOP) { \
@@ -2309,8 +2433,9 @@ pop_type(uint8 type, uint8 **p_frame_ref, uint32 *p_stack_cell_num,
               && (stack_cell_num < 2                                \
                   || *(frame_ref - 2) != REF_F64_1                  \
                   || *(frame_ref - 1) != REF_F64_2))) {             \
-        set_error_buf(error_buf, error_buf_size, "type mismatch: "  \
-              "expected data but stack was empty or other type");   \
+        set_error_buf(error_buf, error_buf_size,                    \
+                "WASM module load failed: type mismatch: "          \
+                "expect data but stack was empty or other type");   \
         goto fail;                                                  \
       }                                                             \
       (frame_csp - (depth + 1))->jumped_by_br = true;               \
@@ -2324,6 +2449,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");
         return false;
     }
@@ -2436,13 +2562,11 @@ wasm_loader_prepare_bytecode(WASMModule *module, WASMFunction *func,
                 break;
 
             case WASM_OP_ELSE:
-                if (csp_num < 2) {
-                    set_error_buf(error_buf, error_buf_size, "invalid else");
-                    goto fail;
-                }
-
-                if ((frame_csp - 1)->block_type != BLOCK_TYPE_IF) {
-                    set_error_buf(error_buf, error_buf_size, "invalid else");
+                if (csp_num < 2
+                    || (frame_csp - 1)->block_type != BLOCK_TYPE_IF) {
+                    set_error_buf(error_buf, error_buf_size,
+                                  "WASM loader prepare bytecode failed: "
+                                  "opcode else found without matched opcode if");
                     goto fail;
                 }
 
@@ -2594,7 +2718,9 @@ handle_op_br:
                 read_leb_uint32(p, p_end, func_idx);
 
                 if (func_idx >= module->import_function_count + module->function_count) {
-                    set_error_buf(error_buf, error_buf_size, "function index is overflow");
+                    set_error_buf(error_buf, error_buf_size,
+                                  "WASM loader prepare bytecode failed: "
+                                  "function index out of range");
                     goto fail;
                 }
 
@@ -2623,6 +2749,7 @@ handle_op_br:
                 if (module->table_count == 0
                     && module->import_table_count == 0) {
                     set_error_buf(error_buf, error_buf_size,
+                                  "WASM loader prepare bytecode failed: "
                                   "call indirect without default table");
                     goto fail;
                 }
@@ -2632,6 +2759,7 @@ handle_op_br:
                 /* reserved byte 0x00 */
                 if (*p++ != 0x00) {
                     set_error_buf(error_buf, error_buf_size,
+                                  "WASM loader prepare bytecode failed: "
                                   "zero flag expected");
                     goto fail;
                 }
@@ -2640,7 +2768,8 @@ handle_op_br:
 
                 if (type_idx >= module->type_count) {
                     set_error_buf(error_buf, error_buf_size,
-                                  "function index is overflow");
+                                  "WASM loader prepare bytecode failed: "
+                                  "function index out of range");
                     goto fail;
                 }
 
@@ -2659,7 +2788,8 @@ handle_op_br:
             {
                 if (stack_cell_num <= 0) {
                     set_error_buf(error_buf, error_buf_size,
-                                  "invalid drop: stack was empty");
+                                  "WASM loader prepare bytecode failed: "
+                                  "opcode drop was found but stack was empty");
                     goto fail;
                 }
 
@@ -2672,7 +2802,8 @@ handle_op_br:
                 else {
                     if (stack_cell_num <= 1) {
                         set_error_buf(error_buf, error_buf_size,
-                                      "invalid drop: stack was empty");
+                                      "WASM loader prepare bytecode failed: "
+                                      "opcode drop was found but stack was empty");
                         goto fail;
                     }
                     frame_ref -= 2;
@@ -2690,7 +2821,8 @@ handle_op_br:
 
                 if (stack_cell_num <= 0) {
                     set_error_buf(error_buf, error_buf_size,
-                                  "invalid drop: stack was empty");
+                                  "WASM loader prepare bytecode failed: "
+                                  "opcode select was found but stack was empty");
                     goto fail;
                 }
 
@@ -2739,7 +2871,8 @@ handle_op_br:
                 read_leb_uint32(p, p_end, global_idx);
                 if (global_idx >= global_count) {
                     set_error_buf(error_buf, error_buf_size,
-                                  "invalid index: global index out of range");
+                                  "WASM loader prepare bytecode failed: "
+                                  "global index out of range");
                     goto fail;
                 }
 
@@ -2756,7 +2889,8 @@ handle_op_br:
                 read_leb_uint32(p, p_end, global_idx);
                 if (global_idx >= global_count) {
                     set_error_buf(error_buf, error_buf_size,
-                                  "invalid index: global index out of range");
+                                  "WASM loader prepare bytecode failed: "
+                                  "global index out of range");
                     goto fail;
                 }
 
@@ -2852,6 +2986,7 @@ handle_op_br:
                 /* reserved byte 0x00 */
                 if (*p++ != 0x00) {
                     set_error_buf(error_buf, error_buf_size,
+                                  "WASM loader prepare bytecode failed: "
                                   "zero flag expected");
                     goto fail;
                 }
@@ -2863,6 +2998,7 @@ handle_op_br:
                 /* reserved byte 0x00 */
                 if (*p++ != 0x00) {
                     set_error_buf(error_buf, error_buf_size,
+                                  "WASM loader prepare bytecode failed: "
                                   "zero flag expected");
                     goto fail;
                 }

+ 6 - 5
core/iwasm/runtime/vmcore-wasm/wasm_runtime.c

@@ -358,7 +358,9 @@ tables_instantiate(const WASMModule *module,
             return NULL;
         }
 
-        memset(table, 0, (uint32)total_size);
+        /* Set all elements to -1 to mark them as uninitialized elements */
+        memset(table, -1, (uint32)total_size);
+        table->elem_type = import->u.table.elem_type;
         table->cur_size = import->u.table.init_size;
         table->max_size = import->u.table.max_size;
     }
@@ -376,7 +378,9 @@ tables_instantiate(const WASMModule *module,
             return NULL;
         }
 
-        memset(table, 0, (uint32)total_size);
+        /* Set all elements to -1 to mark them as uninitialized elements */
+        memset(table, -1, (uint32)total_size);
+        table->elem_type = module->tables[i].elem_type;
         table->cur_size = module->tables[i].init_size;
         table->max_size = module->tables[i].max_size;
     }
@@ -683,9 +687,6 @@ export_functions_instantiate(const WASMModule *module,
 
     for (i = 0; i < module->export_count; i++, export++)
         if (export->kind == EXPORT_KIND_FUNC) {
-            wasm_assert(export->index >= module->import_function_count
-                        && export->index < module->import_function_count
-                           + module->function_count);
             export_func->name = export->name;
             export_func->function = &module_inst->functions[export->index];
             export_func++;

+ 1 - 0
doc/build_wasm_app.md

@@ -63,6 +63,7 @@ deb-src http://apt.llvm.org/bionic/ llvm-toolchain-bionic-8 main
 # 9
 deb http://apt.llvm.org/bionic/ llvm-toolchain-bionic-9 main
 deb-src http://apt.llvm.org/bionic/ llvm-toolchain-bionic-9 main
+```
 
 (2) Download and install clang-8 tool-chain using following commands: