fuzz: Adds fuzz target for parse_jobs_ini
authorPhilippe Antoine <contact@catenacyber.fr>
Tue, 5 Jan 2021 11:59:46 +0000 (12:59 +0100)
committerPhilippe Antoine <contact@catenacyber.fr>
Mon, 11 Jan 2021 10:33:08 +0000 (11:33 +0100)
And build it

Signed-off-by: Philippe Antoine <contact@catenacyber.fr>
Makefile
init.c
t/fuzz/fuzz_parseini.c [new file with mode: 0644]
t/fuzz/onefile.c [new file with mode: 0644]

index a838af9a773b6aee8568d058366a045fb0cc8e8a..f74e59e1242caf1d59c70d0a4936d51e67d584e5 100644 (file)
--- 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 f9c20bdb17993e6f5c1003ace756af91d914c47f..cda16c4d7a6b5627901a429bc9c0553533c92884 100644 (file)
--- 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 (file)
index 0000000..7e422c1
--- /dev/null
@@ -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 (file)
index 0000000..2ed3bbe
--- /dev/null
@@ -0,0 +1,51 @@
+#include <stdint.h>
+#include <stdlib.h>
+#include <stdio.h>
+
+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;
+}