1 // Copyright 2020 Google Inc.
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 // http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14
15 #include <assert.h>
16 #include <string>
17
18 #include "include/flac_parser.h"
19
20 #include <jni.h>
21
22 // #include <android/log.h>
23
24 #include <cassert>
25 #include <cstdlib>
26 #include <cstring>
27
28 #define LOG_TAG "FLACParser"
29
30 #define LITERAL_TO_STRING_INTERNAL(x) #x
31 #define LITERAL_TO_STRING(x) LITERAL_TO_STRING_INTERNAL(x)
32
33 #define CHECK(x) if (!(x)) return 0;
34
35 const int endian = 1;
36 #define isBigEndian() (*(reinterpret_cast<const char *>(&endian)) == 0)
37
38 // The FLAC parser calls our C++ static callbacks using C calling conventions,
39 // inside FLAC__stream_decoder_process_until_end_of_metadata
40 // and FLAC__stream_decoder_process_single.
41 // We immediately then call our corresponding C++ instance methods
42 // with the same parameter list, but discard redundant information.
43
read_callback(const FLAC__StreamDecoder *,FLAC__byte buffer[],size_t * bytes,void * client_data)44 FLAC__StreamDecoderReadStatus FLACParser::read_callback(
45 const FLAC__StreamDecoder * /* decoder */, FLAC__byte buffer[],
46 size_t *bytes, void *client_data) {
47 return reinterpret_cast<FLACParser *>(client_data)
48 ->readCallback(buffer, bytes);
49 }
50
seek_callback(const FLAC__StreamDecoder *,FLAC__uint64 absolute_byte_offset,void * client_data)51 FLAC__StreamDecoderSeekStatus FLACParser::seek_callback(
52 const FLAC__StreamDecoder * /* decoder */,
53 FLAC__uint64 absolute_byte_offset, void *client_data) {
54 return reinterpret_cast<FLACParser *>(client_data)
55 ->seekCallback(absolute_byte_offset);
56 }
57
tell_callback(const FLAC__StreamDecoder *,FLAC__uint64 * absolute_byte_offset,void * client_data)58 FLAC__StreamDecoderTellStatus FLACParser::tell_callback(
59 const FLAC__StreamDecoder * /* decoder */,
60 FLAC__uint64 *absolute_byte_offset, void *client_data) {
61 return reinterpret_cast<FLACParser *>(client_data)
62 ->tellCallback(absolute_byte_offset);
63 }
64
length_callback(const FLAC__StreamDecoder *,FLAC__uint64 * stream_length,void * client_data)65 FLAC__StreamDecoderLengthStatus FLACParser::length_callback(
66 const FLAC__StreamDecoder * /* decoder */, FLAC__uint64 *stream_length,
67 void *client_data) {
68 return reinterpret_cast<FLACParser *>(client_data)
69 ->lengthCallback(stream_length);
70 }
71
eof_callback(const FLAC__StreamDecoder *,void * client_data)72 FLAC__bool FLACParser::eof_callback(const FLAC__StreamDecoder * /* decoder */,
73 void *client_data) {
74 return reinterpret_cast<FLACParser *>(client_data)->eofCallback();
75 }
76
write_callback(const FLAC__StreamDecoder *,const FLAC__Frame * frame,const FLAC__int32 * const buffer[],void * client_data)77 FLAC__StreamDecoderWriteStatus FLACParser::write_callback(
78 const FLAC__StreamDecoder * /* decoder */, const FLAC__Frame *frame,
79 const FLAC__int32 *const buffer[], void *client_data) {
80 return reinterpret_cast<FLACParser *>(client_data)
81 ->writeCallback(frame, buffer);
82 }
83
metadata_callback(const FLAC__StreamDecoder *,const FLAC__StreamMetadata * metadata,void * client_data)84 void FLACParser::metadata_callback(const FLAC__StreamDecoder * /* decoder */,
85 const FLAC__StreamMetadata *metadata,
86 void *client_data) {
87 reinterpret_cast<FLACParser *>(client_data)->metadataCallback(metadata);
88 }
89
error_callback(const FLAC__StreamDecoder *,FLAC__StreamDecoderErrorStatus status,void * client_data)90 void FLACParser::error_callback(const FLAC__StreamDecoder * /* decoder */,
91 FLAC__StreamDecoderErrorStatus status,
92 void *client_data) {
93 reinterpret_cast<FLACParser *>(client_data)->errorCallback(status);
94 }
95
96 // These are the corresponding callbacks with C++ calling conventions
97
readCallback(FLAC__byte buffer[],size_t * bytes)98 FLAC__StreamDecoderReadStatus FLACParser::readCallback(FLAC__byte buffer[],
99 size_t *bytes) {
100 size_t requested = *bytes;
101 ssize_t actual = mDataSource->readAt(mCurrentPos, buffer, requested);
102 if (0 > actual) {
103 *bytes = 0;
104 return FLAC__STREAM_DECODER_READ_STATUS_ABORT;
105 } else if (0 == actual) {
106 *bytes = 0;
107 mEOF = true;
108 return FLAC__STREAM_DECODER_READ_STATUS_END_OF_STREAM;
109 } else {
110 assert(actual <= requested);
111 *bytes = actual;
112 mCurrentPos += actual;
113 return FLAC__STREAM_DECODER_READ_STATUS_CONTINUE;
114 }
115 }
116
seekCallback(FLAC__uint64 absolute_byte_offset)117 FLAC__StreamDecoderSeekStatus FLACParser::seekCallback(
118 FLAC__uint64 absolute_byte_offset) {
119 mCurrentPos = absolute_byte_offset;
120 mEOF = false;
121 return FLAC__STREAM_DECODER_SEEK_STATUS_OK;
122 }
123
tellCallback(FLAC__uint64 * absolute_byte_offset)124 FLAC__StreamDecoderTellStatus FLACParser::tellCallback(
125 FLAC__uint64 *absolute_byte_offset) {
126 *absolute_byte_offset = mCurrentPos;
127 return FLAC__STREAM_DECODER_TELL_STATUS_OK;
128 }
129
lengthCallback(FLAC__uint64 * stream_length)130 FLAC__StreamDecoderLengthStatus FLACParser::lengthCallback(
131 FLAC__uint64 *stream_length) {
132 return FLAC__STREAM_DECODER_LENGTH_STATUS_UNSUPPORTED;
133 }
134
eofCallback()135 FLAC__bool FLACParser::eofCallback() { return mEOF; }
136
writeCallback(const FLAC__Frame * frame,const FLAC__int32 * const buffer[])137 FLAC__StreamDecoderWriteStatus FLACParser::writeCallback(
138 const FLAC__Frame *frame, const FLAC__int32 *const buffer[]) {
139 if (mWriteRequested) {
140 mWriteRequested = false;
141 // FLAC parser doesn't free or realloc buffer until next frame or finish
142 mWriteHeader = frame->header;
143 mWriteBuffer = buffer;
144 mWriteCompleted = true;
145 return FLAC__STREAM_DECODER_WRITE_STATUS_CONTINUE;
146 } else {
147 return FLAC__STREAM_DECODER_WRITE_STATUS_ABORT;
148 }
149 }
150
metadataCallback(const FLAC__StreamMetadata * metadata)151 void FLACParser::metadataCallback(const FLAC__StreamMetadata *metadata) {
152 switch (metadata->type) {
153 case FLAC__METADATA_TYPE_STREAMINFO:
154 if (!mStreamInfoValid) {
155 mStreamInfo = metadata->data.stream_info;
156 mStreamInfoValid = true;
157 } else {
158 break;
159 }
160 break;
161 case FLAC__METADATA_TYPE_SEEKTABLE:
162 mSeekTable = &metadata->data.seek_table;
163 break;
164 case FLAC__METADATA_TYPE_VORBIS_COMMENT:
165 if (!mVorbisCommentsValid) {
166 FLAC__StreamMetadata_VorbisComment vorbisComment =
167 metadata->data.vorbis_comment;
168 for (FLAC__uint32 i = 0; i < vorbisComment.num_comments; ++i) {
169 FLAC__StreamMetadata_VorbisComment_Entry vorbisCommentEntry =
170 vorbisComment.comments[i];
171 if (vorbisCommentEntry.entry != NULL) {
172 std::string comment(
173 reinterpret_cast<char *>(vorbisCommentEntry.entry),
174 vorbisCommentEntry.length);
175 mVorbisComments.push_back(comment);
176 }
177 }
178 mVorbisCommentsValid = true;
179 } else {
180 break;
181 }
182 break;
183 case FLAC__METADATA_TYPE_PICTURE: {
184 const FLAC__StreamMetadata_Picture *parsedPicture =
185 &metadata->data.picture;
186 FlacPicture picture;
187 picture.mimeType.assign(std::string(parsedPicture->mime_type));
188 picture.description.assign(
189 std::string((char *)parsedPicture->description));
190 picture.data.assign(parsedPicture->data,
191 parsedPicture->data + parsedPicture->data_length);
192 picture.width = parsedPicture->width;
193 picture.height = parsedPicture->height;
194 picture.depth = parsedPicture->depth;
195 picture.colors = parsedPicture->colors;
196 picture.type = parsedPicture->type;
197 mPictures.push_back(picture);
198 mPicturesValid = true;
199 break;
200 }
201 default:
202 break;
203 }
204 }
205
errorCallback(FLAC__StreamDecoderErrorStatus status)206 void FLACParser::errorCallback(FLAC__StreamDecoderErrorStatus status) {
207 mErrorStatus = status;
208 }
209
210 // Copy samples from FLAC native 32-bit non-interleaved to
211 // correct bit-depth (non-zero padded), interleaved.
212 // These are candidates for optimization if needed.
copyToByteArrayBigEndian(int8_t * dst,const int * const * src,unsigned bytesPerSample,unsigned nSamples,unsigned nChannels)213 static void copyToByteArrayBigEndian(int8_t *dst, const int *const *src,
214 unsigned bytesPerSample, unsigned nSamples,
215 unsigned nChannels) {
216 for (unsigned i = 0; i < nSamples; ++i) {
217 for (unsigned c = 0; c < nChannels; ++c) {
218 // point to the first byte of the source address
219 // and then skip the first few bytes (most significant bytes)
220 // depending on the bit depth
221 const int8_t *byteSrc =
222 reinterpret_cast<const int8_t *>(&src[c][i]) + 4 - bytesPerSample;
223 memcpy(dst, byteSrc, bytesPerSample);
224 dst = dst + bytesPerSample;
225 }
226 }
227 }
228
copyToByteArrayLittleEndian(int8_t * dst,const int * const * src,unsigned bytesPerSample,unsigned nSamples,unsigned nChannels)229 static void copyToByteArrayLittleEndian(int8_t *dst, const int *const *src,
230 unsigned bytesPerSample,
231 unsigned nSamples, unsigned nChannels) {
232 for (unsigned i = 0; i < nSamples; ++i) {
233 for (unsigned c = 0; c < nChannels; ++c) {
234 // with little endian, the most significant bytes will be at the end
235 // copy the bytes in little endian will remove the most significant byte
236 // so we are good here.
237 memcpy(dst, &(src[c][i]), bytesPerSample);
238 dst = dst + bytesPerSample;
239 }
240 }
241 }
242
copyTrespass(int8_t *,const int * const *,unsigned,unsigned,unsigned)243 static void copyTrespass(int8_t * /* dst */, const int *const * /* src */,
244 unsigned /* bytesPerSample */, unsigned /* nSamples */,
245 unsigned /* nChannels */) {
246 ;
247 }
248
249 // FLACParser
250
FLACParser(DataSource * source)251 FLACParser::FLACParser(DataSource *source)
252 : mDataSource(source),
253 mCopy(copyTrespass),
254 mDecoder(NULL),
255 mCurrentPos(0LL),
256 mEOF(false),
257 mStreamInfoValid(false),
258 mSeekTable(NULL),
259 firstFrameOffset(0LL),
260 mVorbisCommentsValid(false),
261 mPicturesValid(false),
262 mWriteRequested(false),
263 mWriteCompleted(false),
264 mWriteBuffer(NULL),
265 mErrorStatus((FLAC__StreamDecoderErrorStatus)-1) {
266 memset(&mStreamInfo, 0, sizeof(mStreamInfo));
267 memset(&mWriteHeader, 0, sizeof(mWriteHeader));
268 }
269
~FLACParser()270 FLACParser::~FLACParser() {
271 if (mDecoder != NULL) {
272 FLAC__stream_decoder_delete(mDecoder);
273 mDecoder = NULL;
274 }
275 }
276
init()277 bool FLACParser::init() {
278 // setup libFLAC parser
279 mDecoder = FLAC__stream_decoder_new();
280 if (mDecoder == NULL) {
281 // The new should succeed, since probably all it does is a malloc
282 // that always succeeds in Android. But to avoid dependence on the
283 // libFLAC internals, we check and log here.
284 return false;
285 }
286 FLAC__stream_decoder_set_md5_checking(mDecoder, false);
287 FLAC__stream_decoder_set_metadata_ignore_all(mDecoder);
288 FLAC__stream_decoder_set_metadata_respond(mDecoder,
289 FLAC__METADATA_TYPE_STREAMINFO);
290 FLAC__stream_decoder_set_metadata_respond(mDecoder,
291 FLAC__METADATA_TYPE_SEEKTABLE);
292 FLAC__stream_decoder_set_metadata_respond(mDecoder,
293 FLAC__METADATA_TYPE_VORBIS_COMMENT);
294 FLAC__stream_decoder_set_metadata_respond(mDecoder,
295 FLAC__METADATA_TYPE_PICTURE);
296 FLAC__StreamDecoderInitStatus initStatus;
297 initStatus = FLAC__stream_decoder_init_stream(
298 mDecoder, read_callback, seek_callback, tell_callback, length_callback,
299 eof_callback, write_callback, metadata_callback, error_callback,
300 reinterpret_cast<void *>(this));
301 if (initStatus != FLAC__STREAM_DECODER_INIT_STATUS_OK) {
302 // A failure here probably indicates a programming error and so is
303 // unlikely to happen. But we check and log here similarly to above.
304 return false;
305 }
306 return true;
307 }
308
decodeMetadata()309 bool FLACParser::decodeMetadata() {
310 // parse all metadata
311 if (!FLAC__stream_decoder_process_until_end_of_metadata(mDecoder)) {
312 return false;
313 }
314 // store first frame offset
315 FLAC__stream_decoder_get_decode_position(mDecoder, &firstFrameOffset);
316
317 if (mStreamInfoValid) {
318 // check channel count
319 if (getChannels() == 0 || getChannels() > 8) {
320 return false;
321 }
322 // check bit depth
323 switch (getBitsPerSample()) {
324 case 8:
325 case 16:
326 case 24:
327 case 32:
328 break;
329 default:
330 return false;
331 }
332 // configure the appropriate copy function based on device endianness.
333 if (isBigEndian()) {
334 mCopy = copyToByteArrayBigEndian;
335 } else {
336 mCopy = copyToByteArrayLittleEndian;
337 }
338 } else {
339 return false;
340 }
341 return true;
342 }
343
readBuffer(void * output,size_t output_size)344 size_t FLACParser::readBuffer(void *output, size_t output_size) {
345 mWriteRequested = true;
346 mWriteCompleted = false;
347
348 if (!FLAC__stream_decoder_process_single(mDecoder)) {
349 return -1;
350 }
351 if (!mWriteCompleted) {
352 if (FLAC__stream_decoder_get_state(mDecoder) !=
353 FLAC__STREAM_DECODER_END_OF_STREAM) {
354 }
355 return -1;
356 }
357
358 // verify that block header keeps the promises made by STREAMINFO
359 unsigned blocksize = mWriteHeader.blocksize;
360 if (blocksize == 0 || blocksize > getMaxBlockSize()) {
361 return -1;
362 }
363 if (mWriteHeader.sample_rate != getSampleRate() ||
364 mWriteHeader.channels != getChannels() ||
365 mWriteHeader.bits_per_sample != getBitsPerSample()) {
366 return -1;
367 }
368
369 unsigned bytesPerSample = getBitsPerSample() >> 3;
370 size_t bufferSize = blocksize * getChannels() * bytesPerSample;
371 if (bufferSize > output_size) {
372 return -1;
373 }
374
375 // copy PCM from FLAC write buffer to our media buffer, with interleaving.
376 (*mCopy)(reinterpret_cast<int8_t *>(output), mWriteBuffer, bytesPerSample,
377 blocksize, getChannels());
378
379 // fill in buffer metadata
380 CHECK(mWriteHeader.number_type == FLAC__FRAME_NUMBER_TYPE_SAMPLE_NUMBER);
381
382 return bufferSize;
383 }
384
getSeekPositions(int64_t timeUs,std::array<int64_t,4> & result)385 bool FLACParser::getSeekPositions(int64_t timeUs,
386 std::array<int64_t, 4> &result) {
387 if (!mSeekTable) {
388 return false;
389 }
390
391 unsigned sampleRate = getSampleRate();
392 int64_t totalSamples = getTotalSamples();
393 int64_t targetSampleNumber = (timeUs * sampleRate) / 1000000LL;
394 if (targetSampleNumber >= totalSamples) {
395 targetSampleNumber = totalSamples - 1;
396 }
397
398 FLAC__StreamMetadata_SeekPoint* points = mSeekTable->points;
399 unsigned length = mSeekTable->num_points;
400
401 for (unsigned i = length; i != 0; i--) {
402 int64_t sampleNumber = points[i - 1].sample_number;
403 if (sampleNumber == -1) { // placeholder
404 continue;
405 }
406 if (sampleNumber <= targetSampleNumber) {
407 result[0] = (sampleNumber * 1000000LL) / sampleRate;
408 result[1] = firstFrameOffset + points[i - 1].stream_offset;
409 if (sampleNumber == targetSampleNumber || i >= length ||
410 points[i].sample_number == -1) { // placeholder
411 // exact seek, or no following non-placeholder seek point
412 result[2] = result[0];
413 result[3] = result[1];
414 } else {
415 result[2] = (points[i].sample_number * 1000000LL) / sampleRate;
416 result[3] = firstFrameOffset + points[i].stream_offset;
417 }
418 return true;
419 }
420 }
421 result[0] = 0;
422 result[1] = firstFrameOffset;
423 result[2] = 0;
424 result[3] = firstFrameOffset;
425 return true;
426 }
427
428 namespace {
429
430 class FuzzDataSource : public DataSource {
431 const uint8_t *data_;
432 size_t size_;
433
434 public:
FuzzDataSource(const uint8_t * data,size_t size)435 FuzzDataSource(const uint8_t *data, size_t size) {
436 data_ = data;
437 size_ = size;
438 }
439
readAt(off64_t offset,void * const data,size_t size)440 ssize_t readAt(off64_t offset, void *const data, size_t size) {
441 if (offset > size_)
442 return -1;
443 size_t remaining = size_ - offset;
444 if (remaining < size)
445 size = remaining;
446 memcpy(data, data_ + offset, size);
447 return size;
448 }
449 };
450
451 } // namespace
452
453 // Fuzz FLAC format and instrument the result as exoplayer JNI would:
454 // https://github.com/google/ExoPlayer/blob/release-v2/extensions/flac/src/main/jni/
LLVMFuzzerTestOneInput(const uint8_t * data,size_t size)455 extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
456 FuzzDataSource source(data, size);
457 FLACParser parser(&source);
458
459 // Early parsing
460 if (!parser.init() || !parser.decodeMetadata())
461 return 0;
462
463 auto streamInfo = parser.getStreamInfo();
464
465 // Similar implementation than ExoPlayer
466 int buffer_size = streamInfo.max_blocksize * streamInfo.channels * 2;
467 assert(buffer_size >= 0); // Not expected
468 auto buffer = new uint8_t[buffer_size];
469 int runs = 0;
470 while (parser.readBuffer(buffer, buffer_size) >= buffer_size) {
471 runs++;
472 continue;
473 }
474 delete[] buffer;
475
476 return 0;
477 }
478