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