Rizin
unix-like reverse engineering framework and cli tools
round_trip_stream_fuzzer.c
Go to the documentation of this file.
1 
7 #include <stddef.h>
8 #include <stdint.h>
9 #include <stdlib.h>
10 #include <string.h>
11 
12 #include "fuzz_helpers.h"
13 #define LZ4_STATIC_LINKING_ONLY
14 #include "lz4.h"
15 #define LZ4_HC_STATIC_LINKING_ONLY
16 #include "lz4hc.h"
17 
18 typedef struct {
19  char const* buf;
20  size_t size;
21  size_t pos;
23 
24 typedef struct {
25  char* buf;
26  size_t size;
27  size_t pos;
28 } cursor_t;
29 
30 typedef struct {
38  int level;
39 } state_t;
40 
42 {
43  cursor_t cursor;
44  cursor.buf = (char*)malloc(size);
45  cursor.size = size;
46  cursor.pos = 0;
47  FUZZ_ASSERT(cursor.buf);
48  return cursor;
49 }
50 
51 typedef void (*round_trip_t)(state_t* state);
52 
53 void cursor_free(cursor_t cursor)
54 {
55  free(cursor.buf);
56 }
57 
58 state_t state_create(char const* data, size_t size, uint32_t seed)
59 {
60  state_t state;
61 
62  state.seed = seed;
63 
64  state.data.buf = (char const*)data;
65  state.data.size = size;
66  state.data.pos = 0;
67 
68  /* Extra margin because we are streaming. */
69  state.compressed = cursor_create(1024 + 2 * LZ4_compressBound(size));
70  state.roundTrip = cursor_create(size);
71 
72  state.cstream = LZ4_createStream();
73  FUZZ_ASSERT(state.cstream);
74  state.cstreamHC = LZ4_createStreamHC();
75  FUZZ_ASSERT(state.cstream);
76  state.dstream = LZ4_createStreamDecode();
77  FUZZ_ASSERT(state.dstream);
78 
79  return state;
80 }
81 
83 {
84  cursor_free(state.compressed);
85  cursor_free(state.roundTrip);
86  LZ4_freeStream(state.cstream);
87  LZ4_freeStreamHC(state.cstreamHC);
88  LZ4_freeStreamDecode(state.dstream);
89 }
90 
91 static void state_reset(state_t* state, uint32_t seed)
92 {
94  LZ4_resetStream_fast(state->cstream);
95  LZ4_resetStreamHC_fast(state->cstreamHC, state->level);
96  LZ4_setStreamDecode(state->dstream, NULL, 0);
97  state->data.pos = 0;
98  state->compressed.pos = 0;
99  state->roundTrip.pos = 0;
100  state->seed = seed;
101 }
102 
103 static void state_decompress(state_t* state, char const* src, int srcSize)
104 {
105  char* dst = state->roundTrip.buf + state->roundTrip.pos;
106  int const dstCapacity = state->roundTrip.size - state->roundTrip.pos;
107  int const dSize = LZ4_decompress_safe_continue(state->dstream, src, dst,
108  srcSize, dstCapacity);
109  FUZZ_ASSERT(dSize >= 0);
110  state->roundTrip.pos += dSize;
111 }
112 
113 static void state_checkRoundTrip(state_t const* state)
114 {
115  char const* data = state->data.buf;
116  size_t const size = state->data.size;
117  FUZZ_ASSERT_MSG(size == state->roundTrip.pos, "Incorrect size!");
118  FUZZ_ASSERT_MSG(!memcmp(data, state->roundTrip.buf, size), "Corruption!");
119 }
120 
125 static size_t state_trimDict(state_t* state)
126 {
127  /* 64 KB is the max dict size, allow slightly beyond that to test trim. */
128  uint32_t maxDictSize = MIN(70 * 1024, state->data.size);
129  size_t const dictSize = FUZZ_rand32(&state->seed, 0, maxDictSize);
130  DEBUGLOG(2, "dictSize = %zu", dictSize);
131  FUZZ_ASSERT(state->data.pos == 0);
132  FUZZ_ASSERT(state->roundTrip.pos == 0);
133  memcpy(state->roundTrip.buf, state->data.buf, dictSize);
134  state->data.pos += dictSize;
135  state->roundTrip.pos += dictSize;
136  return dictSize;
137 }
138 
140 {
141  while (state->data.pos != state->data.size) {
142  char const* src = state->data.buf + state->data.pos;
143  char* dst = state->compressed.buf + state->compressed.pos;
144  int const srcRemaining = state->data.size - state->data.pos;
145  int const srcSize = FUZZ_rand32(&state->seed, 0, srcRemaining);
146  int const dstCapacity = state->compressed.size - state->compressed.pos;
147  int const cSize = LZ4_compress_fast_continue(state->cstream, src, dst,
148  srcSize, dstCapacity, 0);
149  FUZZ_ASSERT(cSize > 0);
150  state->data.pos += srcSize;
151  state->compressed.pos += cSize;
152  state_decompress(state, dst, cSize);
153  }
154 }
155 
157 {
158  int i = 0;
159  cursor_t data2 = cursor_create(state->data.size);
160  memcpy(data2.buf, state->data.buf, state->data.size);
161  while (state->data.pos != state->data.size) {
162  char const* data = (i++ & 1) ? state->data.buf : data2.buf;
163  char const* src = data + state->data.pos;
164  char* dst = state->compressed.buf + state->compressed.pos;
165  int const srcRemaining = state->data.size - state->data.pos;
166  int const srcSize = FUZZ_rand32(&state->seed, 0, srcRemaining);
167  int const dstCapacity = state->compressed.size - state->compressed.pos;
168  int const cSize = LZ4_compress_fast_continue(state->cstream, src, dst,
169  srcSize, dstCapacity, 0);
170  FUZZ_ASSERT(cSize > 0);
171  state->data.pos += srcSize;
172  state->compressed.pos += cSize;
173  state_decompress(state, dst, cSize);
174  }
175  cursor_free(data2);
176 }
177 
179  round_trip_t rt1)
180 {
181  if (FUZZ_rand32(&state->seed, 0, 1)) {
182  rt0(state);
183  } else {
184  rt1(state);
185  }
186 }
187 
189 {
190  char const* dict = state->data.buf;
191  size_t const dictSize = state_trimDict(state);
192  LZ4_loadDict(state->cstream, dict, dictSize);
193  LZ4_setStreamDecode(state->dstream, dict, dictSize);
195 }
196 
198 {
199  char const* dict = state->data.buf;
200  size_t const dictSize = state_trimDict(state);
201  LZ4_stream_t* dictStream = LZ4_createStream();
202  LZ4_loadDict(dictStream, dict, dictSize);
203  LZ4_attach_dictionary(state->cstream, dictStream);
204  LZ4_setStreamDecode(state->dstream, dict, dictSize);
206  LZ4_freeStream(dictStream);
207 }
208 
210 {
211  while (state->data.pos != state->data.size) {
212  char const* src = state->data.buf + state->data.pos;
213  char* dst = state->compressed.buf + state->compressed.pos;
214  int const srcRemaining = state->data.size - state->data.pos;
215  int const srcSize = FUZZ_rand32(&state->seed, 0, srcRemaining);
216  int const dstCapacity = state->compressed.size - state->compressed.pos;
217  int const cSize = LZ4_compress_HC_continue(state->cstreamHC, src, dst,
218  srcSize, dstCapacity);
219  FUZZ_ASSERT(cSize > 0);
220  state->data.pos += srcSize;
221  state->compressed.pos += cSize;
222  state_decompress(state, dst, cSize);
223  }
224 }
225 
227 {
228  int i = 0;
229  cursor_t data2 = cursor_create(state->data.size);
230  DEBUGLOG(2, "extDictHC");
231  memcpy(data2.buf, state->data.buf, state->data.size);
232  while (state->data.pos != state->data.size) {
233  char const* data = (i++ & 1) ? state->data.buf : data2.buf;
234  char const* src = data + state->data.pos;
235  char* dst = state->compressed.buf + state->compressed.pos;
236  int const srcRemaining = state->data.size - state->data.pos;
237  int const srcSize = FUZZ_rand32(&state->seed, 0, srcRemaining);
238  int const dstCapacity = state->compressed.size - state->compressed.pos;
239  int const cSize = LZ4_compress_HC_continue(state->cstreamHC, src, dst,
240  srcSize, dstCapacity);
241  FUZZ_ASSERT(cSize > 0);
242  DEBUGLOG(2, "srcSize = %d", srcSize);
243  state->data.pos += srcSize;
244  state->compressed.pos += cSize;
245  state_decompress(state, dst, cSize);
246  }
247  cursor_free(data2);
248 }
249 
251 {
252  char const* dict = state->data.buf;
253  size_t const dictSize = state_trimDict(state);
254  LZ4_loadDictHC(state->cstreamHC, dict, dictSize);
255  LZ4_setStreamDecode(state->dstream, dict, dictSize);
258 }
259 
261 {
262  char const* dict = state->data.buf;
263  size_t const dictSize = state_trimDict(state);
264  LZ4_streamHC_t* dictStream = LZ4_createStreamHC();
265  LZ4_setCompressionLevel(dictStream, state->level);
266  LZ4_loadDictHC(dictStream, dict, dictSize);
267  LZ4_attach_HC_dictionary(state->cstreamHC, dictStream);
268  LZ4_setStreamDecode(state->dstream, dict, dictSize);
271  LZ4_freeStreamHC(dictStream);
272 }
273 
283 };
284 
285 int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size)
286 {
287  uint32_t seed = FUZZ_seed(&data, &size);
288  state_t state = state_create((char const*)data, size, seed);
289  const int n = sizeof(roundTrips) / sizeof(round_trip_t);
290  int i;
291 
292  for (i = 0; i < n; ++i) {
293  DEBUGLOG(2, "Round trip %d", i);
294  state_reset(&state, seed);
295  roundTrips[i](&state);
297  }
298 
299  state_free(state);
300 
301  return 0;
302 }
lzma_index ** i
Definition: index.h:629
lzma_index * src
Definition: index.h:567
#define NULL
Definition: cris-opc.c:27
FUZZ_STATIC uint32_t FUZZ_seed(uint8_t const **src, size_t *size)
Definition: fuzz_helpers.h:63
#define FUZZ_ASSERT(cond)
Definition: fuzz_helpers.h:46
FUZZ_STATIC uint32_t FUZZ_rand32(uint32_t *state, uint32_t min, uint32_t max)
Definition: fuzz_helpers.h:85
#define FUZZ_ASSERT_MSG(cond, msg)
Definition: fuzz_helpers.h:41
RZ_API void Ht_() free(HtName_(Ht) *ht)
Definition: ht_inc.c:130
voidpf void uLong size
Definition: ioapi.h:138
memcpy(mem, inblock.get(), min(CONTAINING_RECORD(inblock.get(), MEMBLOCK, data) ->size, size))
void * malloc(size_t size)
Definition: malloc.c:123
int LZ4_compressBound(int isize)
Definition: lz4.c:674
int LZ4_loadDict(LZ4_stream_t *LZ4_dict, const char *dictionary, int dictSize)
Definition: lz4.c:1475
LZ4_stream_t * LZ4_createStream(void)
Definition: lz4.c:1423
LZ4_streamDecode_t * LZ4_createStreamDecode(void)
Definition: lz4.c:2265
void LZ4_resetStream_fast(LZ4_stream_t *ctx)
Definition: lz4.c:1461
int LZ4_freeStream(LZ4_stream_t *LZ4_stream)
Definition: lz4.c:1465
#define DEBUGLOG(l,...)
Definition: lz4.c:261
int LZ4_setStreamDecode(LZ4_streamDecode_t *LZ4_streamDecode, const char *dictionary, int dictSize)
Definition: lz4.c:2285
LZ4_FORCE_O2 int LZ4_decompress_safe_continue(LZ4_streamDecode_t *LZ4_streamDecode, const char *source, char *dest, int compressedSize, int maxOutputSize)
Definition: lz4.c:2322
int LZ4_compress_fast_continue(LZ4_stream_t *LZ4_stream, const char *source, char *dest, int inputSize, int maxOutputSize, int acceleration)
Definition: lz4.c:1565
void LZ4_attach_dictionary(LZ4_stream_t *workingStream, const LZ4_stream_t *dictionaryStream)
Definition: lz4.c:1517
int LZ4_freeStreamDecode(LZ4_streamDecode_t *LZ4_stream)
Definition: lz4.c:2272
char int srcSize
Definition: lz4.h:697
char * dst
Definition: lz4.h:724
void LZ4_attach_HC_dictionary(LZ4_streamHC_t *working_stream, const LZ4_streamHC_t *dictionary_stream)
Definition: lz4hc.c:1077
void LZ4_resetStreamHC_fast(LZ4_streamHC_t *LZ4_streamHCPtr, int compressionLevel)
Definition: lz4hc.c:1027
int LZ4_freeStreamHC(LZ4_streamHC_t *LZ4_streamHCPtr)
Definition: lz4hc.c:994
int LZ4_compress_HC_continue(LZ4_streamHC_t *LZ4_streamHCPtr, const char *src, char *dst, int srcSize, int dstCapacity)
Definition: lz4hc.c:1138
LZ4_streamHC_t * LZ4_createStreamHC(void)
Definition: lz4hc.c:985
void LZ4_setCompressionLevel(LZ4_streamHC_t *LZ4_streamHCPtr, int compressionLevel)
Definition: lz4hc.c:1041
int LZ4_loadDictHC(LZ4_streamHC_t *LZ4_streamHCPtr, const char *dictionary, int dictSize)
Definition: lz4hc.c:1056
#define LZ4HC_CLEVEL_MAX
Definition: lz4hc.h:50
#define LZ4HC_CLEVEL_MIN
Definition: lz4hc.h:47
int n
Definition: mipsasm.c:19
static void state_attachDictRoundTrip(state_t *state)
static size_t state_trimDict(state_t *state)
static void state_loadDictRoundTrip(state_t *state)
static void state_randomRoundTrip(state_t *state, round_trip_t rt0, round_trip_t rt1)
state_t state_create(char const *data, size_t size, uint32_t seed)
static void state_extDictRoundTrip(state_t *state)
cursor_t cursor_create(size_t size)
static void state_decompress(state_t *state, char const *src, int srcSize)
int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size)
static void state_reset(state_t *state, uint32_t seed)
static void state_loadDictHCRoundTrip(state_t *state)
static void state_extDictHCRoundTrip(state_t *state)
void state_free(state_t state)
static void state_prefixRoundTrip(state_t *state)
void cursor_free(cursor_t cursor)
void(* round_trip_t)(state_t *state)
static void state_checkRoundTrip(state_t const *state)
static void state_prefixHCRoundTrip(state_t *state)
round_trip_t roundTrips[]
static void state_attachDictHCRoundTrip(state_t *state)
unsigned int uint32_t
Definition: sftypes.h:29
unsigned char uint8_t
Definition: sftypes.h:31
LZ4_stream_t * cstream
LZ4_streamDecode_t * dstream
const_cursor_t data
LZ4_streamHC_t * cstreamHC
Definition: dis.h:43
#define MIN(x, y)
Definition: utils.h:59