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