// Copyright 2022 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. package sanitizers_test import ( "strings" "testing" ) func TestLibFuzzer(t *testing.T) { goos, err := goEnv("GOOS") if err != nil { t.Fatal(err) } goarch, err := goEnv("GOARCH") if err != nil { t.Fatal(err) } if !libFuzzerSupported(goos, goarch) { t.Skipf("skipping on %s/%s; libfuzzer option is not supported.", goos, goarch) } config := configure("fuzzer") config.skipIfCSanitizerBroken(t) cases := []struct { goSrc string cSrc string expectedError string }{ {goSrc: "libfuzzer1.go", expectedError: "panic: found it"}, {goSrc: "libfuzzer2.go", cSrc: "libfuzzer2.c", expectedError: "panic: found it"}, } for _, tc := range cases { tc := tc name := strings.TrimSuffix(tc.goSrc, ".go") t.Run(name, func(t *testing.T) { t.Parallel() dir := newTempDir(t) defer dir.RemoveAll(t) // build Go code in libfuzzer mode to a c-archive outPath := dir.Join(name) archivePath := dir.Join(name + ".a") mustRun(t, config.goCmd("build", "-buildmode=c-archive", "-o", archivePath, srcPath(tc.goSrc))) // build C code (if any) and link with Go code cmd, err := cc(config.cFlags...) if err != nil { t.Fatalf("error running cc: %v", err) } cmd.Args = append(cmd.Args, config.ldFlags...) cmd.Args = append(cmd.Args, "-o", outPath, "-I", dir.Base()) if tc.cSrc != "" { cmd.Args = append(cmd.Args, srcPath(tc.cSrc)) } cmd.Args = append(cmd.Args, archivePath) mustRun(t, cmd) cmd = hangProneCmd(outPath) cmd.Dir = dir.Base() outb, err := cmd.CombinedOutput() out := string(outb) if err == nil { t.Fatalf("fuzzing succeeded unexpectedly; output:\n%s", out) } if !strings.Contains(out, tc.expectedError) { t.Errorf("exited without expected error %q; got\n%s", tc.expectedError, out) } }) } } // libFuzzerSupported is a copy of the function internal/platform.FuzzInstrumented, // because the internal package can't be used here. func libFuzzerSupported(goos, goarch string) bool { switch goarch { case "amd64", "arm64": // TODO(#14565): support more architectures. switch goos { case "darwin", "freebsd", "linux", "windows": return true default: return false } default: return false } }