From 0c6e034459610ca3abef650512a0b5c8ab552799 Mon Sep 17 00:00:00 2001 From: Alex Chernyakhovsky Date: Mon, 30 May 2022 20:00:04 -0400 Subject: [PATCH] Add fuzzing infrastructure This commit adds the --enable-fuzzing (and --enable-asan, to make fuzzing more useful) options and a sample fuzzer for the terminal parser. At this time only libfuzzer is supported. Future changes to add AFL to get more fuzzing capability should be possible with the addition of the afl_driver.cc from Chromium. --- configure.ac | 37 +++++++++++++++++- src/fuzz/Makefile.am | 7 ++++ .../7164cb6ab7e834fa6145bcf283e94b981313980d | 2 + .../71853c6197a6a7f222db0f1978c7cb232b87c5ee | 2 + .../7b98b1bb85d1afb4f154cfbe9c3d4791024a86b7 | Bin 0 -> 8 bytes .../8a92b4d6e188b3e2fa7add9e123b702ed11f3695 | Bin 0 -> 33 bytes .../99feeb7f36e52ff59d86c975a8e5ad1a2ab4629e | Bin 0 -> 17 bytes .../9d5e4e241c99c93786eeddcd93c5ec23dd563881 | Bin 0 -> 129 bytes .../9e016e2a52e879c9c6482303eea8eb7d92b4dd38 | Bin 0 -> 4 bytes .../a09fd95888cb80e1dcea4cc9dbd7d76928909927 | 2 + .../abb6d63b8f739c45c3c44f1772b88338e9b5e7a3 | Bin 0 -> 128 bytes .../adc83b19e793491b1c6ea0fd8b46cd9f32e592fc | 1 + .../b67f23988e8274fcf6150a18dacb5ab3db49520d | 2 + src/fuzz/terminal_parser_fuzzer.cc | 15 +++++++ 14 files changed, 67 insertions(+), 1 deletion(-) create mode 100644 src/fuzz/Makefile.am create mode 100644 src/fuzz/terminal_parser_corpus/7164cb6ab7e834fa6145bcf283e94b981313980d create mode 100644 src/fuzz/terminal_parser_corpus/71853c6197a6a7f222db0f1978c7cb232b87c5ee create mode 100644 src/fuzz/terminal_parser_corpus/7b98b1bb85d1afb4f154cfbe9c3d4791024a86b7 create mode 100644 src/fuzz/terminal_parser_corpus/8a92b4d6e188b3e2fa7add9e123b702ed11f3695 create mode 100644 src/fuzz/terminal_parser_corpus/99feeb7f36e52ff59d86c975a8e5ad1a2ab4629e create mode 100644 src/fuzz/terminal_parser_corpus/9d5e4e241c99c93786eeddcd93c5ec23dd563881 create mode 100644 src/fuzz/terminal_parser_corpus/9e016e2a52e879c9c6482303eea8eb7d92b4dd38 create mode 100644 src/fuzz/terminal_parser_corpus/a09fd95888cb80e1dcea4cc9dbd7d76928909927 create mode 100644 src/fuzz/terminal_parser_corpus/abb6d63b8f739c45c3c44f1772b88338e9b5e7a3 create mode 100644 src/fuzz/terminal_parser_corpus/adc83b19e793491b1c6ea0fd8b46cd9f32e592fc create mode 100644 src/fuzz/terminal_parser_corpus/b67f23988e8274fcf6150a18dacb5ab3db49520d create mode 100644 src/fuzz/terminal_parser_fuzzer.cc diff --git a/configure.ac b/configure.ac index 72836fd..c9bf889 100644 --- a/configure.ac +++ b/configure.ac @@ -68,6 +68,41 @@ AC_ARG_ENABLE([compile-warnings], AC_SUBST([WARNING_CXXFLAGS]) AC_SUBST([PICKY_CXXFLAGS]) +# Check for fuzzing support before the flag wrapper, because if +# requested and missing the functionality is entirely nonexistent. +MISC_CXXFLAGS="" +AC_ARG_ENABLE([fuzzing], + [AS_HELP_STRING([--enable-fuzzing], + [Enable compiler and linker options to enable fuzz testing @<:@no/yes/libfuzzer@:>@])], + [case "$enableval" in + no) + ;; + '' | yes | libfuzzer) + AX_CHECK_COMPILE_FLAG([-fsanitize=fuzzer], + [FUZZING_CFLAGS="$FUZZING_CFLAGS -fsanitize=fuzzer"], [ + AC_MSG_ERROR([Fuzzing requested, but compiler support not present])], [-Werror]) + ;; + *) + AC_MSG_ERROR(["Unknown argument '$enableval' to --enable-fuzzing]) + ;; + esac], + []) +AC_SUBST([FUZZING_CFLAGS]) +AC_SUBST([MISC_CXXFLAGS]) + +AC_ARG_ENABLE([asan], + [AS_HELP_STRING([--enable-asan], + [Enable compiler and linker options to enable AddressSanitizer @<:@no@:>@])], + [asan="$enableval"], + [asan="no"]) + +AS_IF([test x"$asan" != x"no"], [ + AX_CHECK_COMPILE_FLAG([-fsanitize=address,leak], + [MISC_CXXFLAGS="$MISC_CXXFLAGS -fsanitize=address,leak"], [ + AC_MSG_ERROR([ASAN requested, but compiler support not present])], [-Werror]) +]) +AC_SUBST([MISC_CXXFLAGS]) + # We want to check for compiler flag support, but there is no way to make # clang's "argument unused" warning fatal. So we invoke the compiler through a # wrapper script that greps for this message. @@ -119,7 +154,6 @@ AC_SUBST([HARDEN_CFLAGS]) AC_SUBST([HARDEN_LDFLAGS]) # Also check for a few non-hardening-related flags. -MISC_CXXFLAGS="" AX_CHECK_COMPILE_FLAG([-fno-default-inline], [MISC_CXXFLAGS="$MISC_CXXFLAGS -fno-default-inline"], [], [-Werror]) AX_CHECK_COMPILE_FLAG([-pipe], @@ -526,6 +560,7 @@ AC_CONFIG_FILES([ src/Makefile src/crypto/Makefile src/frontend/Makefile + src/fuzz/Makefile src/include/Makefile src/network/Makefile src/protobufs/Makefile diff --git a/src/fuzz/Makefile.am b/src/fuzz/Makefile.am new file mode 100644 index 0000000..af220f1 --- /dev/null +++ b/src/fuzz/Makefile.am @@ -0,0 +1,7 @@ +AM_CXXFLAGS = $(WARNING_CXXFLAGS) $(PICKY_CXXFLAGS) $(HARDEN_CFLAGS) $(MISC_CXXFLAGS) $(CODE_COVERAGE_CXXFLAGS) $(FUZZING_CFLAGS) + +noinst_PROGRAMS = terminal_parser_fuzzer + +terminal_parser_fuzzer_CPPFLAGS = -I$(srcdir)/../terminal -I$(srcdir)/../util +terminal_parser_fuzzer_LDADD = ../terminal/libmoshterminal.a ../util/libmoshutil.a +terminal_parser_fuzzer_SOURCES = terminal_parser_fuzzer.cc diff --git a/src/fuzz/terminal_parser_corpus/7164cb6ab7e834fa6145bcf283e94b981313980d b/src/fuzz/terminal_parser_corpus/7164cb6ab7e834fa6145bcf283e94b981313980d new file mode 100644 index 0000000..1f8b140 --- /dev/null +++ b/src/fuzz/terminal_parser_corpus/7164cb6ab7e834fa6145bcf283e94b981313980d @@ -0,0 +1,2 @@ +µ + diff --git a/src/fuzz/terminal_parser_corpus/71853c6197a6a7f222db0f1978c7cb232b87c5ee b/src/fuzz/terminal_parser_corpus/71853c6197a6a7f222db0f1978c7cb232b87c5ee new file mode 100644 index 0000000..139597f --- /dev/null +++ b/src/fuzz/terminal_parser_corpus/71853c6197a6a7f222db0f1978c7cb232b87c5ee @@ -0,0 +1,2 @@ + + diff --git a/src/fuzz/terminal_parser_corpus/7b98b1bb85d1afb4f154cfbe9c3d4791024a86b7 b/src/fuzz/terminal_parser_corpus/7b98b1bb85d1afb4f154cfbe9c3d4791024a86b7 new file mode 100644 index 0000000000000000000000000000000000000000..6eec04c2e103b3dcbae42aa92f78e064f32ee470 GIT binary patch literal 8 Pcmdm*%fQ9O#lQdn2_peP literal 0 HcmV?d00001 diff --git a/src/fuzz/terminal_parser_corpus/8a92b4d6e188b3e2fa7add9e123b702ed11f3695 b/src/fuzz/terminal_parser_corpus/8a92b4d6e188b3e2fa7add9e123b702ed11f3695 new file mode 100644 index 0000000000000000000000000000000000000000..0dddd61ea5b90fad4ee2c53a287fbaaa8a0b6820 GIT binary patch literal 33 Rcmd-wLIeMi03!nf8vx6P4<-Nr literal 0 HcmV?d00001 diff --git a/src/fuzz/terminal_parser_corpus/99feeb7f36e52ff59d86c975a8e5ad1a2ab4629e b/src/fuzz/terminal_parser_corpus/99feeb7f36e52ff59d86c975a8e5ad1a2ab4629e new file mode 100644 index 0000000000000000000000000000000000000000..08b4630bc5418b6bb4c94224c66116bfd6f62257 GIT binary patch literal 17 Pcmd=3|DOQ~{QnOCBAEmS literal 0 HcmV?d00001 diff --git a/src/fuzz/terminal_parser_corpus/9d5e4e241c99c93786eeddcd93c5ec23dd563881 b/src/fuzz/terminal_parser_corpus/9d5e4e241c99c93786eeddcd93c5ec23dd563881 new file mode 100644 index 0000000000000000000000000000000000000000..32ae753cd5cb6c6459d4bacb89748b18dc926f00 GIT binary patch literal 129 zcmb>X|NrlQ5MW>cVJ;v>0;oKoL<2;Ui;IB^Ng0?4HU(@D!)k~e2Sgky3pAX|$PmLC E085t~KL7v# literal 0 HcmV?d00001 diff --git a/src/fuzz/terminal_parser_corpus/9e016e2a52e879c9c6482303eea8eb7d92b4dd38 b/src/fuzz/terminal_parser_corpus/9e016e2a52e879c9c6482303eea8eb7d92b4dd38 new file mode 100644 index 0000000000000000000000000000000000000000..803bafdc1d6869b32cbb264d2c8bc8d49e000284 GIT binary patch literal 4 Lcmd<$V&DP*08{`U literal 0 HcmV?d00001 diff --git a/src/fuzz/terminal_parser_corpus/a09fd95888cb80e1dcea4cc9dbd7d76928909927 b/src/fuzz/terminal_parser_corpus/a09fd95888cb80e1dcea4cc9dbd7d76928909927 new file mode 100644 index 0000000..a64f715 --- /dev/null +++ b/src/fuzz/terminal_parser_corpus/a09fd95888cb80e1dcea4cc9dbd7d76928909927 @@ -0,0 +1,2 @@ + +ÿÿÿÿÿÿÿÿ \ No newline at end of file diff --git a/src/fuzz/terminal_parser_corpus/abb6d63b8f739c45c3c44f1772b88338e9b5e7a3 b/src/fuzz/terminal_parser_corpus/abb6d63b8f739c45c3c44f1772b88338e9b5e7a3 new file mode 100644 index 0000000000000000000000000000000000000000..e6d57639fb6bd732e3f06ce45552f78ee5e891b1 GIT binary patch literal 128 vcmb +#include + +#include "parser.h" + +extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) { + Parser::UTF8Parser parser; + Parser::Actions result; + + for (size_t i = 0; i < size; i++) { + parser.input(data[i], result); + } + + return 0; +}