diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_signal_interceptors.inc b/compiler-rt/lib/sanitizer_common/sanitizer_signal_interceptors.inc --- a/compiler-rt/lib/sanitizer_common/sanitizer_signal_interceptors.inc +++ b/compiler-rt/lib/sanitizer_common/sanitizer_signal_interceptors.inc @@ -53,7 +53,13 @@ INTERCEPTOR(int, sigaction_symname, int signum, const __sanitizer_sigaction *act, __sanitizer_sigaction *oldact) { - if (GetHandleSignalMode(signum) == kHandleSignalExclusive) return 0; + if (GetHandleSignalMode(signum) == kHandleSignalExclusive) { + if (oldact) { + act = nullptr; + } else { + return 0; + } + } SIGNAL_INTERCEPTOR_SIGACTION_IMPL(signum, act, oldact); } #define INIT_SIGACTION COMMON_INTERCEPT_FUNCTION(sigaction_symname) diff --git a/compiler-rt/test/msan/interception_sigaction_test.cpp b/compiler-rt/test/msan/interception_sigaction_test.cpp new file mode 100644 --- /dev/null +++ b/compiler-rt/test/msan/interception_sigaction_test.cpp @@ -0,0 +1,26 @@ +// RUN: %clangxx_msan -O0 -g %s -o %t +// RUN: %t 2>&1 | FileCheck %s +#include +#include +#include +#include +#include + +extern "C" int __interceptor_sigaction(int signum, const struct sigaction *act, struct sigaction *oldact); +extern "C" int sigaction(int signum, const struct sigaction *act, struct sigaction *oldact) { + write(2, "sigaction call\n", sizeof("sigaction call\n") - 1); + return __interceptor_sigaction(signum, act, oldact); +} + +int main() { + struct sigaction oldact; + sigaction(11, nullptr, &oldact); + for (int i = 0; i < sizeof(oldact); ++i) { + if (oldact.sa_handler || oldact.sa_sigaction) { + write(2, "oldact filled\n", sizeof("oldact filled\n") - 1); + } + } + return 0; + // CHECK: sigaction call + // CHECK: oldact filled +}