Re: [FFmpeg-devel] [PATCH] tools: add a fuzzer tool for bitstream filters

2019-12-03 Thread Michael Niedermayer
On Tue, Dec 03, 2019 at 04:59:26PM -0300, James Almer wrote:
> On 12/3/2019 4:31 PM, Andriy Gelman wrote:
> > On Mon, 02. Dec 13:15, James Almer wrote:
> >> Signed-off-by: James Almer 
> >> ---
> >> Untested.
> >>
> >> The BSF can be set the same way a decoder can in target_dec_fuzzer. The
> >> codec_id will be randomly chosen from the supported list, if any.
> >>
> >>  tools/Makefile|   3 +
> >>  tools/target_bsf_fuzzer.c | 166 ++
> >>  2 files changed, 169 insertions(+)
> >>  create mode 100644 tools/target_bsf_fuzzer.c
[...]
> > 
> > 
> >> +while (data < end) {
> > 
> >> +// Search for the TAG
> >> +while (data + sizeof(fuzz_tag) < end) {
> >> +if (data[0] == (fuzz_tag & 0xFF) && AV_RN64(data) == fuzz_tag)
> >> +break;
> >> +data++;
> >> +}
> > 
> > Is the idea here to add "FUZZ_TAG" via the -dict option when running the
> > fuzzer? 
> 
> I don't know, but Michael might.

I dont know how or if FUZZ_TAG "connects" back into the fuzzer.

But the same issue also exist for every chunk, slice, packet header
the fuzzer has to generate valid data 

thx

[...]
-- 
Michael GnuPG fingerprint: 9FF2128B147EF6730BADF133611EC787040B0FAB

When the tyrant has disposed of foreign enemies by conquest or treaty, and
there is nothing more to fear from them, then he is always stirring up
some war or other, in order that the people may require a leader. -- Plato


signature.asc
Description: PGP signature
___
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
https://ffmpeg.org/mailman/listinfo/ffmpeg-devel

To unsubscribe, visit link above, or email
ffmpeg-devel-requ...@ffmpeg.org with subject "unsubscribe".

Re: [FFmpeg-devel] [PATCH] tools: add a fuzzer tool for bitstream filters

2019-12-03 Thread James Almer
On 12/3/2019 4:31 PM, Andriy Gelman wrote:
> On Mon, 02. Dec 13:15, James Almer wrote:
>> Signed-off-by: James Almer 
>> ---
>> Untested.
>>
>> The BSF can be set the same way a decoder can in target_dec_fuzzer. The
>> codec_id will be randomly chosen from the supported list, if any.
>>
>>  tools/Makefile|   3 +
>>  tools/target_bsf_fuzzer.c | 166 ++
>>  2 files changed, 169 insertions(+)
>>  create mode 100644 tools/target_bsf_fuzzer.c
>>
>> diff --git a/tools/Makefile b/tools/Makefile
>> index 370ee35416..001093105b 100644
>> --- a/tools/Makefile
>> +++ b/tools/Makefile
>> @@ -5,6 +5,9 @@ TOOLS-$(CONFIG_ZLIB) += cws2fws
>>  tools/target_dec_%_fuzzer.o: tools/target_dec_fuzzer.c
>>  $(COMPILE_C) -DFFMPEG_DECODER=$*
>>  
>> +tools/target_bsf_%_fuzzer.o: tools/target_bsf_fuzzer.c
>> +$(COMPILE_C) -DFFMPEG_BSF=$*
>> +
>>  tools/target_dem_fuzzer.o: tools/target_dem_fuzzer.c
>>  $(COMPILE_C)
>>  
>> diff --git a/tools/target_bsf_fuzzer.c b/tools/target_bsf_fuzzer.c
>> new file mode 100644
>> index 00..6849aaed0d
>> --- /dev/null
>> +++ b/tools/target_bsf_fuzzer.c
>> @@ -0,0 +1,166 @@
>> +/*
>> + * This file is part of FFmpeg.
>> + *
>> + * FFmpeg is free software; you can redistribute it and/or
>> + * modify it under the terms of the GNU Lesser General Public
>> + * License as published by the Free Software Foundation; either
>> + * version 2.1 of the License, or (at your option) any later version.
>> + *
>> + * FFmpeg is distributed in the hope that it will be useful,
>> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
>> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
>> + * Lesser General Public License for more details.
>> + *
>> + * You should have received a copy of the GNU Lesser General Public
>> + * License along with FFmpeg; if not, write to the Free Software
>> + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 
>> USA
>> + */
>> +
>> +#include "config.h"
>> +#include "libavutil/imgutils.h"
>> +
>> +#include "libavcodec/avcodec.h"
>> +#include "libavcodec/bsf.h"
>> +#include "libavcodec/bytestream.h"
>> +#include "libavcodec/internal.h"
>> +
>> +int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size);
>> +
>> +static void error(const char *err)
>> +{
>> +fprintf(stderr, "%s", err);
>> +exit(1);
>> +}
>> +
>> +static AVBitStreamFilter *f = NULL;
>> +
>> +static const uint64_t FUZZ_TAG = 0x4741542D5A5A5546ULL;
>> +
>> +int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
>> +const uint64_t fuzz_tag = FUZZ_TAG;
>> +const uint8_t *last = data;
>> +const uint8_t *end = data + size;
>> +AVBSFContext *bsf = NULL;
>> +AVPacket in, out;
>> +uint64_t keyframes = 0;
>> +int res;
>> +
>> +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 = _SYMBOL(FFMPEG_BSF);
>> +#else
>> +extern AVBitStreamFilter ff_null_bsf;
>> +f = _null_bsf;
>> +#endif
>> +av_log_set_level(AV_LOG_PANIC);
>> +}
>> +
>> +res = av_bsf_alloc(f, );
>> +if (res < 0)
>> +error("Failed memory allocation");
>> +
>> +if (size > 1024) {
>> +GetByteContext gbc;
>> +int extradata_size;
>> +size -= 1024;
>> +bytestream2_init(, data + size, 1024);
>> +bsf->par_in->width  = 
>> bytestream2_get_le32();
>> +bsf->par_in->height = 
>> bytestream2_get_le32();
>> +bsf->par_in->bit_rate   = 
>> bytestream2_get_le64();
>> +bsf->par_in->bits_per_coded_sample  = 
>> bytestream2_get_le32();
>> +
> 
>> +if (f->codec_ids) {
> 
>> +int i, j, idx = bytestream2_get_byte();
> 
> Can you just read a bigger number instead of checking ++j == 8 below? 
> Maybe bytestream2_get_be24()? 

The idea was read bytes until one bit was a 0 to signal to stop the
loop. It would in theory work even with a bsf that supports INT_MAX
amount of codecs, and eventually stop anyway since the GetByteContext
would run out of data and start returning zeroes.

> 
>> +int id = AV_CODEC_ID_NONE;
>> +for (i = 0, j = 0; f->codec_ids[i] != AV_CODEC_ID_NONE; i++) {
>> +// Iterate through all supported codec ids and get a random 
>> one
>> +if (idx & (1 << j)) {
>> +// There's at least one bsf that reports supporting 
>> more than eight codecs
> 
>> +if (++j == 8) {
>> +idx = bytestream2_get_byte();
>> +j = 0;
>> +}
>> +continue;
>> +}
>> +id = f->codec_ids[i];
>> +break;
>> +}
> 
> The selection of the codecs doesn't seem uniform. 
> The 

Re: [FFmpeg-devel] [PATCH] tools: add a fuzzer tool for bitstream filters

2019-12-03 Thread Andriy Gelman
On Mon, 02. Dec 13:15, James Almer wrote:
> Signed-off-by: James Almer 
> ---
> Untested.
> 
> The BSF can be set the same way a decoder can in target_dec_fuzzer. The
> codec_id will be randomly chosen from the supported list, if any.
> 
>  tools/Makefile|   3 +
>  tools/target_bsf_fuzzer.c | 166 ++
>  2 files changed, 169 insertions(+)
>  create mode 100644 tools/target_bsf_fuzzer.c
> 
> diff --git a/tools/Makefile b/tools/Makefile
> index 370ee35416..001093105b 100644
> --- a/tools/Makefile
> +++ b/tools/Makefile
> @@ -5,6 +5,9 @@ TOOLS-$(CONFIG_ZLIB) += cws2fws
>  tools/target_dec_%_fuzzer.o: tools/target_dec_fuzzer.c
>   $(COMPILE_C) -DFFMPEG_DECODER=$*
>  
> +tools/target_bsf_%_fuzzer.o: tools/target_bsf_fuzzer.c
> + $(COMPILE_C) -DFFMPEG_BSF=$*
> +
>  tools/target_dem_fuzzer.o: tools/target_dem_fuzzer.c
>   $(COMPILE_C)
>  
> diff --git a/tools/target_bsf_fuzzer.c b/tools/target_bsf_fuzzer.c
> new file mode 100644
> index 00..6849aaed0d
> --- /dev/null
> +++ b/tools/target_bsf_fuzzer.c
> @@ -0,0 +1,166 @@
> +/*
> + * This file is part of FFmpeg.
> + *
> + * FFmpeg is free software; you can redistribute it and/or
> + * modify it under the terms of the GNU Lesser General Public
> + * License as published by the Free Software Foundation; either
> + * version 2.1 of the License, or (at your option) any later version.
> + *
> + * FFmpeg is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
> + * Lesser General Public License for more details.
> + *
> + * You should have received a copy of the GNU Lesser General Public
> + * License along with FFmpeg; if not, write to the Free Software
> + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 
> USA
> + */
> +
> +#include "config.h"
> +#include "libavutil/imgutils.h"
> +
> +#include "libavcodec/avcodec.h"
> +#include "libavcodec/bsf.h"
> +#include "libavcodec/bytestream.h"
> +#include "libavcodec/internal.h"
> +
> +int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size);
> +
> +static void error(const char *err)
> +{
> +fprintf(stderr, "%s", err);
> +exit(1);
> +}
> +
> +static AVBitStreamFilter *f = NULL;
> +
> +static const uint64_t FUZZ_TAG = 0x4741542D5A5A5546ULL;
> +
> +int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
> +const uint64_t fuzz_tag = FUZZ_TAG;
> +const uint8_t *last = data;
> +const uint8_t *end = data + size;
> +AVBSFContext *bsf = NULL;
> +AVPacket in, out;
> +uint64_t keyframes = 0;
> +int res;
> +
> +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 = _SYMBOL(FFMPEG_BSF);
> +#else
> +extern AVBitStreamFilter ff_null_bsf;
> +f = _null_bsf;
> +#endif
> +av_log_set_level(AV_LOG_PANIC);
> +}
> +
> +res = av_bsf_alloc(f, );
> +if (res < 0)
> +error("Failed memory allocation");
> +
> +if (size > 1024) {
> +GetByteContext gbc;
> +int extradata_size;
> +size -= 1024;
> +bytestream2_init(, data + size, 1024);
> +bsf->par_in->width  = bytestream2_get_le32();
> +bsf->par_in->height = bytestream2_get_le32();
> +bsf->par_in->bit_rate   = bytestream2_get_le64();
> +bsf->par_in->bits_per_coded_sample  = bytestream2_get_le32();
> +

> +if (f->codec_ids) {

> +int i, j, idx = bytestream2_get_byte();

Can you just read a bigger number instead of checking ++j == 8 below? 
Maybe bytestream2_get_be24()? 

> +int id = AV_CODEC_ID_NONE;
> +for (i = 0, j = 0; f->codec_ids[i] != AV_CODEC_ID_NONE; i++) {
> +// Iterate through all supported codec ids and get a random 
> one
> +if (idx & (1 << j)) {
> +// There's at least one bsf that reports supporting more 
> than eight codecs

> +if (++j == 8) {
> +idx = bytestream2_get_byte();
> +j = 0;
> +}
> +continue;
> +}
> +id = f->codec_ids[i];
> +break;
> +}

The selection of the codecs doesn't seem uniform. 
The probability of each codec is more like (1/2)^n, where n is codec index. I'm
not sure if the fuzzer will eventually learn this.

It may be better to use: id = idx % num_supported_codecs. But of course
num_supported_codecs would have to be evaluated first.

> +// Force using a codec if all were skipped
> +if (id == AV_CODEC_ID_NONE)
> +id = f->codec_ids[0];
> +bsf->par_in->codec_id = id;
> +