Remove the binding between current thread and module instance and bugs fix (#131)

Remove wasm_export_api.h that may confuse
Implement wasm_runtime_validate_app_str_addr()
Fix bugs of loader and pass more spec cases

Signed-off-by: Weining Lu <weining.x.lu@intel.com>
This commit is contained in:
Weining
2019-10-11 15:25:23 +08:00
committed by wenyongh
parent bbae4426a0
commit 2a8b1ef454
37 changed files with 496 additions and 552 deletions

View File

@ -255,37 +255,23 @@ void
wasm_runtime_clear_exception(wasm_module_inst_t module_inst);
/**
* Attach the current native thread to a WASM module instance.
* A native thread cannot be attached simultaneously to two WASM module
* instances. The WASM module instance will be attached to the native
* thread which it is instantiated in by default.
* Set custom data to WASM module instance.
*
* @param module_inst the WASM module instance to attach
* @param thread_data the thread data that current native thread requires
* the WASM module instance to store
*
* @return true if SUCCESS, false otherwise
*/
bool
wasm_runtime_attach_current_thread(wasm_module_inst_t module_inst,
void *thread_data);
/**
* Detach the current native thread from a WASM module instance.
*
* @param module_inst the WASM module instance to detach
* @param module_inst the WASM module instance
* @param custom_data the custom data to be set
*/
void
wasm_runtime_detach_current_thread(wasm_module_inst_t module_inst);
wasm_runtime_set_custom_data(wasm_module_inst_t module_inst,
void *custom_data);
/**
* Get the thread data that the current native thread requires the WASM
* module instance to store when attaching.
* Get the custom data within a WASM module instance.
*
* @return the thread data stored when attaching
* @param module_inst the WASM module instance
*
* @return the custom data (NULL if not set yet)
*/
void*
wasm_runtime_get_current_thread_data();
wasm_runtime_get_custom_data(wasm_module_inst_t module_inst);
/**
* Allocate memory from the heap of WASM module instance
@ -342,6 +328,23 @@ bool
wasm_runtime_validate_app_addr(wasm_module_inst_t module_inst,
int32_t app_offset, uint32_t size);
/**
* Similar to wasm_runtime_validate_app_addr(), except that the size parameter
* is not provided. This function validates the app string address, check whether it
* belongs to WASM module instance's address space, or in its heap space or
* memory space. Moreover, it checks whether it is the offset of a string that
* is end with '\0'.
* @param module_inst the WASM module instance
* @param app_str_offset the app address of the string to validate, which is a
* relative address
*
* @return true if success, false otherwise. If failed, an exception will
* be thrown.
*/
bool
wasm_runtime_validate_app_str_addr(wasm_module_inst_t module_inst,
int32_t app_str_offset);
/**
* Validate the native address, check whether it belongs to WASM module
* instance's address space, or in its heap space or memory space.

View File

@ -18,7 +18,8 @@
void invokeNative(void (*native_code)(), uint32 argv[], uint32 argc)
{
WASMThread *self;
wasm_assert(argc >= sizeof(WASMModuleInstance *)/sizeof(uint32));
switch(argc) {
case 0:
native_code();
@ -84,9 +85,11 @@ void invokeNative(void (*native_code)(), uint32 argv[], uint32 argc)
native_code(argv[0], argv[1], argv[2], argv[3], argv[4], argv[5], argv[6], argv[7], argv[8], argv[9], argv[10], argv[11], argv[12], argv[13], argv[14], argv[15], argv[16], argv[17], argv[18], argv[19]);
break;
default:
{
/* FIXME: If this happen, add more cases. */
self = wasm_runtime_get_self();
wasm_runtime_set_exception(self->module_inst, "the argument number of native function exceeds maximum");
WASMModuleInstance *module_inst = *(WASMModuleInstance**)argv;
wasm_runtime_set_exception(module_inst, "the argument number of native function exceeds maximum");
return;
}
}
}

View File

@ -2178,10 +2178,11 @@ wasm_interp_call_func_bytecode(WASMThread *self,
}
void
wasm_interp_call_wasm(WASMFunctionInstance *function,
wasm_interp_call_wasm(WASMModuleInstance *module_inst,
WASMFunctionInstance *function,
uint32 argc, uint32 argv[])
{
WASMThread *self = wasm_runtime_get_self();
WASMThread *self = &module_inst->main_tlr;
WASMRuntimeFrame *prev_frame = wasm_thread_get_cur_frame(self);
WASMInterpFrame *frame, *outs_area;

View File

@ -23,6 +23,7 @@
extern "C" {
#endif
struct WASMModuleInstance;
struct WASMFunctionInstance;
typedef struct WASMInterpFrame {
@ -69,7 +70,8 @@ wasm_interp_interp_frame_size(unsigned all_cell_num)
}
void
wasm_interp_call_wasm(struct WASMFunctionInstance *function,
wasm_interp_call_wasm(struct WASMModuleInstance *module_inst,
struct WASMFunctionInstance *function,
uint32 argc, uint32 argv[]);
#ifdef __cplusplus

View File

@ -60,14 +60,14 @@ read_leb(const uint8 *buf, const uint8 *buf_end,
*p_offset += 1;
result |= ((byte & 0x7f) << shift);
shift += 7;
bcnt += 1;
if ((byte & 0x80) == 0) {
break;
}
bcnt += 1;
}
if (bcnt > (maxbits + 7 - 1) / 7) {
set_error_buf(error_buf, error_buf_size,
"WASM module load failed: unsigned LEB overflow.");
"integer representation too long");
return false;
}
if (sign && (shift < maxbits) && (byte & 0x40)) {
@ -625,17 +625,19 @@ load_function_section(const uint8 *buf, const uint8 *buf_end,
const uint8 *p = buf, *p_end = buf_end;
const uint8 *p_code = buf_code, *p_code_end, *p_code_save;
uint32 func_count, total_size;
uint32 code_count, code_size, type_index, i, j, k, local_type_index;
uint32 code_count = 0, code_size, type_index, i, j, k, local_type_index;
uint32 local_count, local_set_count, sub_local_count;
uint8 type;
WASMFunction *func;
read_leb_uint32(p, p_end, func_count);
read_leb_uint32(p_code, buf_code_end, code_count);
if (buf_code)
read_leb_uint32(p_code, buf_code_end, code_count);
if (func_count != code_count) {
set_error_buf(error_buf, error_buf_size,
"Load function section failed: invalid function count.");
"function and code section have inconsistent lengths");
return false;
}
@ -677,6 +679,11 @@ load_function_section(const uint8 *buf, const uint8 *buf_end,
/* Calculate total local count */
for (j = 0; j < local_set_count; j++) {
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,
"too many locals");
return false;
}
read_leb_uint8(p_code, buf_code_end, type);
local_count += sub_local_count;
}
@ -1084,11 +1091,29 @@ load_data_segment_section(const uint8 *buf, const uint8 *buf_end,
}
static bool
load_code_section(const uint8 *buf, const uint8 *buf_end, WASMModule *module,
load_code_section(const uint8 *buf, const uint8 *buf_end,
const uint8 *buf_func,
const uint8 *buf_func_end,
WASMModule *module,
char *error_buf, uint32 error_buf_size)
{
/* code has been loaded in function section, so pass it here */
/* TODO: should check if there really have section_size code bytes */
const uint8 *p = buf, *p_end = buf_end;
const uint8 *p_func = buf_func;
uint32 func_count = 0, code_count;
/* code has been loaded in function section, so pass it here, just check
* whether function and code section have inconsistent lengths */
read_leb_uint32(p, p_end, code_count);
if (buf_func)
read_leb_uint32(p_func, buf_func_end, func_count);
if (func_count != code_count) {
set_error_buf(error_buf, error_buf_size,
"function and code section have inconsistent lengths");
return false;
}
LOG_VERBOSE("Load code segment section success.\n");
return true;
}
@ -1132,14 +1157,19 @@ load_from_sections(WASMModule *module, WASMSection *sections,
char *error_buf, uint32 error_buf_size)
{
WASMSection *section = sections;
const uint8 *buf, *buf_end, *buf_code = NULL, *buf_code_end = NULL;
const uint8 *buf, *buf_end, *buf_code = NULL, *buf_code_end = NULL,
*buf_func = NULL, *buf_func_end = NULL;
uint32 i;
/* Find code and function sections if have */
while (section) {
if (section->section_type == SECTION_TYPE_CODE) {
buf_code = section->section_body;
buf_code_end = buf_code + section->section_body_size;
break;
}
else if (section->section_type == SECTION_TYPE_FUNC) {
buf_func = section->section_body;
buf_func_end = buf_func + section->section_body_size;
}
section = section->next;
}
@ -1151,6 +1181,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);
break;
case SECTION_TYPE_TYPE:
if (!load_type_section(buf, buf_end, module, error_buf, error_buf_size))
@ -1161,11 +1193,6 @@ load_from_sections(WASMModule *module, WASMSection *sections,
return false;
break;
case SECTION_TYPE_FUNC:
if (!buf_code) {
set_error_buf(error_buf, error_buf_size,
"WASM module load failed: find code section failed.");
return false;
}
if (!load_function_section(buf, buf_end, buf_code, buf_code_end,
module, error_buf, error_buf_size))
return false;
@ -1195,7 +1222,8 @@ load_from_sections(WASMModule *module, WASMSection *sections,
return false;
break;
case SECTION_TYPE_CODE:
if (!load_code_section(buf, buf_end, module, error_buf, error_buf_size))
if (!load_code_section(buf, buf_end, buf_func, buf_func_end,
module, error_buf, error_buf_size))
return false;
break;
case SECTION_TYPE_DATA:
@ -1356,7 +1384,7 @@ create_sections(const uint8 *buf, uint32 size,
p += section_size;
}
else {
set_error_buf(error_buf, error_buf_size, "invalid section type");
set_error_buf(error_buf, error_buf_size, "invalid section id");
return false;
}
}
@ -2540,7 +2568,14 @@ handle_op_br:
}
read_leb_uint32(p, p_end, type_idx);
read_leb_uint8(p, p_end, u8); /* 0x00 */
/* reserved byte 0x00 */
if (*p++ != 0x00) {
set_error_buf(error_buf, error_buf_size,
"zero flag expected");
goto fail;
}
POP_I32();
if (type_idx >= module->type_count) {
@ -2752,13 +2787,23 @@ handle_op_br:
case WASM_OP_MEMORY_SIZE:
CHECK_MEMORY();
read_leb_uint32(p, p_end, u32); /* 0x00 */
/* reserved byte 0x00 */
if (*p++ != 0x00) {
set_error_buf(error_buf, error_buf_size,
"zero flag expected");
goto fail;
}
PUSH_I32();
break;
case WASM_OP_MEMORY_GROW:
CHECK_MEMORY();
read_leb_uint32(p, p_end, u32); /* 0x00 */
/* reserved byte 0x00 */
if (*p++ != 0x00) {
set_error_buf(error_buf, error_buf_size,
"zero flag expected");
goto fail;
}
POP_I32();
PUSH_I32();
break;

View File

@ -44,8 +44,6 @@ wasm_runtime_init()
if (ws_thread_sys_init() != 0)
return false;
wasm_runtime_set_tlr(NULL);
wasm_native_init();
return true;
}
@ -53,7 +51,6 @@ wasm_runtime_init()
void
wasm_runtime_destroy()
{
wasm_runtime_set_tlr(NULL);
ws_thread_sys_destroy();
}
@ -71,7 +68,7 @@ wasm_runtime_call_wasm(WASMModuleInstance *module_inst,
unsigned argc, uint32 argv[])
{
/* Only init stack when no application is running. */
if (!wasm_runtime_get_self()->cur_frame) {
if (!module_inst->main_tlr.cur_frame) {
if (!exec_env) {
if (!module_inst->wasm_stack) {
if (!(module_inst->wasm_stack =
@ -107,7 +104,7 @@ wasm_runtime_call_wasm(WASMModuleInstance *module_inst,
}
}
wasm_interp_call_wasm(function, argc, argv);
wasm_interp_call_wasm(module_inst, function, argc, argv);
return !wasm_runtime_get_exception(module_inst) ? true : false;
}
@ -959,9 +956,7 @@ wasm_runtime_instantiate(WASMModule *module,
module_inst->wasm_stack_size = stack_size;
module_inst->main_tlr.module_inst = module_inst;
/* Bind thread data with current native thread:
set thread local root to current thread. */
wasm_runtime_set_tlr(&module_inst->main_tlr);
/* The native thread handle may be used in future, e.g multiple threads. */
module_inst->main_tlr.handle = ws_self_thread();
/* Execute __post_instantiate and start function */
@ -1133,34 +1128,17 @@ wasm_runtime_destroy_exec_env(WASMExecEnv *env)
}
}
bool
wasm_runtime_attach_current_thread(WASMModuleInstance *module_inst,
void *thread_data)
{
wasm_runtime_set_tlr(&module_inst->main_tlr);
module_inst->main_tlr.handle = ws_self_thread();
module_inst->thread_data = thread_data;
return true;
}
void
wasm_runtime_detach_current_thread(WASMModuleInstance *module_inst)
wasm_runtime_set_custom_data(WASMModuleInstance *module_inst,
void *custom_data)
{
module_inst->thread_data = NULL;
module_inst->custom_data = custom_data;
}
void*
wasm_runtime_get_current_thread_data()
wasm_runtime_get_custom_data(WASMModuleInstance *module_inst)
{
WASMThread *tlr = wasm_runtime_get_self();
return (tlr && tlr->module_inst) ? tlr->module_inst->thread_data : NULL;
}
WASMModuleInstance *
wasm_runtime_get_current_module_inst()
{
WASMThread *tlr = wasm_runtime_get_self();
return tlr ? tlr->module_inst : NULL;
return module_inst->custom_data;
}
int32
@ -1247,6 +1225,30 @@ fail:
return false;
}
bool
wasm_runtime_validate_app_str_addr(WASMModuleInstance *module_inst,
int32 app_str_offset)
{
int32 app_end_offset;
char *str, *str_end;
if (!wasm_runtime_get_app_addr_range(module_inst, app_str_offset,
NULL, &app_end_offset))
goto fail;
str = wasm_runtime_addr_app_to_native(module_inst, app_str_offset);
str_end = str + (app_end_offset - app_str_offset);
while (str < str_end && *str != '\0')
str++;
if (str == str_end)
goto fail;
return true;
fail:
wasm_runtime_set_exception(module_inst, "out of bounds memory access");
return false;
}
bool
wasm_runtime_validate_native_addr(WASMModuleInstance *module_inst,
void *native_ptr, uint32 size)

View File

@ -164,8 +164,9 @@ typedef struct WASMModuleInstance {
/* The exception buffer of wasm interpreter for current thread. */
char cur_exception[128];
/* The thread data of the attaching thread */
void *thread_data;
/* The custom data that can be set/get by
* wasm_runtime_set_custom_data/wasm_runtime_get_custom_data */
void *custom_data;
/* Main Thread */
WASMThread main_tlr;
@ -283,38 +284,57 @@ wasm_runtime_get_exception(WASMModuleInstance *module);
bool
wasm_runtime_enlarge_memory(WASMModuleInstance *module, int inc_page_count);
/* See wasm-export.h for description */
/* See wasm_export.h for description */
WASMModuleInstance *
wasm_runtime_get_current_module_inst();
/* See wasm-export.h for description */
/* See wasm_export.h for description */
int32
wasm_runtime_module_malloc(WASMModuleInstance *module_inst, uint32 size);
/* See wasm-export.h for description */
/* See wasm_export.h for description */
void
wasm_runtime_module_free(WASMModuleInstance *module_inst, int32 ptr);
/* See wasm-export.h for description */
/* See wasm_export.h for description */
bool
wasm_runtime_validate_app_addr(WASMModuleInstance *module_inst,
int32 app_offset, uint32 size);
/* See wasm-export.h for description */
/* See wasm_export.h for description */
bool
wasm_runtime_validate_app_str_addr(WASMModuleInstance *module_inst,
int32 app_offset);
/* See wasm_export.h for description */
bool
wasm_runtime_validate_native_addr(WASMModuleInstance *module_inst,
void *native_ptr, uint32 size);
/* See wasm-export.h for description */
/* See wasm_export.h for description */
void *
wasm_runtime_addr_app_to_native(WASMModuleInstance *module_inst,
int32 app_offset);
/* See wasm-export.h for description */
/* See wasm_export.h for description */
int32
wasm_runtime_addr_native_to_app(WASMModuleInstance *module_inst,
void *native_ptr);
/* See wasm_export.h for description */
bool
wasm_runtime_get_app_addr_range(WASMModuleInstance *module_inst,
int32_t app_offset,
int32_t *p_app_start_offset,
int32_t *p_app_end_offset);
/* See wasm_export.h for description */
bool
wasm_runtime_get_native_addr_range(WASMModuleInstance *module_inst,
uint8_t *native_ptr,
uint8_t **p_native_start_addr,
uint8_t **p_native_end_addr);
bool
wasm_runtime_invoke_native(void *func_ptr, WASMType *func_type,
WASMModuleInstance *module_inst,