[FFmpeg-devel] tools/target_dec_fuzzer: add support to fuzz bitstream filters

Submitted by James Almer on Aug. 30, 2019, 4:39 p.m.

Details

Message ID 20190830163900.6795-1-jamrial@gmail.com
State New
Headers show

Commit Message

James Almer Aug. 30, 2019, 4:39 p.m.
Signed-off-by: James Almer <jamrial@gmail.com>
---
Untested. I'm also not sure how to add the FFMPEG_BSF define to tools/Makefile,
and have it coexist with FFMPEG_DECODER. Assuming it's needed.

 tools/target_dec_fuzzer.c | 43 +++++++++++++++++++++++++++++++++++++++
 1 file changed, 43 insertions(+)

Comments

James Almer Sept. 3, 2019, 1:49 p.m.
On 8/30/2019 1:39 PM, James Almer wrote:
> Signed-off-by: James Almer <jamrial@gmail.com>
> ---
> Untested. I'm also not sure how to add the FFMPEG_BSF define to tools/Makefile,
> and have it coexist with FFMPEG_DECODER. Assuming it's needed.
> 
>  tools/target_dec_fuzzer.c | 43 +++++++++++++++++++++++++++++++++++++++
>  1 file changed, 43 insertions(+)
> 
> diff --git a/tools/target_dec_fuzzer.c b/tools/target_dec_fuzzer.c
> index 0d10503cfb..b8fe1f2aa1 100644
> --- a/tools/target_dec_fuzzer.c
> +++ b/tools/target_dec_fuzzer.c
> @@ -65,6 +65,8 @@ static void error(const char *err)
>  }
>  
>  static AVCodec *c = NULL;
> +static AVBitStreamFilter *f = NULL;
> +
>  static AVCodec *AVCodecInitialize(enum AVCodecID codec_id)
>  {
>      AVCodec *res;
> @@ -102,6 +104,7 @@ int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
>                            int *got_picture_ptr,
>                            const AVPacket *avpkt) = NULL;
>      AVCodecParserContext *parser = NULL;
> +    AVBSFContext *bsf = NULL;
>  
>  
>      if (!c) {
> @@ -120,6 +123,27 @@ int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
>          av_log_set_level(AV_LOG_PANIC);
>      }
>  
> +    if (!f) {
> +#ifdef FFMPEG_BSF
> +#define BSF_SYMBOL0(BSF) ff_##BSF##_bsf
> +#define BSF_SYMBOL(BSF) BSF_SYMBOL0(BSF)
> +        extern AVBitStreamFilter BSF_SYMBOL(FFMPEG_BSF);
> +        f = &BSF_SYMBOL(FFMPEG_BSF);
> +
> +        if (f->codec_ids) {
> +            const enum AVCodecID *ids;
> +            for (ids = f->codec_ids; *ids != AV_CODEC_ID_NONE; ids++)
> +                if (*ids == c->id)
> +                    break;
> +            if (ids == AV_CODEC_ID_NONE)
> +                error("Invalid bsf");
> +        }
> +#else
> +        extern AVBitStreamFilter ff_null_bsf;
> +        f = &ff_null_bsf;
> +#endif
> +    }
> +
>      switch (c->type) {
>      case AVMEDIA_TYPE_AUDIO   : decode_handler = avcodec_decode_audio4; break;
>      case AVMEDIA_TYPE_VIDEO   : decode_handler = avcodec_decode_video2; break;
> @@ -181,6 +205,18 @@ int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
>      }
>      parser_avctx->codec_id = ctx->codec_id;
>  
> +    res = av_bsf_alloc(f, &bsf);
> +    if (res < 0)
> +        error("Failed memory allocation");
> +
> +    res = avcodec_parameters_from_context(bsf->par_in, ctx);
> +    if (res < 0)
> +        error("Failed memory allocation");
> +
> +    res = av_bsf_init(bsf);
> +    if (res < 0)
> +        return 0; // Failure of av_bsf_init() does not imply that a issue was found
> +
>      int got_frame;
>      AVFrame *frame = av_frame_alloc();
>      if (!frame)
> @@ -237,6 +273,11 @@ int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
>              }
>  
>            // Iterate through all data
> +          res = av_bsf_send_packet(bsf, &avpkt);
> +          while (res >= 0) {
> +            res = av_bsf_receive_packet(bsf, &avpkt);
> +            if (res < 0)
> +                break;
>            while (avpkt.size > 0 && it++ < maxiteration) {
>              av_frame_unref(frame);
>              int ret = decode_handler(ctx, frame, &got_frame, &avpkt);
> @@ -255,6 +296,7 @@ int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
>              avpkt.size -= ret;
>            }
>            av_packet_unref(&avpkt);
> +          }
>          }
>          av_packet_unref(&parsepkt);
>      }
> @@ -270,6 +312,7 @@ maximums_reached:
>  
>      fprintf(stderr, "pixels decoded: %"PRId64", iterations: %d\n", ec_pixels, it);
>  
> +    av_bsf_free(&bsf);
>      av_frame_free(&frame);
>      avcodec_free_context(&ctx);
>      avcodec_free_context(&parser_avctx);

Ping.

Patch hide | download patch | download mbox

diff --git a/tools/target_dec_fuzzer.c b/tools/target_dec_fuzzer.c
index 0d10503cfb..b8fe1f2aa1 100644
--- a/tools/target_dec_fuzzer.c
+++ b/tools/target_dec_fuzzer.c
@@ -65,6 +65,8 @@  static void error(const char *err)
 }
 
 static AVCodec *c = NULL;
+static AVBitStreamFilter *f = NULL;
+
 static AVCodec *AVCodecInitialize(enum AVCodecID codec_id)
 {
     AVCodec *res;
@@ -102,6 +104,7 @@  int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
                           int *got_picture_ptr,
                           const AVPacket *avpkt) = NULL;
     AVCodecParserContext *parser = NULL;
+    AVBSFContext *bsf = NULL;
 
 
     if (!c) {
@@ -120,6 +123,27 @@  int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
         av_log_set_level(AV_LOG_PANIC);
     }
 
+    if (!f) {
+#ifdef FFMPEG_BSF
+#define BSF_SYMBOL0(BSF) ff_##BSF##_bsf
+#define BSF_SYMBOL(BSF) BSF_SYMBOL0(BSF)
+        extern AVBitStreamFilter BSF_SYMBOL(FFMPEG_BSF);
+        f = &BSF_SYMBOL(FFMPEG_BSF);
+
+        if (f->codec_ids) {
+            const enum AVCodecID *ids;
+            for (ids = f->codec_ids; *ids != AV_CODEC_ID_NONE; ids++)
+                if (*ids == c->id)
+                    break;
+            if (ids == AV_CODEC_ID_NONE)
+                error("Invalid bsf");
+        }
+#else
+        extern AVBitStreamFilter ff_null_bsf;
+        f = &ff_null_bsf;
+#endif
+    }
+
     switch (c->type) {
     case AVMEDIA_TYPE_AUDIO   : decode_handler = avcodec_decode_audio4; break;
     case AVMEDIA_TYPE_VIDEO   : decode_handler = avcodec_decode_video2; break;
@@ -181,6 +205,18 @@  int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
     }
     parser_avctx->codec_id = ctx->codec_id;
 
+    res = av_bsf_alloc(f, &bsf);
+    if (res < 0)
+        error("Failed memory allocation");
+
+    res = avcodec_parameters_from_context(bsf->par_in, ctx);
+    if (res < 0)
+        error("Failed memory allocation");
+
+    res = av_bsf_init(bsf);
+    if (res < 0)
+        return 0; // Failure of av_bsf_init() does not imply that a issue was found
+
     int got_frame;
     AVFrame *frame = av_frame_alloc();
     if (!frame)
@@ -237,6 +273,11 @@  int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
             }
 
           // Iterate through all data
+          res = av_bsf_send_packet(bsf, &avpkt);
+          while (res >= 0) {
+            res = av_bsf_receive_packet(bsf, &avpkt);
+            if (res < 0)
+                break;
           while (avpkt.size > 0 && it++ < maxiteration) {
             av_frame_unref(frame);
             int ret = decode_handler(ctx, frame, &got_frame, &avpkt);
@@ -255,6 +296,7 @@  int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
             avpkt.size -= ret;
           }
           av_packet_unref(&avpkt);
+          }
         }
         av_packet_unref(&parsepkt);
     }
@@ -270,6 +312,7 @@  maximums_reached:
 
     fprintf(stderr, "pixels decoded: %"PRId64", iterations: %d\n", ec_pixels, it);
 
+    av_bsf_free(&bsf);
     av_frame_free(&frame);
     avcodec_free_context(&ctx);
     avcodec_free_context(&parser_avctx);