Add functions exposed via the MSAN interface to enable MSAN within binaries that perform manual stack switching (e.g. through using fibers or coroutines). This functionality is analogous to the fiber APIs available for ASAN and TSAN. Fixes google/sanitizers#1232 Reviewed By: vitalybuka Differential Revision: https://reviews.llvm.org/D86471
66 lines
1.7 KiB
C++
66 lines
1.7 KiB
C++
// RUN: %clangxx_msan -fno-sanitize=memory -c %s -o %t-main.o
|
|
// RUN: %clangxx_msan %t-main.o %s -o %t
|
|
// RUN: %run %t
|
|
|
|
#include <assert.h>
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <ucontext.h>
|
|
#include <unistd.h>
|
|
|
|
#include <sanitizer/msan_interface.h>
|
|
|
|
#if __has_feature(memory_sanitizer)
|
|
|
|
__attribute__((noinline)) int bar(int a, int b) {
|
|
volatile int zero = 0;
|
|
return zero;
|
|
}
|
|
|
|
void foo(int x, int y, int expected) {
|
|
assert(__msan_test_shadow(&x, sizeof(x)) == expected);
|
|
assert(__msan_test_shadow(&y, sizeof(y)) == expected);
|
|
|
|
// Poisons parameter shadow in TLS so that the next call (to foo) from
|
|
// uninstrumented main has params 1 and 2 poisoned no matter what.
|
|
int a, b;
|
|
(void)bar(a, b);
|
|
}
|
|
|
|
#else
|
|
|
|
// This code is not instrumented by MemorySanitizer to prevent it from modifying
|
|
// MSAN TLS data for this test.
|
|
|
|
int foo(int, int, int);
|
|
|
|
int main(int argc, char **argv) {
|
|
int x, y;
|
|
// The parameters should _not_ be poisoned; this is the first call to foo.
|
|
foo(x, y, -1);
|
|
// The parameters should be poisoned; the prior call to foo left them so.
|
|
foo(x, y, 0);
|
|
|
|
ucontext_t ctx;
|
|
if (getcontext(&ctx) == -1) {
|
|
perror("getcontext");
|
|
_exit(1);
|
|
}
|
|
|
|
// Simulate a fiber switch occurring from MSAN's perspective (though no switch
|
|
// actually occurs).
|
|
const void *previous_stack_bottom = nullptr;
|
|
size_t previous_stack_size = 0;
|
|
__msan_start_switch_fiber(ctx.uc_stack.ss_sp, ctx.uc_stack.ss_size);
|
|
__msan_finish_switch_fiber(&previous_stack_bottom, &previous_stack_size);
|
|
|
|
// The simulated fiber switch will reset the TLS parameter shadow. So even
|
|
// though the most recent call to foo left the parameter shadow poisoned, the
|
|
// parameters are _not_ expected to be poisoned now.
|
|
foo(x, y, -1);
|
|
|
|
return 0;
|
|
}
|
|
|
|
#endif
|