From df96828b91c54f1c08ef7759d501956be4df4af6 Mon Sep 17 00:00:00 2001 From: YAMAMOTO Takashi Date: Tue, 23 Apr 2024 12:36:40 +0900 Subject: [PATCH 01/21] add wasm_runtime_detect_native_stack_overflow --- core/iwasm/common/wasm_runtime_common.c | 29 +++++++++++++++++++++++++ core/iwasm/common/wasm_runtime_common.h | 3 +++ 2 files changed, 32 insertions(+) diff --git a/core/iwasm/common/wasm_runtime_common.c b/core/iwasm/common/wasm_runtime_common.c index 665141fb00..3d3d38521f 100644 --- a/core/iwasm/common/wasm_runtime_common.c +++ b/core/iwasm/common/wasm_runtime_common.c @@ -7015,3 +7015,32 @@ wasm_runtime_get_module_name(wasm_module_t module) return ""; } + +/* + * wasm_runtime_detect_native_stack_overflow + * + * - raise "native stack overflow" exception if available native stack + * at this point is less than WASM_STACK_GUARD_SIZE. in that case, + * return false. + * + * - update native_stack_top_min. + */ +bool +wasm_runtime_detect_native_stack_overflow(WASMExecEnv *exec_env) +{ + uint8 *boundary; +#if defined(OS_ENABLE_HW_BOUND_CHECK) && WASM_DISABLE_STACK_HW_BOUND_CHECK == 0 + uint32 page_size = os_getpagesize(); + uint32 guard_page_count = STACK_OVERFLOW_CHECK_GUARD_PAGE_COUNT; + boundary = exec_env->native_stack_boundary + page_size * guard_page_count; +#else + boundary = exec_env->native_stack_boundary; +#endif + RECORD_STACK_USAGE(exec_env, (uint8 *)&boundary); + if ((uint8 *)&boundary < boundary) { + wasm_runtime_set_exception(wasm_runtime_get_module_inst(exec_env), + "native stack overflow"); + return false; + } + return true; +} diff --git a/core/iwasm/common/wasm_runtime_common.h b/core/iwasm/common/wasm_runtime_common.h index 62c35473af..ede307361d 100644 --- a/core/iwasm/common/wasm_runtime_common.h +++ b/core/iwasm/common/wasm_runtime_common.h @@ -1189,6 +1189,9 @@ wasm_runtime_end_blocking_op(WASMExecEnv *exec_env); void wasm_runtime_interrupt_blocking_op(WASMExecEnv *exec_env); +bool +wasm_runtime_detect_native_stack_overflow(WASMExecEnv *exec_env); + #if WASM_ENABLE_LINUX_PERF != 0 bool wasm_runtime_get_linux_perf(void); From ffa17f39bbdecac3c41ef409fdfb99417d7a7413 Mon Sep 17 00:00:00 2001 From: YAMAMOTO Takashi Date: Tue, 23 Apr 2024 12:37:02 +0900 Subject: [PATCH 02/21] consume wasm_runtime_detect_native_stack_overflow this changes the accounting by one small function call. i don't think it can cause real problems though. --- core/iwasm/aot/aot_runtime.c | 11 ++--------- core/iwasm/interpreter/wasm_interp_classic.c | 13 +++++++------ core/iwasm/interpreter/wasm_interp_fast.c | 13 +++++++------ core/iwasm/interpreter/wasm_runtime.c | 7 +------ 4 files changed, 17 insertions(+), 27 deletions(-) diff --git a/core/iwasm/aot/aot_runtime.c b/core/iwasm/aot/aot_runtime.c index 09bf4b1e6e..f34decb5ea 100644 --- a/core/iwasm/aot/aot_runtime.c +++ b/core/iwasm/aot/aot_runtime.c @@ -1967,8 +1967,6 @@ invoke_native_with_hw_bound_check(WASMExecEnv *exec_env, void *func_ptr, AOTModuleInstance *module_inst = (AOTModuleInstance *)exec_env->module_inst; WASMExecEnv *exec_env_tls = wasm_runtime_get_exec_env_tls(); WASMJmpBuf jmpbuf_node = { 0 }, *jmpbuf_node_pop; - uint32 page_size = os_getpagesize(); - uint32 guard_page_count = STACK_OVERFLOW_CHECK_GUARD_PAGE_COUNT; #ifdef BH_PLATFORM_WINDOWS int result; bool has_exception; @@ -1979,10 +1977,7 @@ invoke_native_with_hw_bound_check(WASMExecEnv *exec_env, void *func_ptr, /* Check native stack overflow firstly to ensure we have enough native stack to run the following codes before actually calling the aot function in invokeNative function. */ - RECORD_STACK_USAGE(exec_env, (uint8 *)&module_inst); - if ((uint8 *)&module_inst - < exec_env->native_stack_boundary + page_size * guard_page_count) { - aot_set_exception_with_id(module_inst, EXCE_NATIVE_STACK_OVERFLOW); + if (!wasm_runtime_detect_native_stack_overflow(exec_env)) { return false; } @@ -2790,9 +2785,7 @@ aot_call_indirect(WASMExecEnv *exec_env, uint32 tbl_idx, uint32 table_elem_idx, exec_env->native_stack_boundary must have been set, we don't set it again */ - RECORD_STACK_USAGE(exec_env, (uint8 *)&module_inst); - if ((uint8 *)&module_inst < exec_env->native_stack_boundary) { - aot_set_exception_with_id(module_inst, EXCE_NATIVE_STACK_OVERFLOW); + if (!wasm_runtime_detect_native_stack_overflow(exec_env)) { goto fail; } diff --git a/core/iwasm/interpreter/wasm_interp_classic.c b/core/iwasm/interpreter/wasm_interp_classic.c index 026e9dd419..443dd14910 100644 --- a/core/iwasm/interpreter/wasm_interp_classic.c +++ b/core/iwasm/interpreter/wasm_interp_classic.c @@ -7108,12 +7108,13 @@ wasm_interp_call_wasm(WASMModuleInstance *module_inst, WASMExecEnv *exec_env, } argc = function->param_cell_num; - RECORD_STACK_USAGE(exec_env, (uint8 *)&prev_frame); -#if !(defined(OS_ENABLE_HW_BOUND_CHECK) \ - && WASM_DISABLE_STACK_HW_BOUND_CHECK == 0) - if ((uint8 *)&prev_frame < exec_env->native_stack_boundary) { - wasm_set_exception((WASMModuleInstance *)exec_env->module_inst, - "native stack overflow"); +#if defined(OS_ENABLE_HW_BOUND_CHECK) && WASM_DISABLE_STACK_HW_BOUND_CHECK == 0 + /* + * wasm_runtime_detect_native_stack_overflow is done by + * call_wasm_with_hw_bound_check. + */ +#else + if (!wasm_runtime_detect_native_stack_overflow(exec_env)) { return; } #endif diff --git a/core/iwasm/interpreter/wasm_interp_fast.c b/core/iwasm/interpreter/wasm_interp_fast.c index 417e3b0163..40cc56afb5 100644 --- a/core/iwasm/interpreter/wasm_interp_fast.c +++ b/core/iwasm/interpreter/wasm_interp_fast.c @@ -6081,12 +6081,13 @@ wasm_interp_call_wasm(WASMModuleInstance *module_inst, WASMExecEnv *exec_env, } argc = function->param_cell_num; - RECORD_STACK_USAGE(exec_env, (uint8 *)&prev_frame); -#if !(defined(OS_ENABLE_HW_BOUND_CHECK) \ - && WASM_DISABLE_STACK_HW_BOUND_CHECK == 0) - if ((uint8 *)&prev_frame < exec_env->native_stack_boundary) { - wasm_set_exception((WASMModuleInstance *)exec_env->module_inst, - "native stack overflow"); +#if defined(OS_ENABLE_HW_BOUND_CHECK) && WASM_DISABLE_STACK_HW_BOUND_CHECK == 0 + /* + * wasm_runtime_detect_native_stack_overflow is done by + * call_wasm_with_hw_bound_check. + */ +#else + if (!wasm_runtime_detect_native_stack_overflow(exec_env)) { return; } #endif diff --git a/core/iwasm/interpreter/wasm_runtime.c b/core/iwasm/interpreter/wasm_runtime.c index cf480fb218..7495e2a173 100644 --- a/core/iwasm/interpreter/wasm_runtime.c +++ b/core/iwasm/interpreter/wasm_runtime.c @@ -3139,8 +3139,6 @@ call_wasm_with_hw_bound_check(WASMModuleInstance *module_inst, { WASMExecEnv *exec_env_tls = wasm_runtime_get_exec_env_tls(); WASMJmpBuf jmpbuf_node = { 0 }, *jmpbuf_node_pop; - uint32 page_size = os_getpagesize(); - uint32 guard_page_count = STACK_OVERFLOW_CHECK_GUARD_PAGE_COUNT; WASMRuntimeFrame *prev_frame = wasm_exec_env_get_cur_frame(exec_env); uint8 *prev_top = exec_env->wasm_stack.top; #ifdef BH_PLATFORM_WINDOWS @@ -3153,10 +3151,7 @@ call_wasm_with_hw_bound_check(WASMModuleInstance *module_inst, /* Check native stack overflow firstly to ensure we have enough native stack to run the following codes before actually calling the aot function in invokeNative function. */ - RECORD_STACK_USAGE(exec_env, (uint8 *)&exec_env_tls); - if ((uint8 *)&exec_env_tls - < exec_env->native_stack_boundary + page_size * guard_page_count) { - wasm_set_exception(module_inst, "native stack overflow"); + if (!wasm_runtime_detect_native_stack_overflow(exec_env)) { return; } From 49d2a64424ad21a2ead286cab935e6632468e599 Mon Sep 17 00:00:00 2001 From: YAMAMOTO Takashi Date: Tue, 23 Apr 2024 12:55:29 +0900 Subject: [PATCH 03/21] export wasm_runtime_detect_native_stack_overflow --- core/iwasm/common/wasm_runtime_common.h | 2 +- core/iwasm/include/wasm_export.h | 3 +++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/core/iwasm/common/wasm_runtime_common.h b/core/iwasm/common/wasm_runtime_common.h index ede307361d..0fd87a101b 100644 --- a/core/iwasm/common/wasm_runtime_common.h +++ b/core/iwasm/common/wasm_runtime_common.h @@ -1189,7 +1189,7 @@ wasm_runtime_end_blocking_op(WASMExecEnv *exec_env); void wasm_runtime_interrupt_blocking_op(WASMExecEnv *exec_env); -bool +WASM_RUNTIME_API_EXTERN bool wasm_runtime_detect_native_stack_overflow(WASMExecEnv *exec_env); #if WASM_ENABLE_LINUX_PERF != 0 diff --git a/core/iwasm/include/wasm_export.h b/core/iwasm/include/wasm_export.h index 104a9e83c1..2b1fd48b25 100644 --- a/core/iwasm/include/wasm_export.h +++ b/core/iwasm/include/wasm_export.h @@ -1756,6 +1756,9 @@ wasm_runtime_set_module_name(wasm_module_t module, const char *name, WASM_RUNTIME_API_EXTERN const char * wasm_runtime_get_module_name(wasm_module_t module); +WASM_RUNTIME_API_EXTERN bool +wasm_runtime_detect_native_stack_overflow(wasm_exec_env_t exec_env); + #ifdef __cplusplus } #endif From 81e5d036bbbfecb6981a4d0a52fe296b475cb128 Mon Sep 17 00:00:00 2001 From: YAMAMOTO Takashi Date: Tue, 23 Apr 2024 12:57:03 +0900 Subject: [PATCH 04/21] samples/native-stack-overflow: use wasm_runtime_detect_native_stack_overflow replace homegrown check. --- samples/native-stack-overflow/src/native_impl.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/samples/native-stack-overflow/src/native_impl.c b/samples/native-stack-overflow/src/native_impl.c index 9e6cec5616..e6a69f3a48 100644 --- a/samples/native-stack-overflow/src/native_impl.c +++ b/samples/native-stack-overflow/src/native_impl.c @@ -45,9 +45,12 @@ host_consume_stack_and_call_indirect(wasm_exec_env_t exec_env, uint32_t funcidx, void *boundary = os_thread_get_stack_boundary(); void *fp = __builtin_frame_address(0); ptrdiff_t diff = fp - boundary; - if ((unsigned char *)fp < (unsigned char *)boundary + 1024 * 5) { - wasm_runtime_set_exception(wasm_runtime_get_module_inst(exec_env), - "native stack overflow 2"); + /* + * because this function performs recursive calls depending on + * the user input, we don't have an apriori knowledge how much stack + * we need. perform the overflow check on each iteration. + */ + if (!wasm_runtime_detect_native_stack_overflow(exec_env)) { return 0; } if (diff > stack) { From 0c95ad01183e0069707d2631702bc1d5d1861a79 Mon Sep 17 00:00:00 2001 From: YAMAMOTO Takashi Date: Tue, 23 Apr 2024 12:57:55 +0900 Subject: [PATCH 05/21] Add wasm_runtime_detect_native_stack_overflow_size This allows each native function to require more native stack. cf. https://github.com/bytecodealliance/wasm-micro-runtime/issues/3325 --- core/iwasm/common/wasm_runtime_common.c | 23 +++++++++++++++++++++++ core/iwasm/common/wasm_runtime_common.h | 4 ++++ core/iwasm/include/wasm_export.h | 4 ++++ 3 files changed, 31 insertions(+) diff --git a/core/iwasm/common/wasm_runtime_common.c b/core/iwasm/common/wasm_runtime_common.c index 3d3d38521f..fa2f261303 100644 --- a/core/iwasm/common/wasm_runtime_common.c +++ b/core/iwasm/common/wasm_runtime_common.c @@ -7044,3 +7044,26 @@ wasm_runtime_detect_native_stack_overflow(WASMExecEnv *exec_env) } return true; } + +bool +wasm_runtime_detect_native_stack_overflow_size(WASMExecEnv *exec_env, + uint32 requested_size) +{ + uint8 *boundary; +#if defined(OS_ENABLE_HW_BOUND_CHECK) && WASM_DISABLE_STACK_HW_BOUND_CHECK == 0 + uint32 page_size = os_getpagesize(); + uint32 guard_page_count = STACK_OVERFLOW_CHECK_GUARD_PAGE_COUNT; + boundary = exec_env->native_stack_boundary + page_size * guard_page_count; +#else + boundary = exec_env->native_stack_boundary; +#endif + RECORD_STACK_USAGE(exec_env, (uint8 *)&boundary); + /* adjust the boundary for the requested size */ + boundary = boundary - WASM_STACK_GUARD_SIZE + requested_size; + if ((uint8 *)&boundary < boundary) { + wasm_runtime_set_exception(wasm_runtime_get_module_inst(exec_env), + "native stack overflow"); + return false; + } + return true; +} diff --git a/core/iwasm/common/wasm_runtime_common.h b/core/iwasm/common/wasm_runtime_common.h index 0fd87a101b..abaa330111 100644 --- a/core/iwasm/common/wasm_runtime_common.h +++ b/core/iwasm/common/wasm_runtime_common.h @@ -1192,6 +1192,10 @@ wasm_runtime_interrupt_blocking_op(WASMExecEnv *exec_env); WASM_RUNTIME_API_EXTERN bool wasm_runtime_detect_native_stack_overflow(WASMExecEnv *exec_env); +WASM_RUNTIME_API_EXTERN bool +wasm_runtime_detect_native_stack_overflow_size(WASMExecEnv *exec_env, + uint32 requested_size); + #if WASM_ENABLE_LINUX_PERF != 0 bool wasm_runtime_get_linux_perf(void); diff --git a/core/iwasm/include/wasm_export.h b/core/iwasm/include/wasm_export.h index 2b1fd48b25..407d0d7013 100644 --- a/core/iwasm/include/wasm_export.h +++ b/core/iwasm/include/wasm_export.h @@ -1759,6 +1759,10 @@ wasm_runtime_get_module_name(wasm_module_t module); WASM_RUNTIME_API_EXTERN bool wasm_runtime_detect_native_stack_overflow(wasm_exec_env_t exec_env); +WASM_RUNTIME_API_EXTERN bool +wasm_runtime_detect_native_stack_overflow_size(wasm_exec_env_t exec_env, + uint32_t required_size); + #ifdef __cplusplus } #endif From 2107dbaae6a9afae9358de182183b879582de5c9 Mon Sep 17 00:00:00 2001 From: YAMAMOTO Takashi Date: Tue, 23 Apr 2024 16:22:10 +0900 Subject: [PATCH 06/21] interpreters: Check native stack overflow for recursive calls --- core/iwasm/interpreter/wasm_interp_classic.c | 8 ++++++++ core/iwasm/interpreter/wasm_interp_fast.c | 8 ++++++++ 2 files changed, 16 insertions(+) diff --git a/core/iwasm/interpreter/wasm_interp_classic.c b/core/iwasm/interpreter/wasm_interp_classic.c index 443dd14910..30268234ab 100644 --- a/core/iwasm/interpreter/wasm_interp_classic.c +++ b/core/iwasm/interpreter/wasm_interp_classic.c @@ -1290,6 +1290,14 @@ wasm_interp_call_func_import(WASMModuleInstance *module_inst, uintptr_t aux_stack_origin_boundary = 0; uintptr_t aux_stack_origin_bottom = 0; + /* + * perform stack overflow check before calling + * wasm_interp_call_func_bytecode recursively. + */ + if (!wasm_runtime_detect_native_stack_overflow(exec_env)) { + return; + } + if (!sub_func_inst) { snprintf(buf, sizeof(buf), "failed to call unlinked import function (%s, %s)", diff --git a/core/iwasm/interpreter/wasm_interp_fast.c b/core/iwasm/interpreter/wasm_interp_fast.c index 40cc56afb5..c33b6d0fc2 100644 --- a/core/iwasm/interpreter/wasm_interp_fast.c +++ b/core/iwasm/interpreter/wasm_interp_fast.c @@ -1275,6 +1275,14 @@ wasm_interp_call_func_import(WASMModuleInstance *module_inst, uintptr_t aux_stack_origin_boundary = 0; uintptr_t aux_stack_origin_bottom = 0; + /* + * perform stack overflow check before calling + * wasm_interp_call_func_bytecode recursively. + */ + if (!wasm_runtime_detect_native_stack_overflow(exec_env)) { + return; + } + if (!sub_func_inst) { snprintf(buf, sizeof(buf), "failed to call unlinked import function (%s, %s)", From 32e5b5dda7f52696b36557fa9ceffc675ddd67df Mon Sep 17 00:00:00 2001 From: YAMAMOTO Takashi Date: Tue, 23 Apr 2024 16:23:21 +0900 Subject: [PATCH 07/21] interpreters: Check native stack overflow before calling native functions --- core/iwasm/interpreter/wasm_interp_classic.c | 4 ++++ core/iwasm/interpreter/wasm_interp_fast.c | 4 ++++ 2 files changed, 8 insertions(+) diff --git a/core/iwasm/interpreter/wasm_interp_classic.c b/core/iwasm/interpreter/wasm_interp_classic.c index 30268234ab..2763bc2bea 100644 --- a/core/iwasm/interpreter/wasm_interp_classic.c +++ b/core/iwasm/interpreter/wasm_interp_classic.c @@ -1159,6 +1159,10 @@ wasm_interp_call_func_native(WASMModuleInstance *module_inst, uint8 *frame_ref; #endif + if (!wasm_runtime_detect_native_stack_overflow(exec_env)) { + return; + } + all_cell_num = local_cell_num; #if WASM_ENABLE_GC != 0 all_cell_num += (local_cell_num + 3) / 4; diff --git a/core/iwasm/interpreter/wasm_interp_fast.c b/core/iwasm/interpreter/wasm_interp_fast.c index c33b6d0fc2..b861b271eb 100644 --- a/core/iwasm/interpreter/wasm_interp_fast.c +++ b/core/iwasm/interpreter/wasm_interp_fast.c @@ -1167,6 +1167,10 @@ wasm_interp_call_func_native(WASMModuleInstance *module_inst, all_cell_num += (local_cell_num + 3) / 4; #endif + if (!wasm_runtime_detect_native_stack_overflow(exec_env)) { + return; + } + if (!(frame = ALLOC_FRAME(exec_env, wasm_interp_interp_frame_size(all_cell_num), prev_frame))) From 5b228123d940a5abc8223b472f7767749a8b8e20 Mon Sep 17 00:00:00 2001 From: YAMAMOTO Takashi Date: Wed, 24 Apr 2024 17:41:13 +0900 Subject: [PATCH 08/21] add a comment on wasm_runtime_detect_native_stack_overflow --- core/iwasm/include/wasm_export.h | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/core/iwasm/include/wasm_export.h b/core/iwasm/include/wasm_export.h index 407d0d7013..07e8811cca 100644 --- a/core/iwasm/include/wasm_export.h +++ b/core/iwasm/include/wasm_export.h @@ -1756,6 +1756,20 @@ wasm_runtime_set_module_name(wasm_module_t module, const char *name, WASM_RUNTIME_API_EXTERN const char * wasm_runtime_get_module_name(wasm_module_t module); +/* + * wasm_runtime_detect_native_stack_overflow + * + * Detect native stack shortage. + * Ensure that the calling thread still has a reasonable amount of + * native stack (WASM_STACK_GUARD_SIZE bytes) available. + * + * If enough stack is left, returns true. + * Otherwise, raise a "native stack overflow" trap and returns false. + * + * Note: please do not expect a very strict detection. it's a good idea + * to give some margins. wasm_runtime_detect_native_stack_overflow itslf + * requires a small amount of stack to run. + */ WASM_RUNTIME_API_EXTERN bool wasm_runtime_detect_native_stack_overflow(wasm_exec_env_t exec_env); From b373c271cd28d5d1172c1f16c3ce66bf3604a665 Mon Sep 17 00:00:00 2001 From: YAMAMOTO Takashi Date: Wed, 24 Apr 2024 17:53:08 +0900 Subject: [PATCH 09/21] add a comment on wasm_runtime_detect_native_stack_overflow_size --- core/iwasm/include/wasm_export.h | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/core/iwasm/include/wasm_export.h b/core/iwasm/include/wasm_export.h index 07e8811cca..4373198d8e 100644 --- a/core/iwasm/include/wasm_export.h +++ b/core/iwasm/include/wasm_export.h @@ -1773,6 +1773,35 @@ wasm_runtime_get_module_name(wasm_module_t module); WASM_RUNTIME_API_EXTERN bool wasm_runtime_detect_native_stack_overflow(wasm_exec_env_t exec_env); +/* + * wasm_runtime_detect_native_stack_overflow_size + * + * Similar to wasm_runtime_detect_native_stack_overflow, + * but use the caller-specified size instead of WASM_STACK_GUARD_SIZE. + * + * An expected usage: + * ```c + * __attribute__((noinline)) // inlining can break the stack check + * void stack_hog(void) + * { + * // consume a lot of stack here + * } + * + * void + * stack_hog_wrapper(exec_env) { + * // the amount of stack stack_hog would consume, + * // plus a small margin + * uint32_t size = 10000000; + * + * if (!wasm_runtime_detect_native_stack_overflow_size(exec_env, size)) { + * // wasm_runtime_detect_native_stack_overflow_size has raised + * // a trap. + * return; + * } + * stack_hog(); + * } + * ``` + */ WASM_RUNTIME_API_EXTERN bool wasm_runtime_detect_native_stack_overflow_size(wasm_exec_env_t exec_env, uint32_t required_size); From 9d5c3ac851bc00e3e992718b8ef472b4087a9db1 Mon Sep 17 00:00:00 2001 From: YAMAMOTO Takashi Date: Wed, 24 Apr 2024 18:03:45 +0900 Subject: [PATCH 10/21] host_consume_stack: use wasm_runtime_detect_native_stack_overflow_size --- samples/native-stack-overflow/src/native_impl.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/samples/native-stack-overflow/src/native_impl.c b/samples/native-stack-overflow/src/native_impl.c index e6a69f3a48..5e43c7a83b 100644 --- a/samples/native-stack-overflow/src/native_impl.c +++ b/samples/native-stack-overflow/src/native_impl.c @@ -96,6 +96,11 @@ consume_stack1(wasm_exec_env_t exec_env, void *base, uint32_t stack) uint32_t host_consume_stack(wasm_exec_env_t exec_env, uint32_t stack) { + /* this function consumes a bit more than "stack" bytes */ + if (!wasm_runtime_detect_native_stack_overflow_size(exec_env, + 500 + stack)) { + return 0; + } void *base = __builtin_frame_address(0); return consume_stack1(exec_env, base, stack); } From a8ca16979948b13aea2a4194a1c39677c8656a2b Mon Sep 17 00:00:00 2001 From: YAMAMOTO Takashi Date: Wed, 24 Apr 2024 14:55:06 +0900 Subject: [PATCH 11/21] samples/native-stack-overflow: reduce a margin --- samples/native-stack-overflow/src/native_impl.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/samples/native-stack-overflow/src/native_impl.c b/samples/native-stack-overflow/src/native_impl.c index 5e43c7a83b..c125c52a62 100644 --- a/samples/native-stack-overflow/src/native_impl.c +++ b/samples/native-stack-overflow/src/native_impl.c @@ -98,7 +98,7 @@ host_consume_stack(wasm_exec_env_t exec_env, uint32_t stack) { /* this function consumes a bit more than "stack" bytes */ if (!wasm_runtime_detect_native_stack_overflow_size(exec_env, - 500 + stack)) { + 64 + stack)) { return 0; } void *base = __builtin_frame_address(0); From 0397d4f6d8d66ceae5a26e7517d4e4130cd2f061 Mon Sep 17 00:00:00 2001 From: YAMAMOTO Takashi Date: Thu, 25 Apr 2024 15:34:35 +0900 Subject: [PATCH 12/21] CI: build and run samples/native-stack-overflow --- .github/workflows/compilation_on_android_ubuntu.yml | 7 +++++++ .github/workflows/compilation_on_macos.yml | 7 +++++++ .github/workflows/nightly_run.yml | 8 ++++++++ 3 files changed, 22 insertions(+) diff --git a/.github/workflows/compilation_on_android_ubuntu.yml b/.github/workflows/compilation_on_android_ubuntu.yml index 6b2a1a1148..21437ffc09 100644 --- a/.github/workflows/compilation_on_android_ubuntu.yml +++ b/.github/workflows/compilation_on_android_ubuntu.yml @@ -491,6 +491,13 @@ jobs: ./iwasm wasm-apps/trap.aot | grep "#" > call_stack_aot.txt bash -x ../symbolicate.sh + - name: Build Sample [native-stack-overflow] + run: | + cd samples/native-stack-overflow + ./build.sh + ./run.sh test1 + ./run.sh test2 + test: needs: [ diff --git a/.github/workflows/compilation_on_macos.yml b/.github/workflows/compilation_on_macos.yml index c0b565bff7..d9598a00be 100644 --- a/.github/workflows/compilation_on_macos.yml +++ b/.github/workflows/compilation_on_macos.yml @@ -379,3 +379,10 @@ jobs: ./iwasm wasm-apps/trap.wasm | grep "#" > call_stack.txt ./iwasm wasm-apps/trap.aot | grep "#" > call_stack_aot.txt bash -x ../symbolicate.sh + + - name: Build Sample [native-stack-overflow] + run: | + cd samples/native-stack-overflow + ./build.sh + ./run.sh test1 + ./run.sh test2 diff --git a/.github/workflows/nightly_run.yml b/.github/workflows/nightly_run.yml index 4335822bd9..3e4e89caf6 100644 --- a/.github/workflows/nightly_run.yml +++ b/.github/workflows/nightly_run.yml @@ -548,6 +548,13 @@ jobs: ./build.sh ./run.sh + - name: Build Sample [native-stack-overflow] + run: | + cd samples/native-stack-overflow + ./build.sh + ./run.sh test1 + ./run.sh test2 + - name: Build Sample [native-lib] run: | mkdir build && cd build @@ -567,6 +574,7 @@ jobs: python3 ./sample_test_run.py $(pwd)/out exit $? working-directory: ./wamr-app-framework/samples/simple + test: needs: [ From 725aac31d7009c5104f9e7057fef0b5081c19d0a Mon Sep 17 00:00:00 2001 From: YAMAMOTO Takashi Date: Thu, 25 Apr 2024 15:38:25 +0900 Subject: [PATCH 13/21] samples/native-stack-overflow: clang-format --- samples/native-stack-overflow/src/native_impl.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/samples/native-stack-overflow/src/native_impl.c b/samples/native-stack-overflow/src/native_impl.c index c125c52a62..c41545c5c7 100644 --- a/samples/native-stack-overflow/src/native_impl.c +++ b/samples/native-stack-overflow/src/native_impl.c @@ -97,8 +97,7 @@ uint32_t host_consume_stack(wasm_exec_env_t exec_env, uint32_t stack) { /* this function consumes a bit more than "stack" bytes */ - if (!wasm_runtime_detect_native_stack_overflow_size(exec_env, - 64 + stack)) { + if (!wasm_runtime_detect_native_stack_overflow_size(exec_env, 64 + stack)) { return 0; } void *base = __builtin_frame_address(0); From a887eca0164849ec3c80073cc79f7ab5e480459a Mon Sep 17 00:00:00 2001 From: YAMAMOTO Takashi Date: Thu, 25 Apr 2024 16:04:17 +0900 Subject: [PATCH 14/21] appease GCC -Wmaybe-uninitialized --- samples/native-stack-overflow/src/main.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/samples/native-stack-overflow/src/main.c b/samples/native-stack-overflow/src/main.c index b17dd4612d..0719293233 100644 --- a/samples/native-stack-overflow/src/main.c +++ b/samples/native-stack-overflow/src/main.c @@ -114,7 +114,7 @@ main(int argc, char **argv) "--------\n"); unsigned int stack; - unsigned int prevstack; + unsigned int prevstack = 0; /* appease GCC -Wmaybe-uninitialized */ unsigned int stack_range_start = 0; unsigned int stack_range_end = 4096 * 6; unsigned int step = 16; From 71d02fd8f205127a3ad2053fc65ae33fe5f1afe7 Mon Sep 17 00:00:00 2001 From: YAMAMOTO Takashi Date: Thu, 25 Apr 2024 16:08:47 +0900 Subject: [PATCH 15/21] fix build with GCC --- samples/native-stack-overflow/src/native_impl.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/samples/native-stack-overflow/src/native_impl.c b/samples/native-stack-overflow/src/native_impl.c index c41545c5c7..17208629c0 100644 --- a/samples/native-stack-overflow/src/native_impl.c +++ b/samples/native-stack-overflow/src/native_impl.c @@ -66,7 +66,9 @@ host_consume_stack_and_call_indirect(wasm_exec_env_t exec_env, uint32_t funcidx, __attribute__((noinline)) static uint32_t consume_stack1(wasm_exec_env_t exec_env, void *base, uint32_t stack) +#if defined(__clang__) __attribute__((disable_tail_calls)) +#endif { void *fp = __builtin_frame_address(0); ptrdiff_t diff = (unsigned char *)base - (unsigned char *)fp; From 74be5980d2cd2357f9f82952f5d9d53089b70fb6 Mon Sep 17 00:00:00 2001 From: YAMAMOTO Takashi Date: Thu, 25 Apr 2024 16:36:51 +0900 Subject: [PATCH 16/21] samples/native-stack-overflow: use size_level=0 To avoid: LLVM ERROR: Only small, tiny and large code models are allowed on AArch64 --- samples/native-stack-overflow/build.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/samples/native-stack-overflow/build.sh b/samples/native-stack-overflow/build.sh index df31131a5b..ac9f410f45 100755 --- a/samples/native-stack-overflow/build.sh +++ b/samples/native-stack-overflow/build.sh @@ -69,7 +69,7 @@ echo "#################### build wasm apps done" echo "#################### aot-compile" WAMRC=${WAMR_DIR}/wamr-compiler/build/wamrc -${WAMRC} -o ${OUT_DIR}/wasm-apps/${OUT_FILE}.aot ${OUT_DIR}/wasm-apps/${OUT_FILE} +${WAMRC} -o ${OUT_DIR}/wasm-apps/${OUT_FILE}.aot --size-level=0 ${OUT_DIR}/wasm-apps/${OUT_FILE} echo "#################### aot-compile (--bounds-checks=1)" -${WAMRC} -o ${OUT_DIR}/wasm-apps/${OUT_FILE}.aot.bounds-checks --bounds-checks=1 ${OUT_DIR}/wasm-apps/${OUT_FILE} +${WAMRC} -o ${OUT_DIR}/wasm-apps/${OUT_FILE}.aot.bounds-checks --size-level=0 --bounds-checks=1 ${OUT_DIR}/wasm-apps/${OUT_FILE} From fcfff69557a33b8cd5689113163b860a88dba211 Mon Sep 17 00:00:00 2001 From: YAMAMOTO Takashi Date: Thu, 25 Apr 2024 17:30:30 +0900 Subject: [PATCH 17/21] CI: skip samples/native-stack-overflow on macOS arm64 as i have no good way to debug right now. the failure seen on the CI: ``` ====== Interpreter test1 stack size | fail? | leak? | exception --------------------------------------------------------------------------- 0 - 24576 | failed | ok | Exception: native stack overflow ====== Interpreter WAMR_DISABLE_HW_BOUND_CHECK=1 test1 stack size | fail? | leak? | exception --------------------------------------------------------------------------- 0 - 3568 | failed | ok | Exception: native stack overflow 3568 - 24576 | failed | ok | Exception: wasm operand stack overflow ====== AOT test1 stack size | fail? | leak? | exception --------------------------------------------------------------------------- 0 - 24576 | failed | ok | Exception: native stack overflow ====== AOT WAMR_DISABLE_HW_BOUND_CHECK=1 test1 stack size | fail? | leak? | exception --------------------------------------------------------------------------- 0 - 4000 | failed | ok | Exception: native stack overflow 4000 - 24576 | ok | ok | ====== Interpreter test2 stack size | fail? | leak? | exception --------------------------------------------------------------------------- 0 - 24576 | failed | ok | Exception: native stack overflow ====== Interpreter WAMR_DISABLE_HW_BOUND_CHECK=1 test2 ./run.sh: line 12: 14708 Segmentation fault: 11 out/native-stack-overflow.WAMR_DISABLE_HW_BOUND_CHECK out/wasm-apps/testapp.wasm ${NAME} ``` --- .github/workflows/compilation_on_macos.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/workflows/compilation_on_macos.yml b/.github/workflows/compilation_on_macos.yml index d9598a00be..559f25ed79 100644 --- a/.github/workflows/compilation_on_macos.yml +++ b/.github/workflows/compilation_on_macos.yml @@ -380,7 +380,9 @@ jobs: ./iwasm wasm-apps/trap.aot | grep "#" > call_stack_aot.txt bash -x ../symbolicate.sh + # skip on arm64 (macos-14) for now - name: Build Sample [native-stack-overflow] + if: matrix.os != 'macos-14' run: | cd samples/native-stack-overflow ./build.sh From 6607b2ff0b93e3a3e11f8cdd5daf20283ed0d527 Mon Sep 17 00:00:00 2001 From: YAMAMOTO Takashi Date: Thu, 25 Apr 2024 19:03:07 +0900 Subject: [PATCH 18/21] disable tail-call for gcc fix an infinite loop in consume_stack1 --- samples/native-stack-overflow/CMakeLists.txt | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/samples/native-stack-overflow/CMakeLists.txt b/samples/native-stack-overflow/CMakeLists.txt index 9858feea1f..efe5b5dc05 100644 --- a/samples/native-stack-overflow/CMakeLists.txt +++ b/samples/native-stack-overflow/CMakeLists.txt @@ -72,6 +72,11 @@ if (CMAKE_C_COMPILER_ID MATCHES "Clang" AND CMAKE_C_COMPILER_VERSION VERSION_GRE set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fstack-usage") endif () +# GCC doesn't have disable_tail_calls attribute +if (CMAKE_C_COMPILER_ID MATCHES "GNU") +set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fno-optimize-sibling-calls") +endif () + # build out vmlib set (WAMR_ROOT_DIR ${CMAKE_CURRENT_LIST_DIR}/../..) include (${WAMR_ROOT_DIR}/build-scripts/runtime_lib.cmake) From f6b57abaff65a4399d7d45561f7ae0dfe411c039 Mon Sep 17 00:00:00 2001 From: YAMAMOTO Takashi Date: Thu, 25 Apr 2024 22:16:17 +0900 Subject: [PATCH 19/21] minor comment fixes --- core/iwasm/include/wasm_export.h | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/core/iwasm/include/wasm_export.h b/core/iwasm/include/wasm_export.h index 4373198d8e..c7513396fc 100644 --- a/core/iwasm/include/wasm_export.h +++ b/core/iwasm/include/wasm_export.h @@ -1763,11 +1763,12 @@ wasm_runtime_get_module_name(wasm_module_t module); * Ensure that the calling thread still has a reasonable amount of * native stack (WASM_STACK_GUARD_SIZE bytes) available. * - * If enough stack is left, returns true. - * Otherwise, raise a "native stack overflow" trap and returns false. + * If enough stack is left, this function returns true. + * Otherwise, this function raises a "native stack overflow" trap and + * returns false. * * Note: please do not expect a very strict detection. it's a good idea - * to give some margins. wasm_runtime_detect_native_stack_overflow itslf + * to give some margins. wasm_runtime_detect_native_stack_overflow itself * requires a small amount of stack to run. */ WASM_RUNTIME_API_EXTERN bool From be17b3ff9bc64ebef220f9a07462f080129cd4ff Mon Sep 17 00:00:00 2001 From: YAMAMOTO Takashi Date: Fri, 26 Apr 2024 13:06:59 +0900 Subject: [PATCH 20/21] simplify --- .../native-stack-overflow/src/native_impl.c | 24 +++---------------- 1 file changed, 3 insertions(+), 21 deletions(-) diff --git a/samples/native-stack-overflow/src/native_impl.c b/samples/native-stack-overflow/src/native_impl.c index 17208629c0..7037e1029b 100644 --- a/samples/native-stack-overflow/src/native_impl.c +++ b/samples/native-stack-overflow/src/native_impl.c @@ -9,10 +9,6 @@ #include #include -#if defined(__APPLE__) -#include -#endif - #include "wasm_export.h" #include "bh_platform.h" @@ -73,22 +69,6 @@ consume_stack1(wasm_exec_env_t exec_env, void *base, uint32_t stack) void *fp = __builtin_frame_address(0); ptrdiff_t diff = (unsigned char *)base - (unsigned char *)fp; assert(diff > 0); - char buf[16]; - /* - * note: we prefer to use memset_s here because, unlike memset, - * memset_s is not allowed to be optimized away. - * - * memset_s is available for macOS 10.13+ according to: - * https://developer.apple.com/documentation/kernel/2876438-memset_s - */ -#if defined(__STDC_LIB_EXT1__) \ - || (defined(__MAC_OS_X_VERSION_MAX_ALLOWED) \ - && __MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_3) - memset_s(buf, sizeof(buf), 0, sizeof(buf)); -#else -#warning memset_s is not available - memset(buf, 0, sizeof(buf)); -#endif if (diff > stack) { return diff; } @@ -98,7 +78,9 @@ consume_stack1(wasm_exec_env_t exec_env, void *base, uint32_t stack) uint32_t host_consume_stack(wasm_exec_env_t exec_env, uint32_t stack) { - /* this function consumes a bit more than "stack" bytes */ + /* + * this function consumes a bit more than "stack" bytes. + */ if (!wasm_runtime_detect_native_stack_overflow_size(exec_env, 64 + stack)) { return 0; } From 6196f1c8e7ac640544ea0e6deae67b2de2c534da Mon Sep 17 00:00:00 2001 From: YAMAMOTO Takashi Date: Fri, 26 Apr 2024 13:08:49 +0900 Subject: [PATCH 21/21] handle native_stack_boundary==NULL case --- core/iwasm/common/wasm_runtime_common.c | 24 ++++++++++++++---------- 1 file changed, 14 insertions(+), 10 deletions(-) diff --git a/core/iwasm/common/wasm_runtime_common.c b/core/iwasm/common/wasm_runtime_common.c index fa2f261303..2b481710ce 100644 --- a/core/iwasm/common/wasm_runtime_common.c +++ b/core/iwasm/common/wasm_runtime_common.c @@ -7028,15 +7028,17 @@ wasm_runtime_get_module_name(wasm_module_t module) bool wasm_runtime_detect_native_stack_overflow(WASMExecEnv *exec_env) { - uint8 *boundary; + uint8 *boundary = exec_env->native_stack_boundary; + RECORD_STACK_USAGE(exec_env, (uint8 *)&boundary); + if (boundary == NULL) { + /* the platfrom doesn't support os_thread_get_stack_boundary */ + return true; + } #if defined(OS_ENABLE_HW_BOUND_CHECK) && WASM_DISABLE_STACK_HW_BOUND_CHECK == 0 uint32 page_size = os_getpagesize(); uint32 guard_page_count = STACK_OVERFLOW_CHECK_GUARD_PAGE_COUNT; - boundary = exec_env->native_stack_boundary + page_size * guard_page_count; -#else - boundary = exec_env->native_stack_boundary; + boundary = boundary + page_size * guard_page_count; #endif - RECORD_STACK_USAGE(exec_env, (uint8 *)&boundary); if ((uint8 *)&boundary < boundary) { wasm_runtime_set_exception(wasm_runtime_get_module_inst(exec_env), "native stack overflow"); @@ -7049,15 +7051,17 @@ bool wasm_runtime_detect_native_stack_overflow_size(WASMExecEnv *exec_env, uint32 requested_size) { - uint8 *boundary; + uint8 *boundary = exec_env->native_stack_boundary; + RECORD_STACK_USAGE(exec_env, (uint8 *)&boundary); + if (boundary == NULL) { + /* the platfrom doesn't support os_thread_get_stack_boundary */ + return true; + } #if defined(OS_ENABLE_HW_BOUND_CHECK) && WASM_DISABLE_STACK_HW_BOUND_CHECK == 0 uint32 page_size = os_getpagesize(); uint32 guard_page_count = STACK_OVERFLOW_CHECK_GUARD_PAGE_COUNT; - boundary = exec_env->native_stack_boundary + page_size * guard_page_count; -#else - boundary = exec_env->native_stack_boundary; + boundary = boundary + page_size * guard_page_count; #endif - RECORD_STACK_USAGE(exec_env, (uint8 *)&boundary); /* adjust the boundary for the requested size */ boundary = boundary - WASM_STACK_GUARD_SIZE + requested_size; if ((uint8 *)&boundary < boundary) {