summaryrefslogtreecommitdiffstats
path: root/src/spdk/isa-l/tests/fuzz
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--src/spdk/isa-l/tests/fuzz/Makefile.am52
-rw-r--r--src/spdk/isa-l/tests/fuzz/Makefile.unx12
-rw-r--r--src/spdk/isa-l/tests/fuzz/igzip_checked_inflate_fuzz_test.c72
-rw-r--r--src/spdk/isa-l/tests/fuzz/igzip_dump_inflate_corpus.c40
-rw-r--r--src/spdk/isa-l/tests/fuzz/igzip_fuzz_inflate.c41
-rw-r--r--src/spdk/isa-l/tests/fuzz/igzip_simple_inflate_fuzz_test.c22
-rw-r--r--src/spdk/isa-l/tests/fuzz/igzip_simple_round_trip_fuzz_test.c130
7 files changed, 369 insertions, 0 deletions
diff --git a/src/spdk/isa-l/tests/fuzz/Makefile.am b/src/spdk/isa-l/tests/fuzz/Makefile.am
new file mode 100644
index 000000000..424a028e5
--- /dev/null
+++ b/src/spdk/isa-l/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.o 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/src/spdk/isa-l/tests/fuzz/Makefile.unx b/src/spdk/isa-l/tests/fuzz/Makefile.unx
new file mode 100644
index 000000000..afa20a36d
--- /dev/null
+++ b/src/spdk/isa-l/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/src/spdk/isa-l/tests/fuzz/igzip_checked_inflate_fuzz_test.c b/src/spdk/isa-l/tests/fuzz/igzip_checked_inflate_fuzz_test.c
new file mode 100644
index 000000000..557433d6b
--- /dev/null
+++ b/src/spdk/isa-l/tests/fuzz/igzip_checked_inflate_fuzz_test.c
@@ -0,0 +1,72 @@
+#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 and when zlib notices
+ * an error faster than isal */
+ 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
+ || (iret == ISAL_END_INPUT && zstate.avail_in < 3));
+
+ } 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/src/spdk/isa-l/tests/fuzz/igzip_dump_inflate_corpus.c b/src/spdk/isa-l/tests/fuzz/igzip_dump_inflate_corpus.c
new file mode 100644
index 000000000..36771b3df
--- /dev/null
+++ b/src/spdk/isa-l/tests/fuzz/igzip_dump_inflate_corpus.c
@@ -0,0 +1,40 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include "inflate_std_vects.h"
+
+#define DNAME_MAX 256
+#define FNAME_MAX (DNAME_MAX + 81)
+
+int main(int argc, char *argv[])
+{
+ uint8_t *buf;
+ int i, len, err;
+ FILE *fout = NULL;
+ char fname[FNAME_MAX];
+ char dname[DNAME_MAX];
+
+ if (argc != 2) {
+ fprintf(stderr, "Usage: %s <outdir>\n", argv[0]);
+ exit(1);
+ }
+ strncpy(dname, argv[1], DNAME_MAX - 1);
+
+ 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%04d_e%04d", 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);
+ }
+
+ return 0;
+}
diff --git a/src/spdk/isa-l/tests/fuzz/igzip_fuzz_inflate.c b/src/spdk/isa-l/tests/fuzz/igzip_fuzz_inflate.c
new file mode 100644
index 000000000..b28739d3b
--- /dev/null
+++ b/src/spdk/isa-l/tests/fuzz/igzip_fuzz_inflate.c
@@ -0,0 +1,41 @@
+#define _FILE_OFFSET_BITS 64
+#include <stdio.h>
+#include <stdlib.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);
+ }
+
+ if (fread(in_buf, 1, in_file_size, in) != in_file_size) {
+ fprintf(stderr, "Failed to read from %s\n", argv[1]);
+ exit(1);
+ }
+
+ return LLVMFuzzerTestOneInput(in_buf, in_file_size);
+}
diff --git a/src/spdk/isa-l/tests/fuzz/igzip_simple_inflate_fuzz_test.c b/src/spdk/isa-l/tests/fuzz/igzip_simple_inflate_fuzz_test.c
new file mode 100644
index 000000000..b5f22e845
--- /dev/null
+++ b/src/spdk/isa-l/tests/fuzz/igzip_simple_inflate_fuzz_test.c
@@ -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;
+}
diff --git a/src/spdk/isa-l/tests/fuzz/igzip_simple_round_trip_fuzz_test.c b/src/spdk/isa-l/tests/fuzz/igzip_simple_round_trip_fuzz_test.c
new file mode 100644
index 000000000..381969156
--- /dev/null
+++ b/src/spdk/isa-l/tests/fuzz/igzip_simple_round_trip_fuzz_test.c
@@ -0,0 +1,130 @@
+#include <stdlib.h>
+#include <stdint.h>
+#include <stddef.h>
+#include <string.h>
+#include <assert.h>
+#include <byteswap.h>
+#include "igzip_lib.h"
+#include "unaligned.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;
+
+ switch (level) {
+ case 0:
+ lev_buf_size = ISAL_DEF_LVL0_MIN + (in_param) *
+ (ISAL_DEF_LVL0_EXTRA_LARGE / LEVEL_BIT_MASK);
+ break;
+ case 1:
+ lev_buf_size = ISAL_DEF_LVL1_MIN + (in_param) *
+ (ISAL_DEF_LVL1_EXTRA_LARGE / LEVEL_BIT_MASK);
+ break;
+#ifdef ISAL_DEF_LVL2_MIN
+ case 2:
+ lev_buf_size = ISAL_DEF_LVL2_MIN + (in_param) *
+ (ISAL_DEF_LVL2_EXTRA_LARGE / LEVEL_BIT_MASK);
+ break;
+#endif
+#ifdef ISAL_DEF_LVL3_MIN
+ case 3:
+ lev_buf_size = ISAL_DEF_LVL3_MIN + (in_param) *
+ (ISAL_DEF_LVL3_EXTRA_LARGE / LEVEL_BIT_MASK);
+ break;
+#endif
+ }
+ 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;
+ istate.avail_in = cstate.total_out;
+ 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 = load_u32(&isal_cmp_buf[trailer_idx]);
+ else if (wrapper_type == IGZIP_ZLIB || wrapper_type == IGZIP_ZLIB_NO_HDR)
+ crc = bswap_32(load_u32(&isal_cmp_buf[trailer_idx]));
+
+ assert(istate.crc == crc);
+ free(isal_cmp_buf);
+ free(isal_out_buf);
+ free(isal_lev_buf);
+ return ret;
+}