Skip to content

Commit

Permalink
Currently, there isn't a reliable way to build
Browse files Browse the repository at this point in the history
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
  • Loading branch information
srosenberg committed May 22, 2024
1 parent 0e7e4e3 commit 8f31dca
Show file tree
Hide file tree
Showing 2 changed files with 49 additions and 0 deletions.
8 changes: 8 additions & 0 deletions go/tools/builders/compilepkg.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ import (
"os/exec"
"path"
"path/filepath"
"slices"
"sort"
"strings"
)
Expand Down Expand Up @@ -343,6 +344,13 @@ func compileArchive(
cgoSrcs[i-len(goSrcs)] = coverSrc
}
}
if strings.HasPrefix(packagePath, "external") && slices.Contains(gcFlags, "-d=libfuzzer") {
// Remove -d=libfuzzer from gcFlags when compiling external packages. We don't really want to instrument them,
// and they won't compile without libfuzzer_shim.go.
gcFlags = slices.DeleteFunc(gcFlags, func(s string) bool {
return s == "-d=libfuzzer"
})
}

// If we have cgo, generate separate C and go files, and compile the
// C files.
Expand Down
41 changes: 41 additions & 0 deletions go/tools/bzltestutil/libfuzzer_shim.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
// Copyright 2021 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.

// N.B. This source is lifted verbatim from trace.go, added in
// https://github.com/golang/go/commit/74f49f3366826f95a464cc15838a0668c92e3357
//
// It's essentially a shim to allow linking a Go test binary without libfuzzer.
// We chose the 'bzltestutil' package because it's a bazel dependency for all Go test binaries.

//go:build !libfuzzer

package bzltestutil

import _ "unsafe" // for go:linkname

//go:linkname libfuzzerTraceCmp1 runtime.libfuzzerTraceCmp1
//go:linkname libfuzzerTraceCmp2 runtime.libfuzzerTraceCmp2
//go:linkname libfuzzerTraceCmp4 runtime.libfuzzerTraceCmp4
//go:linkname libfuzzerTraceCmp8 runtime.libfuzzerTraceCmp8

//go:linkname libfuzzerTraceConstCmp1 runtime.libfuzzerTraceConstCmp1
//go:linkname libfuzzerTraceConstCmp2 runtime.libfuzzerTraceConstCmp2
//go:linkname libfuzzerTraceConstCmp4 runtime.libfuzzerTraceConstCmp4
//go:linkname libfuzzerTraceConstCmp8 runtime.libfuzzerTraceConstCmp8

//go:linkname libfuzzerHookStrCmp runtime.libfuzzerHookStrCmp
//go:linkname libfuzzerHookEqualFold runtime.libfuzzerHookEqualFold

func libfuzzerTraceCmp1(arg0, arg1 uint8, fakePC int) {}
func libfuzzerTraceCmp2(arg0, arg1 uint16, fakePC int) {}
func libfuzzerTraceCmp4(arg0, arg1 uint32, fakePC int) {}
func libfuzzerTraceCmp8(arg0, arg1 uint64, fakePC int) {}

func libfuzzerTraceConstCmp1(arg0, arg1 uint8, fakePC int) {}
func libfuzzerTraceConstCmp2(arg0, arg1 uint16, fakePC int) {}
func libfuzzerTraceConstCmp4(arg0, arg1 uint32, fakePC int) {}
func libfuzzerTraceConstCmp8(arg0, arg1 uint64, fakePC int) {}

func libfuzzerHookStrCmp(arg0, arg1 string, fakePC int) {}
func libfuzzerHookEqualFold(arg0, arg1 string, fakePC int) {}

0 comments on commit 8f31dca

Please sign in to comment.