]> git.sesse.net Git - ffmpeg/blobdiff - tools/target_dec_fuzzer.c
Merge commit '89725a8512721fffd190021ded2d3f5b42e20e2a'
[ffmpeg] / tools / target_dec_fuzzer.c
index cb3bc50919bea99c87c533b9b63f8eb8391ac418..5a0b53e546a55e4ed3576ec9110b6715707b3464 100644 (file)
    https://security.googleblog.com/2016/08/guided-in-process-fuzzing-of-chrome.html
 */
 
+#include "config.h"
 #include "libavutil/avassert.h"
+#include "libavutil/imgutils.h"
 #include "libavutil/intreadwrite.h"
 
 #include "libavcodec/avcodec.h"
+#include "libavcodec/bytestream.h"
 #include "libavformat/avformat.h"
 
+int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size);
+
 static void error(const char *err)
 {
     fprintf(stderr, "%s", err);
@@ -61,7 +66,7 @@ static AVCodec *c = NULL;
 static AVCodec *AVCodecInitialize(enum AVCodecID codec_id)
 {
     AVCodec *res;
-    av_register_all();
+
     av_log_set_level(AV_LOG_PANIC);
     res = avcodec_find_decoder(codec_id);
     if (!res)
@@ -69,11 +74,6 @@ static AVCodec *AVCodecInitialize(enum AVCodecID codec_id)
     return res;
 }
 
-#if defined(FUZZ_FFMPEG_VIDEO)
-#define decode_handler avcodec_decode_video2
-#elif defined(FUZZ_FFMPEG_AUDIO)
-#define decode_handler avcodec_decode_audio4
-#elif defined(FUZZ_FFMPEG_SUBTITLE)
 static int subtitle_handler(AVCodecContext *avctx, void *frame,
                             int *got_sub_ptr, AVPacket *avpkt)
 {
@@ -84,27 +84,22 @@ static int subtitle_handler(AVCodecContext *avctx, void *frame,
     return ret;
 }
 
-#define decode_handler subtitle_handler
-#else
-#error "Specify encoder type"  // To catch mistakes
-#endif
-
 // Class to handle buffer allocation and resize for each frame
 typedef struct FuzzDataBuffer {
     size_t size_;
     uint8_t *data_;
 } FuzzDataBuffer;
 
-void FDBCreate(FuzzDataBuffer *FDB) {
+static void FDBCreate(FuzzDataBuffer *FDB) {
     FDB->size_ = 0x1000;
     FDB->data_ = av_malloc(FDB->size_);
     if (!FDB->data_)
         error("Failed memory allocation");
 }
 
-void FDBDesroy(FuzzDataBuffer *FDB) { av_free(FDB->data_); }
+static void FDBDesroy(FuzzDataBuffer *FDB) { av_free(FDB->data_); }
 
-void FDBRealloc(FuzzDataBuffer *FDB, size_t size) {
+static void FDBRealloc(FuzzDataBuffer *FDB, size_t size) {
     size_t needed = size + FF_INPUT_BUFFER_PADDING_SIZE;
     av_assert0(needed > size);
     if (needed > FDB->size_) {
@@ -116,7 +111,7 @@ void FDBRealloc(FuzzDataBuffer *FDB, size_t size) {
     }
 }
 
-void FDBPrepare(FuzzDataBuffer *FDB, AVPacket *dst, const uint8_t *data,
+static void FDBPrepare(FuzzDataBuffer *FDB, AVPacket *dst, const uint8_t *data,
                 size_t size)
 {
     FDBRealloc(FDB, size);
@@ -141,9 +136,30 @@ int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
     const uint8_t *last = data;
     const uint8_t *end = data + size;
     uint32_t it = 0;
-
-    if (!c)
+    int (*decode_handler)(AVCodecContext *avctx, AVFrame *picture,
+                          int *got_picture_ptr,
+                          const AVPacket *avpkt) = NULL;
+
+    if (!c) {
+#ifdef FFMPEG_DECODER
+#define DECODER_SYMBOL0(CODEC) ff_##CODEC##_decoder
+#define DECODER_SYMBOL(CODEC) DECODER_SYMBOL0(CODEC)
+        extern AVCodec DECODER_SYMBOL(FFMPEG_DECODER);
+        avcodec_register(&DECODER_SYMBOL(FFMPEG_DECODER));
+        int codec_id = DECODER_SYMBOL(FFMPEG_DECODER).id;
+
+        c = AVCodecInitialize(codec_id);  // Done once.
+#else
+        avcodec_register_all();
         c = AVCodecInitialize(FFMPEG_CODEC);  // Done once.
+#endif
+    }
+
+    switch (c->type) {
+    case AVMEDIA_TYPE_AUDIO   : decode_handler = avcodec_decode_audio4; break;
+    case AVMEDIA_TYPE_VIDEO   : decode_handler = avcodec_decode_video2; break;
+    case AVMEDIA_TYPE_SUBTITLE: decode_handler = subtitle_handler     ; break;
+    }
 
     AVCodecContext* ctx = avcodec_alloc_context3(NULL);
     if (!ctx)
@@ -151,9 +167,23 @@ int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
 
     ctx->max_pixels = 4096 * 4096; //To reduce false positive OOM and hangs
 
+    if (size > 1024) {
+        GetByteContext gbc;
+        bytestream2_init(&gbc, data + size - 1024, 1024);
+        ctx->width                              = bytestream2_get_le32(&gbc);
+        ctx->height                             = bytestream2_get_le32(&gbc);
+        ctx->bit_rate                           = bytestream2_get_le64(&gbc);
+        ctx->bits_per_coded_sample              = bytestream2_get_le32(&gbc);
+        if (av_image_check_size(ctx->width, ctx->height, 0, ctx))
+            ctx->width = ctx->height = 0;
+        size -= 1024;
+    }
+
     int res = avcodec_open2(ctx, c, NULL);
-    if (res < 0)
-        return res;
+    if (res < 0) {
+        av_free(ctx);
+        return 0; // Failure of avcodec_open2() does not imply that a issue was found
+    }
 
     FDBCreate(&buffer);
     int got_frame;