xref: /aosp_15_r20/external/lz4/ossfuzz/round_trip_stream_fuzzer.c (revision 27162e4e17433d5aa7cb38e7b6a433a09405fc7f)
1*27162e4eSAndroid Build Coastguard Worker /**
2*27162e4eSAndroid Build Coastguard Worker  * This fuzz target performs a lz4 streaming round-trip test
3*27162e4eSAndroid Build Coastguard Worker  * (compress & decompress), compares the result with the original, and calls
4*27162e4eSAndroid Build Coastguard Worker  * abort() on corruption.
5*27162e4eSAndroid Build Coastguard Worker  */
6*27162e4eSAndroid Build Coastguard Worker 
7*27162e4eSAndroid Build Coastguard Worker #include <stddef.h>
8*27162e4eSAndroid Build Coastguard Worker #include <stdint.h>
9*27162e4eSAndroid Build Coastguard Worker #include <stdlib.h>
10*27162e4eSAndroid Build Coastguard Worker #include <string.h>
11*27162e4eSAndroid Build Coastguard Worker 
12*27162e4eSAndroid Build Coastguard Worker #include "fuzz_helpers.h"
13*27162e4eSAndroid Build Coastguard Worker #define LZ4_STATIC_LINKING_ONLY
14*27162e4eSAndroid Build Coastguard Worker #include "lz4.h"
15*27162e4eSAndroid Build Coastguard Worker #define LZ4_HC_STATIC_LINKING_ONLY
16*27162e4eSAndroid Build Coastguard Worker #include "lz4hc.h"
17*27162e4eSAndroid Build Coastguard Worker 
18*27162e4eSAndroid Build Coastguard Worker typedef struct {
19*27162e4eSAndroid Build Coastguard Worker   char const* buf;
20*27162e4eSAndroid Build Coastguard Worker   size_t size;
21*27162e4eSAndroid Build Coastguard Worker   size_t pos;
22*27162e4eSAndroid Build Coastguard Worker } const_cursor_t;
23*27162e4eSAndroid Build Coastguard Worker 
24*27162e4eSAndroid Build Coastguard Worker typedef struct {
25*27162e4eSAndroid Build Coastguard Worker   char* buf;
26*27162e4eSAndroid Build Coastguard Worker   size_t size;
27*27162e4eSAndroid Build Coastguard Worker   size_t pos;
28*27162e4eSAndroid Build Coastguard Worker } cursor_t;
29*27162e4eSAndroid Build Coastguard Worker 
30*27162e4eSAndroid Build Coastguard Worker typedef struct {
31*27162e4eSAndroid Build Coastguard Worker   LZ4_stream_t* cstream;
32*27162e4eSAndroid Build Coastguard Worker   LZ4_streamHC_t* cstreamHC;
33*27162e4eSAndroid Build Coastguard Worker   LZ4_streamDecode_t* dstream;
34*27162e4eSAndroid Build Coastguard Worker   const_cursor_t data;
35*27162e4eSAndroid Build Coastguard Worker   cursor_t compressed;
36*27162e4eSAndroid Build Coastguard Worker   cursor_t roundTrip;
37*27162e4eSAndroid Build Coastguard Worker   uint32_t seed;
38*27162e4eSAndroid Build Coastguard Worker   int level;
39*27162e4eSAndroid Build Coastguard Worker } state_t;
40*27162e4eSAndroid Build Coastguard Worker 
cursor_create(size_t size)41*27162e4eSAndroid Build Coastguard Worker cursor_t cursor_create(size_t size)
42*27162e4eSAndroid Build Coastguard Worker {
43*27162e4eSAndroid Build Coastguard Worker   cursor_t cursor;
44*27162e4eSAndroid Build Coastguard Worker   cursor.buf = (char*)malloc(size);
45*27162e4eSAndroid Build Coastguard Worker   cursor.size = size;
46*27162e4eSAndroid Build Coastguard Worker   cursor.pos = 0;
47*27162e4eSAndroid Build Coastguard Worker   FUZZ_ASSERT(cursor.buf);
48*27162e4eSAndroid Build Coastguard Worker   return cursor;
49*27162e4eSAndroid Build Coastguard Worker }
50*27162e4eSAndroid Build Coastguard Worker 
51*27162e4eSAndroid Build Coastguard Worker typedef void (*round_trip_t)(state_t* state);
52*27162e4eSAndroid Build Coastguard Worker 
cursor_free(cursor_t cursor)53*27162e4eSAndroid Build Coastguard Worker void cursor_free(cursor_t cursor)
54*27162e4eSAndroid Build Coastguard Worker {
55*27162e4eSAndroid Build Coastguard Worker     free(cursor.buf);
56*27162e4eSAndroid Build Coastguard Worker }
57*27162e4eSAndroid Build Coastguard Worker 
state_create(char const * data,size_t size,uint32_t seed)58*27162e4eSAndroid Build Coastguard Worker state_t state_create(char const* data, size_t size, uint32_t seed)
59*27162e4eSAndroid Build Coastguard Worker {
60*27162e4eSAndroid Build Coastguard Worker     state_t state;
61*27162e4eSAndroid Build Coastguard Worker 
62*27162e4eSAndroid Build Coastguard Worker     state.seed = seed;
63*27162e4eSAndroid Build Coastguard Worker 
64*27162e4eSAndroid Build Coastguard Worker     state.data.buf = (char const*)data;
65*27162e4eSAndroid Build Coastguard Worker     state.data.size = size;
66*27162e4eSAndroid Build Coastguard Worker     state.data.pos = 0;
67*27162e4eSAndroid Build Coastguard Worker 
68*27162e4eSAndroid Build Coastguard Worker     /* Extra margin because we are streaming. */
69*27162e4eSAndroid Build Coastguard Worker     state.compressed = cursor_create(1024 + 2 * LZ4_compressBound(size));
70*27162e4eSAndroid Build Coastguard Worker     state.roundTrip = cursor_create(size);
71*27162e4eSAndroid Build Coastguard Worker 
72*27162e4eSAndroid Build Coastguard Worker     state.cstream = LZ4_createStream();
73*27162e4eSAndroid Build Coastguard Worker     FUZZ_ASSERT(state.cstream);
74*27162e4eSAndroid Build Coastguard Worker     state.cstreamHC = LZ4_createStreamHC();
75*27162e4eSAndroid Build Coastguard Worker     FUZZ_ASSERT(state.cstream);
76*27162e4eSAndroid Build Coastguard Worker     state.dstream = LZ4_createStreamDecode();
77*27162e4eSAndroid Build Coastguard Worker     FUZZ_ASSERT(state.dstream);
78*27162e4eSAndroid Build Coastguard Worker 
79*27162e4eSAndroid Build Coastguard Worker     return state;
80*27162e4eSAndroid Build Coastguard Worker }
81*27162e4eSAndroid Build Coastguard Worker 
state_free(state_t state)82*27162e4eSAndroid Build Coastguard Worker void state_free(state_t state)
83*27162e4eSAndroid Build Coastguard Worker {
84*27162e4eSAndroid Build Coastguard Worker     cursor_free(state.compressed);
85*27162e4eSAndroid Build Coastguard Worker     cursor_free(state.roundTrip);
86*27162e4eSAndroid Build Coastguard Worker     LZ4_freeStream(state.cstream);
87*27162e4eSAndroid Build Coastguard Worker     LZ4_freeStreamHC(state.cstreamHC);
88*27162e4eSAndroid Build Coastguard Worker     LZ4_freeStreamDecode(state.dstream);
89*27162e4eSAndroid Build Coastguard Worker }
90*27162e4eSAndroid Build Coastguard Worker 
state_reset(state_t * state,uint32_t seed)91*27162e4eSAndroid Build Coastguard Worker static void state_reset(state_t* state, uint32_t seed)
92*27162e4eSAndroid Build Coastguard Worker {
93*27162e4eSAndroid Build Coastguard Worker     state->level = FUZZ_rand32(&seed, LZ4HC_CLEVEL_MIN, LZ4HC_CLEVEL_MAX);
94*27162e4eSAndroid Build Coastguard Worker     LZ4_resetStream_fast(state->cstream);
95*27162e4eSAndroid Build Coastguard Worker     LZ4_resetStreamHC_fast(state->cstreamHC, state->level);
96*27162e4eSAndroid Build Coastguard Worker     LZ4_setStreamDecode(state->dstream, NULL, 0);
97*27162e4eSAndroid Build Coastguard Worker     state->data.pos = 0;
98*27162e4eSAndroid Build Coastguard Worker     state->compressed.pos = 0;
99*27162e4eSAndroid Build Coastguard Worker     state->roundTrip.pos = 0;
100*27162e4eSAndroid Build Coastguard Worker     state->seed = seed;
101*27162e4eSAndroid Build Coastguard Worker }
102*27162e4eSAndroid Build Coastguard Worker 
state_decompress(state_t * state,char const * src,int srcSize)103*27162e4eSAndroid Build Coastguard Worker static void state_decompress(state_t* state, char const* src, int srcSize)
104*27162e4eSAndroid Build Coastguard Worker {
105*27162e4eSAndroid Build Coastguard Worker     char* dst = state->roundTrip.buf + state->roundTrip.pos;
106*27162e4eSAndroid Build Coastguard Worker     int const dstCapacity = state->roundTrip.size - state->roundTrip.pos;
107*27162e4eSAndroid Build Coastguard Worker     int const dSize = LZ4_decompress_safe_continue(state->dstream, src, dst,
108*27162e4eSAndroid Build Coastguard Worker                                                    srcSize, dstCapacity);
109*27162e4eSAndroid Build Coastguard Worker     FUZZ_ASSERT(dSize >= 0);
110*27162e4eSAndroid Build Coastguard Worker     state->roundTrip.pos += dSize;
111*27162e4eSAndroid Build Coastguard Worker }
112*27162e4eSAndroid Build Coastguard Worker 
state_checkRoundTrip(state_t const * state)113*27162e4eSAndroid Build Coastguard Worker static void state_checkRoundTrip(state_t const* state)
114*27162e4eSAndroid Build Coastguard Worker {
115*27162e4eSAndroid Build Coastguard Worker     char const* data = state->data.buf;
116*27162e4eSAndroid Build Coastguard Worker     size_t const size = state->data.size;
117*27162e4eSAndroid Build Coastguard Worker     FUZZ_ASSERT_MSG(size == state->roundTrip.pos, "Incorrect size!");
118*27162e4eSAndroid Build Coastguard Worker     FUZZ_ASSERT_MSG(!memcmp(data, state->roundTrip.buf, size), "Corruption!");
119*27162e4eSAndroid Build Coastguard Worker }
120*27162e4eSAndroid Build Coastguard Worker 
121*27162e4eSAndroid Build Coastguard Worker /**
122*27162e4eSAndroid Build Coastguard Worker  * Picks a dictionary size and trims the dictionary off of the data.
123*27162e4eSAndroid Build Coastguard Worker  * We copy the dictionary to the roundTrip so our validation passes.
124*27162e4eSAndroid Build Coastguard Worker  */
state_trimDict(state_t * state)125*27162e4eSAndroid Build Coastguard Worker static size_t state_trimDict(state_t* state)
126*27162e4eSAndroid Build Coastguard Worker {
127*27162e4eSAndroid Build Coastguard Worker     /* 64 KB is the max dict size, allow slightly beyond that to test trim. */
128*27162e4eSAndroid Build Coastguard Worker     uint32_t maxDictSize = MIN(70 * 1024, state->data.size);
129*27162e4eSAndroid Build Coastguard Worker     size_t const dictSize = FUZZ_rand32(&state->seed, 0, maxDictSize);
130*27162e4eSAndroid Build Coastguard Worker     DEBUGLOG(2, "dictSize = %zu", dictSize);
131*27162e4eSAndroid Build Coastguard Worker     FUZZ_ASSERT(state->data.pos == 0);
132*27162e4eSAndroid Build Coastguard Worker     FUZZ_ASSERT(state->roundTrip.pos == 0);
133*27162e4eSAndroid Build Coastguard Worker     memcpy(state->roundTrip.buf, state->data.buf, dictSize);
134*27162e4eSAndroid Build Coastguard Worker     state->data.pos += dictSize;
135*27162e4eSAndroid Build Coastguard Worker     state->roundTrip.pos += dictSize;
136*27162e4eSAndroid Build Coastguard Worker     return dictSize;
137*27162e4eSAndroid Build Coastguard Worker }
138*27162e4eSAndroid Build Coastguard Worker 
state_prefixRoundTrip(state_t * state)139*27162e4eSAndroid Build Coastguard Worker static void state_prefixRoundTrip(state_t* state)
140*27162e4eSAndroid Build Coastguard Worker {
141*27162e4eSAndroid Build Coastguard Worker     while (state->data.pos != state->data.size) {
142*27162e4eSAndroid Build Coastguard Worker         char const* src = state->data.buf + state->data.pos;
143*27162e4eSAndroid Build Coastguard Worker         char* dst = state->compressed.buf + state->compressed.pos;
144*27162e4eSAndroid Build Coastguard Worker         int const srcRemaining = state->data.size - state->data.pos;
145*27162e4eSAndroid Build Coastguard Worker         int const srcSize = FUZZ_rand32(&state->seed, 0, srcRemaining);
146*27162e4eSAndroid Build Coastguard Worker         int const dstCapacity = state->compressed.size - state->compressed.pos;
147*27162e4eSAndroid Build Coastguard Worker         int const cSize = LZ4_compress_fast_continue(state->cstream, src, dst,
148*27162e4eSAndroid Build Coastguard Worker                                                      srcSize, dstCapacity, 0);
149*27162e4eSAndroid Build Coastguard Worker         FUZZ_ASSERT(cSize > 0);
150*27162e4eSAndroid Build Coastguard Worker         state->data.pos += srcSize;
151*27162e4eSAndroid Build Coastguard Worker         state->compressed.pos += cSize;
152*27162e4eSAndroid Build Coastguard Worker         state_decompress(state, dst, cSize);
153*27162e4eSAndroid Build Coastguard Worker     }
154*27162e4eSAndroid Build Coastguard Worker }
155*27162e4eSAndroid Build Coastguard Worker 
state_extDictRoundTrip(state_t * state)156*27162e4eSAndroid Build Coastguard Worker static void state_extDictRoundTrip(state_t* state)
157*27162e4eSAndroid Build Coastguard Worker {
158*27162e4eSAndroid Build Coastguard Worker     int i = 0;
159*27162e4eSAndroid Build Coastguard Worker     cursor_t data2 = cursor_create(state->data.size);
160*27162e4eSAndroid Build Coastguard Worker     memcpy(data2.buf, state->data.buf, state->data.size);
161*27162e4eSAndroid Build Coastguard Worker     while (state->data.pos != state->data.size) {
162*27162e4eSAndroid Build Coastguard Worker         char const* data = (i++ & 1) ? state->data.buf : data2.buf;
163*27162e4eSAndroid Build Coastguard Worker         char const* src = data + state->data.pos;
164*27162e4eSAndroid Build Coastguard Worker         char* dst = state->compressed.buf + state->compressed.pos;
165*27162e4eSAndroid Build Coastguard Worker         int const srcRemaining = state->data.size - state->data.pos;
166*27162e4eSAndroid Build Coastguard Worker         int const srcSize = FUZZ_rand32(&state->seed, 0, srcRemaining);
167*27162e4eSAndroid Build Coastguard Worker         int const dstCapacity = state->compressed.size - state->compressed.pos;
168*27162e4eSAndroid Build Coastguard Worker         int const cSize = LZ4_compress_fast_continue(state->cstream, src, dst,
169*27162e4eSAndroid Build Coastguard Worker                                                      srcSize, dstCapacity, 0);
170*27162e4eSAndroid Build Coastguard Worker         FUZZ_ASSERT(cSize > 0);
171*27162e4eSAndroid Build Coastguard Worker         state->data.pos += srcSize;
172*27162e4eSAndroid Build Coastguard Worker         state->compressed.pos += cSize;
173*27162e4eSAndroid Build Coastguard Worker         state_decompress(state, dst, cSize);
174*27162e4eSAndroid Build Coastguard Worker     }
175*27162e4eSAndroid Build Coastguard Worker     cursor_free(data2);
176*27162e4eSAndroid Build Coastguard Worker }
177*27162e4eSAndroid Build Coastguard Worker 
state_randomRoundTrip(state_t * state,round_trip_t rt0,round_trip_t rt1)178*27162e4eSAndroid Build Coastguard Worker static void state_randomRoundTrip(state_t* state, round_trip_t rt0,
179*27162e4eSAndroid Build Coastguard Worker                                   round_trip_t rt1)
180*27162e4eSAndroid Build Coastguard Worker {
181*27162e4eSAndroid Build Coastguard Worker     if (FUZZ_rand32(&state->seed, 0, 1)) {
182*27162e4eSAndroid Build Coastguard Worker       rt0(state);
183*27162e4eSAndroid Build Coastguard Worker     } else {
184*27162e4eSAndroid Build Coastguard Worker       rt1(state);
185*27162e4eSAndroid Build Coastguard Worker     }
186*27162e4eSAndroid Build Coastguard Worker }
187*27162e4eSAndroid Build Coastguard Worker 
state_loadDictRoundTrip(state_t * state)188*27162e4eSAndroid Build Coastguard Worker static void state_loadDictRoundTrip(state_t* state)
189*27162e4eSAndroid Build Coastguard Worker {
190*27162e4eSAndroid Build Coastguard Worker     char const* dict = state->data.buf;
191*27162e4eSAndroid Build Coastguard Worker     size_t const dictSize = state_trimDict(state);
192*27162e4eSAndroid Build Coastguard Worker     LZ4_loadDict(state->cstream, dict, dictSize);
193*27162e4eSAndroid Build Coastguard Worker     LZ4_setStreamDecode(state->dstream, dict, dictSize);
194*27162e4eSAndroid Build Coastguard Worker     state_randomRoundTrip(state, state_prefixRoundTrip, state_extDictRoundTrip);
195*27162e4eSAndroid Build Coastguard Worker }
196*27162e4eSAndroid Build Coastguard Worker 
state_attachDictRoundTrip(state_t * state)197*27162e4eSAndroid Build Coastguard Worker static void state_attachDictRoundTrip(state_t* state)
198*27162e4eSAndroid Build Coastguard Worker {
199*27162e4eSAndroid Build Coastguard Worker     char const* dict = state->data.buf;
200*27162e4eSAndroid Build Coastguard Worker     size_t const dictSize = state_trimDict(state);
201*27162e4eSAndroid Build Coastguard Worker     LZ4_stream_t* dictStream = LZ4_createStream();
202*27162e4eSAndroid Build Coastguard Worker     LZ4_loadDict(dictStream, dict, dictSize);
203*27162e4eSAndroid Build Coastguard Worker     LZ4_attach_dictionary(state->cstream, dictStream);
204*27162e4eSAndroid Build Coastguard Worker     LZ4_setStreamDecode(state->dstream, dict, dictSize);
205*27162e4eSAndroid Build Coastguard Worker     state_randomRoundTrip(state, state_prefixRoundTrip, state_extDictRoundTrip);
206*27162e4eSAndroid Build Coastguard Worker     LZ4_freeStream(dictStream);
207*27162e4eSAndroid Build Coastguard Worker }
208*27162e4eSAndroid Build Coastguard Worker 
state_prefixHCRoundTrip(state_t * state)209*27162e4eSAndroid Build Coastguard Worker static void state_prefixHCRoundTrip(state_t* state)
210*27162e4eSAndroid Build Coastguard Worker {
211*27162e4eSAndroid Build Coastguard Worker     while (state->data.pos != state->data.size) {
212*27162e4eSAndroid Build Coastguard Worker         char const* src = state->data.buf + state->data.pos;
213*27162e4eSAndroid Build Coastguard Worker         char* dst = state->compressed.buf + state->compressed.pos;
214*27162e4eSAndroid Build Coastguard Worker         int const srcRemaining = state->data.size - state->data.pos;
215*27162e4eSAndroid Build Coastguard Worker         int const srcSize = FUZZ_rand32(&state->seed, 0, srcRemaining);
216*27162e4eSAndroid Build Coastguard Worker         int const dstCapacity = state->compressed.size - state->compressed.pos;
217*27162e4eSAndroid Build Coastguard Worker         int const cSize = LZ4_compress_HC_continue(state->cstreamHC, src, dst,
218*27162e4eSAndroid Build Coastguard Worker                                                    srcSize, dstCapacity);
219*27162e4eSAndroid Build Coastguard Worker         FUZZ_ASSERT(cSize > 0);
220*27162e4eSAndroid Build Coastguard Worker         state->data.pos += srcSize;
221*27162e4eSAndroid Build Coastguard Worker         state->compressed.pos += cSize;
222*27162e4eSAndroid Build Coastguard Worker         state_decompress(state, dst, cSize);
223*27162e4eSAndroid Build Coastguard Worker     }
224*27162e4eSAndroid Build Coastguard Worker }
225*27162e4eSAndroid Build Coastguard Worker 
state_extDictHCRoundTrip(state_t * state)226*27162e4eSAndroid Build Coastguard Worker static void state_extDictHCRoundTrip(state_t* state)
227*27162e4eSAndroid Build Coastguard Worker {
228*27162e4eSAndroid Build Coastguard Worker     int i = 0;
229*27162e4eSAndroid Build Coastguard Worker     cursor_t data2 = cursor_create(state->data.size);
230*27162e4eSAndroid Build Coastguard Worker     DEBUGLOG(2, "extDictHC");
231*27162e4eSAndroid Build Coastguard Worker     memcpy(data2.buf, state->data.buf, state->data.size);
232*27162e4eSAndroid Build Coastguard Worker     while (state->data.pos != state->data.size) {
233*27162e4eSAndroid Build Coastguard Worker         char const* data = (i++ & 1) ? state->data.buf : data2.buf;
234*27162e4eSAndroid Build Coastguard Worker         char const* src = data + state->data.pos;
235*27162e4eSAndroid Build Coastguard Worker         char* dst = state->compressed.buf + state->compressed.pos;
236*27162e4eSAndroid Build Coastguard Worker         int const srcRemaining = state->data.size - state->data.pos;
237*27162e4eSAndroid Build Coastguard Worker         int const srcSize = FUZZ_rand32(&state->seed, 0, srcRemaining);
238*27162e4eSAndroid Build Coastguard Worker         int const dstCapacity = state->compressed.size - state->compressed.pos;
239*27162e4eSAndroid Build Coastguard Worker         int const cSize = LZ4_compress_HC_continue(state->cstreamHC, src, dst,
240*27162e4eSAndroid Build Coastguard Worker                                                    srcSize, dstCapacity);
241*27162e4eSAndroid Build Coastguard Worker         FUZZ_ASSERT(cSize > 0);
242*27162e4eSAndroid Build Coastguard Worker         DEBUGLOG(2, "srcSize = %d", srcSize);
243*27162e4eSAndroid Build Coastguard Worker         state->data.pos += srcSize;
244*27162e4eSAndroid Build Coastguard Worker         state->compressed.pos += cSize;
245*27162e4eSAndroid Build Coastguard Worker         state_decompress(state, dst, cSize);
246*27162e4eSAndroid Build Coastguard Worker     }
247*27162e4eSAndroid Build Coastguard Worker     cursor_free(data2);
248*27162e4eSAndroid Build Coastguard Worker }
249*27162e4eSAndroid Build Coastguard Worker 
state_loadDictHCRoundTrip(state_t * state)250*27162e4eSAndroid Build Coastguard Worker static void state_loadDictHCRoundTrip(state_t* state)
251*27162e4eSAndroid Build Coastguard Worker {
252*27162e4eSAndroid Build Coastguard Worker     char const* dict = state->data.buf;
253*27162e4eSAndroid Build Coastguard Worker     size_t const dictSize = state_trimDict(state);
254*27162e4eSAndroid Build Coastguard Worker     LZ4_loadDictHC(state->cstreamHC, dict, dictSize);
255*27162e4eSAndroid Build Coastguard Worker     LZ4_setStreamDecode(state->dstream, dict, dictSize);
256*27162e4eSAndroid Build Coastguard Worker     state_randomRoundTrip(state, state_prefixHCRoundTrip,
257*27162e4eSAndroid Build Coastguard Worker                           state_extDictHCRoundTrip);
258*27162e4eSAndroid Build Coastguard Worker }
259*27162e4eSAndroid Build Coastguard Worker 
state_attachDictHCRoundTrip(state_t * state)260*27162e4eSAndroid Build Coastguard Worker static void state_attachDictHCRoundTrip(state_t* state)
261*27162e4eSAndroid Build Coastguard Worker {
262*27162e4eSAndroid Build Coastguard Worker     char const* dict = state->data.buf;
263*27162e4eSAndroid Build Coastguard Worker     size_t const dictSize = state_trimDict(state);
264*27162e4eSAndroid Build Coastguard Worker     LZ4_streamHC_t* dictStream = LZ4_createStreamHC();
265*27162e4eSAndroid Build Coastguard Worker     LZ4_setCompressionLevel(dictStream, state->level);
266*27162e4eSAndroid Build Coastguard Worker     LZ4_loadDictHC(dictStream, dict, dictSize);
267*27162e4eSAndroid Build Coastguard Worker     LZ4_attach_HC_dictionary(state->cstreamHC, dictStream);
268*27162e4eSAndroid Build Coastguard Worker     LZ4_setStreamDecode(state->dstream, dict, dictSize);
269*27162e4eSAndroid Build Coastguard Worker     state_randomRoundTrip(state, state_prefixHCRoundTrip,
270*27162e4eSAndroid Build Coastguard Worker                           state_extDictHCRoundTrip);
271*27162e4eSAndroid Build Coastguard Worker     LZ4_freeStreamHC(dictStream);
272*27162e4eSAndroid Build Coastguard Worker }
273*27162e4eSAndroid Build Coastguard Worker 
274*27162e4eSAndroid Build Coastguard Worker round_trip_t roundTrips[] = {
275*27162e4eSAndroid Build Coastguard Worker   &state_prefixRoundTrip,
276*27162e4eSAndroid Build Coastguard Worker   &state_extDictRoundTrip,
277*27162e4eSAndroid Build Coastguard Worker   &state_loadDictRoundTrip,
278*27162e4eSAndroid Build Coastguard Worker   &state_attachDictRoundTrip,
279*27162e4eSAndroid Build Coastguard Worker   &state_prefixHCRoundTrip,
280*27162e4eSAndroid Build Coastguard Worker   &state_extDictHCRoundTrip,
281*27162e4eSAndroid Build Coastguard Worker   &state_loadDictHCRoundTrip,
282*27162e4eSAndroid Build Coastguard Worker   &state_attachDictHCRoundTrip,
283*27162e4eSAndroid Build Coastguard Worker };
284*27162e4eSAndroid Build Coastguard Worker 
LLVMFuzzerTestOneInput(const uint8_t * data,size_t size)285*27162e4eSAndroid Build Coastguard Worker int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size)
286*27162e4eSAndroid Build Coastguard Worker {
287*27162e4eSAndroid Build Coastguard Worker     uint32_t seed = FUZZ_seed(&data, &size);
288*27162e4eSAndroid Build Coastguard Worker     state_t state = state_create((char const*)data, size, seed);
289*27162e4eSAndroid Build Coastguard Worker     const int n = sizeof(roundTrips) / sizeof(round_trip_t);
290*27162e4eSAndroid Build Coastguard Worker     int i;
291*27162e4eSAndroid Build Coastguard Worker 
292*27162e4eSAndroid Build Coastguard Worker     for (i = 0; i < n; ++i) {
293*27162e4eSAndroid Build Coastguard Worker         DEBUGLOG(2, "Round trip %d", i);
294*27162e4eSAndroid Build Coastguard Worker         state_reset(&state, seed);
295*27162e4eSAndroid Build Coastguard Worker         roundTrips[i](&state);
296*27162e4eSAndroid Build Coastguard Worker         state_checkRoundTrip(&state);
297*27162e4eSAndroid Build Coastguard Worker     }
298*27162e4eSAndroid Build Coastguard Worker 
299*27162e4eSAndroid Build Coastguard Worker     state_free(state);
300*27162e4eSAndroid Build Coastguard Worker 
301*27162e4eSAndroid Build Coastguard Worker     return 0;
302*27162e4eSAndroid Build Coastguard Worker }
303