1
2
3
4
5
6
7 package sanitizers_test
8
9 import (
10 "fmt"
11 "internal/platform"
12 "internal/testenv"
13 "strings"
14 "testing"
15 )
16
17 func TestASAN(t *testing.T) {
18 testenv.MustHaveGoBuild(t)
19 testenv.MustHaveCGO(t)
20 goos, err := goEnv("GOOS")
21 if err != nil {
22 t.Fatal(err)
23 }
24 goarch, err := goEnv("GOARCH")
25 if err != nil {
26 t.Fatal(err)
27 }
28
29 if !platform.ASanSupported(goos, goarch) {
30 t.Skipf("skipping on %s/%s; -asan option is not supported.", goos, goarch)
31 }
32
33
34
35
36
37 if !compilerRequiredAsanVersion(goos, goarch) {
38 t.Skipf("skipping on %s/%s: too old version of compiler", goos, goarch)
39 }
40
41 t.Parallel()
42 requireOvercommit(t)
43 config := configure("address")
44 config.skipIfCSanitizerBroken(t)
45
46 mustRun(t, config.goCmd("build", "std"))
47
48 cases := []struct {
49 src string
50 memoryAccessError string
51 errorLocation string
52 experiments []string
53 }{
54 {src: "asan1_fail.go", memoryAccessError: "heap-use-after-free", errorLocation: "asan1_fail.go:25"},
55 {src: "asan2_fail.go", memoryAccessError: "heap-buffer-overflow", errorLocation: "asan2_fail.go:31"},
56 {src: "asan3_fail.go", memoryAccessError: "use-after-poison", errorLocation: "asan3_fail.go:13"},
57 {src: "asan4_fail.go", memoryAccessError: "use-after-poison", errorLocation: "asan4_fail.go:13"},
58 {src: "asan5_fail.go", memoryAccessError: "use-after-poison", errorLocation: "asan5_fail.go:18"},
59 {src: "asan_useAfterReturn.go"},
60 {src: "asan_unsafe_fail1.go", memoryAccessError: "use-after-poison", errorLocation: "asan_unsafe_fail1.go:25"},
61 {src: "asan_unsafe_fail2.go", memoryAccessError: "use-after-poison", errorLocation: "asan_unsafe_fail2.go:25"},
62 {src: "asan_unsafe_fail3.go", memoryAccessError: "use-after-poison", errorLocation: "asan_unsafe_fail3.go:18"},
63 {src: "asan_global1_fail.go", memoryAccessError: "global-buffer-overflow", errorLocation: "asan_global1_fail.go:12"},
64 {src: "asan_global2_fail.go", memoryAccessError: "global-buffer-overflow", errorLocation: "asan_global2_fail.go:19"},
65 {src: "asan_global3_fail.go", memoryAccessError: "global-buffer-overflow", errorLocation: "asan_global3_fail.go:13"},
66 {src: "asan_global4_fail.go", memoryAccessError: "global-buffer-overflow", errorLocation: "asan_global4_fail.go:21"},
67 {src: "asan_global5.go"},
68 {src: "arena_fail.go", memoryAccessError: "use-after-poison", errorLocation: "arena_fail.go:26", experiments: []string{"arenas"}},
69 }
70 for _, tc := range cases {
71 tc := tc
72 name := strings.TrimSuffix(tc.src, ".go")
73 t.Run(name, func(t *testing.T) {
74 t.Parallel()
75
76 dir := newTempDir(t)
77 defer dir.RemoveAll(t)
78
79 outPath := dir.Join(name)
80 mustRun(t, config.goCmdWithExperiments("build", []string{"-o", outPath, srcPath(tc.src)}, tc.experiments))
81
82 cmd := hangProneCmd(outPath)
83 if tc.memoryAccessError != "" {
84 outb, err := cmd.CombinedOutput()
85 out := string(outb)
86 if err != nil && strings.Contains(out, tc.memoryAccessError) {
87
88
89
90 const noSymbolizer = "external symbolizer"
91
92 if tc.errorLocation != "" &&
93 !strings.Contains(out, tc.errorLocation) &&
94 !strings.Contains(out, noSymbolizer) &&
95 compilerSupportsLocation() {
96
97 t.Errorf("%#q exited without expected location of the error\n%s; got failure\n%s", strings.Join(cmd.Args, " "), tc.errorLocation, out)
98 }
99 return
100 }
101 t.Fatalf("%#q exited without expected memory access error\n%s; got failure\n%s", strings.Join(cmd.Args, " "), tc.memoryAccessError, out)
102 }
103 mustRun(t, cmd)
104 })
105 }
106 }
107
108 func TestASANLinkerX(t *testing.T) {
109 testenv.MustHaveGoBuild(t)
110 testenv.MustHaveCGO(t)
111
112 goos, err := goEnv("GOOS")
113 if err != nil {
114 t.Fatal(err)
115 }
116 goarch, err := goEnv("GOARCH")
117 if err != nil {
118 t.Fatal(err)
119 }
120
121 if !platform.ASanSupported(goos, goarch) {
122 t.Skipf("skipping on %s/%s; -asan option is not supported.", goos, goarch)
123 }
124 if !compilerRequiredAsanVersion(goos, goarch) {
125 t.Skipf("skipping on %s/%s: too old version of compiler", goos, goarch)
126 }
127
128 t.Parallel()
129 requireOvercommit(t)
130 config := configure("address")
131 config.skipIfCSanitizerBroken(t)
132
133 dir := newTempDir(t)
134 defer dir.RemoveAll(t)
135
136 var ldflags string
137 for i := 1; i <= 10; i++ {
138 ldflags += fmt.Sprintf("-X=main.S%d=%d -X=cmd/cgo/internal/testsanitizers/testdata/asan_linkerx/p.S%d=%d ", i, i, i, i)
139 }
140
141
142 outPath := dir.Join("main.exe")
143 cmd := config.goCmd("build", "-ldflags="+ldflags, "-o", outPath)
144 cmd.Dir = srcPath("asan_linkerx")
145 mustRun(t, cmd)
146
147
148 mustRun(t, hangProneCmd(outPath))
149 }
150
View as plain text