diff options
-rw-r--r-- | Makefile.am | 3 | ||||
-rw-r--r-- | configure.ac | 73 | ||||
-rw-r--r-- | fuzz/Makefile.am | 36 | ||||
-rwxr-xr-x | fuzz/fuzzers.test | 8 | ||||
-rwxr-xr-x | fuzz/init-fuzzers.sh | 23 | ||||
-rwxr-xr-x | fuzz/test-fuzzers.sh | 33 |
6 files changed, 175 insertions, 1 deletions
diff --git a/Makefile.am b/Makefile.am index 670e7a5..5f36fd7 100644 --- a/Makefile.am +++ b/Makefile.am @@ -4,6 +4,9 @@ SUBDIRS = libcnary src include tools test if HAVE_CYTHON SUBDIRS += cython endif +if BUILD_FUZZERS +SUBDIRS += fuzz +endif docs/html: $(top_builddir)/doxygen.cfg $(top_srcdir)/include/plist/*.h rm -rf docs diff --git a/configure.ac b/configure.ac index 1ad1341..43017bf 100644 --- a/configure.ac +++ b/configure.ac @@ -156,6 +156,76 @@ case "$GLOBAL_CFLAGS" in AC_DEFINE([HAVE_FVISIBILITY], [1], [Define if compiled with -fvisibility=hidden]) esac +AC_ARG_WITH([fuzzers], + [AS_HELP_STRING([--with-fuzzers], + [build fuzzers and libplist with sanitizers (default is no)])], + [build_fuzzers=true], + [build_fuzzers=false]) +if test "x$build_fuzzers" = "xtrue"; then + AS_COMPILER_FLAG([-fsanitize=address], [ + SANITIZER_FLAGS+=" -fsanitize=address" + ASAN_AVAILABLE=yes + ], []) + if test "$ASAN_AVAILABLE" = "yes"; then + AS_COMPILER_FLAG([-fsanitize=address -fsanitize-address-use-after-scope], [ + SANITIZER_FLAGS+=" -fsanitize-address-use-after-scope" + ], []) + SANITIZERS+="ASAN " + fi + + AS_COMPILER_FLAG([-fsanitize=undefined], [ + SANITIZER_FLAGS+=" -fsanitize=undefined" + UBSAN_AVAILABLE=yes + ], []) + + if test "$UBSAN_AVAILABLE" = "yes"; then + SANITIZERS+="UBSAN " + fi + + if test -z "$SANITIZER_FLAGS"; then + AC_MSG_ERROR([compiler doesn't support -fsanitize=address nor -fsanitize=undefined]) + fi + + COVERAGE_CHECKS="trace-pc-guard trace-cmp edge" + for COV_CHECK in $COVERAGE_CHECKS; do + AS_COMPILER_FLAG([-fsanitize-coverage=$COV_CHECK], [ + if test -z "$SAN_COV_FLAGS"; then + SAN_COV_FLAGS="$COV_CHECK" + else + SAN_COV_FLAGS+=",$COV_CHECK" + fi + ], []) + done + if test -n "$SAN_COV_FLAGS"; then + SANITIZER_FLAGS+=" -fsanitize-coverage=$SAN_COV_FLAGS" + else + AC_MSG_WARN([No sanitizer coverage supported by compiler]) + fi + + CFLAGS="-O1" + + AS_COMPILER_FLAG([-fno-omit-frame-pointer], [ + CFLAGS+=" -fno-omit-frame-pointer" + ], []) + + AS_COMPILER_FLAG([-gline-tables-only], [ + CFLAGS+=" -gline-tables-only" + ], + [ + CFLAGS+=" -g" + ]) + + CFLAGS+=" -DFUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION" + CFLAGS+=" $SANITIZER_FLAGS" + CXXFLAGS="$CFLAGS -std=c++11" + EXTRA_CONF+=" Build fuzzers ...........: yes +" + EXTRA_CONF+=" Enabled sanitizers ......: $SANITIZERS +" + AS_COMPILER_FLAGS(TEST_CFLAGS, [$CFLAGS]) +fi +AM_CONDITIONAL([BUILD_FUZZERS],[test "x$build_fuzzers" = "xtrue"]) + m4_ifdef([AM_SILENT_RULES],[AM_SILENT_RULES([yes])]) AC_OUTPUT([ @@ -168,6 +238,7 @@ include/Makefile tools/Makefile cython/Makefile test/Makefile +fuzz/Makefile doxygen.cfg ]) @@ -178,7 +249,7 @@ Configuration for $PACKAGE $VERSION: Install prefix ..........: $prefix Debug code ..............: $debug Python bindings .........: $cython_python_bindings - +$EXTRA_CONF Now type 'make' to build $PACKAGE $VERSION, and then 'make install' for installation. " diff --git a/fuzz/Makefile.am b/fuzz/Makefile.am new file mode 100644 index 0000000..b9798f9 --- /dev/null +++ b/fuzz/Makefile.am @@ -0,0 +1,36 @@ +if BUILD_FUZZERS + +libFuzzer.a: Fuzzer/build.sh + @echo "Building $@" + @./Fuzzer/build.sh + +Fuzzer/build.sh: LIBFUZZER_SRC + +LIBFUZZER_SRC: + @if test -d Fuzzer ; then \ + if test -d Fuzzer/.git ; then \ + echo Making sure libFuzzer source tree is up-to-date... ; \ + cd Fuzzer && git checkout . && git pull && cd .. ; \ + fi \ + else \ + echo Checking out libFuzzer source code... ; \ + git clone https://chromium.googlesource.com/chromium/llvm-project/llvm/lib/Fuzzer ; \ + fi + +CLEANFILES = libFuzzer.a + +noinst_PROGRAMS = xplist_fuzzer bplist_fuzzer + +xplist_fuzzer_SOURCES = xplist_fuzzer.cc +xplist_fuzzer_LDFLAGS = -static +xplist_fuzzer_LDADD = $(top_builddir)/src/libplist.la libFuzzer.a + +bplist_fuzzer_SOURCES = bplist_fuzzer.cc +bplist_fuzzer_LDFLAGS = -static +bplist_fuzzer_LDADD = $(top_builddir)/src/libplist.la libFuzzer.a + +TESTS = fuzzers.test + +EXTRA_DIST = bplist.dict xplist.dict init-fuzzers.sh test-fuzzers.sh fuzzers.test + +endif diff --git a/fuzz/fuzzers.test b/fuzz/fuzzers.test new file mode 100755 index 0000000..dd3fb08 --- /dev/null +++ b/fuzz/fuzzers.test @@ -0,0 +1,8 @@ +## -*- sh -*- + +set -e + +./init-fuzzers.sh + +./test-fuzzers.sh + diff --git a/fuzz/init-fuzzers.sh b/fuzz/init-fuzzers.sh new file mode 100755 index 0000000..e48baa8 --- /dev/null +++ b/fuzz/init-fuzzers.sh @@ -0,0 +1,23 @@ +#!/bin/sh + +CURDIR=`pwd` +FUZZDIR=`dirname $0` + +cd ${FUZZDIR} + +if ! test -x xplist_fuzzer || ! test -x bplist_fuzzer; then + echo "ERROR: you need to build the fuzzers first." + cd ${CURDIR} + exit 1 +fi + +mkdir -p xplist-input +cp ../test/data/*.plist xplist-input/ +./xplist_fuzzer -merge=1 xplist-input crashes leaks -dict=xplist.dict + +mkdir -p bplist-input +cp ../test/data/*.bplist bplist-input/ +./bplist_fuzzer -merge=1 bplist-input crashes leaks -dict=bplist.dict + +cd ${CURDIR} +exit 0 diff --git a/fuzz/test-fuzzers.sh b/fuzz/test-fuzzers.sh new file mode 100755 index 0000000..5c758c4 --- /dev/null +++ b/fuzz/test-fuzzers.sh @@ -0,0 +1,33 @@ +#!/bin/sh + +CURDIR=`pwd` +FUZZDIR=`dirname $0` + +cd ${FUZZDIR} + +if ! test -x xplist_fuzzer || ! test -x bplist_fuzzer; then + echo "ERROR: you need to build the fuzzers first." + cd ${CURDIR} + exit 1 +fi + +if ! test -d xplist-input || ! test -d bplist-input; then + echo "ERROR: fuzzer corpora directories are not present. Did you run init-fuzzers.sh ?" + cd ${CURDIR} + exit 1 +fi + +echo "### TESTING xplist_fuzzer ###" +if ! ./xplist_fuzzer xplist-input -dict=xplist.dict -runs=10000; then + cd ${CURDIR} + exit 1 +fi + +echo "### TESTING bplist_fuzzer ###" +if ! ./bplist_fuzzer bplist-input -dict=bplist.dict -runs=10000; then + cd ${CURDIR} + exit 1 +fi + +cd ${CURDIR} +exit 0 |