diff mbox

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

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

Commit Message

James Almer Aug. 30, 2019, 4:39 p.m. UTC
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. UTC | #1
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.
James Almer Nov. 27, 2019, 2:41 p.m. UTC | #2
On 9/3/2019 10:49 AM, James Almer wrote:
> 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.

Another ping.
Michael Niedermayer Nov. 27, 2019, 4:09 p.m. UTC | #3
On Wed, Nov 27, 2019 at 11:41:09AM -0300, James Almer wrote:
> On 9/3/2019 10:49 AM, James Almer wrote:
> > On 8/30/2019 1:39 PM, James Almer wrote:
> >> Signed-off-by: James Almer <jamrial@gmail.com>
> >> ---

> >> Untested.

i can test if it applies


> >> 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.

maybe something like
tools/target_bsf_%_fuzzer.o: tools/target_dec_fuzzer.c
    $(COMPILE_C) -DFFMPEG_BSF=$*
    
but maybe i misunderdtand ...



> >>
> >>  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.
> 
> Another ping.

doesnt apply

Applying: tools/target_dec_fuzzer: add support to fuzz bitstream filters
error: sha1 information is lacking or useless (tools/target_dec_fuzzer.c).
error: could not build fake ancestor
Patch failed at 0001 tools/target_dec_fuzzer: add support to fuzz bitstream filters
hint: Use 'git am --show-current-patch' to see the failed patch
When you have resolved this problem, run "git am --continue".
If you prefer to skip this patch, run "git am --skip" instead.
To restore the original branch and stop patching, run "git am --abort".


[...]
James Almer Nov. 27, 2019, 4:17 p.m. UTC | #4
On 11/27/2019 1:09 PM, Michael Niedermayer wrote:
> On Wed, Nov 27, 2019 at 11:41:09AM -0300, James Almer wrote:
>> On 9/3/2019 10:49 AM, James Almer wrote:
>>> On 8/30/2019 1:39 PM, James Almer wrote:
>>>> Signed-off-by: James Almer <jamrial@gmail.com>
>>>> ---
> 
>>>> Untested.
> 
> i can test if it applies
> 
> 
>>>> 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.
> 
> maybe something like
> tools/target_bsf_%_fuzzer.o: tools/target_dec_fuzzer.c
>     $(COMPILE_C) -DFFMPEG_BSF=$*
>     
> but maybe i misunderdtand ...

But then what's the decoder used for it? Where is FFMPEG_CODEC defined
in the absence of FFMPEG_DECODER?

> 
> 
> 
>>>>
>>>>  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.
>>
>> Another ping.
> 
> doesnt apply
> 
> Applying: tools/target_dec_fuzzer: add support to fuzz bitstream filters
> error: sha1 information is lacking or useless (tools/target_dec_fuzzer.c).
> error: could not build fake ancestor
> Patch failed at 0001 tools/target_dec_fuzzer: add support to fuzz bitstream filters
> hint: Use 'git am --show-current-patch' to see the failed patch
> When you have resolved this problem, run "git am --continue".
> If you prefer to skip this patch, run "git am --skip" instead.
> To restore the original branch and stop patching, run "git am --abort".

One chunk failed to apply. I fixed it, but will wait for an answer to
the above, so i can also add something to tools/Makefile.
Michael Niedermayer Nov. 27, 2019, 8:19 p.m. UTC | #5
On Wed, Nov 27, 2019 at 01:17:34PM -0300, James Almer wrote:
> On 11/27/2019 1:09 PM, Michael Niedermayer wrote:
> > On Wed, Nov 27, 2019 at 11:41:09AM -0300, James Almer wrote:
> >> On 9/3/2019 10:49 AM, James Almer wrote:
> >>> On 8/30/2019 1:39 PM, James Almer wrote:
> >>>> Signed-off-by: James Almer <jamrial@gmail.com>
> >>>> ---
> > 
> >>>> Untested.
> > 
> > i can test if it applies
> > 
> > 
> >>>> 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.
> > 
> > maybe something like
> > tools/target_bsf_%_fuzzer.o: tools/target_dec_fuzzer.c
> >     $(COMPILE_C) -DFFMPEG_BSF=$*
> >     
> > but maybe i misunderdtand ...
> 
> But then what's the decoder used for it? Where is FFMPEG_CODEC defined
> in the absence of FFMPEG_DECODER?

do we need a decoder ?
the code could take the codec_id from the bsf codec_ids

[...]
James Almer Nov. 27, 2019, 10:20 p.m. UTC | #6
On 11/27/2019 5:19 PM, Michael Niedermayer wrote:
> On Wed, Nov 27, 2019 at 01:17:34PM -0300, James Almer wrote:
>> On 11/27/2019 1:09 PM, Michael Niedermayer wrote:
>>> On Wed, Nov 27, 2019 at 11:41:09AM -0300, James Almer wrote:
>>>> On 9/3/2019 10:49 AM, James Almer wrote:
>>>>> On 8/30/2019 1:39 PM, James Almer wrote:
>>>>>> Signed-off-by: James Almer <jamrial@gmail.com>
>>>>>> ---
>>>
>>>>>> Untested.
>>>
>>> i can test if it applies
>>>
>>>
>>>>>> 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.
>>>
>>> maybe something like
>>> tools/target_bsf_%_fuzzer.o: tools/target_dec_fuzzer.c
>>>     $(COMPILE_C) -DFFMPEG_BSF=$*
>>>     
>>> but maybe i misunderdtand ...
>>
>> But then what's the decoder used for it? Where is FFMPEG_CODEC defined
>> in the absence of FFMPEG_DECODER?
> 
> do we need a decoder ?
> the code could take the codec_id from the bsf codec_ids

Not using a decoder would require writing a different tool just for
bsfs, because the way it's implemented in this patch, it processes a
packet with a bsf before passing it to a decoder.

Also, some bsfs support more than one codec, so we still need to pass
two arguments: a bfs, and a codec. We can't just pick the first codec_id
reported by the bsf.
So i again wonder how exactly does the glue work here, and how can we
pass two values to any given fuzzer tool in tools/Makefile.
diff mbox

Patch

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);