avcodec/interplayvideo: check decoding_map_size with video_data_size
[ffmpeg.git] / tools / target_dec_fuzzer.c
index 62d62a9..a94d5e6 100644 (file)
@@ -56,6 +56,8 @@
 
 int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size);
 
+extern AVCodec * codec_list[];
+
 static void error(const char *err)
 {
     fprintf(stderr, "%s", err);
@@ -138,12 +140,15 @@ int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
     int (*decode_handler)(AVCodecContext *avctx, AVFrame *picture,
                           int *got_picture_ptr,
                           const AVPacket *avpkt) = NULL;
+    AVCodecParserContext *parser = 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);
+        codec_list[0] = &DECODER_SYMBOL(FFMPEG_DECODER);
         avcodec_register(&DECODER_SYMBOL(FFMPEG_DECODER));
 
         c = &DECODER_SYMBOL(FFMPEG_DECODER);
@@ -161,7 +166,8 @@ int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
     }
 
     AVCodecContext* ctx = avcodec_alloc_context3(NULL);
-    if (!ctx)
+    AVCodecContext* parser_avctx = avcodec_alloc_context3(NULL);
+    if (!ctx || !parser_avctx)
         error("Failed memory allocation");
 
     ctx->max_pixels = 4096 * 4096; //To reduce false positive OOM and hangs
@@ -173,6 +179,9 @@ int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
         ctx->height                             = bytestream2_get_le32(&gbc);
         ctx->bit_rate                           = bytestream2_get_le64(&gbc);
         ctx->bits_per_coded_sample              = bytestream2_get_le32(&gbc);
+        // Try to initialize a parser for this codec, note, this may fail which just means we test without one
+        if (bytestream2_get_byte(&gbc) & 1)
+            parser = av_parser_init(c->id);
         if (av_image_check_size(ctx->width, ctx->height, 0, ctx))
             ctx->width = ctx->height = 0;
         size -= 1024;
@@ -181,8 +190,10 @@ int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
     int res = avcodec_open2(ctx, c, NULL);
     if (res < 0) {
         av_free(ctx);
+        av_free(parser_avctx);
         return 0; // Failure of avcodec_open2() does not imply that a issue was found
     }
+    parser_avctx->codec_id = ctx->codec_id;
 
     FDBCreate(&buffer);
     int got_frame;
@@ -191,7 +202,7 @@ int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
         error("Failed memory allocation");
 
     // Read very simple container
-    AVPacket avpkt;
+    AVPacket avpkt, parsepkt;
     while (data < end && it < maxiteration) {
         // Search for the TAG
         while (data + sizeof(fuzz_tag) < end) {
@@ -202,12 +213,34 @@ int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
         if (data + sizeof(fuzz_tag) > end)
             data = end;
 
-        FDBPrepare(&buffer, &avpkt, last, data - last);
+        FDBPrepare(&buffer, &parsepkt, last, data - last);
         data += sizeof(fuzz_tag);
         last = data;
 
-        // Iterate through all data
-        while (avpkt.size > 0 && it++ < maxiteration) {
+        while (parsepkt.size > 0) {
+
+            if (parser) {
+                av_init_packet(&avpkt);
+                int ret = av_parser_parse2(parser, parser_avctx, &avpkt.data, &avpkt.size,
+                                           parsepkt.data, parsepkt.size,
+                                           parsepkt.pts, parsepkt.dts, parsepkt.pos);
+                parsepkt.data += ret;
+                parsepkt.size -= ret;
+                parsepkt.pos  += ret;
+                avpkt.pts = parser->pts;
+                avpkt.dts = parser->dts;
+                avpkt.pos = parser->pos;
+                if ( parser->key_frame == 1 ||
+                    (parser->key_frame == -1 && parser->pict_type == AV_PICTURE_TYPE_I))
+                    avpkt.flags |= AV_PKT_FLAG_KEY;
+                avpkt.flags |= parsepkt.flags & AV_PKT_FLAG_DISCARD;
+            } else {
+                avpkt = parsepkt;
+                parsepkt.size = 0;
+            }
+
+          // Iterate through all data
+          while (avpkt.size > 0 && it++ < maxiteration) {
             av_frame_unref(frame);
             int ret = decode_handler(ctx, frame, &got_frame, &avpkt);
 
@@ -220,6 +253,7 @@ int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
                 ret = avpkt.size;
             avpkt.data += ret;
             avpkt.size -= ret;
+          }
         }
     }
 
@@ -235,6 +269,9 @@ int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
     av_frame_free(&frame);
     avcodec_free_context(&ctx);
     av_freep(&ctx);
+    avcodec_free_context(&parser_avctx);
+    av_freep(&parser_avctx);
+    av_parser_close(parser);
     FDBDesroy(&buffer);
     return 0;
 }