hcl/hclsyntax/fuzz
2020-05-14 15:03:29 -04:00
..
config Unfold the "hcl" directory up into the root 2019-09-09 16:08:19 -07:00
expr Unfold the "hcl" directory up into the root 2019-09-09 16:08:19 -07:00
template Unfold the "hcl" directory up into the root 2019-09-09 16:08:19 -07:00
traversal Unfold the "hcl" directory up into the root 2019-09-09 16:08:19 -07:00
.gitignore Unfold the "hcl" directory up into the root 2019-09-09 16:08:19 -07:00
Makefile Unfold the "hcl" directory up into the root 2019-09-09 16:08:19 -07:00
README.md Update other fuzz docs for consistency 2020-05-14 15:03:29 -04:00

hclsyntax fuzzing utilities

This directory contains helper functions and corpuses that can be used to fuzz-test the hclsyntax parsers using 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 one or all of the parsers:

$ 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

~> 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 hclsyntax 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