2017-10-07 03:48:38 +02:00
|
|
|
#include <stdlib.h>
|
|
|
|
#include <stdint.h>
|
|
|
|
#include <stddef.h>
|
|
|
|
#include <string.h>
|
|
|
|
#include <assert.h>
|
|
|
|
#include <byteswap.h>
|
|
|
|
#include "igzip_lib.h"
|
2018-12-13 22:12:51 +01:00
|
|
|
#include "unaligned.h"
|
2017-10-07 03:48:38 +02:00
|
|
|
|
|
|
|
#define LEVEL_BITS 2
|
|
|
|
#define HEADER_BITS 3
|
|
|
|
#define LVL_BUF_BITS 3
|
|
|
|
|
2024-04-19 18:10:01 +02:00
|
|
|
#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
|
2017-10-07 03:48:38 +02:00
|
|
|
|
2024-04-19 18:10:01 +02:00
|
|
|
#define MIN(x, y) (((x) > (y)) ? y : x)
|
2017-10-07 03:48:38 +02:00
|
|
|
|
|
|
|
const int header_size[] = {
|
2024-04-19 18:10:01 +02:00
|
|
|
0, // IGZIP_DEFLATE
|
|
|
|
10, // IGZIP_GZIP
|
|
|
|
0, // IGZIP_GZIP_NO_HDR
|
|
|
|
2, // IGZIP_ZLIB
|
|
|
|
0, // IGZIP_ZLIB_NO_HDR
|
2017-10-07 03:48:38 +02:00
|
|
|
};
|
|
|
|
|
|
|
|
const int trailer_size[] = {
|
2024-04-19 18:10:01 +02:00
|
|
|
0, // IGZIP_DEFLATE
|
|
|
|
8, // IGZIP_GZIP
|
|
|
|
8, // IGZIP_GZIP_NO_HDR
|
|
|
|
4, // IGZIP_ZLIB
|
|
|
|
4, // IGZIP_ZLIB_NO_HDR
|
2017-10-07 03:48:38 +02:00
|
|
|
};
|
|
|
|
|
2024-04-19 18:10:01 +02:00
|
|
|
int
|
|
|
|
LLVMFuzzerTestOneInput(const uint8_t *data, size_t size)
|
2017-10-07 03:48:38 +02:00
|
|
|
{
|
2024-04-19 18:10:01 +02:00
|
|
|
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;
|
2017-11-21 21:26:49 +01:00
|
|
|
#ifdef ISAL_DEF_LVL2_MIN
|
2024-04-19 18:10:01 +02:00
|
|
|
case 2:
|
|
|
|
lev_buf_size = ISAL_DEF_LVL2_MIN +
|
|
|
|
(in_param) * (ISAL_DEF_LVL2_EXTRA_LARGE / LEVEL_BIT_MASK);
|
|
|
|
break;
|
2017-11-21 21:26:49 +01:00
|
|
|
#endif
|
|
|
|
#ifdef ISAL_DEF_LVL3_MIN
|
2024-04-19 18:10:01 +02:00
|
|
|
case 3:
|
|
|
|
lev_buf_size = ISAL_DEF_LVL3_MIN +
|
|
|
|
(in_param) * (ISAL_DEF_LVL3_EXTRA_LARGE / LEVEL_BIT_MASK);
|
|
|
|
break;
|
2017-11-21 21:26:49 +01:00
|
|
|
#endif
|
2024-04-19 18:10:01 +02:00
|
|
|
}
|
|
|
|
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_le_u32(&isal_cmp_buf[trailer_idx]);
|
|
|
|
else if (wrapper_type == IGZIP_ZLIB || wrapper_type == IGZIP_ZLIB_NO_HDR)
|
|
|
|
crc = load_be_u32(&isal_cmp_buf[trailer_idx]);
|
|
|
|
|
|
|
|
assert(istate.crc == crc);
|
|
|
|
free(isal_cmp_buf);
|
|
|
|
free(isal_out_buf);
|
|
|
|
free(isal_lev_buf);
|
|
|
|
return ret;
|
2017-10-07 03:48:38 +02:00
|
|
|
}
|