Source file src/cmd/cgo/internal/testsanitizers/testdata/msan8.go
1 // Copyright 2021 The Go Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 package main 6 7 /* 8 #include <pthread.h> 9 #include <signal.h> 10 #include <stdint.h> 11 12 #include <sanitizer/msan_interface.h> 13 14 // cgoTracebackArg is the type of the argument passed to msanGoTraceback. 15 struct cgoTracebackArg { 16 uintptr_t context; 17 uintptr_t sigContext; 18 uintptr_t* buf; 19 uintptr_t max; 20 }; 21 22 // msanGoTraceback is registered as the cgo traceback function. 23 // This will be called when a signal occurs. 24 void msanGoTraceback(void* parg) { 25 struct cgoTracebackArg* arg = (struct cgoTracebackArg*)(parg); 26 arg->buf[0] = 0; 27 } 28 29 // Don't warn if the compiler doesn't support the maybe_undef attribute. 30 #pragma GCC diagnostic ignored "-Wattributes" 31 32 // msanGoWait will be called with all registers undefined as far as 33 // msan is concerned. It just waits for a signal. 34 // Because the registers are msan-undefined, the signal handler will 35 // be invoked with all registers msan-undefined. 36 // The maybe_undef attribute tells clang to not complain about 37 // passing uninitialized values. 38 __attribute__((noinline)) 39 void msanGoWait(unsigned long a1 __attribute__((maybe_undef)), 40 unsigned long a2 __attribute__((maybe_undef)), 41 unsigned long a3 __attribute__((maybe_undef)), 42 unsigned long a4 __attribute__((maybe_undef)), 43 unsigned long a5 __attribute__((maybe_undef)), 44 unsigned long a6 __attribute__((maybe_undef))) { 45 sigset_t mask; 46 47 sigemptyset(&mask); 48 sigsuspend(&mask); 49 } 50 51 // msanGoSignalThread is the thread ID of the msanGoLoop thread. 52 static pthread_t msanGoSignalThread; 53 54 // msanGoSignalThreadSet is used to record that msanGoSignalThread 55 // has been initialized. This is accessed atomically. 56 static int32_t msanGoSignalThreadSet; 57 58 // uninit is explicitly poisoned, so that we can make all registers 59 // undefined by calling msanGoWait. 60 static unsigned long uninit; 61 62 // msanGoLoop loops calling msanGoWait, with the arguments passed 63 // such that msan thinks that they are undefined. msan permits 64 // undefined values to be used as long as they are not used to 65 // for conditionals or for memory access. 66 void msanGoLoop() { 67 int i; 68 69 msanGoSignalThread = pthread_self(); 70 __atomic_store_n(&msanGoSignalThreadSet, 1, __ATOMIC_SEQ_CST); 71 72 // Force uninit to be undefined for msan. 73 __msan_poison(&uninit, sizeof uninit); 74 for (i = 0; i < 100; i++) { 75 msanGoWait(uninit, uninit, uninit, uninit, uninit, uninit); 76 } 77 } 78 79 // msanGoReady returns whether msanGoSignalThread is set. 80 int msanGoReady() { 81 return __atomic_load_n(&msanGoSignalThreadSet, __ATOMIC_SEQ_CST) != 0; 82 } 83 84 // msanGoSendSignal sends a signal to the msanGoLoop thread. 85 void msanGoSendSignal() { 86 pthread_kill(msanGoSignalThread, SIGWINCH); 87 } 88 */ 89 import "C" 90 91 import ( 92 "runtime" 93 "time" 94 ) 95 96 func main() { 97 runtime.SetCgoTraceback(0, C.msanGoTraceback, nil, nil) 98 99 c := make(chan bool) 100 go func() { 101 defer func() { c <- true }() 102 C.msanGoLoop() 103 }() 104 105 for C.msanGoReady() == 0 { 106 time.Sleep(time.Microsecond) 107 } 108 109 loop: 110 for { 111 select { 112 case <-c: 113 break loop 114 default: 115 C.msanGoSendSignal() 116 time.Sleep(time.Microsecond) 117 } 118 } 119 } 120