]> Cypherpunks repositories - gostls13.git/commitdiff
cmd/go: consolidate fuzz-support checks
authorBryan C. Mills <bcmills@google.com>
Thu, 28 Oct 2021 19:00:33 +0000 (15:00 -0400)
committerBryan C. Mills <bcmills@google.com>
Thu, 28 Oct 2021 20:43:02 +0000 (20:43 +0000)
We had been repeating conditions for specific platforms and
architectures to gate fuzzing tests, but the more of those tests we
add the more we will have to update if the set of supported platforms
and archictures expands over time.

We also ought to provide a friendlier error message when
'go test -fuzz' is used on non-supported platforms.

This change adds predicates in cmd/internal/sys, which already
contains similar predicates for related functionality (such as the
race detector), and uses those predicates in 'go test' and TestScript.

For #48495

Change-Id: If24c3997aeb4d201258e21e5b6cf4f7c08fbadd7
Reviewed-on: https://go-review.googlesource.com/c/go/+/359481
Trust: Bryan C. Mills <bcmills@google.com>
Trust: Katie Hockman <katie@golang.org>
Run-TryBot: Bryan C. Mills <bcmills@google.com>
TryBot-Result: Go Bot <gobot@golang.org>
Reviewed-by: Katie Hockman <katie@golang.org>
28 files changed:
src/cmd/go/go_test.go
src/cmd/go/internal/test/test.go
src/cmd/go/internal/work/init.go
src/cmd/go/script_test.go
src/cmd/go/testdata/script/README
src/cmd/go/testdata/script/test_fuzz.txt
src/cmd/go/testdata/script/test_fuzz_cache.txt
src/cmd/go/testdata/script/test_fuzz_chatty.txt
src/cmd/go/testdata/script/test_fuzz_cleanup.txt
src/cmd/go/testdata/script/test_fuzz_deadline.txt
src/cmd/go/testdata/script/test_fuzz_fuzztime.txt
src/cmd/go/testdata/script/test_fuzz_io_error.txt
src/cmd/go/testdata/script/test_fuzz_match.txt
src/cmd/go/testdata/script/test_fuzz_minimize.txt
src/cmd/go/testdata/script/test_fuzz_minimize_interesting.txt
src/cmd/go/testdata/script/test_fuzz_multiple.txt
src/cmd/go/testdata/script/test_fuzz_mutate_crash.txt
src/cmd/go/testdata/script/test_fuzz_mutate_fail.txt
src/cmd/go/testdata/script/test_fuzz_mutator.txt
src/cmd/go/testdata/script/test_fuzz_non_crash_signal.txt
src/cmd/go/testdata/script/test_fuzz_parallel.txt
src/cmd/go/testdata/script/test_fuzz_run.txt
src/cmd/go/testdata/script/test_fuzz_seed_corpus.txt
src/cmd/go/testdata/script/test_fuzz_setenv.txt
src/cmd/go/testdata/script/test_fuzz_unsupported.txt [new file with mode: 0644]
src/cmd/internal/sys/supported.go
src/internal/fuzz/counters_unsupported.go
src/internal/fuzz/sys_unimplemented.go

index 339014e94e877e798f60eaded7332d229b5b329e..c13d77a1afb5fb4b193d697a421399ce5a7e7dbd 100644 (file)
@@ -43,10 +43,12 @@ func init() {
 }
 
 var (
-       canRace = false // whether we can run the race detector
-       canCgo  = false // whether we can use cgo
-       canMSan = false // whether we can run the memory sanitizer
-       canASan = false // whether we can run the address sanitizer
+       canRace          = false // whether we can run the race detector
+       canCgo           = false // whether we can use cgo
+       canMSan          = false // whether we can run the memory sanitizer
+       canASan          = false // whether we can run the address sanitizer
+       canFuzz          = false // whether we can search for new fuzz failures
+       fuzzInstrumented = false // whether fuzzing uses instrumentation
 )
 
 var exeSuffix string = func() string {
@@ -206,6 +208,8 @@ func TestMain(m *testing.M) {
                if isAlpineLinux() || runtime.Compiler == "gccgo" {
                        canRace = false
                }
+               canFuzz = sys.FuzzSupported(runtime.GOOS, runtime.GOARCH)
+               fuzzInstrumented = sys.FuzzInstrumented(runtime.GOOS, runtime.GOARCH)
        }
        // Don't let these environment variables confuse the test.
        os.Setenv("GOENV", "off")
index ea1d4ff20e9ff15d7edb5ed8c5c5a32e91cf463a..0806d29f219e6ce1bcd2c04c1cb65c766b383d06 100644 (file)
@@ -31,9 +31,10 @@ import (
        "cmd/go/internal/lockedfile"
        "cmd/go/internal/modload"
        "cmd/go/internal/search"
+       "cmd/go/internal/str"
        "cmd/go/internal/trace"
        "cmd/go/internal/work"
-       "cmd/go/internal/str"
+       "cmd/internal/sys"
        "cmd/internal/test2json"
 )
 
@@ -651,8 +652,13 @@ func runTest(ctx context.Context, cmd *base.Command, args []string) {
        if testO != "" && len(pkgs) != 1 {
                base.Fatalf("cannot use -o flag with multiple packages")
        }
-       if testFuzz != "" && len(pkgs) != 1 {
-               base.Fatalf("cannot use -fuzz flag with multiple packages")
+       if testFuzz != "" {
+               if !sys.FuzzSupported(cfg.Goos, cfg.Goarch) {
+                       base.Fatalf("-fuzz flag is not supported on %s/%s", cfg.Goos, cfg.Goarch)
+               }
+               if len(pkgs) != 1 {
+                       base.Fatalf("cannot use -fuzz flag with multiple packages")
+               }
        }
        if testProfile() != "" && len(pkgs) != 1 {
                base.Fatalf("cannot use %s flag with multiple packages", testProfile())
index b2ee00d53cf687583ce32914921713659a816842..9111150233bad632673391deae8204bee3630272 100644 (file)
@@ -67,20 +67,7 @@ func BuildInit() {
 // instrumentation is added. 'go test -fuzz' still works without coverage,
 // but it generates random inputs without guidance, so it's much less effective.
 func fuzzInstrumentFlags() []string {
-       // TODO: expand the set of supported platforms, with testing. Nothing about
-       // the instrumentation is OS specific, but only amd64 and arm64 are
-       // supported in the runtime. See src/runtime/libfuzzer*.
-       //
-       // Keep in sync with build constraints in
-       // internal/fuzz/counters_{un,}supported.go
-       switch cfg.Goos {
-       case "darwin", "freebsd", "linux", "windows":
-       default:
-               return nil
-       }
-       switch cfg.Goarch {
-       case "amd64", "arm64":
-       default:
+       if !sys.FuzzInstrumented(cfg.Goos, cfg.Goarch) {
                return nil
        }
        return []string{"-d=libfuzzer"}
index acb1f91b440a97d58c67615f73cd6a091e2e721a..98c1b68ed9f1ad2f80876f91160ec0ac93056cfd 100644 (file)
@@ -357,6 +357,10 @@ Script:
                                ok = canASan
                        case "race":
                                ok = canRace
+                       case "fuzz":
+                               ok = canFuzz
+                       case "fuzz-instrumented":
+                               ok = fuzzInstrumented
                        case "net":
                                ok = testenv.HasExternalNetwork()
                        case "link":
index 2b88e880c9369375ec86a9b53ff2358e23da0c92..2b55fa89777d17f7e2927980a5a52a69b01e60c4 100644 (file)
@@ -80,6 +80,8 @@ should only run when the condition is satisfied. The available conditions are:
  - Test environment details:
    - [short] for testing.Short()
    - [cgo], [msan], [asan], [race] for whether cgo, msan, asan, and the race detector can be used
+   - [fuzz] for whether 'go test -fuzz' can be used at all
+   - [fuzz-instrumented] for whether 'go test -fuzz' uses coverage-instrumented binaries
    - [net] for whether the external network can be used
    - [link] for testenv.HasLink()
    - [root] for os.Geteuid() == 0
index 4665202bf0b0069fcb1a42cf7b1bfd43f01610f4..020012d73e530b7add21c283bac72f50682f465e 100644 (file)
@@ -1,5 +1,4 @@
-# TODO(jayconrod): support shared memory on more platforms.
-[!darwin] [!linux] [!windows] skip
+[!fuzz] skip
 
 # Test that running a fuzz target that returns without failing or calling
 # f.Fuzz fails and causes a non-zero exit status.
@@ -495,4 +494,4 @@ go test fuzz v1
 []byte("12345")
 -- corpustesting/testdata/fuzz/FuzzWrongType/1 --
 go test fuzz v1
-int("00000")
\ No newline at end of file
+int("00000")
index fc1c9a17525667992c7ff61bb2e644fd8dd1842e..552966b06bdd706ac7e9fdd9bef1128357a1e30c 100644 (file)
@@ -1,9 +1,4 @@
-# TODO(jayconrod): support shared memory on more platforms.
-[!darwin] [!linux] [!windows] skip
-
-# Instrumentation not supported on other archs.
-# See #14565.
-[!amd64] [!arm64] skip
+[!fuzz-instrumented] skip
 
 [short] skip
 env GOCACHE=$WORK/cache
index 9ebd480c9017f009921f667e7d53fe7f98f04f8c..1abcbbd389427ad20b1cb0218d89e20f7daf116d 100644 (file)
@@ -1,6 +1,4 @@
-# TODO(jayconrod): support shared memory on more platforms.
-[!darwin] [!linux] [!windows] skip
-
+[!fuzz] skip
 [short] skip
 
 # Run chatty fuzz targets with an error.
index 88625916bab97b25a9fe2471fd11942a48ad8ea9..b65022bd74e7a060478918783caa03673fd49bc9 100644 (file)
@@ -1,5 +1,4 @@
-# TODO(jayconrod): support shared memory on more platforms.
-[!darwin] [!linux] [!windows] skip
+[!fuzz] skip
 [short] skip
 
 # Cleanup should run after F.Skip.
index 12f1054f614a50ba6e4f520f6a69a37198bd1dd5..5ba76a3d4fea9af135b17d6284ca579ee6dde186 100644 (file)
@@ -1,6 +1,4 @@
-# TODO(jayconrod): support shared memory on more platforms.
-[!darwin] [!linux] [!windows] skip
-
+[!fuzz] skip
 [short] skip
 
 # The fuzz function should be able to detect whether -timeout
index c3933bc7e266e7c7c822bf2b12e7b3aae129f2fc..56d94a4bcf58e6cab05961c1e2b42853bcbfa993 100644 (file)
@@ -1,6 +1,4 @@
-# TODO(jayconrod): support shared memory on more platforms.
-[!darwin] [!linux] [!windows] skip
-
+[!fuzz] skip
 [short] skip
 
 # There are no seed values, so 'go test' should finish quickly.
index 4c7ab4c152395c50549b3f596509f348a8449845..1a0aa6427e89f69cb09ab99353a5082a63d60d4d 100644 (file)
@@ -6,7 +6,7 @@
 # This is unlikely, but possible. It's difficult to simulate interruptions
 # due to ^C and EOF errors which are more common. We don't report those.
 [short] skip
-[!darwin] [!linux] [!windows] skip
+[!fuzz] skip
 
 # If the I/O error occurs before F.Fuzz is called, the coordinator should
 # stop the worker and say that.
index 3a2ca631add184341578fae2e95db9bfe92e7f02..0c0085f2c23bb33cce6fa8761617859e6a0a7c43 100644 (file)
@@ -1,5 +1,4 @@
-# TODO(jayconrod): support shared memory on more platforms.
-[!darwin] [!linux] [!windows] skip
+[!fuzz] skip
 
 # Matches only fuzz targets to test.
 go test standalone_fuzz_test.go
index 3293e878bb73830901811e48febedac67856d596..462fb9a963e78f193f614240f968197bcb014cb9 100644 (file)
@@ -1,6 +1,4 @@
-# TODO(jayconrod): support shared memory on more platforms.
-[!darwin] [!linux] [!windows] skip
-
+[!fuzz] skip
 [short] skip
 
 # We clean the fuzz cache during this test. Don't clean the user's cache.
index 8ea4cdb8a5a18481ef02270adeede11ed94f8cce..e017a4cad320190356b6b2fa92c439a8a9324f79 100644 (file)
@@ -1,8 +1,4 @@
-# TODO(jayconrod): support shared memory on more platforms.
-[!darwin] [!linux] [!windows] skip
-
-# Instrumentation only supported on 64-bit architectures.
-[!amd64] [!arm64] skip
+[!fuzz-instrumented] skip
 
 # Test that when an interesting value is discovered (one that expands coverage),
 # the fuzzing engine minimizes it before writing it to the cache.
index 6a7732f514936d0a585d45b56d3302f4c483163a..d96b2b6206c946e95b04704e43d723b74a6cd2d2 100644 (file)
@@ -2,9 +2,7 @@
 # enabled, and multiple package or multiple fuzz targets match.
 # TODO(#46312): support fuzzing multiple targets in multiple packages.
 
-# TODO(jayconrod): support shared memory on more platforms.
-[!darwin] [!linux] [!windows] skip
-
+[!fuzz] skip
 [short] skip
 
 # With fuzzing disabled, multiple targets can be tested.
index 628e003f419351313934be8ac478ef4a0b176a5e..4c4fa8e6514107afcbd62a7b83a13e729eb70ce1 100644 (file)
@@ -1,5 +1,4 @@
-# TODO(jayconrod): support shared memory on more platforms.
-[!darwin] [!linux] [!windows] skip
+[!fuzz] skip
 
 # Tests that a crash caused by a mutator-discovered input writes the bad input
 # to testdata, and fails+reports correctly. This tests the end-to-end behavior
index 935c22a05e28d5acbcc1f8fba91067d0384cb3c2..b5eab17349456cdffae387307772d54f933ccc89 100644 (file)
@@ -1,5 +1,4 @@
-# TODO(jayconrod): support shared memory on more platforms.
-[!darwin] [!linux] [!windows] skip
+[!fuzz] skip
 
 # Check that if a worker does not call F.Fuzz or calls F.Fail first,
 # 'go test' exits non-zero and no crasher is recorded.
index 9d0738e169338da1627271395821ea134f609869..76b86488ad8ba5b29082493675344c549e804151 100644 (file)
@@ -1,5 +1,4 @@
-# TODO(jayconrod): support shared memory on more platforms.
-[!darwin] [!linux] [!windows] skip
+[!fuzz] skip
 
 # Test basic fuzzing mutator behavior.
 #
index 1568757de75764e651544ca78718184ad6edc216..f1a4c6669fff21398456d1072b5388fd8ba1cd62 100644 (file)
@@ -1,7 +1,7 @@
 # NOTE: this test is skipped on Windows, since there's no concept of signals.
 # When a process terminates another process, it provides an exit code.
-# TODO(jayconrod): support shared memory on more platforms.
-[!darwin] [!freebsd] [!linux] skip
+[windows] skip
+[!fuzz] skip
 [short] skip
 
 # FuzzNonCrash sends itself a signal that does not appear to be a crash.
index a49f30a27f917b8837f8e808eda561c769e79eed..1795e0b2a5178a5a0f4c5a20fa49b380d827ff78 100644 (file)
@@ -1,6 +1,4 @@
-# TODO(jayconrod): support shared memory on more platforms.
-[!darwin] [!linux] [!windows] skip
-
+[!fuzz] skip
 [short] skip
 
 # When running seed inputs, T.Parallel should let multiple inputs run in
index e546d997cb1f627dcab5da01d54955d1754e62f0..99a4413d32210f7f5fe779cdb1525f02542ae63f 100644 (file)
@@ -1,6 +1,4 @@
-# TODO(jayconrod): support shared memory on more platforms.
-[!darwin] [!linux] [!windows] skip
-
+[!fuzz] skip
 [short] skip
 env GOCACHE=$WORK/cache
 
@@ -142,4 +140,4 @@ go test fuzz v1
 string("fails")
 -- testdata/fuzz/FuzzFoo/thispasses --
 go test fuzz v1
-string("passes")
\ No newline at end of file
+string("passes")
index 18f634a3b64d3b1cd6eb1209191602b427a354c9..4be9a6e3850180efaf219bb2d49ff8107b7af802 100644 (file)
@@ -1,10 +1,4 @@
-# TODO(jayconrod): support shared memory on more platforms.
-[!darwin] [!linux] [!windows] skip
-
-# Instrumentation not supported on other archs.
-# See #14565.
-[!amd64] [!arm64] skip
-
+[!fuzz-instrumented] skip
 [short] skip
 env GOCACHE=$WORK/cache
 
@@ -206,4 +200,4 @@ go test fuzz v1
 int(10)
 -- cache-file-bytes --
 go test fuzz v1
-[]byte("11111111111111111111")
\ No newline at end of file
+[]byte("11111111111111111111")
index 9738697a91e2f237e9f7043a8c7686158bd312f9..2924569de119029083c2a2d5bef7352adc8a9bd1 100644 (file)
@@ -1,5 +1,5 @@
+[!fuzz] skip
 [short] skip
-[!darwin] [!linux] [!windows] skip
 
 go test -fuzz=FuzzA -fuzztime=100x fuzz_setenv_test.go
 
diff --git a/src/cmd/go/testdata/script/test_fuzz_unsupported.txt b/src/cmd/go/testdata/script/test_fuzz_unsupported.txt
new file mode 100644 (file)
index 0000000..1ed0b8a
--- /dev/null
@@ -0,0 +1,18 @@
+[fuzz] skip
+
+! go test -fuzz=. -fuzztime=1x
+! stdout .
+stderr '^-fuzz flag is not supported on '$GOOS'/'$GOARCH'$'
+
+-- go.mod --
+module example
+
+go 1.18
+-- fuzz_test.go --
+package example
+
+import "testing"
+
+func FuzzTrivial(f *testing.F) {
+       f.Fuzz(func(t *testing.T, _ []byte) {})
+}
index 473e3905878144544012db396cbaf6f9aae0b736..18ca50f9278dcbdfed813489b2569e30be3d5b34 100644 (file)
@@ -45,6 +45,29 @@ func ASanSupported(goos, goarch string) bool {
        }
 }
 
+// FuzzSupported reports whether goos/goarch supports fuzzing
+// ('go test -fuzz=.').
+func FuzzSupported(goos, goarch string) bool {
+       switch goos {
+       case "darwin", "linux", "windows":
+               return true
+       default:
+               return false
+       }
+}
+
+// FuzzInstrumented reports whether fuzzing on goos/goarch uses coverage
+// instrumentation. (FuzzInstrumented implies FuzzSupported.)
+func FuzzInstrumented(goos, goarch string) bool {
+       switch goarch {
+       case "amd64", "arm64":
+               // TODO(#14565): support more architectures.
+               return FuzzSupported(goos, goarch)
+       default:
+               return false
+       }
+}
+
 // MustLinkExternal reports whether goos/goarch requires external linking.
 // (This is the opposite of internal/testenv.CanInternalLink. Keep them in sync.)
 func MustLinkExternal(goos, goarch string) bool {
index 9595cb93f7b83bc647eb1522e60ba3ae8df2e5b4..bf281570681fb57542fc5d7dba7b644d964c75e5 100644 (file)
@@ -2,6 +2,12 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+// TODO: expand the set of supported platforms, with testing. Nothing about
+// the instrumentation is OS specific, but only amd64 and arm64 are
+// supported in the runtime. See src/runtime/libfuzzer*.
+//
+// If you update this constraint, also update cmd/internal/sys.FuzzInstrumeted.
+//
 //go:build !((darwin || linux || windows || freebsd) && (amd64 || arm64))
 
 package fuzz
index 05954bb07fb3d249246311b0f4258be840d1d35c..123a32583c54cc90003c5663441f9ffe744e2f54 100644 (file)
@@ -2,7 +2,8 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
-// TODO(jayconrod): support more platforms.
+// If you update this constraint, also update cmd/internal/sys.FuzzSupported.
+//
 //go:build !darwin && !linux && !windows
 
 package fuzz