Source file src/cmd/cgo/internal/testsanitizers/cshared_test.go

     1  // Copyright 2017 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  //go:build linux || (freebsd && amd64)
     6  
     7  package sanitizers_test
     8  
     9  import (
    10  	"fmt"
    11  	"internal/platform"
    12  	"internal/testenv"
    13  	"os"
    14  	"os/exec"
    15  	"strings"
    16  	"testing"
    17  )
    18  
    19  func TestShared(t *testing.T) {
    20  	testenv.MustHaveGoBuild(t)
    21  	testenv.MustHaveCGO(t)
    22  	testenv.MustHaveBuildMode(t, "c-shared")
    23  
    24  	t.Parallel()
    25  	requireOvercommit(t)
    26  
    27  	GOOS, err := goEnv("GOOS")
    28  	if err != nil {
    29  		t.Fatal(err)
    30  	}
    31  
    32  	GOARCH, err := goEnv("GOARCH")
    33  	if err != nil {
    34  		t.Fatal(err)
    35  	}
    36  
    37  	libExt := "so"
    38  	if GOOS == "darwin" {
    39  		libExt = "dylib"
    40  	}
    41  
    42  	cases := []struct {
    43  		src       string
    44  		sanitizer string
    45  	}{
    46  		{
    47  			src:       "msan_shared.go",
    48  			sanitizer: "memory",
    49  		},
    50  		{
    51  			src:       "tsan_shared.go",
    52  			sanitizer: "thread",
    53  		},
    54  	}
    55  
    56  	for _, tc := range cases {
    57  		name := strings.TrimSuffix(tc.src, ".go")
    58  		//The memory sanitizer tests require support for the -msan option.
    59  		if tc.sanitizer == "memory" && !platform.MSanSupported(GOOS, GOARCH) {
    60  			t.Logf("skipping %s test on %s/%s; -msan option is not supported.", name, GOOS, GOARCH)
    61  			continue
    62  		}
    63  		if tc.sanitizer == "thread" && !compilerRequiredTsanVersion(GOOS, GOARCH) {
    64  			t.Logf("skipping %s test on %s/%s; compiler version too old for -tsan.", name, GOOS, GOARCH)
    65  			continue
    66  		}
    67  
    68  		t.Run(name, func(t *testing.T) {
    69  			t.Parallel()
    70  			config := configure(tc.sanitizer)
    71  			config.skipIfCSanitizerBroken(t)
    72  
    73  			dir := newTempDir(t)
    74  			defer dir.RemoveAll(t)
    75  
    76  			lib := dir.Join(fmt.Sprintf("lib%s.%s", name, libExt))
    77  			mustRun(t, config.goCmd("build", "-buildmode=c-shared", "-o", lib, srcPath(tc.src)))
    78  
    79  			cSrc := dir.Join("main.c")
    80  			if err := os.WriteFile(cSrc, cMain, 0600); err != nil {
    81  				t.Fatalf("failed to write C source file: %v", err)
    82  			}
    83  
    84  			dstBin := dir.Join(name)
    85  			cmd, err := cc(config.cFlags...)
    86  			if err != nil {
    87  				t.Fatal(err)
    88  			}
    89  			cmd.Args = append(cmd.Args, config.ldFlags...)
    90  			cmd.Args = append(cmd.Args, "-o", dstBin, cSrc, lib)
    91  			mustRun(t, cmd)
    92  
    93  			cmdArgs := []string{dstBin}
    94  			if tc.sanitizer == "thread" && GOOS == "linux" {
    95  				// Disable ASLR for TSAN. See https://go.dev/issue/59418.
    96  				out, err := exec.Command("uname", "-m").Output()
    97  				if err != nil {
    98  					t.Fatalf("failed to run `uname -m`: %v", err)
    99  				}
   100  				arch := strings.TrimSpace(string(out))
   101  				if _, err := exec.Command("setarch", arch, "-R", "true").Output(); err != nil {
   102  					// Some systems don't have permission to run `setarch`.
   103  					// See https://go.dev/issue/70463.
   104  					t.Logf("failed to run `setarch %s -R true`: %v", arch, err)
   105  				} else {
   106  					cmdArgs = []string{"setarch", arch, "-R", dstBin}
   107  				}
   108  			}
   109  			cmd = hangProneCmd(cmdArgs[0], cmdArgs[1:]...)
   110  			replaceEnv(cmd, "LD_LIBRARY_PATH", ".")
   111  			mustRun(t, cmd)
   112  		})
   113  	}
   114  }
   115  

View as plain text