diff --git a/Makefile b/Makefile index b350d7748f..2bec5d53f8 100644 --- a/Makefile +++ b/Makefile @@ -49,9 +49,15 @@ FF_STATIC_DEP_LIBS := $(STATIC_DEP_LIBS) $(TOOLS): %$(EXESUF): %.o $(LD) $(LDFLAGS) $(LDEXEFLAGS) $(LD_O) $(filter-out $(FF_DEP_LIBS), $^) $(EXTRALIBS-$(*F)) $(EXTRALIBS) $(ELIBS) -target_dec_%_fuzzer$(EXESUF): target_dec_%_fuzzer.o $(FF_DEP_LIBS) +target_dec_%_libfuzzer$(EXESUF): target_dec_%_libfuzzer.o target_dec_%_fuzzer.o $(FF_DEP_LIBS) $(LD) $(LDFLAGS) $(LDEXEFLAGS) $(LD_O) $^ $(ELIBS) $(FF_EXTRALIBS) $(LIBFUZZER_PATH) +target_dec_%_afl$(EXESUF): target_dec_%_afl.o target_dec_%_fuzzer.o $(FF_DEP_LIBS) + $(LD) $(LDFLAGS) $(LDEXEFLAGS) $(LD_O) $^ $(ELIBS) $(FF_EXTRALIBS) + target_enc_%_fuzzer$(EXESUF): target_enc_%_fuzzer.o $(FF_DEP_LIBS) $(LD) $(LDFLAGS) $(LDEXEFLAGS) $(LD_O) $^ $(ELIBS) $(FF_EXTRALIBS) $(LIBFUZZER_PATH) diff --git a/configure b/configure index e8f6d2e2b6..228ef8971f 100755 --- a/configure +++ b/configure @@ -510,7 +510,8 @@ Developer options (useful when working on FFmpeg itself): --random-seed=VALUE seed value for --enable/disable-random --disable-valgrind-backtrace do not print a backtrace under Valgrind (only applies to --disable-optimizations builds) - --enable-ossfuzz Enable building fuzzer tool + --enable-afl Enable building AFL tool + --enable-ossfuzz Enable building libfuzzer tool --libfuzzer=PATH path to libfuzzer --ignore-tests=TESTS comma-separated list (without "fate-" prefix in the name) of tests whose result is ignored @@ -2105,6 +2106,7 @@ CONFIG_LIST=" macos_kperf memory_poisoning neon_clobber_test + afl ossfuzz pic ptx_compression diff --git a/libavcodec/allcodecs.c b/libavcodec/allcodecs.c index f5317616b7..56f9ebcf87 100644 --- a/libavcodec/allcodecs.c +++ b/libavcodec/allcodecs.c @@ -903,7 +903,7 @@ extern const FFCodec ff_anull_decoder; extern const FFCodec ff_anull_encoder; // The iterate API is not usable with ossfuzz due to the excessive size of binaries created -#if CONFIG_OSSFUZZ +#if CONFIG_AFL || CONFIG_OSSFUZZ const FFCodec * codec_list[] = { NULL, NULL, diff --git a/tools/Makefile b/tools/Makefile index 7ae6e3cb75..77bb9a8d12 100644 --- a/tools/Makefile +++ b/tools/Makefile @@ -5,6 +5,15 @@ TOOLS-$(CONFIG_ZLIB) += cws2fws tools/target_dec_%_fuzzer.o: tools/target_dec_fuzzer.c $(COMPILE_C) -DFFMPEG_DECODER=$* +tools/target_dec_%_libfuzzer.o: tools/target_dec_libfuzzer.c + $(COMPILE_C) -DFFMPEG_DECODER=$* + +tools/target_dec_%_afl.o: tools/target_dec_afl.c + $(COMPILE_C) -DFFMPEG_DECODER=$* + tools/target_enc_%_fuzzer.o: tools/target_enc_fuzzer.c $(COMPILE_C) -DFFMPEG_ENCODER=$* diff --git a/tools/target_dec_afl.c b/tools/target_dec_afl.c new file mode 100644 index 0000000000..2c7eda2938 --- /dev/null +++ b/tools/target_dec_afl.c @@ -0,0 +1,21 @@ +#include "tools/target_dec_fuzzer.h" + +#include + +__AFL_FUZZ_INIT(); + +int main(void) +{ +#ifdef __AFL_HAVE_MANUAL_CONTROL + __AFL_INIT(); +#endif + + unsigned char *data = __AFL_FUZZ_TESTCASE_BUF; + + while (__AFL_LOOP(10000)) { + int size = __AFL_FUZZ_TESTCASE_LEN; + fuzz_testcase(data, size); + } + + return 0; +} diff --git a/tools/target_dec_fuzzer.c b/tools/target_dec_fuzzer.c index 432e948816..d86493f71d 100644 --- a/tools/target_dec_fuzzer.c +++ b/tools/target_dec_fuzzer.c @@ -45,6 +45,8 @@ https://security.googleblog.com/2016/08/guided-in-process-fuzzing-of-chrome.html */ +#include "tools/target_dec_fuzzer.h" + #include "config.h" #include "libavutil/avassert.h" #include "libavutil/avstring.h" @@ -61,8 +63,6 @@ //For FF_SANE_NB_CHANNELS, so we dont waste energy testing things that will get instantly rejected #include "libavcodec/internal.h" -int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size); - extern const FFCodec * codec_list[]; static void error(const char *err) @@ -71,7 +71,6 @@ static void error(const char *err) exit(1); } -static const FFCodec *c = NULL; static const FFCodec *AVCodecInitialize(enum AVCodecID codec_id) { const AVCodec *res; @@ -166,7 +165,9 @@ static int fuzz_get_buffer2(AVCodecContext *ctx, AVFrame *frame, int flags) } } -int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { +int fuzz_testcase(const uint8_t *data, size_t size) { + static const FFCodec *c; + uint64_t maxpixels_per_frame = 4096 * 4096; uint64_t maxpixels; @@ -186,24 +187,17 @@ int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { uint64_t flushpattern = -1; AVDictionary *opts = NULL; - if (!c) { #ifdef FFMPEG_DECODER #define DECODER_SYMBOL0(CODEC) ff_##CODEC##_decoder #define DECODER_SYMBOL(CODEC) DECODER_SYMBOL0(CODEC) - extern FFCodec DECODER_SYMBOL(FFMPEG_DECODER); - codec_list[0] = &DECODER_SYMBOL(FFMPEG_DECODER); + extern FFCodec DECODER_SYMBOL(FFMPEG_DECODER); + codec_list[0] = &DECODER_SYMBOL(FFMPEG_DECODER); -#if FFMPEG_DECODER == tiff || FFMPEG_DECODER == tdsc - extern FFCodec DECODER_SYMBOL(mjpeg); - codec_list[1] = &DECODER_SYMBOL(mjpeg); -#endif - - c = &DECODER_SYMBOL(FFMPEG_DECODER); + c = &DECODER_SYMBOL(FFMPEG_DECODER); #else - c = AVCodecInitialize(FFMPEG_CODEC); // Done once. + c = AVCodecInitialize(FFMPEG_CODEC); // Done once. #endif - av_log_set_level(AV_LOG_PANIC); - } + av_log_set_level(AV_LOG_PANIC); switch (c->p.type) { case AVMEDIA_TYPE_AUDIO : diff --git a/tools/target_dec_fuzzer.h b/tools/target_dec_fuzzer.h new file mode 100644 index 0000000000..e1f3977c6f --- /dev/null +++ b/tools/target_dec_fuzzer.h @@ -0,0 +1,4 @@ +#include +#include + +int fuzz_testcase(const uint8_t *data, size_t size); diff --git a/tools/target_dec_libfuzzer.c b/tools/target_dec_libfuzzer.c new file mode 100644 index 0000000000..235994beed --- /dev/null +++ b/tools/target_dec_libfuzzer.c @@ -0,0 +1,7 @@ +#include "tools/target_dec_fuzzer.h" + +int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size); + +int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { + return fuzz_testcase(data, size); +}