xref: /isa-l/tests/fuzz/igzip_simple_round_trip_fuzz_test.c (revision 9ab5a9e579c4fb4e2a3c92d73ccd6d97291d0e80)
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