• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 #include <cstddef>
2 #include <cstdint>
3 
4 #include <fuzzing/datasource/datasource.hpp>
5 #include <fuzzing/memory.hpp>
6 
7 #include "FLAC++/decoder.h"
8 
Get(const uint64_t id)9 template <> 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 
35 namespace FLAC {
36 	namespace Decoder {
37         class FuzzerStream : public Stream {
38             private:
39                 fuzzing::datasource::Datasource& ds;
40             public:
FuzzerStream(fuzzing::datasource::Datasource & dsrc)41                 FuzzerStream(fuzzing::datasource::Datasource& dsrc) :
42                     Stream(), ds(dsrc) { }
43 
read_callback(FLAC__byte buffer[],size_t * bytes)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 
write_callback(const::FLAC__Frame * frame,const FLAC__int32 * const buffer[])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 
error_callback(::FLAC__StreamDecoderErrorStatus status)91                 void error_callback(::FLAC__StreamDecoderErrorStatus status)  override {
92                     fuzzing::memory::memory_test(status);
93                 }
94 
metadata_callback(const::FLAC__StreamMetadata * metadata)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 
seek_callback(FLAC__uint64 absolute_byte_offset)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 
LLVMFuzzerTestOneInput(const uint8_t * data,size_t size)148 extern "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 
349 end:
350     {
351         const bool res = decoder.finish();
352         fuzzing::memory::memory_test(res);
353     }
354     return 0;
355 }
356