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  // msanGoWait will be called with all registers undefined as far as
    30  // msan is concerned. It just waits for a signal.
    31  // Because the registers are msan-undefined, the signal handler will
    32  // be invoked with all registers msan-undefined.
    33  __attribute__((noinline))
    34  void msanGoWait(unsigned long a1, unsigned long a2, unsigned long a3, unsigned long a4, unsigned long a5, unsigned long a6) {
    35  	sigset_t mask;
    36  
    37  	sigemptyset(&mask);
    38          sigsuspend(&mask);
    39  }
    40  
    41  // msanGoSignalThread is the thread ID of the msanGoLoop thread.
    42  static pthread_t msanGoSignalThread;
    43  
    44  // msanGoSignalThreadSet is used to record that msanGoSignalThread
    45  // has been initialized. This is accessed atomically.
    46  static int32_t msanGoSignalThreadSet;
    47  
    48  // uninit is explicitly poisoned, so that we can make all registers
    49  // undefined by calling msanGoWait.
    50  static unsigned long uninit;
    51  
    52  // msanGoLoop loops calling msanGoWait, with the arguments passed
    53  // such that msan thinks that they are undefined. msan permits
    54  // undefined values to be used as long as they are not used to
    55  // for conditionals or for memory access.
    56  void msanGoLoop() {
    57  	int i;
    58  
    59  	msanGoSignalThread = pthread_self();
    60          __atomic_store_n(&msanGoSignalThreadSet, 1, __ATOMIC_SEQ_CST);
    61  
    62  	// Force uninit to be undefined for msan.
    63  	__msan_poison(&uninit, sizeof uninit);
    64  	for (i = 0; i < 100; i++) {
    65  		msanGoWait(uninit, uninit, uninit, uninit, uninit, uninit);
    66          }
    67  }
    68  
    69  // msanGoReady returns whether msanGoSignalThread is set.
    70  int msanGoReady() {
    71  	return __atomic_load_n(&msanGoSignalThreadSet, __ATOMIC_SEQ_CST) != 0;
    72  }
    73  
    74  // msanGoSendSignal sends a signal to the msanGoLoop thread.
    75  void msanGoSendSignal() {
    76  	pthread_kill(msanGoSignalThread, SIGWINCH);
    77  }
    78  */
    79  import "C"
    80  
    81  import (
    82  	"runtime"
    83  	"time"
    84  )
    85  
    86  func main() {
    87  	runtime.SetCgoTraceback(0, C.msanGoTraceback, nil, nil)
    88  
    89  	c := make(chan bool)
    90  	go func() {
    91  		defer func() { c <- true }()
    92  		C.msanGoLoop()
    93  	}()
    94  
    95  	for C.msanGoReady() == 0 {
    96  		time.Sleep(time.Microsecond)
    97  	}
    98  
    99  loop:
   100  	for {
   101  		select {
   102  		case <-c:
   103  			break loop
   104  		default:
   105  			C.msanGoSendSignal()
   106  			time.Sleep(time.Microsecond)
   107  		}
   108  	}
   109  }
   110  

View as plain text