Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added go-fuzz for parser #253

Merged
merged 1 commit into from
Oct 17, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
122 changes: 122 additions & 0 deletions .github/workflows/test-fuzz.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,122 @@
name: Fuzz
on:
push:
pull_request:
workflow_dispatch:

jobs:
run:
name: Run
runs-on: ubuntu-latest
env:
GOOS: ${{ matrix.goos }}
GOARCH: ${{ matrix.goarch }}
GOFLAGS: '-trimpath -mod=readonly'
GO111MODULE: 'on'
strategy:
fail-fast: false
matrix:
go:
# Misplaced compiler directive error with Go 1.15.x.
# https://github.com/dvyukov/go-fuzz/issues/294
# Keep this version fixed so that we can analyze
# coverage profiles locally.
- 1.14.9
goos:
- linux
goarch:
- amd64
func:
- FuzzParseQuery
steps:
- name: Checkout code
uses: actions/checkout@v2
with:
path: genji

- name: Checkout corpus
uses: actions/checkout@v2
with:
repository: genjidb/go-fuzz-corpus
path: genji/fuzz/testdata/fuzz

- name: Install Go
uses: actions/setup-go@v2
with:
go-version: ${{ matrix.go }}

- name: Get cache path
# FIXME use GOMODCACHE instead of GOPATH once
# https://github.com/dvyukov/go-fuzz/issues/294
# is fixed and we can bump Go to 1.15 or greater.
run: echo "::set-output name=dir::$(go env GOPATH)"
id: modcache

- name: Set up cache
uses: actions/cache@v2
with:
# FIXME remove -fuzz- once we can use GOMODCACHE
path: ${{ steps.modcache.outputs.dir }}
key: modcache-fuzz-${{ matrix.goos }}-${{ matrix.goarch }}-${{ hashFiles('**/go.sum') }}
restore-keys: modcache-fuzz-

- name: Download dependencies
run: go mod download
working-directory: genji/fuzz

# Using libFuzzer
#
# - https://github.com/mdempsky/go114-fuzz-build
# https://google.github.io/oss-fuzz/getting-started/new-project-guide/go-lang/
#
# go114-fuzz-build -o fuzz.a .
# clang -fsanitize=fuzzer -o fuzz fuzz.a
#
# - https://github.com/dvyukov/go-fuzz#libfuzzer-support
#
# go-fuzz-build -libfuzzer -o fuzz.a
# clang -fsanitize=fuzzer -o fuzz fuzz.a
#
# ./fuzz -max_len=1024 -max_total_time=300 corpus
#
# I haven’t tried go114-fuzz-build which uses builtin Go libFuzzer support,
# but I’ve had a better experience with go-fuzz vs libFuzzer without corpus.

- name: Run tests
run: |
go run github.com/dvyukov/go-fuzz/go-fuzz-build -func ${{ matrix.func }} && timeout -s INT -k 30 300 \
go run github.com/dvyukov/go-fuzz/go-fuzz -workdir=testdata/fuzz/${{ matrix.func }} -dumpcover
working-directory: genji/fuzz

- name: Prepare report
if: ${{ success() || failure() }}
id: report
run: |
mv testdata/fuzz/${{ matrix.func }}/coverprofile coverprofile-coverage.out
mv testdata/fuzz/${{ matrix.func }}/sonarprofile sonarprofile-coverage.out

# go-fuzz dumps coverage profiles that are not reproducible.
# We fix that by trimming absolute paths.
perl -pi -e '
s:^/opt/.*/src/::;
s:^/home/.*/mod/(.*)@[^/]*:\1:;
s:^/home/.*(?!/cmd)/genji/:github.com/genjidb/genji/:;
' coverprofile-coverage.out sonarprofile-coverage.out

# https://github.com/dvyukov/go-fuzz/issues/170#issuecomment-462297614
perl -ni -e 'print unless /0.0,1.1/' coverprofile-coverage.out
working-directory: genji/fuzz

- name: Upload coverage
if: ${{ success() || failure() }}
uses: actions/upload-artifact@v2
with:
name: ${{ matrix.func }}_cover_go${{ matrix.go }}
path: genji/fuzz/*coverage.*

- name: Upload corpus
if: ${{ success() || failure() }}
uses: actions/upload-artifact@v2
with:
name: ${{ matrix.func }}_corpus
path: genji/fuzz/testdata/fuzz/${{ matrix.func }}
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,8 @@
[![go.dev reference](https://img.shields.io/badge/go.dev-reference-007d9c?logo=go&logoColor=white&style=flat-square)](https://pkg.go.dev/github.com/genjidb/genji)
[![Slack channel](https://img.shields.io/badge/slack-join%20chat-green.svg)](https://gophers.slack.com/messages/CKPCYQFE0)

![Fuzz](https://github.com/genjidb/genji/workflows/Fuzz/badge.svg)

Genji is a schemaless database that allows running SQL queries on documents.

Checkout the [SQL documentation](https://genji.dev/docs/genji-sql), the [Go doc](https://pkg.go.dev/github.com/genjidb/genji) and the [usage example](#usage) in the README to get started quickly.
Expand Down
38 changes: 38 additions & 0 deletions fuzz/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
# Fuzz Tests

Fuzzing Genji with [go-fuzz](https://github.com/dvyukov/go-fuzz).

## Quick Start

1. Install [go-fuzz](https://github.com/dvyukov/go-fuzz)
```
go install github.com/dvyukov/go-fuzz/go-fuzz-build github.com/dvyukov/go-fuzz/go-fuzz
```

2. Download the initial corpus
```
git clone https://github.com/genjidb/go-fuzz-corpus testdata/fuzz
```

3. Build the test program with necessary instrumentation
```
go-fuzz-build -func FuzzParseQuery
```
This will produce fuzz-fuzz.zip archive.

4. Run the fuzzer.
```
go-fuzz -workdir=testdata/fuzz/FuzzParseQuery
```
The results will be written to `testdata/fuzz/FuzzParseQuery`.
Note that go-fuzz runs forever until manually stopped.

Example output:
```
2020/10/14 12:03:58 workers: 2, corpus: 166 (13s ago), crashers: 2, restarts: 1/9663, execs: 1526845 (16418/sec), cover: 924, uptime: 1m33s
```
Here, `corpus` is number of interesting inputs the fuzzer has discovered, and `crashers` is number of discovered bugs (check out `testdata/fuzz/FuzzParseQuery/crashers` dir).

See [README file from go-fuzz](https://github.com/dvyukov/go-fuzz/blob/master/README.md) for more information.
96 changes: 96 additions & 0 deletions fuzz/fuzz_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
package fuzz

import (
"io/ioutil"
"os"
"path/filepath"
"reflect"
"runtime"
"strings"
"testing"
)

func TestFuzzParseQuery(t *testing.T) { testFuzz(t, FuzzParseQuery) }

func TestFuncName(t *testing.T) {
got := funcName(funcName)
expected := "funcName"
if got != expected {
t.Errorf("funcName(%s): expected %q, got %q", expected, expected, got)
}
}

// funcName returns the name of a function f.
// It is used to infer the workdir of a fuzz function.
func funcName(f interface{}) string {
v := reflect.ValueOf(f)
pc := v.Pointer()
fn := runtime.FuncForPC(pc)
name := fn.Name()
return name[strings.LastIndex(name, ".")+1:]
}

// testFuzz runs fuzz function once for each input in corpus.
// It assumes the directory structure from github.com/thepudds/fzgo.
// That is, testdata/fuzz/<FuzzName>/corpus stores the corpus.
func testFuzz(t *testing.T, fuzz func([]byte) int) {
t.Helper()

name := funcName(fuzz)

workdir := filepath.Join("testdata", "fuzz", name)
corpus := filepath.Join(workdir, "corpus")
crashers := filepath.Join(workdir, "crashers")

walkFn := func(path string, info os.FileInfo, err error) error {
t.Helper()

if err != nil {
// Do nothing if the root directory does not exist.
// Note that we expect testdata to be immutable
// while running tests (but not fuzzing).
if os.IsNotExist(err) {
return nil
}
return err
}

// Don’t descend into subdirectories.
if info.IsDir() && path != corpus && path != crashers {
return filepath.SkipDir
}

if !info.Mode().IsRegular() {
return nil
}

// Skip debug info in crashers directory.
if path == crashers {
if strings.HasSuffix(path, ".output") || strings.HasSuffix(path, ".quoted") {
return nil
}
}

t.Run(info.Name(), func(t *testing.T) {
t.Helper()

data, err := ioutil.ReadFile(path)
if err != nil {
t.Errorf("read test data: %v", err)
return
}

fuzz(data)
})

return nil
}

roots := []string{corpus, crashers}
for _, root := range roots {
err := filepath.Walk(root, walkFn)
if err != nil {
t.Errorf("walk %q: %v", root, err)
}
}
}
13 changes: 13 additions & 0 deletions fuzz/go.mod
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
module github.com/genjidb/genji/fuzz

go 1.15

require (
github.com/dvyukov/go-fuzz v0.0.0-20201003075337-90825f39c90b
github.com/elazarl/go-bindata-assetfs v1.0.1 // indirect
github.com/genjidb/genji v0.9.0
github.com/stephens2424/writerset v1.0.2 // indirect
golang.org/x/tools v0.0.0-20201013053347-2db1cd791039 // indirect
)

replace github.com/genjidb/genji v0.9.0 => ../
77 changes: 77 additions & 0 deletions fuzz/go.sum
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
github.com/Julusian/godocdown v0.0.0-20170816220326-6d19f8ff2df8/go.mod h1:INZr5t32rG59/5xeltqoCJoNY7e5x/3xoY9WSWVWg74=
github.com/buger/jsonparser v1.0.0 h1:etJTGF5ESxjI0Ic2UaLQs2LQQpa8G9ykQScukbh4L8A=
github.com/buger/jsonparser v1.0.0/go.mod h1:tgcrVJ81GPSF0mz+0nu1Xaz0fazGPrmmJfJtxjbHhUQ=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/dvyukov/go-fuzz v0.0.0-20201003075337-90825f39c90b h1:CXfDl9Y3NKuhOSxF9kXhiLmuYCdufQDrLY2fO1BzqBU=
github.com/dvyukov/go-fuzz v0.0.0-20201003075337-90825f39c90b/go.mod h1:11Gm+ccJnvAhCNLlf5+cS9KjtbaD5I5zaZpFMsTHWTw=
github.com/elazarl/go-bindata-assetfs v1.0.1 h1:m0kkaHRKEu7tUIUFVwhGGGYClXvyl4RE03qmvRTNfbw=
github.com/elazarl/go-bindata-assetfs v1.0.1/go.mod h1:v+YaWX3bdea5J/mo8dSETolEo7R71Vk1u8bnjau5yw4=
github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/golang/protobuf v1.3.4 h1:87PNWwrRvUSnqS4dlcBU/ftvOIBep4sYuBLlh6rX2wk=
github.com/golang/protobuf v1.3.4/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw=
github.com/google/btree v1.0.0 h1:0udJVsspx3VBr5FwtLhQQtuAsVc79tTq0ocGIPAU6qo=
github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI=
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE=
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/robertkrimen/godocdown v0.0.0-20130622164427-0bfa04905481/go.mod h1:C9WhFzY47SzYBIvzFqSvHIR6ROgDo4TtdTuRaOMjF/s=
github.com/stephens2424/writerset v1.0.2 h1:znRLgU6g8RS5euYRcy004XeE4W+Tu44kALzy7ghPif8=
github.com/stephens2424/writerset v1.0.2/go.mod h1:aS2JhsMn6eA7e82oNmW4rfsgAOp9COBTTl8mzkwADnc=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA=
github.com/stretchr/testify v1.6.1 h1:hDPOHmpOpP40lSULcqw7IrRb/u7w6RpDC9399XyoNd0=
github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/vmihailenco/msgpack/v4 v4.3.11/go.mod h1:gborTTJjAo/GWTqqRjrLCn9pgNN+NXzzngzBKDPIqw4=
github.com/vmihailenco/msgpack/v5 v5.0.0-beta.1 h1:d71/KA0LhvkrJ/Ok+Wx9qK7bU8meKA1Hk0jpVI5kJjk=
github.com/vmihailenco/msgpack/v5 v5.0.0-beta.1/go.mod h1:xlngVLeyQ/Qi05oQxhQ+oTuqa03RjMwMfk/7/TCs+QI=
github.com/vmihailenco/tagparser v0.1.1 h1:quXMXlA39OCbd2wAdTsGDlK9RkOk6Wuw+x37wVyIuWY=
github.com/vmihailenco/tagparser v0.1.1/go.mod h1:OeAg3pn3UbLjkWt+rN9oFYB6u/cQgqMEUPoW2WPyhdI=
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
go.etcd.io/bbolt v1.3.5 h1:XAzx9gjCb0Rxj7EoqcClPD1d5ZBxZJk0jbuoPHenBt0=
go.etcd.io/bbolt v1.3.5/go.mod h1:G5EMThwa9y8QZGBClrRx5EY+Yw9kAhnjy3bSjsnlVTQ=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/mod v0.3.0 h1:RM4zey1++hCTbCVQfnWeKs9/IEsaBLA8vTkd0WVtmH4=
golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks=
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20200301022130-244492dfa37a h1:GuSPYbZzB5/dcLNCwLQLsg3obCJtX9IJhpXkvY7kzk0=
golang.org/x/net v0.0.0-20200301022130-244492dfa37a/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20200822124328-c89045814202 h1:VvcQYSHwXgi7W+TpUR6A9g6Up98WAHf3f/ulnJ62IyA=
golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200202164722-d101bd2416d5 h1:LfCXLvNmTYH9kEmVgqbnsWfruoXZIrh4YBgqVHtDvw0=
golang.org/x/sys v0.0.0-20200202164722-d101bd2416d5/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd h1:xhmwyvizuTgC2qz7ZlMluP20uW+C3Rm0FD/WLDX8884=
golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e h1:FDhOuMEY4JVRztM/gsbk+IKUQ8kj74bxZrgw87eMMVc=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20201013053347-2db1cd791039 h1:kLBxO4OPBgPwjg8Vvu+/0DCHIfDwYIGNFcD66NU9kpo=
golang.org/x/tools v0.0.0-20201013053347-2db1cd791039/go.mod h1:z6u4i615ZeAfBE4XtMziQW1fSVJXACjjbWkB/mvPzlU=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE=
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
google.golang.org/appengine v1.6.5 h1:tycE03LOZYQNhDpS27tcQdAzLCVMaj7QT2SXxebnpCM=
google.golang.org/appengine v1.6.5/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 h1:qIbj1fsPNlZgppZ+VLlY7N33q108Sa+fhmuc+sWQYwY=
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
21 changes: 21 additions & 0 deletions fuzz/sqlparser.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
package fuzz

import (
"context"
"strings"

"github.com/genjidb/genji/sql/parser"
)

func FuzzParseQuery(data []byte) int {
var b strings.Builder
b.Write(data)
q, err := parser.ParseQuery(context.Background(), b.String())
if err != nil {
return 0
}
if len(q.Statements) != 0 {
return 1
}
return 0
}
10 changes: 10 additions & 0 deletions fuzz/tools.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
// +build tools

package fuzz

// Makes `go mod tidy` keep tool dependencies in go.mod and go.sum.

import (
_ "github.com/dvyukov/go-fuzz/go-fuzz"
_ "github.com/dvyukov/go-fuzz/go-fuzz-build"
)