mirror of
https://github.com/intel/isa-l.git
synced 2024-12-12 09:23:50 +01:00
test: Add llvm fuzz testing
Moved the afl fuzz test and added llvm fuzz tests including inflate and round trip compress and inflate. Currently only works with clang, std makefile and libFuzzer installed. Need to add checking and support later when libfuzzer is more tightly integrated into the compiler. Change-Id: I2db9ad2335d6c5ed846886703b58225f67bcc935 Signed-off-by: Greg Tucker <greg.b.tucker@intel.com>
This commit is contained in:
parent
f7b6e73146
commit
4f59eeda90
@ -31,6 +31,7 @@ include erasure_code/Makefile.am
|
|||||||
include raid/Makefile.am
|
include raid/Makefile.am
|
||||||
include crc/Makefile.am
|
include crc/Makefile.am
|
||||||
include igzip/Makefile.am
|
include igzip/Makefile.am
|
||||||
|
include tests/fuzz/Makefile.am
|
||||||
|
|
||||||
# LIB version info not necessarily the same as package version
|
# LIB version info not necessarily the same as package version
|
||||||
LIBISAL_CURRENT=2
|
LIBISAL_CURRENT=2
|
||||||
|
@ -33,9 +33,13 @@ default: lib
|
|||||||
|
|
||||||
include $(foreach unit,$(units), $(unit)/Makefile.am)
|
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.
|
# Override individual lib names to make one inclusive library.
|
||||||
lib_name := bin/isa-l.a
|
lib_name := bin/isa-l.a
|
||||||
|
|
||||||
include make.inc
|
include make.inc
|
||||||
|
|
||||||
VPATH = . $(units) include
|
VPATH = . $(units) include tests/fuzz
|
||||||
|
@ -114,7 +114,6 @@ lsrc += igzip/huff_codes.c
|
|||||||
# Include tools and tests using the reference inflate
|
# Include tools and tests using the reference inflate
|
||||||
other_tests += igzip/igzip_inflate_perf
|
other_tests += igzip/igzip_inflate_perf
|
||||||
other_tests += igzip/igzip_inflate_test
|
other_tests += igzip/igzip_inflate_test
|
||||||
other_tests += igzip/igzip_fuzz_inflate
|
|
||||||
lsrc += igzip/igzip_inflate.c
|
lsrc += igzip/igzip_inflate.c
|
||||||
other_src += igzip/checksum_test_ref.h
|
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_LDADD = libisal.la
|
||||||
igzip_igzip_inflate_test_LDFLAGS = -lz
|
igzip_igzip_inflate_test_LDFLAGS = -lz
|
||||||
igzip_igzip_hist_perf_LDADD = libisal.la
|
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
|
|
||||||
|
@ -1,96 +0,0 @@
|
|||||||
#define _FILE_OFFSET_BITS 64
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <assert.h>
|
|
||||||
#include <zlib.h>
|
|
||||||
#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;
|
|
||||||
}
|
|
11
make.inc
11
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_unit_tests = $(notdir $(sort $(check_tests) $(unit_tests)))
|
||||||
all_perf_tests = $(notdir $(sort $(perf_tests)))
|
all_perf_tests = $(notdir $(sort $(perf_tests)))
|
||||||
all_check_tests = $(notdir $(sort $(check_tests)))
|
all_check_tests = $(notdir $(sort $(check_tests)))
|
||||||
|
all_llvm_fuzz_tests = $(notdir $(sort $(llvm_fuzz_tests)))
|
||||||
|
|
||||||
$(all_unit_tests): % : %.c $(lib_name)
|
$(all_unit_tests): % : %.c $(lib_name)
|
||||||
$(all_perf_tests): % : %.c $(lib_name)
|
$(all_perf_tests): % : %.c $(lib_name)
|
||||||
$(sort $(notdir $(examples))): % : %.c $(lib_name)
|
$(sort $(notdir $(examples))): % : %.c $(lib_name)
|
||||||
$(sort $(notdir $(other_tests))): % : %.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))
|
sim test trace: $(addsuffix .run,$(all_unit_tests))
|
||||||
perf: $(addsuffix .run,$(all_perf_tests))
|
perf: $(addsuffix .run,$(all_perf_tests))
|
||||||
check: $(addsuffix .run,$(all_check_tests))
|
check: $(addsuffix .run,$(all_check_tests))
|
||||||
ex: $(notdir $(examples))
|
ex: $(notdir $(examples))
|
||||||
all: lib $(all_tests)
|
all: lib $(all_tests)
|
||||||
other: $(notdir $(other_tests))
|
other: $(notdir $(other_tests))
|
||||||
|
llvm_fuzz_tests: $(all_llvm_fuzz_tests)
|
||||||
tests: $(all_unit_tests)
|
tests: $(all_unit_tests)
|
||||||
perfs: $(all_perf_tests)
|
perfs: $(all_perf_tests)
|
||||||
checks: $(all_check_tests)
|
checks: $(all_check_tests)
|
||||||
@ -273,7 +282,7 @@ perf_report:
|
|||||||
|
|
||||||
clean:
|
clean:
|
||||||
@echo Cleaning up
|
@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
|
doc: isa-l.h
|
||||||
|
52
tests/fuzz/Makefile.am
Normal file
52
tests/fuzz/Makefile.am
Normal file
@ -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
|
12
tests/fuzz/Makefile.unx
Normal file
12
tests/fuzz/Makefile.unx
Normal file
@ -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
|
69
tests/fuzz/igzip_checked_inflate_fuzz_test.c
Normal file
69
tests/fuzz/igzip_checked_inflate_fuzz_test.c
Normal file
@ -0,0 +1,69 @@
|
|||||||
|
#include <string.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <stddef.h>
|
||||||
|
#include <zlib.h>
|
||||||
|
#include <assert.h>
|
||||||
|
#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;
|
||||||
|
}
|
37
tests/fuzz/igzip_dump_inflate_corpus.c
Normal file
37
tests/fuzz/igzip_dump_inflate_corpus.c
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#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 <outdir>\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);
|
||||||
|
}
|
||||||
|
}
|
37
tests/fuzz/igzip_fuzz_inflate.c
Normal file
37
tests/fuzz/igzip_fuzz_inflate.c
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
#define _FILE_OFFSET_BITS 64
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <assert.h>
|
||||||
|
#include <zlib.h>
|
||||||
|
#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 <infile>\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);
|
||||||
|
}
|
22
tests/fuzz/igzip_simple_inflate_fuzz_test.c
Normal file
22
tests/fuzz/igzip_simple_inflate_fuzz_test.c
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
#include <stdlib.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <stddef.h>
|
||||||
|
#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;
|
||||||
|
}
|
113
tests/fuzz/igzip_simple_round_trip_fuzz_test.c
Normal file
113
tests/fuzz/igzip_simple_round_trip_fuzz_test.c
Normal file
@ -0,0 +1,113 @@
|
|||||||
|
#include <stdlib.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <stddef.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <assert.h>
|
||||||
|
#include <byteswap.h>
|
||||||
|
#include "igzip_lib.h"
|
||||||
|
|
||||||
|
#define LEVEL_BITS 2
|
||||||
|
#define HEADER_BITS 3
|
||||||
|
#define LVL_BUF_BITS 3
|
||||||
|
|
||||||
|
#define LEVEL_BIT_MASK ((1<<LEVEL_BITS) - 1)
|
||||||
|
#define HEADER_BIT_MASK ((1<<HEADER_BITS) - 1)
|
||||||
|
#define TYPE0_HDR_SIZE 5
|
||||||
|
#define TYPE0_MAX_SIZE 65535
|
||||||
|
|
||||||
|
#define MIN(x,y) (((x) > (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;
|
||||||
|
}
|
144
tools/test_fuzz.sh
Executable file
144
tools/test_fuzz.sh
Executable file
@ -0,0 +1,144 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
|
usage ()
|
||||||
|
{
|
||||||
|
cat << EOF
|
||||||
|
usage: $0 options
|
||||||
|
options:
|
||||||
|
-h Help
|
||||||
|
-l, --llvm <n> Use llvm fuzz tests and run n times 0=just build, -1=skip (default $use_llvm).
|
||||||
|
-a, --afl <n> Use AFL fuzz tests and run n times 0=just build, -1=skip (default $use_afl).
|
||||||
|
-t, --time <n> Run each group of max time <n>[s,h,m,d] - n seconds, hours, minutes or days.
|
||||||
|
-e <exec|rand|all> Run a specific llvm test or [test, rand, all].
|
||||||
|
-f <file> 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 <dir> Fuzz input dir (default $fuzzin_dir).
|
||||||
|
-o <dir> 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
|
Loading…
Reference in New Issue
Block a user