From: Andreas Rheinhardt <andreas.rheinhardt@outlook.com> To: FFmpeg development discussions and patches <ffmpeg-devel@ffmpeg.org> Subject: [FFmpeg-devel] [PATCH 1/5] avcodec/cri, tdsc, tiff: Use ff_mjpeg_decoder directly Date: Mon, 21 Apr 2025 20:40:12 +0200 Message-ID: <GV1P250MB0737BCA93DFA6CFAE13589CB8FB82@GV1P250MB0737.EURP250.PROD.OUTLOOK.COM> (raw) [-- Attachment #1: Type: text/plain, Size: 29 bytes --] Patches attached. - Andreas [-- Attachment #2: 0001-avcodec-cri-tdsc-tiff-Use-ff_mjpeg_decoder-directly.patch --] [-- Type: text/x-patch, Size: 4762 bytes --] From 56445c4d007f74b4b51282184b773791f6b24641 Mon Sep 17 00:00:00 2001 From: Andreas Rheinhardt <andreas.rheinhardt@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.rheinhardt@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 [-- Attachment #3: 0002-tools-target_dec_fuzzer-Remove-mjpeg-hack.patch --] [-- Type: text/x-patch, Size: 1425 bytes --] From c2dff2428f10d8521f37923f728686483176870b Mon Sep 17 00:00:00 2001 From: Andreas Rheinhardt <andreas.rheinhardt@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.rheinhardt@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 [-- Attachment #4: 0003-avcodec-imm5-Reference-H.264-HEVC-decoders-directly.patch --] [-- Type: text/x-patch, Size: 2462 bytes --] From 3c3e84447f1e775c3e8caed4f8a22e8ae254967b Mon Sep 17 00:00:00 2001 From: Andreas Rheinhardt <andreas.rheinhardt@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.rheinhardt@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 [-- Attachment #5: 0004-avcodec-ftr-Replace-AVERROR_BUG-that-can-be-triggere.patch --] [-- Type: text/x-patch, Size: 1056 bytes --] From c68f31c624f561ca5dffaa694de6608256b0d03f Mon Sep 17 00:00:00 2001 From: Andreas Rheinhardt <andreas.rheinhardt@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.rheinhardt@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 [-- Attachment #6: 0005-tools-target_dec_fuzzer-Assert-on-AVERROR_BUG.patch --] [-- Type: text/x-patch, Size: 2279 bytes --] From 3f176ef2e65e63a46e29c4d1fc3306b8d8550c8b Mon Sep 17 00:00:00 2001 From: Andreas Rheinhardt <andreas.rheinhardt@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.rheinhardt@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 [-- Attachment #7: Type: text/plain, Size: 251 bytes --] _______________________________________________ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org https://ffmpeg.org/mailman/listinfo/ffmpeg-devel To unsubscribe, visit link above, or email ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".
next reply other threads:[~2025-04-21 18:40 UTC|newest] Thread overview: 2+ messages / expand[flat|nested] mbox.gz Atom feed top 2025-04-21 18:40 Andreas Rheinhardt [this message] 2025-04-24 22:52 ` Kacper Michajlow
Reply instructions: You may reply publicly to this message via plain-text email using any one of the following methods: * Save the following mbox file, import it into your mail client, and reply-to-all from there: mbox Avoid top-posting and favor interleaved quoting: https://en.wikipedia.org/wiki/Posting_style#Interleaved_style * Reply using the --to, --cc, and --in-reply-to switches of git-send-email(1): git send-email \ --in-reply-to=GV1P250MB0737BCA93DFA6CFAE13589CB8FB82@GV1P250MB0737.EURP250.PROD.OUTLOOK.COM \ --to=andreas.rheinhardt@outlook.com \ --cc=ffmpeg-devel@ffmpeg.org \ /path/to/YOUR_REPLY https://kernel.org/pub/software/scm/git/docs/git-send-email.html * If your mail client supports setting the In-Reply-To header via mailto: links, try the mailto: link
Git Inbox Mirror of the ffmpeg-devel mailing list - see https://ffmpeg.org/mailman/listinfo/ffmpeg-devel This inbox may be cloned and mirrored by anyone: git clone --mirror https://master.gitmailbox.com/ffmpegdev/0 ffmpegdev/git/0.git # If you have public-inbox 1.1+ installed, you may # initialize and index your mirror using the following commands: public-inbox-init -V2 ffmpegdev ffmpegdev/ https://master.gitmailbox.com/ffmpegdev \ ffmpegdev@gitmailbox.com public-inbox-index ffmpegdev Example config snippet for mirrors. AGPL code for this site: git clone https://public-inbox.org/public-inbox.git