diff --git a/lang/Makefile b/lang/Makefile index 0fd1def3..7e2d49c5 100644 --- a/lang/Makefile +++ b/lang/Makefile @@ -16,7 +16,7 @@ # along with this program. If not, see . SHELL = /usr/bin/env bash -.PHONY: all build clean +.PHONY: all build clean fuzz OLDGOYACC := $(shell go version | grep -E 'go1.6|go1.7') @@ -44,3 +44,6 @@ else goyacc parser.y endif @ROOT="$$( cd "$$( dirname "$${BASH_SOURCE[0]}" )" && cd .. && pwd )" && $$ROOT/misc/header.sh 'y.go' + +fuzz: + @$(MAKE) --quiet -C fuzz diff --git a/lang/fuzz/.gitignore b/lang/fuzz/.gitignore new file mode 100644 index 00000000..9d9320bb --- /dev/null +++ b/lang/fuzz/.gitignore @@ -0,0 +1,4 @@ +corpus/ +crashers/ +suppressions/ +fuzz-fuzz.zip diff --git a/lang/fuzz/Makefile b/lang/fuzz/Makefile new file mode 100644 index 00000000..a51cbb8d --- /dev/null +++ b/lang/fuzz/Makefile @@ -0,0 +1,27 @@ +# Mgmt +# Copyright (C) 2013-2020+ James Shubin and the project contributors +# Written by James Shubin and the project contributors +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +SHELL = /usr/bin/env bash +.PHONY: all fuzz + +all: fuzz + +fuzz: + mkdir -p corpus + find ../.. -name \*.mcl -exec cp {} corpus \; + go-fuzz-build + go-fuzz -bin=./lang-fuzz.zip -workdir=. diff --git a/lang/fuzz/fuzz.go b/lang/fuzz/fuzz.go new file mode 100644 index 00000000..d00858a2 --- /dev/null +++ b/lang/fuzz/fuzz.go @@ -0,0 +1,43 @@ +// Mgmt +// Copyright (C) 2013-2020+ James Shubin and the project contributors +// Written by James Shubin and the project contributors +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +package fuzz + +import ( + "bytes" + + "github.com/purpleidea/mgmt/lang" +) + +// Fuzz is repeatedly called by go-fuzz with semi-random inputs in an attempt to +// make the Lexer/Parser crash. From the go-fuzz docs: Data is a random input +// generated by go-fuzz, note that in most cases it is invalid. The function +// must return 1 if the fuzzer should increase priority of the given input +// during subsequent fuzzing (for example, the input is lexically correct and +// was parsed successfully); -1 if the input must not be added to corpus even if +// gives new coverage; and 0 otherwise; other values are reserved for future +// use. +func Fuzz(data []byte) int { + ast, err := lang.LexParse(bytes.NewReader(data)) + if err != nil { + if ast != nil { + panic("ast != nil on error") + } + return 0 + } + return 1 +} diff --git a/misc/make-deps.sh b/misc/make-deps.sh index 01896618..cf557da5 100755 --- a/misc/make-deps.sh +++ b/misc/make-deps.sh @@ -128,6 +128,7 @@ go get golang.org/x/tools/cmd/stringer # for automatic stringer-ing go get golang.org/x/lint/golint # for `golint`-ing go get golang.org/x/tools/cmd/goimports # for fmt go get github.com/tmthrgd/go-bindata/go-bindata # for compiling in non golang files +go get golang.org/dvyukov/go-fuzz # for fuzzing the mcl lang bits if env | grep -q -e '^TRAVIS=true$' -e '^JENKINS_URL=' -e '^BUILD_TAG=jenkins'; then go get -u gopkg.in/alecthomas/gometalinter.v1 && mv "$(dirname $(command -v gometalinter.v1))/gometalinter.v1" "$(dirname $(command -v gometalinter.v1))/gometalinter" && gometalinter --install # bonus fi