Description
go-fuzz instruments source code, writes it out to a temp dir, and then calls go/build to compile it.
go/packages appears to support this: it generates CompiledGoFiles, which have been preprocessed by cgo. However, if you instrument those files and write them back out, "go build" doesn't work.
The first issue, easily fixed, is that they don't have a ".go" suffix.
The second issue is that cmd/go complains when it finds C/C++ files and/or cgo directives in a directory with only precompiled cgo code, because the precompiled cgo code doesn't contain import "C"
. Sample error message: //go:cgo_ldflag "/usr/local/Cellar/re2/20190101/lib/libre2.a" only allowed in cgo-generated code
.
If you add a dummy file containing just import "C"
to work around that issue, then cmd/go runs cgo on that, which generates duplicate definitions within the package. Sample error message: _Cgo_ptr redeclared in this block
.
As an inferior fallback, I tried to instrument the pre-cgo code instead. However, the AST and type information that go/packages generates is for the CompiledGoFiles, not the GoFiles, so that'd mean typechecking everything by hand, which means losing a bunch of the value provided by go/packages.
For now, I'm just leaving cgo code completely uninstrumented. Unfortunately, this requires adding semi-fragile hacks to find cgo code (whether the file is missing a ".go" suffix) and then reaching through the abstraction layers and copying it verbatim.
I'm not sure how best to fix this. One option would be to have a way to tell cmd/go that all cgo preprocessing has been done. I don't see an obvious fix within go/packages, but it'd be ideal to find one, since that doesn't require waiting six months to be usable.