From a866e7a6c93e2d8bd3612f0fde572bb3670cde05 Mon Sep 17 00:00:00 2001 From: Sam Clegg Date: Fri, 8 Mar 2024 09:58:58 -0800 Subject: [PATCH] Fix for longjmp(.., 0) under wasm EH Fixes: #21486 --- system/lib/compiler-rt/emscripten_setjmp.c | 8 +++++++ test/core/test_longjmp_zero.c | 28 ++++++++++++++++++++++ test/core/test_longjmp_zero.out | 3 +++ test/test_core.py | 4 ++++ 4 files changed, 43 insertions(+) create mode 100644 test/core/test_longjmp_zero.c create mode 100644 test/core/test_longjmp_zero.out diff --git a/system/lib/compiler-rt/emscripten_setjmp.c b/system/lib/compiler-rt/emscripten_setjmp.c index 8dd944b010b5..ae68acb08380 100644 --- a/system/lib/compiler-rt/emscripten_setjmp.c +++ b/system/lib/compiler-rt/emscripten_setjmp.c @@ -90,6 +90,14 @@ thread_local struct __WasmLongjmpArgs __wasm_longjmp_args; // TODO Consider switching to throwing two values at the same time later. void __wasm_longjmp(void *env, int val) { __wasm_longjmp_args.env = env; + /* + * C standard: + * The longjmp function cannot cause the setjmp macro to return + * the value 0; if val is 0, the setjmp macro returns the value 1. + */ + if (val == 0) { + val = 1; + } __wasm_longjmp_args.val = val; __builtin_wasm_throw(C_LONGJMP, &__wasm_longjmp_args); } diff --git a/test/core/test_longjmp_zero.c b/test/core/test_longjmp_zero.c new file mode 100644 index 000000000000..dea87ef64d52 --- /dev/null +++ b/test/core/test_longjmp_zero.c @@ -0,0 +1,28 @@ +/* + * Copyright 2016 The Emscripten Authors. All rights reserved. + * Emscripten is available under two separate licenses, the MIT license and the + * University of Illinois/NCSA Open Source License. Both these licenses can be + * found in the LICENSE file. + */ + +#include +#include + +int main() { + printf("start\n"); + jmp_buf b1; + int val = setjmp(b1); + if (val) { + printf("success\n"); + return 0; + } + /* + * C standard: + * > The longjmp function cannot cause the setjmp macro to return + * > the value 0; if val is 0, the setjmp macro returns the value 1. + */ + printf("longjmp\n"); + longjmp(b1, 0); + __builtin_trap(); + return 0; +} diff --git a/test/core/test_longjmp_zero.out b/test/core/test_longjmp_zero.out new file mode 100644 index 000000000000..8beb03149936 --- /dev/null +++ b/test/core/test_longjmp_zero.out @@ -0,0 +1,3 @@ +start +longjmp +success diff --git a/test/test_core.py b/test/test_core.py index e9d817812ee9..2622dd04f39f 100644 --- a/test/test_core.py +++ b/test/test_core.py @@ -892,6 +892,10 @@ def test_longjmp_standalone(self): def test_longjmp(self): self.do_core_test('test_longjmp.c') + @with_both_sjlj + def test_longjmp_zero(self): + self.do_core_test('test_longjmp_zero.c') + def test_longjmp_with_and_without_exceptions(self): # Emscripten SjLj with and without Emscripten EH support self.set_setting('SUPPORT_LONGJMP', 'emscripten')