make: add fuzz-build and fuzz commands

This commit is contained in:
Oliver Gugger 2020-09-23 14:55:08 +02:00
parent 916b75fd4e
commit 5189cb799a
No known key found for this signature in database
GPG Key ID: 8E4256593F177720
3 changed files with 149 additions and 0 deletions

@ -8,6 +8,8 @@ LINT_PKG := github.com/golangci/golangci-lint/cmd/golangci-lint
GOACC_PKG := github.com/ory/go-acc
FALAFEL_PKG := github.com/lightninglabs/falafel
GOIMPORTS_PKG := golang.org/x/tools/cmd/goimports
GOFUZZ_BUILD_PKG := github.com/dvyukov/go-fuzz/go-fuzz-build
GOFUZZ_PKG := github.com/dvyukov/go-fuzz/go-fuzz
GO_BIN := ${GOPATH}/bin
BTCD_BIN := $(GO_BIN)/btcd
@ -15,6 +17,8 @@ GOMOBILE_BIN := GO111MODULE=off $(GO_BIN)/gomobile
GOVERALLS_BIN := $(GO_BIN)/goveralls
LINT_BIN := $(GO_BIN)/golangci-lint
GOACC_BIN := $(GO_BIN)/go-acc
GOFUZZ_BUILD_BIN := $(GO_BIN)/go-fuzz-build
GOFUZZ_BIN := $(GO_BIN)/go-fuzz
BTCD_DIR :=${GOPATH}/src/$(BTCD_PKG)
MOBILE_BUILD_DIR :=${GOPATH}/src/$(MOBILE_PKG)/build
@ -35,6 +39,7 @@ BTCD_COMMIT := $(shell cat go.mod | \
LINT_COMMIT := v1.18.0
GOACC_COMMIT := ddc355013f90fea78d83d3a6c71f1d37ac07ecd5
FALAFEL_COMMIT := v0.7.1
GOFUZZ_COMMIT := 21309f307f61
DEPGET := cd /tmp && GO111MODULE=on go get -v
GOBUILD := GO111MODULE=on go build -v
@ -51,6 +56,7 @@ XARGS := xargs -L 1
include make/testing_flags.mk
include make/release_flags.mk
include make/fuzz_flags.mk
DEV_TAGS := $(if ${tags},$(DEV_TAGS) ${tags},$(DEV_TAGS))
@ -116,6 +122,14 @@ goimports:
@$(call print, "Installing goimports.")
$(DEPGET) $(GOIMPORTS_PKG)
$(GOFUZZ_BIN):
@$(call print, "Fetching go-fuzz")
$(DEPGET) $(GOFUZZ_PKG)@$(GOFUZZ_COMMIT)
$(GOFUZZ_BUILD_BIN):
@$(call print, "Fetching go-fuzz-build")
$(DEPGET) $(GOFUZZ_BUILD_PKG)@$(GOFUZZ_COMMIT)
# ============
# INSTALLATION
# ============
@ -197,6 +211,17 @@ flake-unit:
@$(call print, "Flake hunting unit tests.")
while [ $$? -eq 0 ]; do GOTRACEBACK=all $(UNIT) -count=1; done
# =============
# FUZZING
# =============
fuzz-build: $(GOFUZZ_BUILD_BIN)
@$(call print, "Creating fuzz harnesses for packages '$(FUZZPKG)'.")
scripts/fuzz.sh build "$(FUZZPKG)"
fuzz-run: $(GOFUZZ_BIN)
@$(call print, "Fuzzing packages '$(FUZZPKG)'.")
scripts/fuzz.sh run "$(FUZZPKG)" "$(FUZZ_TEST_RUN_TIME)" "$(FUZZ_TEST_TIMEOUT)" "$(FUZZ_NUM_PROCESSES)" "$(FUZZ_BASE_WORKDIR)"
# =========
# UTILITIES
# =========

34
make/fuzz_flags.mk Normal file

@ -0,0 +1,34 @@
FUZZPKG = brontide lnwire wtwire
FUZZ_TEST_RUN_TIME = 30
FUZZ_TEST_TIMEOUT = 20
FUZZ_NUM_PROCESSES = 4
FUZZ_BASE_WORKDIR = $(shell pwd)/fuzz
# If specific package is being fuzzed, construct the full name of the
# subpackage.
ifneq ($(pkg),)
FUZZPKG := $(pkg)
endif
# The default run time per fuzz test is pretty low and normally will be
# overwritten by a user depending on the time they have available.
ifneq ($(run_time),)
FUZZ_TEST_RUN_TIME := $(run_time)
endif
# If the timeout needs to be increased, overwrite the default value.
ifneq ($(timeout),)
FUZZ_TEST_TIMEOUT := $(timeout)
endif
# Overwrites the number of parallel processes. Should be set to the number of
# processor cores in a system.
ifneq ($(processes),)
FUZZ_NUM_PROCESSES := $(processes)
endif
# Overwrite the base work directory for the fuzz run. Can be used to supply any
# previously generated corpus.
ifneq ($(base_workdir),)
FUZZ_BASE_WORKDIR := $(base_workdir)
endif

90
scripts/fuzz.sh Executable file

@ -0,0 +1,90 @@
#!/bin/bash
set -e
function build_fuzz() {
PACKAGES=$1
for pkg in $PACKAGES; do
pushd fuzz/$pkg
for file in *.go; do
if [[ "$file" == "fuzz_utils.go" ]]; then
continue
fi
NAME=$(echo $file | sed 's/\.go$//1')
echo "Building zip file for $pkg/$NAME"
go-fuzz-build -func "Fuzz_$NAME" -o "$pkg-$NAME-fuzz.zip" "github.com/lightningnetwork/lnd/fuzz/$pkg"
done
popd
done
}
# timeout is a cross platform alternative to the GNU timeout command that
# unfortunately isn't available on macOS by default.
timeout() {
time=$1
$2 &
pid=$!
sleep $time
kill -s SIGINT $pid
}
function run_fuzz() {
PACKAGES=$1
RUN_TIME=$2
TIMEOUT=$3
PROCS=$4
BASE_WORKDIR=$5
for pkg in $PACKAGES; do
pushd fuzz/$pkg
for file in *.go; do
if [[ "$file" == "fuzz_utils.go" ]]; then
continue
fi
NAME=$(echo $file | sed 's/\.go$//1')
WORKDIR=$BASE_WORKDIR/$pkg/$NAME
mkdir -p $WORKDIR
echo "Running fuzzer $pkg-$NAME-fuzz.zip with $PROCS processors for $RUN_TIME seconds"
COMMAND="go-fuzz -bin=$pkg-$NAME-fuzz.zip -workdir=$WORKDIR -procs=$PROCS -timeout=$TIMEOUT"
echo "$COMMAND"
timeout "$RUN_TIME" "$COMMAND"
done
popd
done
}
# usage prints the usage of the whole script.
function usage() {
echo "Usage: "
echo "fuzz.sh build <packages>"
echo "fuzz.sh run <packages> <run_time> <timeout>"
}
# Extract the sub command and remove it from the list of parameters by shifting
# them to the left.
SUBCOMMAND=$1
shift
# Call the function corresponding to the specified sub command or print the
# usage if the sub command was not found.
case $SUBCOMMAND in
build)
echo "Building fuzz packages"
build_fuzz "$@"
;;
run)
echo "Running fuzzer"
run_fuzz "$@"
;;
*)
usage
exit 1
;;
esac