Patches attached. - Andreas
From 56445c4d007f74b4b51282184b773791f6b24641 Mon Sep 17 00:00:00 2001 From: Andreas Rheinhardt <andreas.rheinha...@outlook.com> Date: Mon, 21 Apr 2025 18:48:10 +0200 Subject: [PATCH 1/5] avcodec/cri,tdsc,tiff: Use ff_mjpeg_decoder directly
This is simpler than calling avcodec_find_decoder(). Notice that av_codec_init_static() has already been called by the time we reach these decoders' init functions, so it is not necessary to call avcodec_find_decoder() for it (which doesn't do anything for the mjpeg decoder anyway). Signed-off-by: Andreas Rheinhardt <andreas.rheinha...@outlook.com> --- libavcodec/cri.c | 10 ++++------ libavcodec/tdsc.c | 10 ++++------ libavcodec/tiff.c | 10 ++++------ 3 files changed, 12 insertions(+), 18 deletions(-) diff --git a/libavcodec/cri.c b/libavcodec/cri.c index 6932bb6745..56ec485f7a 100644 --- a/libavcodec/cri.c +++ b/libavcodec/cri.c @@ -27,6 +27,7 @@ #define BITSTREAM_READER_LE +#include "libavutil/attributes_internal.h" #include "libavutil/intfloat.h" #include "libavutil/display.h" #include "avcodec.h" @@ -51,7 +52,6 @@ typedef struct CRIContext { static av_cold int cri_decode_init(AVCodecContext *avctx) { CRIContext *s = avctx->priv_data; - const AVCodec *codec; int ret; s->jpgframe = av_frame_alloc(); @@ -62,16 +62,14 @@ static av_cold int cri_decode_init(AVCodecContext *avctx) if (!s->jpkt) return AVERROR(ENOMEM); - codec = avcodec_find_decoder(AV_CODEC_ID_MJPEG); - if (!codec) - return AVERROR_BUG; - s->jpeg_avctx = avcodec_alloc_context3(codec); + EXTERN const FFCodec ff_mjpeg_decoder; + s->jpeg_avctx = avcodec_alloc_context3(&ff_mjpeg_decoder.p); if (!s->jpeg_avctx) return AVERROR(ENOMEM); s->jpeg_avctx->flags = avctx->flags; s->jpeg_avctx->flags2 = avctx->flags2; s->jpeg_avctx->idct_algo = avctx->idct_algo; - ret = avcodec_open2(s->jpeg_avctx, codec, NULL); + ret = avcodec_open2(s->jpeg_avctx, NULL, NULL); if (ret < 0) return ret; diff --git a/libavcodec/tdsc.c b/libavcodec/tdsc.c index ab0a70859b..225ddf3701 100644 --- a/libavcodec/tdsc.c +++ b/libavcodec/tdsc.c @@ -36,6 +36,7 @@ #include <stdint.h> #include <zlib.h> +#include "libavutil/attributes_internal.h" #include "libavutil/imgutils.h" #include "libavutil/mem.h" @@ -95,7 +96,6 @@ static av_cold int tdsc_close(AVCodecContext *avctx) static av_cold int tdsc_init(AVCodecContext *avctx) { TDSCContext *ctx = avctx->priv_data; - const AVCodec *codec; int ret; avctx->pix_fmt = AV_PIX_FMT_BGR24; @@ -120,16 +120,14 @@ static av_cold int tdsc_init(AVCodecContext *avctx) return AVERROR(ENOMEM); /* Prepare everything needed for JPEG decoding */ - codec = avcodec_find_decoder(AV_CODEC_ID_MJPEG); - if (!codec) - return AVERROR_BUG; - ctx->jpeg_avctx = avcodec_alloc_context3(codec); + EXTERN const FFCodec ff_mjpeg_decoder; + ctx->jpeg_avctx = avcodec_alloc_context3(&ff_mjpeg_decoder.p); if (!ctx->jpeg_avctx) return AVERROR(ENOMEM); ctx->jpeg_avctx->flags = avctx->flags; ctx->jpeg_avctx->flags2 = avctx->flags2; ctx->jpeg_avctx->idct_algo = avctx->idct_algo; - ret = avcodec_open2(ctx->jpeg_avctx, codec, NULL); + ret = avcodec_open2(ctx->jpeg_avctx, NULL, NULL); if (ret < 0) return ret; diff --git a/libavcodec/tiff.c b/libavcodec/tiff.c index 37b56e9757..e515845a83 100644 --- a/libavcodec/tiff.c +++ b/libavcodec/tiff.c @@ -36,6 +36,7 @@ #include <float.h> #include "libavutil/attributes.h" +#include "libavutil/attributes_internal.h" #include "libavutil/avstring.h" #include "libavutil/error.h" #include "libavutil/intreadwrite.h" @@ -2409,7 +2410,6 @@ again: static av_cold int tiff_init(AVCodecContext *avctx) { TiffContext *s = avctx->priv_data; - const AVCodec *codec; int ret; s->width = 0; @@ -2429,17 +2429,15 @@ static av_cold int tiff_init(AVCodecContext *avctx) return AVERROR(ENOMEM); /* Prepare everything needed for JPEG decoding */ - codec = avcodec_find_decoder(AV_CODEC_ID_MJPEG); - if (!codec) - return AVERROR_BUG; - s->avctx_mjpeg = avcodec_alloc_context3(codec); + EXTERN const FFCodec ff_mjpeg_decoder; + s->avctx_mjpeg = avcodec_alloc_context3(&ff_mjpeg_decoder.p); if (!s->avctx_mjpeg) return AVERROR(ENOMEM); s->avctx_mjpeg->flags = avctx->flags; s->avctx_mjpeg->flags2 = avctx->flags2; s->avctx_mjpeg->idct_algo = avctx->idct_algo; s->avctx_mjpeg->max_pixels = avctx->max_pixels; - ret = avcodec_open2(s->avctx_mjpeg, codec, NULL); + ret = avcodec_open2(s->avctx_mjpeg, NULL, NULL); if (ret < 0) { return ret; } -- 2.45.2
From c2dff2428f10d8521f37923f728686483176870b Mon Sep 17 00:00:00 2001 From: Andreas Rheinhardt <andreas.rheinha...@outlook.com> Date: Mon, 21 Apr 2025 19:01:57 +0200 Subject: [PATCH 2/5] tools/target_dec_fuzzer: Remove mjpeg hack ff_mjpeg_decoder is now referenced directly by the relevant decoders, so that the linker sees the dependency and just does the desired thing. So remove the hack. (Btw: The preprocessor does not do string comparisons, instead undefined tokens in #if checks evaluate to 0, making the check true regardless of the actual codec fuzzed (and leading to linker errors if the mjpeg decoder is disabled).) Signed-off-by: Andreas Rheinhardt <andreas.rheinha...@outlook.com> --- tools/target_dec_fuzzer.c | 5 ----- 1 file changed, 5 deletions(-) diff --git a/tools/target_dec_fuzzer.c b/tools/target_dec_fuzzer.c index b3be69f94d..2a8f39cb34 100644 --- a/tools/target_dec_fuzzer.c +++ b/tools/target_dec_fuzzer.c @@ -193,11 +193,6 @@ int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { 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); #else c = AVCodecInitialize(FFMPEG_CODEC); // Done once. -- 2.45.2
From 3c3e84447f1e775c3e8caed4f8a22e8ae254967b Mon Sep 17 00:00:00 2001 From: Andreas Rheinhardt <andreas.rheinha...@outlook.com> Date: Mon, 21 Apr 2025 19:13:07 +0200 Subject: [PATCH 3/5] avcodec/imm5: Reference H.264/HEVC decoders directly This is simpler and allows to fuzz them -- up until now, the linker did not see the dependency and fuzzing them returned AVERROR_BUG during init. It took just a few seconds here to run into an assert due to a return value of AVERROR(EAGAIN) in the decode callback... Signed-off-by: Andreas Rheinhardt <andreas.rheinha...@outlook.com> --- libavcodec/imm5.c | 18 +++++++----------- 1 file changed, 7 insertions(+), 11 deletions(-) diff --git a/libavcodec/imm5.c b/libavcodec/imm5.c index 2535e7726c..4b9f3f6b75 100644 --- a/libavcodec/imm5.c +++ b/libavcodec/imm5.c @@ -18,6 +18,7 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ +#include "libavutil/attributes_internal.h" #include "libavutil/intreadwrite.h" #include "avcodec.h" @@ -51,32 +52,27 @@ static const struct IMM5_unit { static av_cold int imm5_init(AVCodecContext *avctx) { IMM5Context *ctx = avctx->priv_data; - const AVCodec *codec; int ret; - codec = avcodec_find_decoder(AV_CODEC_ID_H264); - if (!codec) - return AVERROR_BUG; - ctx->h264_avctx = avcodec_alloc_context3(codec); + EXTERN const FFCodec ff_h264_decoder; + ctx->h264_avctx = avcodec_alloc_context3(&ff_h264_decoder.p); if (!ctx->h264_avctx) return AVERROR(ENOMEM); ctx->h264_avctx->thread_count = 1; ctx->h264_avctx->flags = avctx->flags; ctx->h264_avctx->flags2 = avctx->flags2; - ret = avcodec_open2(ctx->h264_avctx, codec, NULL); + ret = avcodec_open2(ctx->h264_avctx, NULL, NULL); if (ret < 0) return ret; - codec = avcodec_find_decoder(AV_CODEC_ID_HEVC); - if (!codec) - return AVERROR_BUG; - ctx->hevc_avctx = avcodec_alloc_context3(codec); + EXTERN const FFCodec ff_hevc_decoder; + ctx->hevc_avctx = avcodec_alloc_context3(&ff_hevc_decoder.p); if (!ctx->hevc_avctx) return AVERROR(ENOMEM); ctx->hevc_avctx->thread_count = 1; ctx->hevc_avctx->flags = avctx->flags; ctx->hevc_avctx->flags2 = avctx->flags2; - ret = avcodec_open2(ctx->hevc_avctx, codec, NULL); + ret = avcodec_open2(ctx->hevc_avctx, NULL, NULL); if (ret < 0) return ret; -- 2.45.2
From c68f31c624f561ca5dffaa694de6608256b0d03f Mon Sep 17 00:00:00 2001 From: Andreas Rheinhardt <andreas.rheinha...@outlook.com> Date: Mon, 21 Apr 2025 19:16:31 +0200 Subject: [PATCH 4/5] avcodec/ftr: Replace AVERROR_BUG that can be triggered Return AVERROR_DECODER_NOT_FOUND. (This can be triggered because this decoder tries to be generic and work with multiple underlying AAC decoders, so that there is no configure dependency for any decoder.) Signed-off-by: Andreas Rheinhardt <andreas.rheinha...@outlook.com> --- libavcodec/ftr.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libavcodec/ftr.c b/libavcodec/ftr.c index 3e7ab92887..06241fdca3 100644 --- a/libavcodec/ftr.c +++ b/libavcodec/ftr.c @@ -51,7 +51,7 @@ static av_cold int ftr_init(AVCodecContext *avctx) codec = avcodec_find_decoder(AV_CODEC_ID_AAC); if (!codec) - return AVERROR_BUG; + return AVERROR_DECODER_NOT_FOUND; for (int i = 0; i < s->nb_context; i++) { s->aac_avctx[i] = avcodec_alloc_context3(codec); -- 2.45.2
From 3f176ef2e65e63a46e29c4d1fc3306b8d8550c8b Mon Sep 17 00:00:00 2001 From: Andreas Rheinhardt <andreas.rheinha...@outlook.com> Date: Mon, 21 Apr 2025 20:01:50 +0200 Subject: [PATCH 5/5] tools/target_dec_fuzzer: Assert on AVERROR_BUG This will bring these bugs to our attention. Signed-off-by: Andreas Rheinhardt <andreas.rheinha...@outlook.com> --- tools/target_dec_fuzzer.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/tools/target_dec_fuzzer.c b/tools/target_dec_fuzzer.c index 2a8f39cb34..d99bfb91d6 100644 --- a/tools/target_dec_fuzzer.c +++ b/tools/target_dec_fuzzer.c @@ -87,6 +87,7 @@ static int subtitle_handler(AVCodecContext *avctx, AVFrame *unused, { AVSubtitle sub; int ret = avcodec_decode_subtitle2(avctx, &sub, got_sub_ptr, avpkt); + av_assert0(ret != AVERROR_BUG); if (ret >= 0 && *got_sub_ptr) avsubtitle_free(&sub); return ret; @@ -96,6 +97,7 @@ static int audio_video_handler(AVCodecContext *avctx, AVFrame *frame, int *got_frame, const AVPacket *dummy) { int ret = avcodec_receive_frame(avctx, frame); + av_assert0(ret != AVERROR_BUG); *got_frame = ret >= 0; return ret; } @@ -469,6 +471,7 @@ int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { int res = avcodec_open2(ctx, &c->p, &opts); if (res < 0) { + av_assert0(res != AVERROR_BUG); avcodec_free_context(&ctx); av_free(parser_avctx); av_parser_close(parser); @@ -542,6 +545,7 @@ int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { if (ctx->codec_type != AVMEDIA_TYPE_SUBTITLE) { int ret = avcodec_send_packet(ctx, avpkt); + av_assert0(ret != AVERROR_BUG); decode_more = ret >= 0; if(!decode_more) { ec_pixels += (ctx->width + 32LL) * (ctx->height + 32LL); @@ -595,8 +599,10 @@ maximums_reached: av_packet_unref(avpkt); - if (ctx->codec_type != AVMEDIA_TYPE_SUBTITLE) - avcodec_send_packet(ctx, NULL); + if (ctx->codec_type != AVMEDIA_TYPE_SUBTITLE) { + int ret = avcodec_send_packet(ctx, NULL); + av_assert0(ret != AVERROR_BUG); + } do { got_frame = 0; -- 2.45.2
_______________________________________________ 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".