summaryrefslogtreecommitdiffstats
path: root/src/isa-l/tests/fuzz/igzip_simple_round_trip_fuzz_test.c
blob: 381969156d7f396692fed1f61008e5d9a1634162 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
#include <stdlib.h>
#include <stdint.h>
#include <stddef.h>
#include <string.h>
#include <assert.h>
#include <byteswap.h>
#include "igzip_lib.h"
#include "unaligned.h"

#define LEVEL_BITS   2
#define HEADER_BITS  3
#define LVL_BUF_BITS 3

#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

#define MIN(x,y) (((x) > (y)) ? y : x )

const int header_size[] = {
	0,			//IGZIP_DEFLATE
	10,			//IGZIP_GZIP
	0,			//IGZIP_GZIP_NO_HDR
	2,			//IGZIP_ZLIB
	0,			//IGZIP_ZLIB_NO_HDR
};

const int trailer_size[] = {
	0,			//IGZIP_DEFLATE
	8,			//IGZIP_GZIP
	8,			//IGZIP_GZIP_NO_HDR
	4,			//IGZIP_ZLIB
	4,			//IGZIP_ZLIB_NO_HDR
};

int LLVMFuzzerTestOneInput(const uint8_t * data, size_t size)
{
	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;
#ifdef ISAL_DEF_LVL2_MIN
		case 2:
			lev_buf_size = ISAL_DEF_LVL2_MIN + (in_param) *
			    (ISAL_DEF_LVL2_EXTRA_LARGE / LEVEL_BIT_MASK);
			break;
#endif
#ifdef ISAL_DEF_LVL3_MIN
		case 3:
			lev_buf_size = ISAL_DEF_LVL3_MIN + (in_param) *
			    (ISAL_DEF_LVL3_EXTRA_LARGE / LEVEL_BIT_MASK);
			break;
#endif
		}
		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_u32(&isal_cmp_buf[trailer_idx]);
	else if (wrapper_type == IGZIP_ZLIB || wrapper_type == IGZIP_ZLIB_NO_HDR)
		crc = bswap_32(load_u32(&isal_cmp_buf[trailer_idx]));

	assert(istate.crc == crc);
	free(isal_cmp_buf);
	free(isal_out_buf);
	free(isal_lev_buf);
	return ret;
}