blob: b2733874bd24cb13ca662a5a82a31deb2a4e2ee3 [file] [log] [blame]
Erik de Castro Lopoe0f7e0e2019-11-17 16:15:51 +11001#include <cstddef>
2#include <cstdint>
3
4#include <fuzzing/datasource/datasource.hpp>
5#include <fuzzing/memory.hpp>
6
7#include "FLAC++/decoder.h"
8
9template <> FLAC__MetadataType fuzzing::datasource::Base::Get<FLAC__MetadataType>(const uint64_t id) {
10 (void)id;
11 switch ( Get<uint8_t>() ) {
12 case 0:
13 return FLAC__METADATA_TYPE_STREAMINFO;
14 case 1:
15 return FLAC__METADATA_TYPE_PADDING;
16 case 2:
17 return FLAC__METADATA_TYPE_APPLICATION;
18 case 3:
19 return FLAC__METADATA_TYPE_SEEKTABLE;
20 case 4:
21 return FLAC__METADATA_TYPE_VORBIS_COMMENT;
22 case 5:
23 return FLAC__METADATA_TYPE_CUESHEET;
24 case 6:
25 return FLAC__METADATA_TYPE_PICTURE;
26 case 7:
27 return FLAC__METADATA_TYPE_UNDEFINED;
28 case 8:
29 return FLAC__MAX_METADATA_TYPE;
30 default:
31 return FLAC__METADATA_TYPE_STREAMINFO;
32 }
33}
34
35namespace FLAC {
36 namespace Decoder {
37 class FuzzerStream : public Stream {
38 private:
39 fuzzing::datasource::Datasource& ds;
40 public:
41 FuzzerStream(fuzzing::datasource::Datasource& dsrc) :
42 Stream(), ds(dsrc) { }
43
44 ::FLAC__StreamDecoderReadStatus read_callback(FLAC__byte buffer[], size_t *bytes) override {
45 try {
46 const size_t maxCopySize = *bytes;
47
48 if ( maxCopySize > 0 ) {
49 /* memset just to test if this overwrites anything, and triggers ASAN */
50 memset(buffer, 0, maxCopySize);
51 }
52
53 const auto data = ds.GetData(0);
54 const auto dataSize = data.size();
55 const auto copySize = std::min(maxCopySize, dataSize);
56
57 if ( copySize > 0 ) {
58 memcpy(buffer, data.data(), copySize);
59 }
60
61 *bytes = copySize;
62
63 return FLAC__STREAM_DECODER_READ_STATUS_CONTINUE;
64 } catch ( ... ) {
65 return FLAC__STREAM_DECODER_READ_STATUS_ABORT;
66 }
67 }
68
69 ::FLAC__StreamDecoderWriteStatus write_callback(const ::FLAC__Frame *frame, const FLAC__int32 * const buffer[]) override {
70 {
71 fuzzing::memory::memory_test(&(frame->header), sizeof(frame->header));
72 fuzzing::memory::memory_test(&(frame->footer), sizeof(frame->footer));
73 }
74
75 {
76 const auto numChannels = get_channels();
77 const size_t bytesPerChannel = frame->header.blocksize * sizeof(FLAC__int32);
78 for (size_t i = 0; i < numChannels; i++) {
79 fuzzing::memory::memory_test(buffer[i], bytesPerChannel);
80 }
81 }
82
83 try {
84 if ( ds.Get<bool>() == true ) {
85 return FLAC__STREAM_DECODER_WRITE_STATUS_ABORT;
86 }
87 } catch ( ... ) { }
88 return FLAC__STREAM_DECODER_WRITE_STATUS_CONTINUE;
89 }
90
91 void error_callback(::FLAC__StreamDecoderErrorStatus status) override {
92 fuzzing::memory::memory_test(status);
93 }
94
95 void metadata_callback(const ::FLAC__StreamMetadata *metadata) override {
96 fuzzing::memory::memory_test(metadata->type);
97 fuzzing::memory::memory_test(metadata->is_last);
98 fuzzing::memory::memory_test(metadata->length);
99 fuzzing::memory::memory_test(metadata->data);
100 }
101
102 ::FLAC__StreamDecoderSeekStatus seek_callback(FLAC__uint64 absolute_byte_offset) override {
103 fuzzing::memory::memory_test(absolute_byte_offset);
104
105 try {
106 if ( ds.Get<bool>() == true ) {
107 return FLAC__STREAM_DECODER_SEEK_STATUS_OK;
108 } else {
109 return FLAC__STREAM_DECODER_SEEK_STATUS_ERROR;
110 }
111 } catch ( ... ) {
112 return FLAC__STREAM_DECODER_SEEK_STATUS_OK;
113 }
114 }
115#if 0
116 ::FLAC__StreamDecoderTellStatus tell_callback(FLAC__uint64 *absolute_byte_offset) override {
117 fuzzing::memory::memory_test(*absolute_byte_offset);
118
119 try {
120 if ( ds.Get<bool>() == true ) {
121 return FLAC__STREAM_DECODER_TELL_STATUS_OK;
122 } else {
123 return FLAC__STREAM_DECODER_TELL_STATUS_ERROR;
124 }
125 } catch ( ... ) {
126 return FLAC__STREAM_DECODER_TELL_STATUS_OK;
127 }
128 }
129
130 ::FLAC__StreamDecoderLengthStatus length_callback(FLAC__uint64 *stream_length) override {
131 fuzzing::memory::memory_test(*stream_length);
132
133 try {
134 if ( ds.Get<bool>() == true ) {
135 return FLAC__STREAM_DECODER_LENGTH_STATUS_OK;
136 } else {
137 return FLAC__STREAM_DECODER_LENGTH_STATUS_ERROR;
138 }
139 } catch ( ... ) {
140 return FLAC__STREAM_DECODER_LENGTH_STATUS_OK;
141 }
142 }
143#endif
144 };
145 }
146}
147
148extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
149 fuzzing::datasource::Datasource ds(data, size);
150 FLAC::Decoder::FuzzerStream decoder(ds);
151
152 try {
153 {
154 ::FLAC__StreamDecoderInitStatus ret;
155
156 if ( ds.Get<bool>() ) {
157 ret = decoder.init();
158 } else {
159 ret = decoder.init_ogg();
160 }
161
162 if ( ret != FLAC__STREAM_DECODER_INIT_STATUS_OK ) {
163 goto end;
164 }
165 }
166
167 if ( ds.Get<bool>() ) {
168#ifdef FUZZER_DEBUG
169 printf("set_ogg_serial_number\n");
170#endif
171 decoder.set_ogg_serial_number(ds.Get<long>());
172 }
173 if ( ds.Get<bool>() ) {
174#ifdef FUZZER_DEBUG
175 printf("set_md5_checking\n");
176#endif
177 decoder.set_md5_checking(ds.Get<bool>());
178 }
179 if ( ds.Get<bool>() ) {
180#ifdef FUZZER_DEBUG
181 printf("set_metadata_respond\n");
182#endif
183 decoder.set_metadata_respond(ds.Get<::FLAC__MetadataType>());
184 }
185 if ( ds.Get<bool>() ) {
186 const auto idVector = ds.GetData(0);
187 unsigned char id[4];
188 if ( idVector.size() >= sizeof(id) ) {
189 memcpy(id, idVector.data(), sizeof(id));
190#ifdef FUZZER_DEBUG
191 printf("set_metadata_respond_application\n");
192#endif
193 decoder.set_metadata_respond_application(id);
194 }
195 }
196 if ( ds.Get<bool>() ) {
197#ifdef FUZZER_DEBUG
198 printf("set_metadata_respond_all\n");
199#endif
200 decoder.set_metadata_respond_all();
201 }
202 if ( ds.Get<bool>() ) {
203#ifdef FUZZER_DEBUG
204 printf("set_metadata_ignore\n");
205#endif
206 decoder.set_metadata_ignore(ds.Get<::FLAC__MetadataType>());
207 }
208 if ( ds.Get<bool>() ) {
209 const auto idVector = ds.GetData(0);
210 unsigned char id[4];
211 if ( idVector.size() >= sizeof(id) ) {
212 memcpy(id, idVector.data(), sizeof(id));
213#ifdef FUZZER_DEBUG
214 printf("set_metadata_ignore_application\n");
215#endif
216 decoder.set_metadata_ignore_application(id);
217 }
218 }
219 if ( ds.Get<bool>() ) {
220#ifdef FUZZER_DEBUG
221 printf("set_metadata_ignore_all\n");
222#endif
223 decoder.set_metadata_ignore_all();
224 }
225
226 while ( ds.Get<bool>() ) {
227 switch ( ds.Get<uint8_t>() ) {
228 case 0:
229 {
230#ifdef FUZZER_DEBUG
231 printf("flush\n");
232#endif
233 const bool res = decoder.flush();
234 fuzzing::memory::memory_test(res);
235 }
236 break;
237 case 1:
238 {
239#ifdef FUZZER_DEBUG
240 printf("reset\n");
241#endif
242 const bool res = decoder.reset();
243 fuzzing::memory::memory_test(res);
244 }
245 break;
246 case 2:
247 {
248#ifdef FUZZER_DEBUG
249 printf("process_single\n");
250#endif
251 const bool res = decoder.process_single();
252 fuzzing::memory::memory_test(res);
253 }
254 break;
255 case 3:
256 {
257#ifdef FUZZER_DEBUG
258 printf("process_until_end_of_metadata\n");
259#endif
260 const bool res = decoder.process_until_end_of_metadata();
261 fuzzing::memory::memory_test(res);
262 }
263 break;
264 case 4:
265 {
266#ifdef FUZZER_DEBUG
267 printf("process_until_end_of_stream\n");
268#endif
269 const bool res = decoder.process_until_end_of_stream();
270 fuzzing::memory::memory_test(res);
271 }
272 break;
273 case 5:
274 {
275#ifdef FUZZER_DEBUG
276 printf("skip_single_frame\n");
277#endif
278 const bool res = decoder.skip_single_frame();
279 fuzzing::memory::memory_test(res);
280 }
281 break;
282 case 6:
283 {
284#ifdef FUZZER_DEBUG
285 printf("seek_absolute\n");
286#endif
287 const bool res = decoder.seek_absolute(ds.Get<uint64_t>());
288 fuzzing::memory::memory_test(res);
289 }
290 break;
291 case 7:
292 {
293#ifdef FUZZER_DEBUG
294 printf("get_md5_checking\n");
295#endif
296 const bool res = decoder.get_md5_checking();
297 fuzzing::memory::memory_test(res);
298 }
299 break;
300 case 8:
301 {
302#ifdef FUZZER_DEBUG
303 printf("get_total_samples\n");
304#endif
305 const bool res = decoder.get_total_samples();
306 fuzzing::memory::memory_test(res);
307 }
308 break;
309 case 9:
310 {
311#ifdef FUZZER_DEBUG
312 printf("get_channels\n");
313#endif
314 const bool res = decoder.get_channels();
315 fuzzing::memory::memory_test(res);
316 }
317 break;
318 case 10:
319 {
320#ifdef FUZZER_DEBUG
321 printf("get_bits_per_sample\n");
322#endif
323 const bool res = decoder.get_bits_per_sample();
324 fuzzing::memory::memory_test(res);
325 }
326 break;
327 case 11:
328 {
329#ifdef FUZZER_DEBUG
330 printf("get_sample_rate\n");
331#endif
332 const bool res = decoder.get_sample_rate();
333 fuzzing::memory::memory_test(res);
334 }
335 break;
336 case 12:
337 {
338#ifdef FUZZER_DEBUG
339 printf("get_blocksize\n");
340#endif
341 const bool res = decoder.get_blocksize();
342 fuzzing::memory::memory_test(res);
343 }
344 break;
345 }
346 }
347 } catch ( ... ) { }
348
349end:
350 {
351 const bool res = decoder.finish();
352 fuzzing::memory::memory_test(res);
353 }
354 return 0;
355}