Files
clang-p2996/compiler-rt/test/msan/Linux/swapcontext_annotation_reset.cpp
Justin Cady 1d3ef5f122 [MSAN] Add fiber switching APIs
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
2020-08-27 19:30:40 -07:00

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