1 /*
2 * This file is part of FFmpeg.
3 *
4 * FFmpeg is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2.1 of the License, or (at your option) any later version.
8 *
9 * FFmpeg is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
13 *
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with FFmpeg; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
17 */
18
19 /* Targeted fuzzer that targets specific codecs depending on two
20 compile-time flags.
21 INSTRUCTIONS:
22
23 * Get the very fresh clang, e.g. see http://libfuzzer.info#versions
24 * Get and build libFuzzer:
25 svn co http://llvm.org/svn/llvm-project/llvm/trunk/lib/Fuzzer
26 ./Fuzzer/build.sh
27 * build ffmpeg for fuzzing:
28 FLAGS="-fsanitize=address -fsanitize-coverage=trace-pc-guard,trace-cmp -g" CC="clang $FLAGS" CXX="clang++ $FLAGS" ./configure --disable-x86asm
29 make clean && make -j
30 * build the fuzz target.
31 Choose the value of FFMPEG_CODEC (e.g. AV_CODEC_ID_DVD_SUBTITLE) and
32 choose one of FUZZ_FFMPEG_VIDEO, FUZZ_FFMPEG_AUDIO, FUZZ_FFMPEG_SUBTITLE.
33 clang -fsanitize=address -fsanitize-coverage=trace-pc-guard,trace-cmp tools/target_dec_fuzzer.c -o target_dec_fuzzer -I. -DFFMPEG_CODEC=AV_CODEC_ID_MPEG1VIDEO -DFUZZ_FFMPEG_VIDEO ../../libfuzzer/libFuzzer.a -Llibavcodec -Llibavdevice -Llibavfilter -Llibavformat -Llibavutil -Llibpostproc -Llibswscale -Llibswresample -Wl,--as-needed -Wl,-z,noexecstack -Wl,--warn-common -Wl,-rpath-link=:libpostproc:libswresample:libswscale:libavfilter:libavdevice:libavformat:libavcodec:libavutil -lavdevice -lavfilter -lavformat -lavcodec -lswresample -lswscale -lavutil -ldl -lxcb -lxcb-shm -lxcb -lxcb-xfixes -lxcb -lxcb-shape -lxcb -lX11 -lasound -lm -lbz2 -lz -pthread
34 * create a corpus directory and put some samples there (empty dir is ok too):
35 mkdir CORPUS && cp some-files CORPUS
36
37 * Run fuzzing:
38 ./target_dec_fuzzer -max_len=100000 CORPUS
39
40 More info:
41 http://libfuzzer.info
42 http://tutorial.libfuzzer.info
43 https://github.com/google/oss-fuzz
44 http://lcamtuf.coredump.cx/afl/
45 https://security.googleblog.com/2016/08/guided-in-process-fuzzing-of-chrome.html
46 */
47
48 #include "config.h"
55
60
61 //For FF_SANE_NB_CHANNELS, so we dont waste energy testing things that will get instantly rejected
63
65
67
68 static void error(
const char *err)
69 {
70 fprintf(stderr, "%s", err);
71 exit(1);
72 }
73
76 {
78
80 if (!res)
81 error(
"Failed to find decoder");
83 }
84
86 int *got_sub_ptr,
const AVPacket *avpkt)
87 {
90 if (
ret >= 0 && *got_sub_ptr)
93 }
94
97 {
99 *got_frame =
ret >= 0;
101 }
102
103 // Ensure we don't loop forever
105
106 static const uint64_t
FUZZ_TAG = 0x4741542D5A5A5546ULL;
107
109 {
110 ptrdiff_t linesize1[4];
114
119
120 for (
i = 0;
i < 4 &&
frame->linesize[
i];
i++)
121 linesize1[
i] =
frame->linesize[
i] =
125
129
131 for (
i = 0;
i < 4 &&
size[
i];
i++) {
132 switch(
ctx->codec_id) {
135 break;
136 default:
138 }
139
143 }
147 }
148
149 return 0;
153 }
154
156 {
157 switch (
ctx->codec_type) {
164 default:
166 }
167 }
168
170 uint64_t maxpixels_per_frame = 4096 * 4096;
171 uint64_t maxpixels;
172
173 uint64_t maxsamples_per_frame = 256*1024*32;
174 uint64_t maxsamples;
176 const uint8_t *last =
data;
179 uint64_t ec_pixels = 0;
180 uint64_t nb_samples = 0;
182 int *got_picture_ptr,
185 uint64_t keyframes = 0;
186 uint64_t flushpattern = -1;
188
190 #ifdef FFMPEG_DECODER
191 #define DECODER_SYMBOL0(CODEC) ff_##CODEC##_decoder
192 #define DECODER_SYMBOL(CODEC) DECODER_SYMBOL0(CODEC)
193 extern FFCodec DECODER_SYMBOL(FFMPEG_DECODER);
194 codec_list[0] = &DECODER_SYMBOL(FFMPEG_DECODER);
195
196 #if FFMPEG_DECODER == tiff || FFMPEG_DECODER == tdsc
197 extern FFCodec DECODER_SYMBOL(mjpeg);
199 #endif
200
201 c = &DECODER_SYMBOL(FFMPEG_DECODER);
202 #else
204 #endif
206 }
207
212 }
215 }
335 }
336
337 maxsamples_per_frame =
FFMIN(maxsamples_per_frame, maxsamples);
338 maxpixels_per_frame =
FFMIN(maxpixels_per_frame , maxpixels);
339
342 if (!
ctx || !parser_avctx)
343 error(
"Failed memory allocation");
344
345 if (
ctx->max_pixels == 0 ||
ctx->max_pixels > maxpixels_per_frame)
346 ctx->max_pixels = maxpixels_per_frame;
//To reduce false positive OOM and hangs
347
348 ctx->max_samples = maxsamples_per_frame;
352
355 int extradata_size;
357 uint64_t request_channel_layout;
359
362 ctx->width = bytestream2_get_le32(&gbc);
363 ctx->height = bytestream2_get_le32(&gbc);
365 ctx->bits_per_coded_sample = bytestream2_get_le32(&gbc);
366 // Try to initialize a parser for this codec, note, this may fail which just means we test without one
367 flags = bytestream2_get_byte(&gbc);
376 }
381
384
385 extradata_size = bytestream2_get_le32(&gbc);
386
387 ctx->sample_rate = bytestream2_get_le32(&gbc) & 0x7FFFFFFF;
389 ctx->block_align = bytestream2_get_le32(&gbc) & 0x7FFFFFFF;
390 ctx->codec_tag = bytestream2_get_le32(&gbc);
392 int n;
395 }
396 keyframes = bytestream2_get_le64(&gbc);
397 request_channel_layout = bytestream2_get_le64(&gbc);
398
399 ctx->idct_algo = bytestream2_get_byte(&gbc) % 25;
400 flushpattern = bytestream2_get_le64(&gbc);
402
403
405 switch (
ctx->codec_id) {
412 break;
413 }
414 }
415
416 // Keep the deprecated request_channel_layout behavior to ensure old fuzzing failures
417 // remain reproducible.
418 if (request_channel_layout) {
419 switch (
ctx->codec_id) {
425 if (request_channel_layout & ~INT64_MIN) {
427 if (!downmix_layout)
428 error(
"Failed memory allocation");
429 av_strlcatf(downmix_layout, 19,
"0x%"PRIx64, request_channel_layout & ~INT64_MIN);
431 }
433 break;
434 // fall-through
437 break;
438 }
439 }
440
441 flags64 = bytestream2_get_le64(&gbc);
442 if (flags64 &1)
444 if (flags64 &2)
446 if (flags64 &4)
448 if (flags64 & 8)
450 if (flags64 & 0x10)
452
453 ctx->workaround_bugs = bytestream2_get_le32(&gbc);
454
457 }
458
459 if (extradata_size <
size) {
461 if (
ctx->extradata) {
462 ctx->extradata_size = extradata_size;
465 }
466 }
468 ctx->width =
ctx->height = 0;
469 }
470
472 if (res < 0) {
477 return 0; // Failure of avcodec_open2() does not imply that a issue was found
478 }
482
483
484 int got_frame;
488 if (!
frame || !avpkt || !parsepkt)
489 error(
"Failed memory allocation");
490
491 // Read very simple container
493 // Search for the TAG
494 while (
data +
sizeof(fuzz_tag) < end) {
496 break;
498 }
499 if (
data +
sizeof(fuzz_tag) > end)
501
503 if (res < 0)
504 error(
"Failed memory allocation");
505 memcpy(parsepkt->
data, last,
data - last);
507 keyframes = (keyframes >> 2) + (keyframes<<62);
508 data +=
sizeof(fuzz_tag);
510
511 while (parsepkt->
size > 0) {
512 int decode_more;
513
514 if (parser) {
517 parsepkt->
pts, parsepkt->
dts, parsepkt->
pos);
518 if (avpkt->
data == parsepkt->
data) {
521 error(
"Failed memory allocation");
522 } else {
524 error(
"Failed memory allocation");
525 }
536 } else {
538 }
539
540 if (!(flushpattern & 7))
542 flushpattern = (flushpattern >> 3) + (flushpattern << 61);
543
546 decode_more =
ret >= 0;
547 if(!decode_more) {
548 ec_pixels += (
ctx->width + 32LL) * (
ctx->height + 32LL);
549 if (
it > 20 || ec_pixels > 4 *
ctx->max_pixels) {
550 ctx->error_concealment = 0;
552 }
553 if (ec_pixels > maxpixels)
554 goto maximums_reached;
555 }
556 } else
557 decode_more = 1;
558
559 // Iterate through all data
562 int ret = decode_handler(
ctx,
frame, &got_frame, avpkt);
563
564 ec_pixels += (
ctx->width + 32LL) * (
ctx->height + 32LL);
565 if (
it > 20 || ec_pixels > 4 *
ctx->max_pixels) {
566 ctx->error_concealment = 0;
568 }
569 if (ec_pixels > maxpixels)
570 goto maximums_reached;
571
573 frame->nb_samples == 0 && !got_frame &&
575 nb_samples +=
ctx->max_samples;
576
577 nb_samples +=
frame->nb_samples;
578 if (nb_samples > maxsamples)
579 goto maximums_reached;
580
581 if (ret <= 0 || ret > avpkt->
size)
582 break;
583
587 decode_more = avpkt->
size > 0;
588 } else
589 decode_more =
ret >= 0;
590 }
592 }
594 }
595 maximums_reached:
596
598
601
602 do {
603 got_frame = 0;
605 decode_handler(
ctx,
frame, &got_frame, avpkt);
606
607 nb_samples +=
frame->nb_samples;
608 if (nb_samples > maxsamples)
609 break;
611
612 fprintf(stderr,
"pixels decoded: %"PRId64
", samples decoded: %"PRId64
", iterations: %d\n", ec_pixels, nb_samples,
it);
613
621 return 0;
622 }