From 1857e6b259fec189376c9d37a97239402502e5c1 Mon Sep 17 00:00:00 2001 From: Philippe Antoine Date: Tue, 5 Jan 2021 12:59:46 +0100 Subject: [PATCH] fuzz: Adds fuzz target for parse_jobs_ini And build it Signed-off-by: Philippe Antoine --- Makefile | 26 +++++++++++++++++++++ init.c | 2 ++ t/fuzz/fuzz_parseini.c | 41 +++++++++++++++++++++++++++++++++ t/fuzz/onefile.c | 51 ++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 120 insertions(+) create mode 100644 t/fuzz/fuzz_parseini.c create mode 100644 t/fuzz/onefile.c diff --git a/Makefile b/Makefile index a838af9a..f74e59e1 100644 --- a/Makefile +++ b/Makefile @@ -346,6 +346,23 @@ T_MEMLOCK_PROGS = t/memlock T_TT_OBJS = t/time-test.o T_TT_PROGS = t/time-test +T_FUZZ_OBJS = t/fuzz/fuzz_parseini.o +T_FUZZ_OBJS += $(OBJS) +ifdef CONFIG_ARITHMETIC +T_FUZZ_OBJS += lex.yy.o y.tab.o +endif +# in case there is no fuzz driver defined by environment variable LIB_FUZZING_ENGINE, use a simple one +# For instance, with compiler clang, address sanitizer and libFuzzer as a fuzzing engine, you should define +# export CFLAGS="-fsanitize=address,fuzzer-no-link" +# export LIB_FUZZING_ENGINE="-fsanitize=address" +# export CC=clang +# before running configure && make +# You can adapt this with different compilers, sanitizers, and fuzzing engines +ifndef LIB_FUZZING_ENGINE +T_FUZZ_OBJS += t/fuzz/onefile.o +endif +T_FUZZ_PROGS = t/fuzz/fuzz_parseini + T_OBJS = $(T_SMALLOC_OBJS) T_OBJS += $(T_IEEE_OBJS) T_OBJS += $(T_ZIPF_OBJS) @@ -359,6 +376,7 @@ T_OBJS += $(T_PIPE_ASYNC_OBJS) T_OBJS += $(T_MEMLOCK_OBJS) T_OBJS += $(T_TT_OBJS) T_OBJS += $(T_IOU_RING_OBJS) +T_OBJS += $(T_FUZZ_OBJS) ifneq (,$(findstring CYGWIN,$(CONFIG_TARGET_OS))) T_DEDUPE_OBJS += $(WINDOWS_OBJS) @@ -382,6 +400,7 @@ endif ifneq (,$(findstring Linux,$(CONFIG_TARGET_OS))) T_TEST_PROGS += $(T_IOU_RING_PROGS) endif +T_TEST_PROGS += $(T_FUZZ_PROGS) PROGS += $(T_PROGS) @@ -533,6 +552,13 @@ t/ieee754: $(T_IEEE_OBJS) fio: $(FIO_OBJS) $(QUIET_LINK)$(CC) $(LDFLAGS) -o $@ $(FIO_OBJS) $(LIBS) $(HDFSLIB) +t/fuzz/fuzz_parseini: $(T_FUZZ_OBJS) +ifndef LIB_FUZZING_ENGINE + $(QUIET_LINK)$(CC) $(LDFLAGS) -o $@ $(T_FUZZ_OBJS) $(LIBS) $(HDFSLIB) +else + $(QUIET_LINK)$(CXX) $(LDFLAGS) -o $@ $(T_FUZZ_OBJS) $(LIB_FUZZING_ENGINE) $(LIBS) $(HDFSLIB) +endif + gfio: $(GFIO_OBJS) $(QUIET_LINK)$(CC) $(filter-out -static, $(LDFLAGS)) -o gfio $(GFIO_OBJS) $(LIBS) $(GFIO_LIBS) $(GTK_LDFLAGS) $(HDFSLIB) diff --git a/init.c b/init.c index f9c20bdb..cda16c4d 100644 --- a/init.c +++ b/init.c @@ -327,6 +327,7 @@ void free_threads_shm(void) static void free_shm(void) { +#ifndef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION if (nr_segments) { flow_exit(); fio_debug_jobp = NULL; @@ -343,6 +344,7 @@ static void free_shm(void) fio_filelock_exit(); file_hash_exit(); scleanup(); +#endif } static int add_thread_segment(void) diff --git a/t/fuzz/fuzz_parseini.c b/t/fuzz/fuzz_parseini.c new file mode 100644 index 00000000..7e422c18 --- /dev/null +++ b/t/fuzz/fuzz_parseini.c @@ -0,0 +1,41 @@ +#include "fio.h" + +static int initialized = 0; + +const char *const fakeargv[] = {(char *) "fuzz", + (char *) "--output", (char *) "/dev/null", + (char *) "--parse-only", + 0}; + +int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) +{ + char *fuzzedini; + + if (size < 2) + return 0; + + if (initialized == 0) { + if (fio_init_options()) { + printf("Failed fio_init_options\n"); + return 1; + } + + parse_cmd_line(4, (char **) fakeargv, 0); + sinit(); + + initialized = 1; + } + fuzzedini = malloc(size); + if (!fuzzedini) { + printf("Failed malloc\n"); + return 1; + } + /* final character is type for parse_jobs_ini */ + memcpy(fuzzedini, data, size - 1); + /* ensures final 0 */ + fuzzedini[size - 1] = 0; + + parse_jobs_ini(fuzzedini, 1, 0, data[size - 1]); + free(fuzzedini); + return 0; +} diff --git a/t/fuzz/onefile.c b/t/fuzz/onefile.c new file mode 100644 index 00000000..2ed3bbe6 --- /dev/null +++ b/t/fuzz/onefile.c @@ -0,0 +1,51 @@ +#include +#include +#include + +int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size); + +int main(int argc, char** argv) +{ + FILE *fp; + uint8_t *data; + size_t size; + + if (argc != 2) + return 1; + + /* opens the file, get its size, and reads it into a buffer */ + fp = fopen(argv[1], "rb"); + if (fp == NULL) + return 2; + + if (fseek(fp, 0L, SEEK_END) != 0) { + fclose(fp); + return 2; + } + size = ftell(fp); + if (size == (size_t) -1) { + fclose(fp); + return 2; + } + if (fseek(fp, 0L, SEEK_SET) != 0) { + fclose(fp); + return 2; + } + data = malloc(size); + if (data == NULL) { + fclose(fp); + return 2; + } + if (fread(data, size, 1, fp) != 1) { + fclose(fp); + free(data); + return 2; + } + + /* launch fuzzer */ + LLVMFuzzerTestOneInput(data, size); + free(data); + fclose(fp); + + return 0; +} -- 2.25.1