From 0e59d91eeddcff4a28add1ce7796ee9cd9ae9e10 Mon Sep 17 00:00:00 2001 From: Yuta Saito Date: Wed, 22 Nov 2023 16:08:53 +0000 Subject: [PATCH] [wasm] Avoid malloc during longjmp `longjmp` can be called to raise `NoMemoryError` or to trigger GC when `malloc` fails to allocate memory in `ruby_xmalloc` family. In such case, `malloc` call in `longjmp` will fail again, and Asyncify unwinding operation corrupts the memory space by using the failed pointer as Asyncify buffer. This commit uses statically allocated buffer to avoid such situation. --- wasm/setjmp.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/wasm/setjmp.c b/wasm/setjmp.c index 198d210bbf..ebbf8949c1 100644 --- a/wasm/setjmp.c +++ b/wasm/setjmp.c @@ -101,7 +101,6 @@ _rb_wasm_setjmp_internal(rb_wasm_jmp_buf *env) asyncify_stop_rewind(); RB_WASM_DEBUG_LOG(" JMP_BUF_STATE_RETURNING"); env->state = JMP_BUF_STATE_CAPTURED; - free(env->longjmp_buf_ptr); _rb_wasm_active_jmpbuf = NULL; return env->payload; } @@ -119,7 +118,10 @@ _rb_wasm_longjmp(rb_wasm_jmp_buf* env, int value) assert(value != 0); env->state = JMP_BUF_STATE_RETURNING; env->payload = value; - env->longjmp_buf_ptr = malloc(sizeof(struct __rb_wasm_asyncify_jmp_buf)); + // Asyncify buffer built during unwinding for longjmp will not + // be used to rewind, so re-use static-variable. + static struct __rb_wasm_asyncify_jmp_buf tmp_longjmp_buf; + env->longjmp_buf_ptr = &tmp_longjmp_buf; _rb_wasm_active_jmpbuf = env; async_buf_init(env->longjmp_buf_ptr); asyncify_start_unwind(env->longjmp_buf_ptr);