diff --git a/src/node.cc b/src/node.cc index 9b0dd072f7b883..96cdcd3064f963 100644 --- a/src/node.cc +++ b/src/node.cc @@ -393,10 +393,19 @@ static LONG TrapWebAssemblyOrContinue(EXCEPTION_POINTERS* exception) { } #else static std::atomic previous_sigsegv_action; +// TODO(align behavior between macos and other in next major version) +#if defined(__APPLE__) +static std::atomic previous_sigbus_action; +#endif // __APPLE__ void TrapWebAssemblyOrContinue(int signo, siginfo_t* info, void* ucontext) { if (!v8::TryHandleWebAssemblyTrapPosix(signo, info, ucontext)) { +#if defined(__APPLE__) + sigaction_cb prev = signo == SIGBUS ? previous_sigbus_action.load() + : previous_sigsegv_action.load(); +#else sigaction_cb prev = previous_sigsegv_action.load(); +#endif // __APPLE__ if (prev != nullptr) { prev(signo, info, ucontext); } else { @@ -426,6 +435,15 @@ void RegisterSignalHandler(int signal, previous_sigsegv_action.store(handler); return; } +// TODO(align behavior between macos and other in next major version) +#if defined(__APPLE__) + if (signal == SIGBUS) { + CHECK(previous_sigbus_action.is_lock_free()); + CHECK(!reset_handler); + previous_sigbus_action.store(handler); + return; + } +#endif // __APPLE__ #endif // NODE_USE_V8_WASM_TRAP_HANDLER struct sigaction sa; memset(&sa, 0, sizeof(sa)); @@ -576,7 +594,7 @@ static void PlatformInit(ProcessInitializationFlags::Flags flags) { #else // Tell V8 to disable emitting WebAssembly // memory bounds checks. This means that we have - // to catch the SIGSEGV in TrapWebAssemblyOrContinue + // to catch the SIGSEGV/SIGBUS in TrapWebAssemblyOrContinue // and pass the signal context to V8. { struct sigaction sa; @@ -584,6 +602,10 @@ static void PlatformInit(ProcessInitializationFlags::Flags flags) { sa.sa_sigaction = TrapWebAssemblyOrContinue; sa.sa_flags = SA_SIGINFO; CHECK_EQ(sigaction(SIGSEGV, &sa, nullptr), 0); +// TODO(align behavior between macos and other in next major version) +#if defined(__APPLE__) + CHECK_EQ(sigaction(SIGBUS, &sa, nullptr), 0); +#endif } #endif // defined(_WIN32) V8::EnableWebAssemblyTrapHandler(false); diff --git a/test/fixtures/out-of-bound.wasm b/test/fixtures/out-of-bound.wasm new file mode 100644 index 00000000000000..a95761b0f51410 Binary files /dev/null and b/test/fixtures/out-of-bound.wasm differ diff --git a/test/fixtures/out-of-bound.wat b/test/fixtures/out-of-bound.wat new file mode 100644 index 00000000000000..36e16821a3bac4 --- /dev/null +++ b/test/fixtures/out-of-bound.wat @@ -0,0 +1,16 @@ +(module + (type $none_=>_none (func)) + (memory $0 1) + (export "_start" (func $_start)) + (func $_start + memory.size + i32.const 64 + i32.mul + i32.const 1024 + i32.mul + i32.const 3 + i32.sub + i32.load + drop + ) +) diff --git a/test/parallel/test-wasm-memory-out-of-bound.js b/test/parallel/test-wasm-memory-out-of-bound.js new file mode 100644 index 00000000000000..56ac96beabd33e --- /dev/null +++ b/test/parallel/test-wasm-memory-out-of-bound.js @@ -0,0 +1,12 @@ +'use strict'; + +const common = require('../common'); +const assert = require('assert'); +const fixtures = require('../common/fixtures'); + +const buffer = fixtures.readSync('out-of-bound.wasm'); +WebAssembly.instantiate(buffer, {}).then(common.mustCall((results) => { + assert.throws(() => { + results.instance.exports._start(); + }, WebAssembly.RuntimeError('memory access out of bounds')); +}));