github.com/rakyll/go@v0.0.0-20170216000551-64c02460d703/misc/cgo/testsanitizers/test.bash (about)

     1  #!/usr/bin/env bash
     2  # Copyright 2015 The Go Authors. All rights reserved.
     3  # Use of this source code is governed by a BSD-style
     4  # license that can be found in the LICENSE file.
     5  
     6  # This directory is intended to test the use of Go with sanitizers
     7  # like msan, asan, etc.  See https://github.com/google/sanitizers .
     8  
     9  set -e
    10  
    11  # The sanitizers were originally developed with clang, so prefer it.
    12  CC=cc
    13  if test -x "$(type -p clang)"; then
    14    CC=clang
    15  fi
    16  export CC
    17  
    18  if [ "$(sysctl -n vm.overcommit_memory)" = 2 ]; then
    19    echo "skipping msan/tsan tests: vm.overcommit_memory=2" >&2
    20    exit 0
    21  fi
    22  
    23  msan=yes
    24  
    25  TMPDIR=${TMPDIR:-/tmp}
    26  echo 'int main() { return 0; }' > ${TMPDIR}/testsanitizers$$.c
    27  if $CC -fsanitize=memory -o ${TMPDIR}/testsanitizers$$ ${TMPDIR}/testsanitizers$$.c 2>&1 | grep "unrecognized" >& /dev/null; then
    28    echo "skipping msan tests: $CC -fsanitize=memory not supported"
    29    msan=no
    30  elif ! test -x ${TMPDIR}/testsanitizers$$; then
    31    echo "skipping msan tests: $CC -fsanitize-memory did not generate an executable"
    32    msan=no
    33  elif ! ${TMPDIR}/testsanitizers$$ >/dev/null 2>&1; then
    34    echo "skipping msan tests: $CC -fsanitize-memory generates broken executable"
    35    msan=no
    36  fi
    37  rm -f ${TMPDIR}/testsanitizers$$.*
    38  
    39  tsan=yes
    40  
    41  # The memory and thread sanitizers in versions of clang before 3.6
    42  # don't work with Go.
    43  if test "$msan" = "yes" && $CC --version | grep clang >& /dev/null; then
    44    ver=$($CC --version | sed -e 's/.* version \([0-9.-]*\).*/\1/')
    45    major=$(echo $ver | sed -e 's/\([0-9]*\).*/\1/')
    46    minor=$(echo $ver | sed -e 's/[0-9]*\.\([0-9]*\).*/\1/')
    47    if test "$major" -lt 3 || test "$major" -eq 3 -a "$minor" -lt 6; then
    48      echo "skipping msan/tsan tests: clang version $major.$minor (older than 3.6)"
    49      msan=no
    50      tsan=no
    51    fi
    52  
    53    # Clang before 3.8 does not work with Linux at or after 4.1.
    54    # golang.org/issue/12898.
    55    if test "$msan" = "yes" -a "$major" -lt 3 || test "$major" -eq 3 -a "$minor" -lt 8; then
    56      if test "$(uname)" = Linux; then
    57        linuxver=$(uname -r)
    58        linuxmajor=$(echo $linuxver | sed -e 's/\([0-9]*\).*/\1/')
    59        linuxminor=$(echo $linuxver | sed -e 's/[0-9]*\.\([0-9]*\).*/\1/')
    60        if test "$linuxmajor" -gt 4 || test "$linuxmajor" -eq 4 -a "$linuxminor" -ge 1; then
    61          echo "skipping msan/tsan tests: clang version $major.$minor (older than 3.8) incompatible with linux version $linuxmajor.$linuxminor (4.1 or newer)"
    62  	msan=no
    63  	tsan=no
    64        fi
    65      fi
    66    fi
    67  fi
    68  
    69  status=0
    70  
    71  testmsanshared() {
    72    goos=$(go env GOOS)
    73    suffix="-installsuffix testsanitizers"
    74    libext="so"
    75    if [ "$goos" == "darwin" ]; then
    76  	  libext="dylib"
    77    fi
    78    go build -msan -buildmode=c-shared $suffix -o ${TMPDIR}/libmsanshared.$libext msan_shared.go
    79  
    80  	echo 'int main() { return 0; }' > ${TMPDIR}/testmsanshared.c
    81    $CC $(go env GOGCCFLAGS) -fsanitize=memory -o ${TMPDIR}/testmsanshared ${TMPDIR}/testmsanshared.c ${TMPDIR}/libmsanshared.$libext
    82  
    83    if ! LD_LIBRARY_PATH=. ${TMPDIR}/testmsanshared; then
    84      echo "FAIL: msan_shared"
    85      status=1
    86    fi
    87    rm -f ${TMPDIR}/{testmsanshared,testmsanshared.c,libmsanshared.$libext}
    88  }
    89  
    90  if test "$msan" = "yes"; then
    91      if ! go build -msan std; then
    92  	echo "FAIL: build -msan std"
    93  	status=1
    94      fi
    95  
    96      if ! go run -msan msan.go; then
    97  	echo "FAIL: msan"
    98  	status=1
    99      fi
   100  
   101      if ! CGO_LDFLAGS="-fsanitize=memory" CGO_CPPFLAGS="-fsanitize=memory" go run -msan -a msan2.go; then
   102  	echo "FAIL: msan2 with -fsanitize=memory"
   103  	status=1
   104      fi
   105  
   106      if ! go run -msan -a msan2.go; then
   107  	echo "FAIL: msan2"
   108  	status=1
   109      fi
   110  
   111      if ! go run -msan msan3.go; then
   112  	echo "FAIL: msan3"
   113  	status=1
   114      fi
   115  
   116      if ! go run -msan msan4.go; then
   117  	echo "FAIL: msan4"
   118  	status=1
   119      fi
   120  
   121      if ! go run -msan msan5.go; then
   122  	echo "FAIL: msan5"
   123  	status=1
   124      fi
   125  
   126      if go run -msan msan_fail.go 2>/dev/null; then
   127  	echo "FAIL: msan_fail"
   128  	status=1
   129      fi
   130  
   131      testmsanshared
   132  fi
   133  
   134  if test "$tsan" = "yes"; then
   135      echo 'int main() { return 0; }' > ${TMPDIR}/testsanitizers$$.c
   136      ok=yes
   137      if ! $CC -fsanitize=thread ${TMPDIR}/testsanitizers$$.c -o ${TMPDIR}/testsanitizers$$ &> ${TMPDIR}/testsanitizers$$.err; then
   138  	ok=no
   139      fi
   140       if grep "unrecognized" ${TMPDIR}/testsanitizers$$.err >& /dev/null; then
   141  	echo "skipping tsan tests: -fsanitize=thread not supported"
   142  	tsan=no
   143       elif test "$ok" != "yes"; then
   144  	 cat ${TMPDIR}/testsanitizers$$.err
   145  	 echo "skipping tsan tests: -fsanitizer=thread build failed"
   146  	 tsan=no
   147       fi
   148       rm -f ${TMPDIR}/testsanitizers$$*
   149  fi
   150  
   151  # Run a TSAN test.
   152  # $1 test name
   153  # $2 environment variables
   154  # $3 go run args
   155  testtsan() {
   156      err=${TMPDIR}/tsanerr$$.out
   157      if ! env $2 go run $3 $1 2>$err; then
   158  	cat $err
   159  	echo "FAIL: $1"
   160  	status=1
   161      elif grep -i warning $err >/dev/null 2>&1; then
   162  	cat $err
   163  	echo "FAIL: $1"
   164  	status=1
   165      fi
   166      rm -f $err
   167  }
   168  
   169  if test "$tsan" = "yes"; then
   170      testtsan tsan.go
   171      testtsan tsan2.go
   172      testtsan tsan3.go
   173      testtsan tsan4.go
   174      testtsan tsan8.go
   175      testtsan tsan9.go
   176  
   177      # These tests are only reliable using clang or GCC version 7 or later.
   178      # Otherwise runtime/cgo/libcgo.h can't tell whether TSAN is in use.
   179      ok=false
   180      if ${CC} --version | grep clang >/dev/null 2>&1; then
   181  	ok=true
   182      else
   183  	ver=$($CC -dumpversion)
   184  	major=$(echo $ver | sed -e 's/\([0-9]*\).*/\1/')
   185  	if test "$major" -lt 7; then
   186  	    echo "skipping remaining TSAN tests: GCC version $major (older than 7)"
   187  	else
   188  	    ok=true
   189  	fi
   190      fi
   191  
   192      if test "$ok" = "true"; then
   193  	# This test requires rebuilding os/user with -fsanitize=thread.
   194  	testtsan tsan5.go "CGO_CFLAGS=-fsanitize=thread CGO_LDFLAGS=-fsanitize=thread" "-installsuffix=tsan"
   195  
   196  	# This test requires rebuilding runtime/cgo with -fsanitize=thread.
   197  	testtsan tsan6.go "CGO_CFLAGS=-fsanitize=thread CGO_LDFLAGS=-fsanitize=thread" "-installsuffix=tsan"
   198  
   199  	# This test requires rebuilding runtime/cgo with -fsanitize=thread.
   200  	testtsan tsan7.go "CGO_CFLAGS=-fsanitize=thread CGO_LDFLAGS=-fsanitize=thread" "-installsuffix=tsan"
   201      fi
   202  fi
   203  
   204  exit $status