Skip to content

Commit 8f31dca

Browse files
committed
Currently, there isn't a reliable way to build
Go test binaries with libfuzzer instrumentation [1]. An attempt such as `bazel run --@io_bazel_rules_go//go/config:gc_goopts=-d=libfuzzer ...` fails to compile owing to unresolved symbols, e.g., runtime.libfuzzerTraceConstCmp8 [2]. This patch adds `libfuzzer_shim.go` (identical to `trace.go` [2]) to the `bzltestutil` package, which ensures the shim is linked with a Go test binary. Furthermore, we exclude `-d=libfuzzer` when compiling any of the _external_ dependencies. [1] bazel-contrib#3088 (comment) [2] golang/go@74f49f3
1 parent 0e7e4e3 commit 8f31dca

File tree

2 files changed

+49
-0
lines changed

2 files changed

+49
-0
lines changed

go/tools/builders/compilepkg.go

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ import (
2727
"os/exec"
2828
"path"
2929
"path/filepath"
30+
"slices"
3031
"sort"
3132
"strings"
3233
)
@@ -343,6 +344,13 @@ func compileArchive(
343344
cgoSrcs[i-len(goSrcs)] = coverSrc
344345
}
345346
}
347+
if strings.HasPrefix(packagePath, "external") && slices.Contains(gcFlags, "-d=libfuzzer") {
348+
// Remove -d=libfuzzer from gcFlags when compiling external packages. We don't really want to instrument them,
349+
// and they won't compile without libfuzzer_shim.go.
350+
gcFlags = slices.DeleteFunc(gcFlags, func(s string) bool {
351+
return s == "-d=libfuzzer"
352+
})
353+
}
346354

347355
// If we have cgo, generate separate C and go files, and compile the
348356
// C files.
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
// Copyright 2021 The Go Authors. All rights reserved.
2+
// Use of this source code is governed by a BSD-style
3+
// license that can be found in the LICENSE file.
4+
5+
// N.B. This source is lifted verbatim from trace.go, added in
6+
// https://github.com/golang/go/commit/74f49f3366826f95a464cc15838a0668c92e3357
7+
//
8+
// It's essentially a shim to allow linking a Go test binary without libfuzzer.
9+
// We chose the 'bzltestutil' package because it's a bazel dependency for all Go test binaries.
10+
11+
//go:build !libfuzzer
12+
13+
package bzltestutil
14+
15+
import _ "unsafe" // for go:linkname
16+
17+
//go:linkname libfuzzerTraceCmp1 runtime.libfuzzerTraceCmp1
18+
//go:linkname libfuzzerTraceCmp2 runtime.libfuzzerTraceCmp2
19+
//go:linkname libfuzzerTraceCmp4 runtime.libfuzzerTraceCmp4
20+
//go:linkname libfuzzerTraceCmp8 runtime.libfuzzerTraceCmp8
21+
22+
//go:linkname libfuzzerTraceConstCmp1 runtime.libfuzzerTraceConstCmp1
23+
//go:linkname libfuzzerTraceConstCmp2 runtime.libfuzzerTraceConstCmp2
24+
//go:linkname libfuzzerTraceConstCmp4 runtime.libfuzzerTraceConstCmp4
25+
//go:linkname libfuzzerTraceConstCmp8 runtime.libfuzzerTraceConstCmp8
26+
27+
//go:linkname libfuzzerHookStrCmp runtime.libfuzzerHookStrCmp
28+
//go:linkname libfuzzerHookEqualFold runtime.libfuzzerHookEqualFold
29+
30+
func libfuzzerTraceCmp1(arg0, arg1 uint8, fakePC int) {}
31+
func libfuzzerTraceCmp2(arg0, arg1 uint16, fakePC int) {}
32+
func libfuzzerTraceCmp4(arg0, arg1 uint32, fakePC int) {}
33+
func libfuzzerTraceCmp8(arg0, arg1 uint64, fakePC int) {}
34+
35+
func libfuzzerTraceConstCmp1(arg0, arg1 uint8, fakePC int) {}
36+
func libfuzzerTraceConstCmp2(arg0, arg1 uint16, fakePC int) {}
37+
func libfuzzerTraceConstCmp4(arg0, arg1 uint32, fakePC int) {}
38+
func libfuzzerTraceConstCmp8(arg0, arg1 uint64, fakePC int) {}
39+
40+
func libfuzzerHookStrCmp(arg0, arg1 string, fakePC int) {}
41+
func libfuzzerHookEqualFold(arg0, arg1 string, fakePC int) {}

0 commit comments

Comments
 (0)