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  

View as plain text