1
0
mirror of https://github.com/golang/go synced 2024-11-14 23:00:29 -07:00

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 <khr@golang.org>
Reviewed-by: Keith Randall <khr@google.com>
Reviewed-by: Cherry Mui <cherryyz@google.com>
Auto-Submit: Ian Lance Taylor <iant@golang.org>
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
This commit is contained in:
Ian Lance Taylor 2024-10-24 21:50:29 -07:00 committed by Gopher Robot
parent 46b576be72
commit 6dc99aa7eb
3 changed files with 92 additions and 46 deletions

View File

@ -7,6 +7,7 @@
package sanitizers_test
import (
"bytes"
"fmt"
"internal/platform"
"internal/testenv"
@ -15,34 +16,9 @@ import (
)
func TestASAN(t *testing.T) {
testenv.MustHaveGoBuild(t)
testenv.MustHaveCGO(t)
goos, err := goEnv("GOOS")
if err != nil {
t.Fatal(err)
}
goarch, err := goEnv("GOARCH")
if err != nil {
t.Fatal(err)
}
// The asan tests require support for the -asan option.
if !platform.ASanSupported(goos, goarch) {
t.Skipf("skipping on %s/%s; -asan option is not supported.", goos, goarch)
}
// The current implementation is only compatible with the ASan library from version
// v7 to v9 (See the description in src/runtime/asan/asan.go). Therefore, using the
// -asan option must use a compatible version of ASan library, which requires that
// the gcc version is not less than 7 and the clang version is not less than 9,
// otherwise a segmentation fault will occur.
if !compilerRequiredAsanVersion(goos, goarch) {
t.Skipf("skipping on %s/%s: too old version of compiler", goos, goarch)
}
config := mustHaveASAN(t)
t.Parallel()
requireOvercommit(t)
config := configure("address")
config.skipIfCSanitizerBroken(t)
mustRun(t, config.goCmd("build", "std"))
cases := []struct {
@ -106,29 +82,10 @@ func TestASAN(t *testing.T) {
}
func TestASANLinkerX(t *testing.T) {
testenv.MustHaveGoBuild(t)
testenv.MustHaveCGO(t)
// Test ASAN with linker's -X flag (see issue 56175).
goos, err := goEnv("GOOS")
if err != nil {
t.Fatal(err)
}
goarch, err := goEnv("GOARCH")
if err != nil {
t.Fatal(err)
}
// The asan tests require support for the -asan option.
if !platform.ASanSupported(goos, goarch) {
t.Skipf("skipping on %s/%s; -asan option is not supported.", goos, goarch)
}
if !compilerRequiredAsanVersion(goos, goarch) {
t.Skipf("skipping on %s/%s: too old version of compiler", goos, goarch)
}
config := mustHaveASAN(t)
t.Parallel()
requireOvercommit(t)
config := configure("address")
config.skipIfCSanitizerBroken(t)
dir := newTempDir(t)
defer dir.RemoveAll(t)
@ -147,3 +104,56 @@ func TestASANLinkerX(t *testing.T) {
// run the binary
mustRun(t, hangProneCmd(outPath))
}
// Issue 66966.
func TestASANFuzz(t *testing.T) {
config := mustHaveASAN(t)
t.Parallel()
dir := newTempDir(t)
defer dir.RemoveAll(t)
cmd := config.goCmd("test", "-fuzz=Fuzz", srcPath("asan_fuzz_test.go"))
t.Logf("%v", cmd)
out, err := cmd.CombinedOutput()
t.Logf("%s", out)
if err == nil {
t.Error("expected fuzzing failure")
}
if bytes.Contains(out, []byte("AddressSanitizer")) {
t.Error(`output contains "AddressSanitizer", but should not`)
}
}
func mustHaveASAN(t *testing.T) *config {
testenv.MustHaveGoBuild(t)
testenv.MustHaveCGO(t)
goos, err := goEnv("GOOS")
if err != nil {
t.Fatal(err)
}
goarch, err := goEnv("GOARCH")
if err != nil {
t.Fatal(err)
}
if !platform.ASanSupported(goos, goarch) {
t.Skipf("skipping on %s/%s; -asan option is not supported.", goos, goarch)
}
// The current implementation is only compatible with the ASan library from version
// v7 to v9 (See the description in src/runtime/asan/asan.go). Therefore, using the
// -asan option must use a compatible version of ASan library, which requires that
// the gcc version is not less than 7 and the clang version is not less than 9,
// otherwise a segmentation fault will occur.
if !compilerRequiredAsanVersion(goos, goarch) {
t.Skipf("skipping on %s/%s: too old version of compiler", goos, goarch)
}
requireOvercommit(t)
config := configure("address")
config.skipIfCSanitizerBroken(t)
return config
}

View File

@ -0,0 +1,30 @@
package main
import (
"slices"
"testing"
)
func Reverse(s string) string {
runes := []rune(s)
slices.Reverse(runes)
return string(runes)
}
// This fuzz test should quickly fail, because Reverse doesn't
// work for strings that are not valid UTF-8.
// What we are testing for is whether we see a failure from ASAN;
// we should see a fuzzing failure, not an ASAN failure.
func FuzzReverse(f *testing.F) {
f.Add("Go")
f.Add("Gopher")
f.Add("Hello, 世界")
f.Fuzz(func(t *testing.T, s string) {
r1 := Reverse(s)
r2 := Reverse(r1)
if s != r2 {
t.Errorf("got %q want %q", r2, s)
}
})
}

View File

@ -2981,6 +2981,12 @@ func (ctxt *Link) address() []*sym.Segment {
ctxt.xdefine("runtime.end", sym.SBSS, int64(Segdata.Vaddr+Segdata.Length))
if fuzzCounters != nil {
if *flagAsan {
// ASAN requires that the symbol marking the end
// of the section be aligned on an 8 byte boundary.
// See issue #66966.
fuzzCounters.Length = uint64(Rnd(int64(fuzzCounters.Length), 8))
}
ctxt.xdefine("runtime.__start___sancov_cntrs", sym.SLIBFUZZER_8BIT_COUNTER, int64(fuzzCounters.Vaddr))
ctxt.xdefine("runtime.__stop___sancov_cntrs", sym.SLIBFUZZER_8BIT_COUNTER, int64(fuzzCounters.Vaddr+fuzzCounters.Length))
ctxt.xdefine("internal/fuzz._counters", sym.SLIBFUZZER_8BIT_COUNTER, int64(fuzzCounters.Vaddr))