66 lines · cpp
1// RUN: %clangxx_msan -fno-sanitize-memory-param-retval -fno-sanitize=memory -c %s -o %t-main.o2// RUN: %clangxx_msan -fno-sanitize-memory-param-retval %t-main.o %s -o %t3// RUN: %run %t4 5#include <assert.h>6#include <stdio.h>7#include <stdlib.h>8#include <ucontext.h>9#include <unistd.h>10 11#include <sanitizer/msan_interface.h>12 13#if __has_feature(memory_sanitizer)14 15__attribute__((noinline)) int bar(int a, int b) {16 volatile int zero = 0;17 return zero;18}19 20void foo(int x, int y, int expected) {21 assert(__msan_test_shadow(&x, sizeof(x)) == expected);22 assert(__msan_test_shadow(&y, sizeof(y)) == expected);23 24 // Poisons parameter shadow in TLS so that the next call (to foo) from25 // uninstrumented main has params 1 and 2 poisoned no matter what.26 int a, b;27 (void)bar(a, b);28}29 30#else31 32// This code is not instrumented by MemorySanitizer to prevent it from modifying33// MSAN TLS data for this test.34 35int foo(int, int, int);36 37int main(int argc, char **argv) {38 int x, y;39 // The parameters should _not_ be poisoned; this is the first call to foo.40 foo(x, y, -1);41 // The parameters should be poisoned; the prior call to foo left them so.42 foo(x, y, 0);43 44 ucontext_t ctx;45 if (getcontext(&ctx) == -1) {46 perror("getcontext");47 _exit(1);48 }49 50 // Simulate a fiber switch occurring from MSAN's perspective (though no switch51 // actually occurs).52 const void *previous_stack_bottom = nullptr;53 size_t previous_stack_size = 0;54 __msan_start_switch_fiber(ctx.uc_stack.ss_sp, ctx.uc_stack.ss_size);55 __msan_finish_switch_fiber(&previous_stack_bottom, &previous_stack_size);56 57 // The simulated fiber switch will reset the TLS parameter shadow. So even58 // though the most recent call to foo left the parameter shadow poisoned, the59 // parameters are _not_ expected to be poisoned now.60 foo(x, y, -1);61 62 return 0;63}64 65#endif66