Skip to content

Commit ed92b1f

Browse files
authored
src: handle wasm out of bound in osx will raise SIGBUS correctly
fix: #46559 OSX will raise both SIGBUS and SIGSEGV when out of bound memory visit, This commit set sigaction in OSX for two signals to handle this. PR-URL: #46561 Fixes: #46559 Reviewed-By: Anna Henningsen <anna@addaleax.net> Reviewed-By: James M Snell <jasnell@gmail.com> Reviewed-By: Darshan Sen <raisinten@gmail.com> Reviewed-By: Minwoo Jung <nodecorelab@gmail.com> Reviewed-By: Michael Dawson <midawson@redhat.com>
1 parent bd7a808 commit ed92b1f

File tree

4 files changed

+51
-1
lines changed

4 files changed

+51
-1
lines changed

src/node.cc

+23-1
Original file line numberDiff line numberDiff line change
@@ -362,10 +362,19 @@ static LONG TrapWebAssemblyOrContinue(EXCEPTION_POINTERS* exception) {
362362
}
363363
#else
364364
static std::atomic<sigaction_cb> previous_sigsegv_action;
365+
// TODO(align behavior between macos and other in next major version)
366+
#if defined(__APPLE__)
367+
static std::atomic<sigaction_cb> previous_sigbus_action;
368+
#endif // __APPLE__
365369

366370
void TrapWebAssemblyOrContinue(int signo, siginfo_t* info, void* ucontext) {
367371
if (!v8::TryHandleWebAssemblyTrapPosix(signo, info, ucontext)) {
372+
#if defined(__APPLE__)
373+
sigaction_cb prev = signo == SIGBUS ? previous_sigbus_action.load()
374+
: previous_sigsegv_action.load();
375+
#else
368376
sigaction_cb prev = previous_sigsegv_action.load();
377+
#endif // __APPLE__
369378
if (prev != nullptr) {
370379
prev(signo, info, ucontext);
371380
} else {
@@ -395,6 +404,15 @@ void RegisterSignalHandler(int signal,
395404
previous_sigsegv_action.store(handler);
396405
return;
397406
}
407+
// TODO(align behavior between macos and other in next major version)
408+
#if defined(__APPLE__)
409+
if (signal == SIGBUS) {
410+
CHECK(previous_sigbus_action.is_lock_free());
411+
CHECK(!reset_handler);
412+
previous_sigbus_action.store(handler);
413+
return;
414+
}
415+
#endif // __APPLE__
398416
#endif // NODE_USE_V8_WASM_TRAP_HANDLER
399417
struct sigaction sa;
400418
memset(&sa, 0, sizeof(sa));
@@ -551,14 +569,18 @@ static void PlatformInit(ProcessInitializationFlags::Flags flags) {
551569
#else
552570
// Tell V8 to disable emitting WebAssembly
553571
// memory bounds checks. This means that we have
554-
// to catch the SIGSEGV in TrapWebAssemblyOrContinue
572+
// to catch the SIGSEGV/SIGBUS in TrapWebAssemblyOrContinue
555573
// and pass the signal context to V8.
556574
{
557575
struct sigaction sa;
558576
memset(&sa, 0, sizeof(sa));
559577
sa.sa_sigaction = TrapWebAssemblyOrContinue;
560578
sa.sa_flags = SA_SIGINFO;
561579
CHECK_EQ(sigaction(SIGSEGV, &sa, nullptr), 0);
580+
// TODO(align behavior between macos and other in next major version)
581+
#if defined(__APPLE__)
582+
CHECK_EQ(sigaction(SIGBUS, &sa, nullptr), 0);
583+
#endif
562584
}
563585
#endif // defined(_WIN32)
564586
V8::EnableWebAssemblyTrapHandler(false);

test/fixtures/out-of-bound.wasm

58 Bytes
Binary file not shown.

test/fixtures/out-of-bound.wat

+16
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
(module
2+
(type $none_=>_none (func))
3+
(memory $0 1)
4+
(export "_start" (func $_start))
5+
(func $_start
6+
memory.size
7+
i32.const 64
8+
i32.mul
9+
i32.const 1024
10+
i32.mul
11+
i32.const 3
12+
i32.sub
13+
i32.load
14+
drop
15+
)
16+
)
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
'use strict';
2+
3+
const common = require('../common');
4+
const assert = require('assert');
5+
const fixtures = require('../common/fixtures');
6+
7+
const buffer = fixtures.readSync('out-of-bound.wasm');
8+
WebAssembly.instantiate(buffer, {}).then(common.mustCall((results) => {
9+
assert.throws(() => {
10+
results.instance.exports._start();
11+
}, WebAssembly.RuntimeError('memory access out of bounds'));
12+
}));

0 commit comments

Comments
 (0)