diff --git a/configure.ac b/configure.ac index 45277d967..a3ab56fa4 100644 --- a/configure.ac +++ b/configure.ac @@ -1253,6 +1253,18 @@ if test x$coverage = xtrue; then CFLAGS="${CFLAGS} -g -O0" fi +if test x$fuzzing = xtrue; then + if test x$libfuzzer = x; then + AC_MSG_NOTICE([fuzz targets enabled without libFuzzer, using local driver]) + CFLAGS="${CFLAGS} -fsanitize=address" + libfuzzer="libFuzzerLocal.a" + else + # required for libFuzzer + FUZZING_LDFLAGS="-stdlib=libc++ -lstdc++" + AC_SUBST(FUZZING_LDFLAGS) + fi +fi + if test x$ruby_gems = xtrue; then AC_PATH_PROG([GEM], [gem], [], [$PATH:/bin:/usr/bin:/usr/local/bin]) if test x$GEM = x; then diff --git a/fuzz/Makefile.am b/fuzz/Makefile.am index 66debc226..6d3d83ff7 100644 --- a/fuzz/Makefile.am +++ b/fuzz/Makefile.am @@ -1,12 +1,12 @@ -CPPFLAGS = @CPPFLAGS@ \ +AM_CPPFLAGS = @CPPFLAGS@ \ -I$(top_srcdir)/src/libstrongswan \ -DPLUGINDIR=\""$(abs_top_builddir)/src/libstrongswan/plugins\"" \ -DPLUGINS="\"${fuzz_plugins}\"" -LDFLAGS = @LDFLAGS@ ${libfuzzer} \ +fuzz_ldflags = ${libfuzzer} \ $(top_builddir)/src/libstrongswan/.libs/libstrongswan.a \ -Wl,-Bstatic -lgmp -Wl,-Bdynamic \ - -stdlib=libc++ -lstdc++ + @FUZZING_LDFLAGS@ FUZZ_TARGETS=fuzz_certs @@ -14,5 +14,9 @@ all-local: $(FUZZ_TARGETS) CLEANFILES=$(FUZZ_TARGETS) -fuzz_certs: fuzz_certs.c - $(CC) $(CPPFLAGS) $(CFLAGS) -o $@ $< $(LDFLAGS) +fuzz_certs: fuzz_certs.c ${libfuzzer} + $(CC) $(AM_CPPFLAGS) $(CFLAGS) -o $@ $< $(fuzz_ldflags) + +noinst_LIBRARIES = libFuzzerLocal.a +libFuzzerLocal_a_SOURCES = libFuzzerLocal.c +libFuzzerLocal_a_LIBADD = $(top_builddir)/src/libstrongswan/libstrongswan.la diff --git a/fuzz/libFuzzerLocal.c b/fuzz/libFuzzerLocal.c new file mode 100644 index 000000000..af5c50c66 --- /dev/null +++ b/fuzz/libFuzzerLocal.c @@ -0,0 +1,59 @@ +/* + * Copyright (C) 2017 Tobias Brunner + * HSR Hochschule fuer Technik Rapperswil + * + * 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 2 of the License, or (at your + * option) any later version. See . + * + * 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. + */ + +#include +#include +#include +#include + +extern int LLVMFuzzerTestOneInput(const unsigned char *data, size_t size); +__attribute__((weak)) extern int LLVMFuzzerInitialize(int *argc, char ***argv); + +/** + * This is a simple driver for the fuzz targets to verify test inputs outside + * of OSS-Fuzz. + * + * Failures will usually cause crashes. + */ +int main(int argc, char **argv) +{ + chunk_t *data; + int i, res = 0; + + fprintf(stderr, "%s: running %d inputs\n", argv[0], argc - 1); + if (LLVMFuzzerInitialize) + { + LLVMFuzzerInitialize(&argc, &argv); + } + for (i = 1; i < argc; i++) + { + fprintf(stderr, "running: %s\n", argv[i]); + data = chunk_map(argv[i], FALSE); + if (!data) + { + fprintf(stderr, "opening %s failed: %s\n", argv[i], strerror(errno)); + return 1; + } + res = LLVMFuzzerTestOneInput(data->ptr, data->len); + fprintf(stderr, "done: %s: (%zd bytes)\n", argv[i], data->len); + chunk_unmap(data); + if (res) + { + break; + } + } + fprintf(stderr, "%s: completed %d inputs\n", argv[0], i-1); + return res; +}