xref: /isa-l/tests/fuzz/igzip_simple_round_trip_fuzz_test.c (revision 43374f6776bbf64866344a5d15465bed2bff38ea)
1 #include <stdlib.h>
2 #include <stdint.h>
3 #include <stddef.h>
4 #include <string.h>
5 #include <assert.h>
6 #include <byteswap.h>
7 #include "igzip_lib.h"
8 
9 #define LEVEL_BITS   2
10 #define HEADER_BITS  3
11 #define LVL_BUF_BITS 3
12 
13 #define LEVEL_BIT_MASK  ((1<<LEVEL_BITS) - 1)
14 #define HEADER_BIT_MASK ((1<<HEADER_BITS) - 1)
15 #define TYPE0_HDR_SIZE 5
16 #define TYPE0_MAX_SIZE 65535
17 
18 #define MIN(x,y) (((x) > (y)) ? y : x )
19 
20 const int header_size[] = {
21 	0,			//IGZIP_DEFLATE
22 	10,			//IGZIP_GZIP
23 	0,			//IGZIP_GZIP_NO_HDR
24 	2,			//IGZIP_ZLIB
25 	0,			//IGZIP_ZLIB_NO_HDR
26 };
27 
28 const int trailer_size[] = {
29 	0,			//IGZIP_DEFLATE
30 	8,			//IGZIP_GZIP
31 	8,			//IGZIP_GZIP_NO_HDR
32 	4,			//IGZIP_ZLIB
33 	4,			//IGZIP_ZLIB_NO_HDR
34 };
35 
36 int LLVMFuzzerTestOneInput(const uint8_t * data, size_t size)
37 {
38 	struct inflate_state istate;
39 	struct isal_zstream cstate;
40 	uint8_t *in_data = (uint8_t *) data;
41 	int ret = 1;
42 
43 	// Parameter default
44 	int level = 1;
45 	int lev_buf_size = ISAL_DEF_LVL1_DEFAULT;
46 	int wrapper_type = 0;
47 	size_t cmp_buf_size = size + ISAL_DEF_MAX_HDR_SIZE;
48 
49 	// Parameters are set by one byte of data input
50 	if (size > 1) {
51 		uint8_t in_param = in_data[--size];
52 		level = MIN(in_param & LEVEL_BIT_MASK, ISAL_DEF_MAX_LEVEL);
53 		in_param >>= LEVEL_BITS;
54 
55 		wrapper_type = (in_param & HEADER_BIT_MASK) % (IGZIP_ZLIB_NO_HDR + 1);
56 		in_param >>= HEADER_BITS;
57 
58 		switch (level) {
59 		case 0:
60 			lev_buf_size = ISAL_DEF_LVL0_MIN + (in_param) *
61 			    (ISAL_DEF_LVL0_EXTRA_LARGE / LEVEL_BIT_MASK);
62 			break;
63 		case 1:
64 			lev_buf_size = ISAL_DEF_LVL1_MIN + (in_param) *
65 			    (ISAL_DEF_LVL1_EXTRA_LARGE / LEVEL_BIT_MASK);
66 			break;
67 #ifdef ISAL_DEF_LVL2_MIN
68 		case 2:
69 			lev_buf_size = ISAL_DEF_LVL2_MIN + (in_param) *
70 			    (ISAL_DEF_LVL2_EXTRA_LARGE / LEVEL_BIT_MASK);
71 			break;
72 #endif
73 #ifdef ISAL_DEF_LVL3_MIN
74 		case 3:
75 			lev_buf_size = ISAL_DEF_LVL3_MIN + (in_param) *
76 			    (ISAL_DEF_LVL3_EXTRA_LARGE / LEVEL_BIT_MASK);
77 			break;
78 #endif
79 		}
80 		if (0 == level)
81 			cmp_buf_size = 2 * size + ISAL_DEF_MAX_HDR_SIZE;
82 		else
83 			cmp_buf_size = size + 8 + (TYPE0_HDR_SIZE * (size / TYPE0_MAX_SIZE));
84 
85 		cmp_buf_size += header_size[wrapper_type] + trailer_size[wrapper_type];
86 	}
87 
88 	uint8_t *isal_cmp_buf = (uint8_t *) malloc(cmp_buf_size);
89 	uint8_t *isal_out_buf = (uint8_t *) malloc(size);
90 	uint8_t *isal_lev_buf = (uint8_t *) malloc(lev_buf_size);
91 	assert(NULL != isal_cmp_buf || NULL != isal_out_buf || NULL != isal_lev_buf);
92 
93 	isal_deflate_init(&cstate);
94 	cstate.end_of_stream = 1;
95 	cstate.flush = NO_FLUSH;
96 	cstate.next_in = in_data;
97 	cstate.avail_in = size;
98 	cstate.next_out = isal_cmp_buf;
99 	cstate.avail_out = cmp_buf_size;
100 	cstate.level = level;
101 	cstate.level_buf = isal_lev_buf;
102 	cstate.level_buf_size = lev_buf_size;
103 	cstate.gzip_flag = wrapper_type;
104 	ret = isal_deflate_stateless(&cstate);
105 
106 	isal_inflate_init(&istate);
107 	istate.next_in = isal_cmp_buf;
108 	istate.avail_in = cstate.total_out;
109 	istate.next_out = isal_out_buf;
110 	istate.avail_out = size;
111 	istate.crc_flag = wrapper_type;
112 	ret |= isal_inflate_stateless(&istate);
113 	ret |= memcmp(isal_out_buf, in_data, size);
114 
115 	// Check trailer
116 	uint32_t crc = 0;
117 	int trailer_idx = cstate.total_out - trailer_size[wrapper_type];
118 
119 	if (wrapper_type == IGZIP_GZIP || wrapper_type == IGZIP_GZIP_NO_HDR)
120 		crc = *(uint32_t *) & isal_cmp_buf[trailer_idx];
121 	else if (wrapper_type == IGZIP_ZLIB || wrapper_type == IGZIP_ZLIB_NO_HDR)
122 		crc = bswap_32(*(uint32_t *) & isal_cmp_buf[trailer_idx]);
123 
124 	assert(istate.crc == crc);
125 	free(isal_cmp_buf);
126 	free(isal_out_buf);
127 	free(isal_lev_buf);
128 	return ret;
129 }
130