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