Skip to content

Commit 6dc99aa

Browse files
ianlancetaylorgopherbot
authored andcommitted
cmd/link: for asan align coverage counter section to 8 bytes
Fixes #66966 Change-Id: I92777a7d7d8afaa82ffcd605aa3e607289b645f1 Reviewed-on: https://go-review.googlesource.com/c/go/+/622477 Reviewed-by: Keith Randall <[email protected]> Reviewed-by: Keith Randall <[email protected]> Reviewed-by: Cherry Mui <[email protected]> Auto-Submit: Ian Lance Taylor <[email protected]> LUCI-TryBot-Result: Go LUCI <[email protected]>
1 parent 46b576b commit 6dc99aa

File tree

3 files changed

+91
-45
lines changed

3 files changed

+91
-45
lines changed

src/cmd/cgo/internal/testsanitizers/asan_test.go

+55-45
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
package sanitizers_test
88

99
import (
10+
"bytes"
1011
"fmt"
1112
"internal/platform"
1213
"internal/testenv"
@@ -15,34 +16,9 @@ import (
1516
)
1617

1718
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-
// The asan tests require support for the -asan option.
29-
if !platform.ASanSupported(goos, goarch) {
30-
t.Skipf("skipping on %s/%s; -asan option is not supported.", goos, goarch)
31-
}
32-
// The current implementation is only compatible with the ASan library from version
33-
// v7 to v9 (See the description in src/runtime/asan/asan.go). Therefore, using the
34-
// -asan option must use a compatible version of ASan library, which requires that
35-
// the gcc version is not less than 7 and the clang version is not less than 9,
36-
// otherwise a segmentation fault will occur.
37-
if !compilerRequiredAsanVersion(goos, goarch) {
38-
t.Skipf("skipping on %s/%s: too old version of compiler", goos, goarch)
39-
}
19+
config := mustHaveASAN(t)
4020

4121
t.Parallel()
42-
requireOvercommit(t)
43-
config := configure("address")
44-
config.skipIfCSanitizerBroken(t)
45-
4622
mustRun(t, config.goCmd("build", "std"))
4723

4824
cases := []struct {
@@ -106,9 +82,53 @@ func TestASAN(t *testing.T) {
10682
}
10783

10884
func TestASANLinkerX(t *testing.T) {
85+
// Test ASAN with linker's -X flag (see issue 56175).
86+
config := mustHaveASAN(t)
87+
88+
t.Parallel()
89+
90+
dir := newTempDir(t)
91+
defer dir.RemoveAll(t)
92+
93+
var ldflags string
94+
for i := 1; i <= 10; i++ {
95+
ldflags += fmt.Sprintf("-X=main.S%d=%d -X=cmd/cgo/internal/testsanitizers/testdata/asan_linkerx/p.S%d=%d ", i, i, i, i)
96+
}
97+
98+
// build the binary
99+
outPath := dir.Join("main.exe")
100+
cmd := config.goCmd("build", "-ldflags="+ldflags, "-o", outPath)
101+
cmd.Dir = srcPath("asan_linkerx")
102+
mustRun(t, cmd)
103+
104+
// run the binary
105+
mustRun(t, hangProneCmd(outPath))
106+
}
107+
108+
// Issue 66966.
109+
func TestASANFuzz(t *testing.T) {
110+
config := mustHaveASAN(t)
111+
112+
t.Parallel()
113+
114+
dir := newTempDir(t)
115+
defer dir.RemoveAll(t)
116+
117+
cmd := config.goCmd("test", "-fuzz=Fuzz", srcPath("asan_fuzz_test.go"))
118+
t.Logf("%v", cmd)
119+
out, err := cmd.CombinedOutput()
120+
t.Logf("%s", out)
121+
if err == nil {
122+
t.Error("expected fuzzing failure")
123+
}
124+
if bytes.Contains(out, []byte("AddressSanitizer")) {
125+
t.Error(`output contains "AddressSanitizer", but should not`)
126+
}
127+
}
128+
129+
func mustHaveASAN(t *testing.T) *config {
109130
testenv.MustHaveGoBuild(t)
110131
testenv.MustHaveCGO(t)
111-
// Test ASAN with linker's -X flag (see issue 56175).
112132
goos, err := goEnv("GOOS")
113133
if err != nil {
114134
t.Fatal(err)
@@ -117,33 +137,23 @@ func TestASANLinkerX(t *testing.T) {
117137
if err != nil {
118138
t.Fatal(err)
119139
}
120-
// The asan tests require support for the -asan option.
121140
if !platform.ASanSupported(goos, goarch) {
122141
t.Skipf("skipping on %s/%s; -asan option is not supported.", goos, goarch)
123142
}
143+
144+
// The current implementation is only compatible with the ASan library from version
145+
// v7 to v9 (See the description in src/runtime/asan/asan.go). Therefore, using the
146+
// -asan option must use a compatible version of ASan library, which requires that
147+
// the gcc version is not less than 7 and the clang version is not less than 9,
148+
// otherwise a segmentation fault will occur.
124149
if !compilerRequiredAsanVersion(goos, goarch) {
125150
t.Skipf("skipping on %s/%s: too old version of compiler", goos, goarch)
126151
}
127152

128-
t.Parallel()
129153
requireOvercommit(t)
154+
130155
config := configure("address")
131156
config.skipIfCSanitizerBroken(t)
132157

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-
// build the binary
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-
// run the binary
148-
mustRun(t, hangProneCmd(outPath))
158+
return config
149159
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
package main
2+
3+
import (
4+
"slices"
5+
"testing"
6+
)
7+
8+
func Reverse(s string) string {
9+
runes := []rune(s)
10+
slices.Reverse(runes)
11+
return string(runes)
12+
}
13+
14+
// This fuzz test should quickly fail, because Reverse doesn't
15+
// work for strings that are not valid UTF-8.
16+
// What we are testing for is whether we see a failure from ASAN;
17+
// we should see a fuzzing failure, not an ASAN failure.
18+
19+
func FuzzReverse(f *testing.F) {
20+
f.Add("Go")
21+
f.Add("Gopher")
22+
f.Add("Hello, 世界")
23+
f.Fuzz(func(t *testing.T, s string) {
24+
r1 := Reverse(s)
25+
r2 := Reverse(r1)
26+
if s != r2 {
27+
t.Errorf("got %q want %q", r2, s)
28+
}
29+
})
30+
}

src/cmd/link/internal/ld/data.go

+6
Original file line numberDiff line numberDiff line change
@@ -2981,6 +2981,12 @@ func (ctxt *Link) address() []*sym.Segment {
29812981
ctxt.xdefine("runtime.end", sym.SBSS, int64(Segdata.Vaddr+Segdata.Length))
29822982

29832983
if fuzzCounters != nil {
2984+
if *flagAsan {
2985+
// ASAN requires that the symbol marking the end
2986+
// of the section be aligned on an 8 byte boundary.
2987+
// See issue #66966.
2988+
fuzzCounters.Length = uint64(Rnd(int64(fuzzCounters.Length), 8))
2989+
}
29842990
ctxt.xdefine("runtime.__start___sancov_cntrs", sym.SLIBFUZZER_8BIT_COUNTER, int64(fuzzCounters.Vaddr))
29852991
ctxt.xdefine("runtime.__stop___sancov_cntrs", sym.SLIBFUZZER_8BIT_COUNTER, int64(fuzzCounters.Vaddr+fuzzCounters.Length))
29862992
ctxt.xdefine("internal/fuzz._counters", sym.SLIBFUZZER_8BIT_COUNTER, int64(fuzzCounters.Vaddr))

0 commit comments

Comments
 (0)