From b5f1f971b4788270e03817c15093409a1181915f Mon Sep 17 00:00:00 2001 From: Alisdair McDiarmid Date: Thu, 14 May 2020 11:45:13 -0400 Subject: [PATCH 1/2] hclwrite: Add fuzz testing --- hclwrite/fuzz/.gitignore | 1 + hclwrite/fuzz/Makefile | 25 ++++++ hclwrite/fuzz/README.md | 82 +++++++++++++++++++ hclwrite/fuzz/config/corpus/attr-expr.hcl | 1 + hclwrite/fuzz/config/corpus/attr-literal.hcl | 1 + hclwrite/fuzz/config/corpus/attr.hcl | 1 + hclwrite/fuzz/config/corpus/block-attrs.hcl | 3 + hclwrite/fuzz/config/corpus/block-comment.hcl | 4 + hclwrite/fuzz/config/corpus/block-empty.hcl | 2 + hclwrite/fuzz/config/corpus/block-nested.hcl | 5 ++ hclwrite/fuzz/config/corpus/complex.hcl | 1 + hclwrite/fuzz/config/corpus/empty.hcl | 0 hclwrite/fuzz/config/corpus/escape-dollar.hcl | 1 + .../fuzz/config/corpus/escape-newline.hcl | 1 + .../fuzz/config/corpus/function-call-tmpl.hcl | 1 + hclwrite/fuzz/config/corpus/function-call.hcl | 1 + hclwrite/fuzz/config/corpus/hash-comment.hcl | 1 + hclwrite/fuzz/config/corpus/index.hcl | 1 + hclwrite/fuzz/config/corpus/int-tmpl.hcl | 1 + hclwrite/fuzz/config/corpus/int.hcl | 1 + hclwrite/fuzz/config/corpus/just-interp.hcl | 1 + hclwrite/fuzz/config/corpus/literal.hcl | 1 + .../fuzz/config/corpus/lots-of-comments.hcl | 14 ++++ hclwrite/fuzz/config/corpus/slash-comment.hcl | 1 + hclwrite/fuzz/config/corpus/splat-attr.hcl | 1 + .../fuzz/config/corpus/splat-dot-full.hcl | 1 + hclwrite/fuzz/config/corpus/splat-full.hcl | 1 + .../corpus/traversal-dot-index-terminal.hcl | 1 + .../config/corpus/traversal-dot-index.hcl | 1 + .../fuzz/config/corpus/traversal-index.hcl | 1 + hclwrite/fuzz/config/corpus/utf8.hcl | 1 + hclwrite/fuzz/config/corpus/var.hcl | 1 + hclwrite/fuzz/config/fuzz.go | 24 ++++++ 33 files changed, 183 insertions(+) create mode 100644 hclwrite/fuzz/.gitignore create mode 100644 hclwrite/fuzz/Makefile create mode 100644 hclwrite/fuzz/README.md create mode 100644 hclwrite/fuzz/config/corpus/attr-expr.hcl create mode 100644 hclwrite/fuzz/config/corpus/attr-literal.hcl create mode 100644 hclwrite/fuzz/config/corpus/attr.hcl create mode 100644 hclwrite/fuzz/config/corpus/block-attrs.hcl create mode 100644 hclwrite/fuzz/config/corpus/block-comment.hcl create mode 100644 hclwrite/fuzz/config/corpus/block-empty.hcl create mode 100644 hclwrite/fuzz/config/corpus/block-nested.hcl create mode 100644 hclwrite/fuzz/config/corpus/complex.hcl create mode 100644 hclwrite/fuzz/config/corpus/empty.hcl create mode 100644 hclwrite/fuzz/config/corpus/escape-dollar.hcl create mode 100644 hclwrite/fuzz/config/corpus/escape-newline.hcl create mode 100644 hclwrite/fuzz/config/corpus/function-call-tmpl.hcl create mode 100644 hclwrite/fuzz/config/corpus/function-call.hcl create mode 100644 hclwrite/fuzz/config/corpus/hash-comment.hcl create mode 100644 hclwrite/fuzz/config/corpus/index.hcl create mode 100644 hclwrite/fuzz/config/corpus/int-tmpl.hcl create mode 100644 hclwrite/fuzz/config/corpus/int.hcl create mode 100644 hclwrite/fuzz/config/corpus/just-interp.hcl create mode 100644 hclwrite/fuzz/config/corpus/literal.hcl create mode 100644 hclwrite/fuzz/config/corpus/lots-of-comments.hcl create mode 100644 hclwrite/fuzz/config/corpus/slash-comment.hcl create mode 100644 hclwrite/fuzz/config/corpus/splat-attr.hcl create mode 100644 hclwrite/fuzz/config/corpus/splat-dot-full.hcl create mode 100644 hclwrite/fuzz/config/corpus/splat-full.hcl create mode 100644 hclwrite/fuzz/config/corpus/traversal-dot-index-terminal.hcl create mode 100644 hclwrite/fuzz/config/corpus/traversal-dot-index.hcl create mode 100644 hclwrite/fuzz/config/corpus/traversal-index.hcl create mode 100644 hclwrite/fuzz/config/corpus/utf8.hcl create mode 100644 hclwrite/fuzz/config/corpus/var.hcl create mode 100644 hclwrite/fuzz/config/fuzz.go diff --git a/hclwrite/fuzz/.gitignore b/hclwrite/fuzz/.gitignore new file mode 100644 index 0000000..9490851 --- /dev/null +++ b/hclwrite/fuzz/.gitignore @@ -0,0 +1 @@ +fuzz*-fuzz.zip diff --git a/hclwrite/fuzz/Makefile b/hclwrite/fuzz/Makefile new file mode 100644 index 0000000..e303748 --- /dev/null +++ b/hclwrite/fuzz/Makefile @@ -0,0 +1,25 @@ + +ifndef FUZZ_WORK_DIR +$(error FUZZ_WORK_DIR is not set) +endif + +default: + @echo "See README.md for usage instructions" + +fuzz-config: fuzz-exec-config + +fuzz-exec-%: fuzz%-fuzz.zip + go-fuzz -bin=./fuzz$*-fuzz.zip -workdir=$(FUZZ_WORK_DIR) + +fuzz%-fuzz.zip: %/fuzz.go + go-fuzz-build -x github.com/hashicorp/hcl/v2/hclwrite/fuzz/$* + +tools: + go get -u github.com/dvyukov/go-fuzz/go-fuzz + go get -u github.com/dvyukov/go-fuzz/go-fuzz-build + +clean: + rm fuzz*-fuzz.zip + +.PHONY: tools clean fuzz-config +.PRECIOUS: fuzzconfig-fuzz.zip diff --git a/hclwrite/fuzz/README.md b/hclwrite/fuzz/README.md new file mode 100644 index 0000000..0e11623 --- /dev/null +++ b/hclwrite/fuzz/README.md @@ -0,0 +1,82 @@ +# hclwrite fuzzing utilities + +This directory contains helper functions and corpuses that can be used to +fuzz-test the `hclwrite` package using [go-fuzz](https://github.com/dvyukov/go-fuzz). + +## Work directory + +`go-fuzz` needs a working directory where it can keep state as it works. This +should ideally be in a ramdisk for efficiency, and should probably _not_ be on +an SSD to avoid thrashing it. Here's how to create a ramdisk: + +### macOS + +``` +$ SIZE_IN_MB=1024 +$ DEVICE=`hdiutil attach -nobrowse -nomount ram://$(($SIZE_IN_MB*2048))` +$ diskutil erasevolume HFS+ RamDisk $DEVICE +$ export RAMDISK=/Volumes/RamDisk +``` + +### Linux + +``` +$ mkdir /mnt/ramdisk +$ mount -t tmpfs -o size=1024M tmpfs /mnt/ramdisk +$ export RAMDISK=/mnt/ramdisk +``` + +## Running the fuzzer + +Next, install `go-fuzz` and its build tool in your `GOPATH`: + +``` +$ make tools FUZZ_WORK_DIR=$RAMDISK +``` + +Now you can fuzz the parser: + +``` +$ make fuzz-config FUZZ_WORK_DIR=$RAMDISK/hclwrite-fuzz-config +``` + +~> Note: `go-fuzz` does not interact well with `goenv`. If you encounter build +errors where the package `go.fuzz.main` could not be found, you may need to use +a machine with a direct installation of Go. + +## Understanding the result + +A small number of subdirectories will be created in the work directory. + +If you let `go-fuzz` run for a few minutes (the more minutes the better) it +may detect "crashers", which are inputs that caused the parser to panic. Details +about these are written to `$FUZZ_WORK_DIR/crashers`: + +``` +$ ls /tmp/hcl2-fuzz-config/crashers +7f5e9ec80c89da14b8b0b238ec88969f658f5a2d +7f5e9ec80c89da14b8b0b238ec88969f658f5a2d.output +7f5e9ec80c89da14b8b0b238ec88969f658f5a2d.quoted +``` + +The base file above (with no extension) is the input that caused a crash. The +`.output` file contains the panic stack trace, which you can use as a clue to +figure out what caused the crash. + +A good first step to fixing a detected crasher is to copy the failing input +into one of the unit tests in the `hclwrite` package and see it crash there +too. After that, it's easy to re-run the test as you try to fix it. The +file with the `.quoted` extension contains a form of the input that is quoted +in Go syntax for easy copy-paste into a test case, even if the input contains +non-printable characters or other inconvenient symbols. + +## Rebuilding for new Upstream Code + +An archive file is created for `go-fuzz` to use on the first run of each +of the above, as a `.zip` file created in this directory. If upstream code +is changed these will need to be deleted to cause them to be rebuilt with +the latest code: + +``` +$ make clean +``` diff --git a/hclwrite/fuzz/config/corpus/attr-expr.hcl b/hclwrite/fuzz/config/corpus/attr-expr.hcl new file mode 100644 index 0000000..908bbc9 --- /dev/null +++ b/hclwrite/fuzz/config/corpus/attr-expr.hcl @@ -0,0 +1 @@ +foo = upper(bar + baz[1]) diff --git a/hclwrite/fuzz/config/corpus/attr-literal.hcl b/hclwrite/fuzz/config/corpus/attr-literal.hcl new file mode 100644 index 0000000..5abc475 --- /dev/null +++ b/hclwrite/fuzz/config/corpus/attr-literal.hcl @@ -0,0 +1 @@ +foo = "bar" diff --git a/hclwrite/fuzz/config/corpus/attr.hcl b/hclwrite/fuzz/config/corpus/attr.hcl new file mode 100644 index 0000000..6c11db6 --- /dev/null +++ b/hclwrite/fuzz/config/corpus/attr.hcl @@ -0,0 +1 @@ +a = foo.bar diff --git a/hclwrite/fuzz/config/corpus/block-attrs.hcl b/hclwrite/fuzz/config/corpus/block-attrs.hcl new file mode 100644 index 0000000..eb529ef --- /dev/null +++ b/hclwrite/fuzz/config/corpus/block-attrs.hcl @@ -0,0 +1,3 @@ +block { + foo = true +} diff --git a/hclwrite/fuzz/config/corpus/block-comment.hcl b/hclwrite/fuzz/config/corpus/block-comment.hcl new file mode 100644 index 0000000..9ed4c68 --- /dev/null +++ b/hclwrite/fuzz/config/corpus/block-comment.hcl @@ -0,0 +1,4 @@ +/* multi + line + comment +*/ diff --git a/hclwrite/fuzz/config/corpus/block-empty.hcl b/hclwrite/fuzz/config/corpus/block-empty.hcl new file mode 100644 index 0000000..b3b13a1 --- /dev/null +++ b/hclwrite/fuzz/config/corpus/block-empty.hcl @@ -0,0 +1,2 @@ +block { +} diff --git a/hclwrite/fuzz/config/corpus/block-nested.hcl b/hclwrite/fuzz/config/corpus/block-nested.hcl new file mode 100644 index 0000000..304183a --- /dev/null +++ b/hclwrite/fuzz/config/corpus/block-nested.hcl @@ -0,0 +1,5 @@ +block { + another_block { + foo = bar + } +} diff --git a/hclwrite/fuzz/config/corpus/complex.hcl b/hclwrite/fuzz/config/corpus/complex.hcl new file mode 100644 index 0000000..00a4a27 --- /dev/null +++ b/hclwrite/fuzz/config/corpus/complex.hcl @@ -0,0 +1 @@ +a = foo.bar[1].baz["foo"].pizza diff --git a/hclwrite/fuzz/config/corpus/empty.hcl b/hclwrite/fuzz/config/corpus/empty.hcl new file mode 100644 index 0000000..e69de29 diff --git a/hclwrite/fuzz/config/corpus/escape-dollar.hcl b/hclwrite/fuzz/config/corpus/escape-dollar.hcl new file mode 100644 index 0000000..01811cd --- /dev/null +++ b/hclwrite/fuzz/config/corpus/escape-dollar.hcl @@ -0,0 +1 @@ +a = "hi $${var.foo}" diff --git a/hclwrite/fuzz/config/corpus/escape-newline.hcl b/hclwrite/fuzz/config/corpus/escape-newline.hcl new file mode 100644 index 0000000..2055548 --- /dev/null +++ b/hclwrite/fuzz/config/corpus/escape-newline.hcl @@ -0,0 +1 @@ +a = "bar\nbaz" diff --git a/hclwrite/fuzz/config/corpus/function-call-tmpl.hcl b/hclwrite/fuzz/config/corpus/function-call-tmpl.hcl new file mode 100644 index 0000000..f641c7a --- /dev/null +++ b/hclwrite/fuzz/config/corpus/function-call-tmpl.hcl @@ -0,0 +1 @@ +a = "b ${title(var.name)} diff --git a/hclwrite/fuzz/config/corpus/function-call.hcl b/hclwrite/fuzz/config/corpus/function-call.hcl new file mode 100644 index 0000000..f3cafb2 --- /dev/null +++ b/hclwrite/fuzz/config/corpus/function-call.hcl @@ -0,0 +1 @@ +a = title(var.name) diff --git a/hclwrite/fuzz/config/corpus/hash-comment.hcl b/hclwrite/fuzz/config/corpus/hash-comment.hcl new file mode 100644 index 0000000..9d18bcb --- /dev/null +++ b/hclwrite/fuzz/config/corpus/hash-comment.hcl @@ -0,0 +1 @@ +# another comment diff --git a/hclwrite/fuzz/config/corpus/index.hcl b/hclwrite/fuzz/config/corpus/index.hcl new file mode 100644 index 0000000..a22dd44 --- /dev/null +++ b/hclwrite/fuzz/config/corpus/index.hcl @@ -0,0 +1 @@ +a = foo[1] diff --git a/hclwrite/fuzz/config/corpus/int-tmpl.hcl b/hclwrite/fuzz/config/corpus/int-tmpl.hcl new file mode 100644 index 0000000..57e94d3 --- /dev/null +++ b/hclwrite/fuzz/config/corpus/int-tmpl.hcl @@ -0,0 +1 @@ +a = "foo ${42}" diff --git a/hclwrite/fuzz/config/corpus/int.hcl b/hclwrite/fuzz/config/corpus/int.hcl new file mode 100644 index 0000000..aec1027 --- /dev/null +++ b/hclwrite/fuzz/config/corpus/int.hcl @@ -0,0 +1 @@ +a = 42 diff --git a/hclwrite/fuzz/config/corpus/just-interp.hcl b/hclwrite/fuzz/config/corpus/just-interp.hcl new file mode 100644 index 0000000..018d5ed --- /dev/null +++ b/hclwrite/fuzz/config/corpus/just-interp.hcl @@ -0,0 +1 @@ +a = "${var.bar}" diff --git a/hclwrite/fuzz/config/corpus/literal.hcl b/hclwrite/fuzz/config/corpus/literal.hcl new file mode 100644 index 0000000..5ae5461 --- /dev/null +++ b/hclwrite/fuzz/config/corpus/literal.hcl @@ -0,0 +1 @@ +a = foo diff --git a/hclwrite/fuzz/config/corpus/lots-of-comments.hcl b/hclwrite/fuzz/config/corpus/lots-of-comments.hcl new file mode 100644 index 0000000..511f085 --- /dev/null +++ b/hclwrite/fuzz/config/corpus/lots-of-comments.hcl @@ -0,0 +1,14 @@ +// comment +block { + // another comment + another_block { # comment + // comment + foo = bar + } + + /* commented out block + blah { + bar = foo + } + */ +} diff --git a/hclwrite/fuzz/config/corpus/slash-comment.hcl b/hclwrite/fuzz/config/corpus/slash-comment.hcl new file mode 100644 index 0000000..fef83a9 --- /dev/null +++ b/hclwrite/fuzz/config/corpus/slash-comment.hcl @@ -0,0 +1 @@ +// comment diff --git a/hclwrite/fuzz/config/corpus/splat-attr.hcl b/hclwrite/fuzz/config/corpus/splat-attr.hcl new file mode 100644 index 0000000..38cfe14 --- /dev/null +++ b/hclwrite/fuzz/config/corpus/splat-attr.hcl @@ -0,0 +1 @@ +a = foo.bar.*.baz diff --git a/hclwrite/fuzz/config/corpus/splat-dot-full.hcl b/hclwrite/fuzz/config/corpus/splat-dot-full.hcl new file mode 100644 index 0000000..22e8eb0 --- /dev/null +++ b/hclwrite/fuzz/config/corpus/splat-dot-full.hcl @@ -0,0 +1 @@ +a = foo.bar.* diff --git a/hclwrite/fuzz/config/corpus/splat-full.hcl b/hclwrite/fuzz/config/corpus/splat-full.hcl new file mode 100644 index 0000000..4441191 --- /dev/null +++ b/hclwrite/fuzz/config/corpus/splat-full.hcl @@ -0,0 +1 @@ +a = foo.bar[*].baz diff --git a/hclwrite/fuzz/config/corpus/traversal-dot-index-terminal.hcl b/hclwrite/fuzz/config/corpus/traversal-dot-index-terminal.hcl new file mode 100644 index 0000000..3f3a306 --- /dev/null +++ b/hclwrite/fuzz/config/corpus/traversal-dot-index-terminal.hcl @@ -0,0 +1 @@ +a = foo.bar.0 diff --git a/hclwrite/fuzz/config/corpus/traversal-dot-index.hcl b/hclwrite/fuzz/config/corpus/traversal-dot-index.hcl new file mode 100644 index 0000000..31cbf8b --- /dev/null +++ b/hclwrite/fuzz/config/corpus/traversal-dot-index.hcl @@ -0,0 +1 @@ +a = foo.bar.4.baz diff --git a/hclwrite/fuzz/config/corpus/traversal-index.hcl b/hclwrite/fuzz/config/corpus/traversal-index.hcl new file mode 100644 index 0000000..5523c37 --- /dev/null +++ b/hclwrite/fuzz/config/corpus/traversal-index.hcl @@ -0,0 +1 @@ +a = foo.bar[4].baz diff --git a/hclwrite/fuzz/config/corpus/utf8.hcl b/hclwrite/fuzz/config/corpus/utf8.hcl new file mode 100644 index 0000000..ffad4b0 --- /dev/null +++ b/hclwrite/fuzz/config/corpus/utf8.hcl @@ -0,0 +1 @@ +foo = "föo ${föo("föo")}" diff --git a/hclwrite/fuzz/config/corpus/var.hcl b/hclwrite/fuzz/config/corpus/var.hcl new file mode 100644 index 0000000..62a9b73 --- /dev/null +++ b/hclwrite/fuzz/config/corpus/var.hcl @@ -0,0 +1 @@ +a = var.bar diff --git a/hclwrite/fuzz/config/fuzz.go b/hclwrite/fuzz/config/fuzz.go new file mode 100644 index 0000000..ea66e67 --- /dev/null +++ b/hclwrite/fuzz/config/fuzz.go @@ -0,0 +1,24 @@ +package fuzzconfig + +import ( + "io/ioutil" + + "github.com/hashicorp/hcl/v2" + "github.com/hashicorp/hcl/v2/hclwrite" +) + +func Fuzz(data []byte) int { + file, diags := hclwrite.ParseConfig(data, "", hcl.Pos{Line: 1, Column: 1}) + + if diags.HasErrors() { + return 0 + } + + _, err := file.WriteTo(ioutil.Discard) + + if err != nil { + return 0 + } + + return 1 +} From e899db5b9fcde6e5d6610e27e97dcd485dafa1d2 Mon Sep 17 00:00:00 2001 From: Alisdair McDiarmid Date: Thu, 14 May 2020 14:42:50 -0400 Subject: [PATCH 2/2] Update other fuzz docs for consistency --- hclsyntax/fuzz/README.md | 43 +++++++++++++++++++++++++++++++--------- json/fuzz/README.md | 39 +++++++++++++++++++++++++++++------- 2 files changed, 66 insertions(+), 16 deletions(-) diff --git a/hclsyntax/fuzz/README.md b/hclsyntax/fuzz/README.md index 38960e2..7ffbc0d 100644 --- a/hclsyntax/fuzz/README.md +++ b/hclsyntax/fuzz/README.md @@ -3,24 +3,49 @@ This directory contains helper functions and corpuses that can be used to fuzz-test the `hclsyntax` parsers using [go-fuzz](https://github.com/dvyukov/go-fuzz). -To fuzz, first install go-fuzz and its build tool in your `GOPATH`: +## Work directory + +`go-fuzz` needs a working directory where it can keep state as it works. This +should ideally be in a ramdisk for efficiency, and should probably _not_ be on +an SSD to avoid thrashing it. Here's how to create a ramdisk: + +### macOS ``` -$ make tools +$ SIZE_IN_MB=1024 +$ DEVICE=`hdiutil attach -nobrowse -nomount ram://$(($SIZE_IN_MB*2048))` +$ diskutil erasevolume HFS+ RamDisk $DEVICE +$ export RAMDISK=/Volumes/RamDisk +``` + +### Linux + +``` +$ mkdir /mnt/ramdisk +$ mount -t tmpfs -o size=1024M tmpfs /mnt/ramdisk +$ export RAMDISK=/mnt/ramdisk +``` + +## Running the fuzzer + +Next, install `go-fuzz` and its build tool in your `GOPATH`: + +``` +$ make tools FUZZ_WORK_DIR=$RAMDISK ``` Now you can fuzz one or all of the parsers: ``` -$ make fuzz-config FUZZ_WORK_DIR=/tmp/hcl2-fuzz-config -$ make fuzz-expr FUZZ_WORK_DIR=/tmp/hcl2-fuzz-expr -$ make fuzz-template FUZZ_WORK_DIR=/tmp/hcl2-fuzz-template -$ make fuzz-traversal FUZZ_WORK_DIR=/tmp/hcl2-fuzz-traversal +$ make fuzz-config FUZZ_WORK_DIR=$RAMDISK/hclsyntax-fuzz-config +$ make fuzz-expr FUZZ_WORK_DIR=$RAMDISK/hclsyntax-fuzz-expr +$ make fuzz-template FUZZ_WORK_DIR=$RAMDISK/hclsyntax-fuzz-template +$ make fuzz-traversal FUZZ_WORK_DIR=$RAMDISK/hclsyntax-fuzz-traversal ``` -In all cases, set `FUZZ_WORK_DIR` to a directory where `go-fuzz` can keep state -as it works. This should ideally be in a ramdisk for efficiency, and should -probably _not_ be on an SSD to avoid thrashing it. +~> Note: `go-fuzz` does not interact well with `goenv`. If you encounter build +errors where the package `go.fuzz.main` could not be found, you may need to use +a machine with a direct installation of Go. ## Understanding the result diff --git a/json/fuzz/README.md b/json/fuzz/README.md index 17f8f9f..b4d7fd1 100644 --- a/json/fuzz/README.md +++ b/json/fuzz/README.md @@ -3,21 +3,46 @@ This directory contains helper functions and corpuses that can be used to fuzz-test the HCL JSON parser using [go-fuzz](https://github.com/dvyukov/go-fuzz). -To fuzz, first install go-fuzz and its build tool in your `GOPATH`: +## Work directory + +`go-fuzz` needs a working directory where it can keep state as it works. This +should ideally be in a ramdisk for efficiency, and should probably _not_ be on +an SSD to avoid thrashing it. Here's how to create a ramdisk: + +### macOS ``` -$ make tools +$ SIZE_IN_MB=1024 +$ DEVICE=`hdiutil attach -nobrowse -nomount ram://$(($SIZE_IN_MB*2048))` +$ diskutil erasevolume HFS+ RamDisk $DEVICE +$ export RAMDISK=/Volumes/RamDisk ``` -Now you can fuzz one or all of the parsers: +### Linux ``` -$ make fuzz-config FUZZ_WORK_DIR=/tmp/hcl2-fuzz-config +$ mkdir /mnt/ramdisk +$ mount -t tmpfs -o size=1024M tmpfs /mnt/ramdisk +$ export RAMDISK=/mnt/ramdisk ``` -In all cases, set `FUZZ_WORK_DIR` to a directory where `go-fuzz` can keep state -as it works. This should ideally be in a ramdisk for efficiency, and should -probably _not_ be on an SSD to avoid thrashing it. +## Running the fuzzer + +Next, install `go-fuzz` and its build tool in your `GOPATH`: + +``` +$ make tools FUZZ_WORK_DIR=$RAMDISK +``` + +Now you can fuzz the parser: + +``` +$ make fuzz-config FUZZ_WORK_DIR=$RAMDISK/json-fuzz-config +``` + +~> Note: `go-fuzz` does not interact well with `goenv`. If you encounter build +errors where the package `go.fuzz.main` could not be found, you may need to use +a machine with a direct installation of Go. ## Understanding the result