From 1c81ad6da58af9d72599f5e34e42e381125a2aae Mon Sep 17 00:00:00 2001 From: wenyongh Date: Wed, 27 Nov 2019 10:52:12 +0800 Subject: [PATCH] Enhance wasm loader and update build app document (#147) --- .../lib/native/libc/libc_builtin_wrapper.c | 37 +- .../sandboxed-system-primitives/src/posix.c | 4 +- core/iwasm/runtime/vmcore-wasm/wasm.h | 5 - core/iwasm/runtime/vmcore-wasm/wasm_interp.c | 19 +- core/iwasm/runtime/vmcore-wasm/wasm_loader.c | 328 +++++++++++++----- core/iwasm/runtime/vmcore-wasm/wasm_runtime.c | 11 +- doc/build_wasm_app.md | 1 + 7 files changed, 276 insertions(+), 129 deletions(-) diff --git a/core/iwasm/lib/native/libc/libc_builtin_wrapper.c b/core/iwasm/lib/native/libc/libc_builtin_wrapper.c index 67171665..f099b63c 100644 --- a/core/iwasm/lib/native/libc/libc_builtin_wrapper.c +++ b/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*/ +#ifndef ENABLE_SPEC_TEST +#define ENABLE_SPEC_TEST 0 +#endif -#ifdef ENABLE_SPEC_TEST +#if ENABLE_SPEC_TEST != 0 static void -print_i32_wrapper(wasm_module_inst_t module_inst, int i32) -{ - bh_printf("%d\n", i32); -} - -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 }, diff --git a/core/iwasm/lib/native/libc/wasmtime-wasi-c/sandboxed-system-primitives/src/posix.c b/core/iwasm/lib/native/libc/wasmtime-wasi-c/sandboxed-system-primitives/src/posix.c index 45c138c9..dac33528 100644 --- a/core/iwasm/lib/native/libc/wasmtime-wasi-c/sandboxed-system-primitives/src/posix.c +++ b/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; diff --git a/core/iwasm/runtime/vmcore-wasm/wasm.h b/core/iwasm/runtime/vmcore-wasm/wasm.h index 72004d84..445f3ad9 100644 --- a/core/iwasm/runtime/vmcore-wasm/wasm.h +++ b/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; diff --git a/core/iwasm/runtime/vmcore-wasm/wasm_interp.c b/core/iwasm/runtime/vmcore-wasm/wasm_interp.c index 86373d1c..b838055a 100644 --- a/core/iwasm/runtime/vmcore-wasm/wasm_interp.c +++ b/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) diff --git a/core/iwasm/runtime/vmcore-wasm/wasm_loader.c b/core/iwasm/runtime/vmcore-wasm/wasm_loader.c index f3bd5105..8a6edd3a 100644 --- a/core/iwasm/runtime/vmcore-wasm/wasm_loader.c +++ b/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; } diff --git a/core/iwasm/runtime/vmcore-wasm/wasm_runtime.c b/core/iwasm/runtime/vmcore-wasm/wasm_runtime.c index aaf6362c..79c786c6 100644 --- a/core/iwasm/runtime/vmcore-wasm/wasm_runtime.c +++ b/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++; diff --git a/doc/build_wasm_app.md b/doc/build_wasm_app.md index c7bc9b95..6ab1e4bf 100644 --- a/doc/build_wasm_app.md +++ b/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: