summaryrefslogtreecommitdiff
path: root/wasm/setjmp.c
diff options
context:
space:
mode:
authorYuta Saito <[email protected]>2023-11-22 16:08:53 +0000
committerYuta Saito <[email protected]>2023-11-23 02:15:42 +0900
commit0e59d91eeddcff4a28add1ce7796ee9cd9ae9e10 (patch)
treeca31c2fb81d8c762580641f9d66d7f9c4f9b5a9b /wasm/setjmp.c
parentc1fc1a00ea9633961153451d0e927db49c1b268d (diff)
[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.
Diffstat (limited to 'wasm/setjmp.c')
-rw-r--r--wasm/setjmp.c6
1 files 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);