1
2
3
4
5
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 tc := tc
58 name := strings.TrimSuffix(tc.src, ".go")
59
60 if tc.sanitizer == "memory" && !platform.MSanSupported(GOOS, GOARCH) {
61 t.Logf("skipping %s test on %s/%s; -msan option is not supported.", name, GOOS, GOARCH)
62 continue
63 }
64 if tc.sanitizer == "thread" && !compilerRequiredTsanVersion(GOOS, GOARCH) {
65 t.Logf("skipping %s test on %s/%s; compiler version too old for -tsan.", name, GOOS, GOARCH)
66 continue
67 }
68
69 t.Run(name, func(t *testing.T) {
70 t.Parallel()
71 config := configure(tc.sanitizer)
72 config.skipIfCSanitizerBroken(t)
73
74 dir := newTempDir(t)
75 defer dir.RemoveAll(t)
76
77 lib := dir.Join(fmt.Sprintf("lib%s.%s", name, libExt))
78 mustRun(t, config.goCmd("build", "-buildmode=c-shared", "-o", lib, srcPath(tc.src)))
79
80 cSrc := dir.Join("main.c")
81 if err := os.WriteFile(cSrc, cMain, 0600); err != nil {
82 t.Fatalf("failed to write C source file: %v", err)
83 }
84
85 dstBin := dir.Join(name)
86 cmd, err := cc(config.cFlags...)
87 if err != nil {
88 t.Fatal(err)
89 }
90 cmd.Args = append(cmd.Args, config.ldFlags...)
91 cmd.Args = append(cmd.Args, "-o", dstBin, cSrc, lib)
92 mustRun(t, cmd)
93
94 cmdArgs := []string{dstBin}
95 if tc.sanitizer == "thread" && GOOS == "linux" {
96
97 arch, err := exec.Command("uname", "-m").Output()
98 if err != nil {
99 t.Fatalf("failed to run `uname -m`: %v", err)
100 }
101 cmdArgs = []string{"setarch", strings.TrimSpace(string(arch)), "-R", dstBin}
102 }
103 cmd = hangProneCmd(cmdArgs[0], cmdArgs[1:]...)
104 replaceEnv(cmd, "LD_LIBRARY_PATH", ".")
105 mustRun(t, cmd)
106 })
107 }
108 }
109
View as plain text