diff --git a/core/iwasm/lib/native/libc/libc_wrapper.c b/core/iwasm/lib/native/libc/libc_wrapper.c index d443888cf..6d3ac0c9f 100644 --- a/core/iwasm/lib/native/libc/libc_wrapper.c +++ b/core/iwasm/lib/native/libc/libc_wrapper.c @@ -52,6 +52,29 @@ wasm_runtime_set_llvm_stack(wasm_module_inst_t module, uint32 llvm_stack); #define module_free(offset) \ wasm_runtime_module_free(module_inst, offset) +static bool +validate_str_addr(wasm_module_inst_t module_inst, int32 str_offset) +{ + int32 app_end_offset; + char *str, *str_end; + + if (!wasm_runtime_get_app_addr_range(module_inst, str_offset, + NULL, &app_end_offset)) + goto fail; + + str = addr_app_to_native(str_offset); + str_end = str + (app_end_offset - 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; +} + typedef int (*out_func_t)(int c, void *ctx); enum pad_type { @@ -64,9 +87,14 @@ enum pad_type { typedef char *_va_list; #define _INTSIZEOF(n) \ ((sizeof(n) + 3) & ~3) -#define _va_arg(ap,t) \ +#define _va_arg(ap, t) \ (*(t*)((ap += _INTSIZEOF(t)) - _INTSIZEOF(t))) +#define CHECK_VA_ARG(ap, t) do { \ + if ((uint8*)ap + _INTSIZEOF(t) > native_end_addr) \ + goto fail; \ +} while (0) + /** * @brief Output an unsigned int in hex format * @@ -172,14 +200,19 @@ print_err(out_func_t out, void *ctx) out('R', ctx); } -static void -_vprintf(out_func_t out, void *ctx, const char *fmt, _va_list ap, - wasm_module_inst_t module_inst) +static bool +_vprintf_wa(out_func_t out, void *ctx, const char *fmt, _va_list ap, + wasm_module_inst_t module_inst) { int might_format = 0; /* 1 if encountered a '%' */ enum pad_type padding = PAD_NONE; int min_width = -1; int long_ctr = 0; + uint8 *native_end_addr; + + if (!wasm_runtime_get_native_addr_range(module_inst, (uint8*)ap, + NULL, &native_end_addr)) + goto fail; /* fmt has already been adjusted if needed */ @@ -232,10 +265,13 @@ _vprintf(out_func_t out, void *ctx, const char *fmt, _va_list ap, int32 d; if (long_ctr < 2) { + CHECK_VA_ARG(ap, int32); d = _va_arg(ap, int32); } else { - int64 lld = _va_arg(ap, int64); + int64 lld; + CHECK_VA_ARG(ap, int64); + lld = _va_arg(ap, int64); if (lld > INT32_MAX || lld < INT32_MIN) { print_err(out, ctx); break; @@ -255,10 +291,13 @@ _vprintf(out_func_t out, void *ctx, const char *fmt, _va_list ap, uint32 u; if (long_ctr < 2) { + CHECK_VA_ARG(ap, uint32); u = _va_arg(ap, uint32); } else { - uint64 llu = _va_arg(ap, uint64); + uint64 llu; + CHECK_VA_ARG(ap, uint64); + llu = _va_arg(ap, uint64); if (llu > INT32_MAX) { print_err(out, ctx); break; @@ -281,8 +320,10 @@ _vprintf(out_func_t out, void *ctx, const char *fmt, _va_list ap, bool is_ptr = (*fmt == 'p') ? true : false; if (long_ctr < 2) { + CHECK_VA_ARG(ap, uint32); x = _va_arg(ap, uint32); } else { + CHECK_VA_ARG(ap, uint64); x = _va_arg(ap, uint64); } _printf_hex_uint(out, ctx, x, !is_ptr, padding, min_width); @@ -292,11 +333,13 @@ _vprintf(out_func_t out, void *ctx, const char *fmt, _va_list ap, case 's': { char *s; char *start; - int32 s_offset = _va_arg(ap, uint32); + int32 s_offset; - if (!validate_app_addr(s_offset, 1)) { - wasm_runtime_set_exception(module_inst, "out of bounds memory access"); - return; + CHECK_VA_ARG(ap, uint32); + s_offset = _va_arg(ap, uint32); + + if (!validate_str_addr(module_inst, s_offset)) { + return false; } s = start = addr_app_to_native(s_offset); @@ -314,7 +357,9 @@ _vprintf(out_func_t out, void *ctx, const char *fmt, _va_list ap, } case 'c': { - int c = _va_arg(ap, int); + int c; + CHECK_VA_ARG(ap, int); + c = _va_arg(ap, int); out(c, ctx); break; } @@ -336,6 +381,11 @@ _vprintf(out_func_t out, void *ctx, const char *fmt, _va_list ap, still_might_format: ++fmt; } + return true; + +fail: + wasm_runtime_set_exception(module_inst, "out of bounds memory access"); + return false; } struct str_context { @@ -391,7 +441,7 @@ parse_printf_args(wasm_module_inst_t module_inst, int32 fmt_offset, _va_list v; } u; - if (!validate_app_addr(fmt_offset, 1) + if (!validate_str_addr(module_inst, fmt_offset) || !validate_app_addr(va_list_offset, sizeof(int32))) return false; @@ -414,7 +464,8 @@ _printf_wrapper(int32 fmt_offset, int32 va_list_offset) if (!parse_printf_args(module_inst, fmt_offset, va_list_offset, &fmt, &va_args)) return 0; - _vprintf((out_func_t) printf_out, &ctx, fmt, va_args, module_inst); + if (!_vprintf_wa((out_func_t)printf_out, &ctx, fmt, va_args, module_inst)) + return 0; return ctx.count; } @@ -427,7 +478,7 @@ _sprintf_wrapper(int32 str_offset, int32 fmt_offset, int32 va_list_offset) const char *fmt; _va_list va_args; - if (!validate_app_addr(str_offset, 1)) + if (!validate_str_addr(module_inst, str_offset)) return 0; str = addr_app_to_native(str_offset); @@ -439,7 +490,8 @@ _sprintf_wrapper(int32 str_offset, int32 fmt_offset, int32 va_list_offset) ctx.max = INT_MAX; ctx.count = 0; - _vprintf((out_func_t) sprintf_out, &ctx, fmt, va_args, module_inst); + if (!_vprintf_wa((out_func_t)sprintf_out, &ctx, fmt, va_args, module_inst)) + return 0; if (ctx.count < ctx.max) { str[ctx.count] = '\0'; @@ -470,7 +522,8 @@ _snprintf_wrapper(int32 str_offset, int32 size, int32 fmt_offset, ctx.max = size; ctx.count = 0; - _vprintf((out_func_t) sprintf_out, &ctx, fmt, va_args, module_inst); + if (!_vprintf_wa((out_func_t)sprintf_out, &ctx, fmt, va_args, module_inst)) + return 0; if (ctx.count < ctx.max) { str[ctx.count] = '\0'; @@ -485,7 +538,7 @@ _puts_wrapper(int32 str_offset) wasm_module_inst_t module_inst = get_module_inst(); const char *str; - if (!validate_app_addr(str_offset, 1)) + if (!validate_str_addr(module_inst, str_offset)) return 0; str = addr_app_to_native(str_offset); @@ -507,7 +560,7 @@ _strdup_wrapper(int32 str_offset) uint32 len; int32 str_ret_offset = 0; - if (!validate_app_addr(str_offset, 1)) + if (!validate_str_addr(module_inst, str_offset)) return 0; str = addr_app_to_native(str_offset); @@ -596,7 +649,7 @@ _strchr_wrapper(int32 s_offset, int32 c) const char *s; char *ret; - if (!validate_app_addr(s_offset, 1)) + if (!validate_str_addr(module_inst, s_offset)) return s_offset; s = addr_app_to_native(s_offset); @@ -610,8 +663,8 @@ _strcmp_wrapper(int32 s1_offset, int32 s2_offset) wasm_module_inst_t module_inst = get_module_inst(); void *s1, *s2; - if (!validate_app_addr(s1_offset, 1) - || !validate_app_addr(s2_offset, 1)) + if (!validate_str_addr(module_inst, s1_offset) + || !validate_str_addr(module_inst, s2_offset)) return 0; s1 = addr_app_to_native(s1_offset); @@ -640,8 +693,8 @@ _strcpy_wrapper(int32 dst_offset, int32 src_offset) wasm_module_inst_t module_inst = get_module_inst(); char *dst, *src; - if (!validate_app_addr(dst_offset, 1) - || !validate_app_addr(src_offset, 1)) + if (!validate_str_addr(module_inst, dst_offset) + || !validate_str_addr(module_inst, src_offset)) return 0; dst = addr_app_to_native(dst_offset); @@ -672,7 +725,7 @@ _strlen_wrapper(int32 s_offset) wasm_module_inst_t module_inst = get_module_inst(); char *s; - if (!validate_app_addr(s_offset, 1)) + if (!validate_str_addr(module_inst, s_offset)) return 0; s = addr_app_to_native(s_offset); diff --git a/core/iwasm/runtime/include/wasm_export.h b/core/iwasm/runtime/include/wasm_export.h index 61de09678..e6c9df5d7 100644 --- a/core/iwasm/runtime/include/wasm_export.h +++ b/core/iwasm/runtime/include/wasm_export.h @@ -391,6 +391,38 @@ int32_t wasm_runtime_addr_native_to_app(wasm_module_inst_t module_inst, void *native_ptr); +/** + * Get the app address range (relative address) that a app address belongs to + * + * @param module_inst the WASM module instance + * @param app_offset the app address to retrieve + * @param p_app_start_offset buffer to output the app start offset if not NULL + * @param p_app_end_offset buffer to output the app end offset if not NULL + * + * @return true if success, false otherwise. + */ +bool +wasm_runtime_get_app_addr_range(wasm_module_inst_t module_inst, + int32_t app_offset, + int32_t *p_app_start_offset, + int32_t *p_app_end_offset); + +/** + * Get the native address range (absolute address) that a native address belongs to + * + * @param module_inst the WASM module instance + * @param native_ptr the native address to retrieve + * @param p_native_start_addr buffer to output the native start address if not NULL + * @param p_native_end_addr buffer to output the native end address if not NULL + * + * @return true if success, false otherwise. + */ +bool +wasm_runtime_get_native_addr_range(wasm_module_inst_t module_inst, + uint8_t *native_ptr, + uint8_t **p_native_start_addr, + uint8_t **p_native_end_addr); + #ifdef __cplusplus } #endif diff --git a/core/iwasm/runtime/vmcore-wasm/wasm_runtime.c b/core/iwasm/runtime/vmcore-wasm/wasm_runtime.c index ec37222bd..eec38bcc9 100644 --- a/core/iwasm/runtime/vmcore-wasm/wasm_runtime.c +++ b/core/iwasm/runtime/vmcore-wasm/wasm_runtime.c @@ -1302,6 +1302,84 @@ wasm_runtime_addr_native_to_app(WASMModuleInstance *module_inst, return 0; } +bool +wasm_runtime_get_app_addr_range(WASMModuleInstance *module_inst, + int32 app_offset, + int32 *p_app_start_offset, + int32 *p_app_end_offset) +{ + int32 app_start_offset, app_end_offset; + WASMMemoryInstance *memory = module_inst->default_memory; + + if (0 <= app_offset && app_offset < memory->heap_base_offset) { + app_start_offset = 0; + app_end_offset = NumBytesPerPage * memory->cur_page_count; + } + else if (memory->heap_base_offset < app_offset + && app_offset < memory->heap_base_offset + + (memory->heap_data_end - memory->heap_data)) { + app_start_offset = memory->heap_base_offset; + app_end_offset = memory->heap_base_offset + + (memory->heap_data_end - memory->heap_data); + } +#if WASM_ENABLE_EXT_MEMORY_SPACE != 0 + else if (module_inst->ext_mem_data + && module_inst->ext_mem_base_offset <= app_offset + && app_offset < module_inst->ext_mem_base_offset + + module_inst->ext_mem_size) { + app_start_offset = module_inst->ext_mem_base_offset; + app_end_offset = app_start_offset + module_inst->ext_mem_size; + } +#endif + else + return false; + + if (p_app_start_offset) + *p_app_start_offset = app_start_offset; + if (p_app_end_offset) + *p_app_end_offset = app_end_offset; + return true; +} + +bool +wasm_runtime_get_native_addr_range(WASMModuleInstance *module_inst, + uint8 *native_ptr, + uint8 **p_native_start_addr, + uint8 **p_native_end_addr) +{ + uint8 *native_start_addr, *native_end_addr; + WASMMemoryInstance *memory = module_inst->default_memory; + + if (memory->base_addr <= (uint8*)native_ptr + && (uint8*)native_ptr < memory->end_addr) { + native_start_addr = memory->memory_data; + native_end_addr = memory->memory_data + + NumBytesPerPage * memory->cur_page_count; + } + else if (memory->heap_data <= (uint8*)native_ptr + && (uint8*)native_ptr < memory->heap_data_end) { + native_start_addr = memory->heap_data; + native_end_addr = memory->heap_data_end; + } +#if WASM_ENABLE_EXT_MEMORY_SPACE != 0 + else if (module_inst->ext_mem_data + && module_inst->ext_mem_data <= (uint8*)native_ptr + && (uint8*)native_ptr < module_inst->ext_mem_data_end) { + native_start_addr = module_inst->ext_mem_data; + native_end_addr = module_inst->ext_mem_data_end; + } +#endif + else + return false; + + if (p_native_start_addr) + *p_native_start_addr = native_start_addr; + if (p_native_end_addr) + *p_native_end_addr = native_end_addr; + return true; +} + + uint32 wasm_runtime_get_temp_ret(WASMModuleInstance *module_inst) {