diff --git a/Makefile.am b/Makefile.am index 10f7b15..fb571ec 100644 --- a/Makefile.am +++ b/Makefile.am @@ -31,6 +31,7 @@ include erasure_code/Makefile.am include raid/Makefile.am include crc/Makefile.am include igzip/Makefile.am +include tests/fuzz/Makefile.am # LIB version info not necessarily the same as package version LIBISAL_CURRENT=2 diff --git a/Makefile.unx b/Makefile.unx index bfc0dae..b8c7a03 100644 --- a/Makefile.unx +++ b/Makefile.unx @@ -33,9 +33,13 @@ default: lib include $(foreach unit,$(units), $(unit)/Makefile.am) +ifneq (,$(findstring igzip,$(units))) + include tests/fuzz/Makefile.am +endif + # Override individual lib names to make one inclusive library. lib_name := bin/isa-l.a include make.inc -VPATH = . $(units) include +VPATH = . $(units) include tests/fuzz diff --git a/igzip/Makefile.am b/igzip/Makefile.am index 09d9187..c960cba 100644 --- a/igzip/Makefile.am +++ b/igzip/Makefile.am @@ -114,7 +114,6 @@ lsrc += igzip/huff_codes.c # Include tools and tests using the reference inflate other_tests += igzip/igzip_inflate_perf other_tests += igzip/igzip_inflate_test -other_tests += igzip/igzip_fuzz_inflate lsrc += igzip/igzip_inflate.c other_src += igzip/checksum_test_ref.h @@ -125,6 +124,3 @@ igzip_inflate_test: LDLIBS += -lz igzip_igzip_inflate_test_LDADD = libisal.la igzip_igzip_inflate_test_LDFLAGS = -lz igzip_igzip_hist_perf_LDADD = libisal.la -igzip_fuzz_inflate: LDLIBS += -lz -igzip_igzip_fuzz_inflate_LDADD = libisal.la -igzip_igzip_fuzz_inflate_LDFLAGS = -lz diff --git a/igzip/igzip_fuzz_inflate.c b/igzip/igzip_fuzz_inflate.c deleted file mode 100644 index af9c72e..0000000 --- a/igzip/igzip_fuzz_inflate.c +++ /dev/null @@ -1,96 +0,0 @@ -#define _FILE_OFFSET_BITS 64 -#include -#include -#include -#include "huff_codes.h" -#include "igzip_lib.h" -#include "test.h" - -#define OUT_BUFFER_SIZE 64*1024 - -int main(int argc, char *argv[]) -{ - FILE *in = NULL; - unsigned char *in_buf = NULL, *isal_out_buf = NULL, *zlib_out_buf = NULL; - uint64_t in_file_size; - int out_buf_size, zret, iret; - struct inflate_state *state = NULL; - z_stream zstate; - char z_msg_invalid_code_set[] = "invalid code lengths set"; - char z_msg_invalid_dist_set[] = "invalid distances set"; - char z_msg_invalid_lit_len_set[] = "invalid literal/lengths set"; - - if (argc != 2) { - fprintf(stderr, "Usage: isal_inflate_file_perf infile\n" - "\t - Runs multiple iterations of igzip on a file to " - "get more accurate time results.\n"); - exit(1); - } - in = fopen(argv[1], "rb"); - if (!in) { - fprintf(stderr, "Can't open %s for reading\n", argv[1]); - exit(1); - } - - /* Allocate space for entire input file and output - * (assuming some possible expansion on output size) - */ - in_file_size = get_filesize(in); - - out_buf_size = OUT_BUFFER_SIZE; - - state = malloc(sizeof(struct inflate_state)); - in_buf = malloc(in_file_size); - isal_out_buf = malloc(OUT_BUFFER_SIZE); - zlib_out_buf = malloc(OUT_BUFFER_SIZE); - - if (state == NULL || in_buf == NULL || isal_out_buf == NULL || zlib_out_buf == NULL) { - fprintf(stderr, "Failed to malloc input and outputs buffers\n"); - exit(1); - } - - fread(in_buf, 1, in_file_size, in); - - /* Inflate data with isal_inflate */ - memset(state, 0xff, sizeof(struct inflate_state)); - - isal_inflate_init(state); - state->next_in = in_buf; - state->avail_in = in_file_size; - state->next_out = isal_out_buf; - state->avail_out = out_buf_size; - - iret = isal_inflate_stateless(state); - - /* Inflate data with zlib */ - zstate.zalloc = Z_NULL; - zstate.zfree = Z_NULL; - zstate.opaque = Z_NULL; - zstate.avail_in = in_file_size; - zstate.next_in = in_buf; - zstate.avail_out = out_buf_size; - zstate.next_out = zlib_out_buf; - inflateInit2(&zstate, -15); - - zret = inflate(&zstate, Z_FINISH); - - if (zret == Z_STREAM_END) { - /* If zlib finished, assert isal finished with the same answer */ - assert(state->block_state == ISAL_BLOCK_FINISH); - assert(zstate.total_out == state->total_out); - assert(memcmp(isal_out_buf, zlib_out_buf, state->total_out) == 0); - } else if (zret < 0) { - if (zret != Z_BUF_ERROR) - /* If zlib errors, assert isal errors, excluding a few - * cases where zlib is overzealous */ - assert(iret < 0 || strcmp(zstate.msg, z_msg_invalid_code_set) == 0 - || strcmp(zstate.msg, z_msg_invalid_dist_set) == 0 - || strcmp(zstate.msg, z_msg_invalid_lit_len_set) == 0); - } else - /* If zlib did not finish or error, assert isal did not finish - * or that isal found an invalid header since isal notices the - * error faster than zlib */ - assert(iret > 0 || iret == ISAL_INVALID_BLOCK); - - return 0; -} diff --git a/make.inc b/make.inc index 85efc29..d3aca79 100644 --- a/make.inc +++ b/make.inc @@ -126,18 +126,27 @@ all_tests = $(notdir $(sort $(perf_tests) $(check_tests) $(unit_tests) $(example all_unit_tests = $(notdir $(sort $(check_tests) $(unit_tests))) all_perf_tests = $(notdir $(sort $(perf_tests))) all_check_tests = $(notdir $(sort $(check_tests))) +all_llvm_fuzz_tests = $(notdir $(sort $(llvm_fuzz_tests))) $(all_unit_tests): % : %.c $(lib_name) $(all_perf_tests): % : %.c $(lib_name) $(sort $(notdir $(examples))): % : %.c $(lib_name) $(sort $(notdir $(other_tests))): % : %.c $(lib_name) +$(all_llvm_fuzz_tests): LDLIBS += -lFuzzer +$(all_llvm_fuzz_tests): CFLAGS += -fsanitize-coverage=trace-pc-guard -fsanitize=address +$(all_llvm_fuzz_tests): CXXFLAGS += -fsanitize-coverage=trace-pc-guard -fsanitize=address +$(all_llvm_fuzz_tests): % : %.o $(lib_name) + $(CXX) $(CXXFLAGS) $^ $(LDLIBS) -o $@ + + sim test trace: $(addsuffix .run,$(all_unit_tests)) perf: $(addsuffix .run,$(all_perf_tests)) check: $(addsuffix .run,$(all_check_tests)) ex: $(notdir $(examples)) all: lib $(all_tests) other: $(notdir $(other_tests)) +llvm_fuzz_tests: $(all_llvm_fuzz_tests) tests: $(all_unit_tests) perfs: $(all_perf_tests) checks: $(all_check_tests) @@ -273,7 +282,7 @@ perf_report: clean: @echo Cleaning up - @$(RM) -r $(O) *.o *.a $(all_tests) $(lib_name) $(so_lib_name) + @$(RM) -r $(O) *.o *.a $(all_tests) $(lib_name) $(so_lib_name) $(all_llvm_fuzz_tests) doc: isa-l.h diff --git a/tests/fuzz/Makefile.am b/tests/fuzz/Makefile.am new file mode 100644 index 0000000..ccbb8c3 --- /dev/null +++ b/tests/fuzz/Makefile.am @@ -0,0 +1,52 @@ +######################################################################## +# Copyright(c) 2011-2017 Intel Corporation All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in +# the documentation and/or other materials provided with the +# distribution. +# * Neither the name of Intel Corporation nor the names of its +# contributors may be used to endorse or promote products derived +# from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +######################################################################## + +src_include += -I $(srcdir)/tests/fuzz + +# AFL fuzz tests +other_tests += tests/fuzz/igzip_fuzz_inflate +igzip_fuzz_inflate: igzip_checked_inflate_fuzz_test.o +igzip_fuzz_inflate: LDLIBS += -lz +tests_fuzz_igzip_fuzz_inflate_LDADD = tests/fuzz/igzip_checked_inflate_fuzz_test.lo libisal.la +tests_fuzz_igzip_fuzz_inflate_LDFLAGS = -lz + +other_tests += tests/fuzz/igzip_dump_inflate_corpus +tests_fuzz_igzip_dump_inflate_corpus_LDADD = libisal.la + +# LLVM fuzz tests +llvm_fuzz_tests = tests/fuzz/igzip_simple_inflate_fuzz_test +other_src += tests/fuzz/igzip_simple_inflate_fuzz_test.c + +llvm_fuzz_tests += tests/fuzz/igzip_checked_inflate_fuzz_test +other_src += tests/fuzz/igzip_checked_inflate_fuzz_test.c + +llvm_fuzz_tests += tests/fuzz/igzip_simple_round_trip_fuzz_test +other_src += tests/fuzz/igzip_simple_round_trip_fuzz_test.c + +igzip_checked_inflate_fuzz_test: LDLIBS += -lz diff --git a/tests/fuzz/Makefile.unx b/tests/fuzz/Makefile.unx new file mode 100644 index 0000000..afa20a3 --- /dev/null +++ b/tests/fuzz/Makefile.unx @@ -0,0 +1,12 @@ + +default: llvm_fuzz_tests + +include ../../igzip/Makefile.am +include Makefile.am +include ../../make.inc + +CC = clang +CXX = clang++ +CXXFLAGS += $(DEFINES) + +VPATH = . ../../igzip ../../include diff --git a/tests/fuzz/igzip_checked_inflate_fuzz_test.c b/tests/fuzz/igzip_checked_inflate_fuzz_test.c new file mode 100644 index 0000000..376c0d3 --- /dev/null +++ b/tests/fuzz/igzip_checked_inflate_fuzz_test.c @@ -0,0 +1,69 @@ +#include +#include +#include +#include +#include +#include +#include "igzip_lib.h" + +int LLVMFuzzerTestOneInput(const uint8_t * data, size_t size) +{ + struct inflate_state state; + z_stream zstate; + size_t out_buf_size = 2 * size; + int zret, iret; + char z_msg_invalid_code_set[] = "invalid code lengths set"; + char z_msg_invalid_dist_set[] = "invalid distances set"; + char z_msg_invalid_lit_len_set[] = "invalid literal/lengths set"; + + uint8_t *isal_out_buf = (uint8_t *) malloc(size * 2); + uint8_t *zlib_out_buf = (uint8_t *) malloc(size * 2); + + assert(NULL != isal_out_buf && NULL != zlib_out_buf); + + /* Inflate data with isal_inflate */ + memset(&state, 0xff, sizeof(struct inflate_state)); + + isal_inflate_init(&state); + state.next_in = (uint8_t *) data; + state.avail_in = size; + state.next_out = isal_out_buf; + state.avail_out = out_buf_size; + + iret = isal_inflate_stateless(&state); + + /* Inflate data with zlib */ + zstate.zalloc = Z_NULL; + zstate.zfree = Z_NULL; + zstate.opaque = Z_NULL; + zstate.avail_in = size; + zstate.next_in = (Bytef *) data; + zstate.avail_out = out_buf_size; + zstate.next_out = zlib_out_buf; + inflateInit2(&zstate, -15); + + zret = inflate(&zstate, Z_FINISH); + + if (zret == Z_STREAM_END) { + /* If zlib finished, assert isal finished with the same answer */ + assert(state.block_state == ISAL_BLOCK_FINISH); + assert(zstate.total_out == state.total_out); + assert(memcmp(isal_out_buf, zlib_out_buf, state.total_out) == 0); + } else if (zret < 0) { + if (zret != Z_BUF_ERROR) + /* If zlib errors, assert isal errors, excluding a few + * cases where zlib is overzealous */ + assert(iret < 0 || strcmp(zstate.msg, z_msg_invalid_code_set) == 0 + || strcmp(zstate.msg, z_msg_invalid_dist_set) == 0 + || strcmp(zstate.msg, z_msg_invalid_lit_len_set) == 0); + } else + /* If zlib did not finish or error, assert isal did not finish + * or that isal found an invalid header since isal notices the + * error faster than zlib */ + assert(iret > 0 || iret == ISAL_INVALID_BLOCK); + + inflateEnd(&zstate); + free(isal_out_buf); + free(zlib_out_buf); + return 0; +} diff --git a/tests/fuzz/igzip_dump_inflate_corpus.c b/tests/fuzz/igzip_dump_inflate_corpus.c new file mode 100644 index 0000000..490655e --- /dev/null +++ b/tests/fuzz/igzip_dump_inflate_corpus.c @@ -0,0 +1,37 @@ +#include +#include +#include +#include "inflate_std_vects.h" + +#define FNAME_MAX 180 + +int main(int argc, char *argv[]) +{ + uint8_t *buf; + int i, len, err; + FILE *fout = NULL; + char fname[FNAME_MAX]; + char dname[FNAME_MAX]; + + if (argc != 2) { + fprintf(stderr, "Usage: %s \n", argv[0]); + exit(1); + } + strncpy(dname, argv[1], FNAME_MAX); + + for (i = 0; i < sizeof(std_vect_array) / sizeof(struct vect_result); i++) { + buf = std_vect_array[i].vector; + len = std_vect_array[i].vector_length; + err = std_vect_array[i].expected_error; + + snprintf(fname, FNAME_MAX, "%s/inflate_corp_n%03d_e%d", dname, i, err); + printf(" writing %s\n", fname); + fout = fopen(fname, "w+"); + if (!fout) { + fprintf(stderr, "Can't open %s for writing\n", fname); + exit(1); + } + fwrite(buf, len, 1, fout); + fclose(fout); + } +} diff --git a/tests/fuzz/igzip_fuzz_inflate.c b/tests/fuzz/igzip_fuzz_inflate.c new file mode 100644 index 0000000..85050b2 --- /dev/null +++ b/tests/fuzz/igzip_fuzz_inflate.c @@ -0,0 +1,37 @@ +#define _FILE_OFFSET_BITS 64 +#include +#include +#include +#include "huff_codes.h" +#include "igzip_lib.h" +#include "test.h" + +extern int LLVMFuzzerTestOneInput(const uint8_t * data, size_t size); + +int main(int argc, char *argv[]) +{ + FILE *in = NULL; + unsigned char *in_buf = NULL; + uint64_t in_file_size; + + if (argc != 2) { + fprintf(stderr, "Usage: isal_fuzz_inflate \n"); + exit(1); + } + in = fopen(argv[1], "rb"); + if (!in) { + fprintf(stderr, "Can't open %s for reading\n", argv[1]); + exit(1); + } + in_file_size = get_filesize(in); + in_buf = malloc(in_file_size); + + if (in_buf == NULL) { + fprintf(stderr, "Failed to malloc input and outputs buffers\n"); + exit(1); + } + + fread(in_buf, 1, in_file_size, in); + + return LLVMFuzzerTestOneInput(in_buf, in_file_size); +} diff --git a/tests/fuzz/igzip_simple_inflate_fuzz_test.c b/tests/fuzz/igzip_simple_inflate_fuzz_test.c new file mode 100644 index 0000000..b5f22e8 --- /dev/null +++ b/tests/fuzz/igzip_simple_inflate_fuzz_test.c @@ -0,0 +1,22 @@ +#include +#include +#include +#include "igzip_lib.h" + +int LLVMFuzzerTestOneInput(const uint8_t * data, size_t size) +{ + struct inflate_state state; + uint8_t *isal_out_buf = (uint8_t *) (malloc(size * 2)); + size_t out_buf_size = 2 * size; + + isal_inflate_init(&state); + state.next_in = (uint8_t *) data; + state.avail_in = size; + state.next_out = isal_out_buf; + state.avail_out = out_buf_size; + + isal_inflate_stateless(&state); + + free(isal_out_buf); + return 0; +} diff --git a/tests/fuzz/igzip_simple_round_trip_fuzz_test.c b/tests/fuzz/igzip_simple_round_trip_fuzz_test.c new file mode 100644 index 0000000..106fc3c --- /dev/null +++ b/tests/fuzz/igzip_simple_round_trip_fuzz_test.c @@ -0,0 +1,113 @@ +#include +#include +#include +#include +#include +#include +#include "igzip_lib.h" + +#define LEVEL_BITS 2 +#define HEADER_BITS 3 +#define LVL_BUF_BITS 3 + +#define LEVEL_BIT_MASK ((1< (y)) ? y : x ) + +const int header_size[] = { + 0, //IGZIP_DEFLATE + 10, //IGZIP_GZIP + 0, //IGZIP_GZIP_NO_HDR + 2, //IGZIP_ZLIB + 0, //IGZIP_ZLIB_NO_HDR +}; + +const int trailer_size[] = { + 0, //IGZIP_DEFLATE + 8, //IGZIP_GZIP + 8, //IGZIP_GZIP_NO_HDR + 4, //IGZIP_ZLIB + 4, //IGZIP_ZLIB_NO_HDR +}; + +int LLVMFuzzerTestOneInput(const uint8_t * data, size_t size) +{ + struct inflate_state istate; + struct isal_zstream cstate; + uint8_t *in_data = (uint8_t *) data; + int ret = 1; + + // Parameter default + int level = 1; + int lev_buf_size = ISAL_DEF_LVL1_DEFAULT; + int wrapper_type = 0; + size_t cmp_buf_size = size + ISAL_DEF_MAX_HDR_SIZE; + + // Parameters are set by one byte of data input + if (size > 1) { + uint8_t in_param = in_data[--size]; + level = MIN(in_param & LEVEL_BIT_MASK, ISAL_DEF_MAX_LEVEL); + in_param >>= LEVEL_BITS; + + wrapper_type = (in_param & HEADER_BIT_MASK) % (IGZIP_ZLIB_NO_HDR + 1); + in_param >>= HEADER_BITS; + + lev_buf_size = (0 == level) ? + ISAL_DEF_LVL0_MIN + (in_param) * (ISAL_DEF_LVL0_EXTRA_LARGE / + LEVEL_BIT_MASK) : + ISAL_DEF_LVL1_MIN + (in_param) * (ISAL_DEF_LVL1_EXTRA_LARGE / + LEVEL_BIT_MASK); + + if (0 == level) + cmp_buf_size = 2 * size + ISAL_DEF_MAX_HDR_SIZE; + else + cmp_buf_size = size + 8 + (TYPE0_HDR_SIZE * (size / TYPE0_MAX_SIZE)); + + cmp_buf_size += header_size[wrapper_type] + trailer_size[wrapper_type]; + } + + uint8_t *isal_cmp_buf = (uint8_t *) malloc(cmp_buf_size); + uint8_t *isal_out_buf = (uint8_t *) malloc(size); + uint8_t *isal_lev_buf = (uint8_t *) malloc(lev_buf_size); + assert(NULL != isal_cmp_buf || NULL != isal_out_buf || NULL != isal_lev_buf); + + isal_deflate_init(&cstate); + cstate.end_of_stream = 1; + cstate.flush = NO_FLUSH; + cstate.next_in = in_data; + cstate.avail_in = size; + cstate.next_out = isal_cmp_buf; + cstate.avail_out = cmp_buf_size; + cstate.level = level; + cstate.level_buf = isal_lev_buf; + cstate.level_buf_size = lev_buf_size; + cstate.gzip_flag = wrapper_type; + ret = isal_deflate_stateless(&cstate); + + isal_inflate_init(&istate); + istate.next_in = isal_cmp_buf + header_size[wrapper_type]; + istate.avail_in = cstate.total_out - header_size[wrapper_type];; + istate.next_out = isal_out_buf; + istate.avail_out = size; + istate.crc_flag = wrapper_type; + ret |= isal_inflate_stateless(&istate); + ret |= memcmp(isal_out_buf, in_data, size); + + // Check trailer + uint32_t crc = 0; + int trailer_idx = cstate.total_out - trailer_size[wrapper_type]; + + if (wrapper_type == IGZIP_GZIP || wrapper_type == IGZIP_GZIP_NO_HDR) + crc = *(uint32_t *) & isal_cmp_buf[trailer_idx]; + else if (wrapper_type == IGZIP_ZLIB || wrapper_type == IGZIP_ZLIB_NO_HDR) + crc = bswap_32(*(uint32_t *) & isal_cmp_buf[trailer_idx]); + + assert(istate.crc == crc); + free(isal_cmp_buf); + free(isal_out_buf); + free(isal_lev_buf); + return ret; +} diff --git a/tools/test_fuzz.sh b/tools/test_fuzz.sh new file mode 100755 index 0000000..8a1fa51 --- /dev/null +++ b/tools/test_fuzz.sh @@ -0,0 +1,144 @@ +#!/usr/bin/env bash + +usage () +{ +cat << EOF +usage: $0 options +options: + -h Help + -l, --llvm Use llvm fuzz tests and run n times 0=just build, -1=skip (default $use_llvm). + -a, --afl Use AFL fuzz tests and run n times 0=just build, -1=skip (default $use_afl). + -t, --time Run each group of max time [s,h,m,d] - n seconds, hours, minutes or days. + -e Run a specific llvm test or [test, rand, all]. + -f Use this file as initial raw input. Can be repeated. + -d <0,1> Use dump of internal inflate test corpus (default $use_internal_corp). + -i Fuzz input dir (default $fuzzin_dir). + -o Fuzz output dir (default $fuzzout_dir). +EOF +exit 0 +} + +# Defaults +use_afl=-1 +use_llvm=1 +samp_files= +use_internal_corp=1 +fuzzin_dir=fuzzin +fuzzout_dir=fuzzout +llvm_opts=" -print_final_stats=1" +afl_timeout_cmd="" +run_secs=0 +llvm_tests=("igzip_simple_inflate_fuzz_test") +llvm_all_tests=("igzip_simple_inflate_fuzz_test" "igzip_checked_inflate_fuzz_test" "igzip_simple_round_trip_fuzz_test") + +# Options +while [ "$1" != "${1##-}" ]; do + case $1 in + -h | --help) + usage + ;; + -t | --time) + run_secs=$(echo $2 | sed -e 's/d$/*24h/' -e 's/h$/*60m/' -e 's/m$/*60/' -e 's/s$//'| bc) + llvm_opts+=" -max_total_time=$run_secs" + afl_timeout_cmd="timeout --preserve-status $run_secs" + echo Run each for $run_secs seconds + shift 2 + ;; + -a | --afl) + use_afl=$2 + shift 2 + ;; + -l | --llvm) + use_llvm=$2 + shift 2 + ;; + -f) + samp_files+="$2 " + use_internal_corp=0 + shift 2 + ;; + -d) + use_internal_corp=$2 + shift 2 + ;; + -e) + case $2 in + all) + llvm_tests=${llvm_all_tests[@]} + ;; + rand) + llvm_tests=${llvm_all_tests[$RANDOM % ${#llvm_all_tests[@]} ]} + ;; + *) + llvm_tests[0]="$2" + ;; + esac + shift 2 + ;; + -i) + fuzzin_dir=$2 + shift 2 + ;; + -o) + fuzzout_dir=$2 + shift 2 + ;; + esac +done + +set -xe #exit on fail +mkdir -p $fuzzout_dir $fuzzin_dir + +# Optionally build afl fuzz tests +if [ $use_afl -ge 0 ]; then + echo Build afl fuzz tests + if ! command -V afl-gcc > /dev/null; then + echo $0 option --afl requires package afl installed + exit 0 + fi + make -f Makefile.unx clean + make -f Makefile.unx units=igzip CC=afl-gcc other +fi + +# Optionally build llvm fuzz tests +if [ $use_llvm -ge 0 ]; then + echo Build llvm fuzz tests + if ! command -V clang++ > /dev/null && + echo int LLVMFuzzerTestOneInput\(\)\{return 0\;\} | clang++ -x c - -lFuzzer -lpthread -o /dev/null; then + echo $0 option --llvm requires clang++ and libFuzzer + exit 0 + fi + rm -rf bin + make -f Makefile.unx units=igzip llvm_fuzz_tests igzip_dump_inflate_corpus CC=clang CXX=clang++ +fi + +# Optionally fill fuzz input with internal tests corpus +[ $use_internal_corp -gt 0 ] && ./igzip_dump_inflate_corpus $fuzzin_dir + +# Optionally compress input samples as input into fuzz dir +for f in $samp_files; do + echo Using sample file $f + f_base=`basename $f` + ./igzip_stateless_file_perf $f -o $fuzzin_dir/samp_${f_base}_cmp +done + +# Optionally run tests alternately one after the other +while [ $use_llvm -gt 0 -o $use_afl -gt 0 ]; do + if [ $use_afl -gt 0 ]; then + echo afl run $use_afl + let use_afl-- + $afl_timeout_cmd afl-fuzz -T "Run inflate $run_secs s" -i $fuzzin_dir -o $fuzzout_dir -M fuzzer1 -- ./igzip_fuzz_inflate @@ + afl-whatsup $fuzzout_dir + fi + + if [ $use_llvm -gt 0 ]; then + echo llvm run $use_llvm + let use_llvm-- + for test in $llvm_tests; do + echo "Run llvm test $test" + ./$test $fuzzin_dir $llvm_opts + done + fi +done + +make -f Makefile.unx clean