PR #25036 opened by michaelni URL: https://code.ffmpeg.org/FFmpeg/FFmpeg/pulls/25036 Patch URL: https://code.ffmpeg.org/FFmpeg/FFmpeg/pulls/25036.patch
>From 808f51692859c25aab5204e0475766983fa99724 Mon Sep 17 00:00:00 2001 From: Michael Niedermayer <[email protected]> Date: Mon, 12 Oct 2026 02:01:35 +0200 Subject: [PATCH 01/24] avutil/opt: do not store an image size that failed to parse Fixes: use of uninitialized memory Fixes: yEDlrREdlez4 Regression since: bd68a61304 Found during the review of https://code.ffmpeg.org/FFmpeg/FFmpeg/pulls/24757 Use of uninitialized memory Replicated through UnModified FFmpeg with Valgrind --- libavutil/opt.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/libavutil/opt.c b/libavutil/opt.c index 03fca6ad15..041ad30280 100644 --- a/libavutil/opt.c +++ b/libavutil/opt.c @@ -534,8 +534,10 @@ static int set_string_image_size(void *obj, const AVOption *o, const char *val, return 0; } ret = av_parse_video_size(&tmp[0], &tmp[1], val); - if (ret < 0) + if (ret < 0) { av_log(logctx, AV_LOG_ERROR, "Unable to parse \"%s\" option value \"%s\" as image size\n", o->name, val); + return ret; + } if (dst) memcpy(dst, tmp, sizeof(tmp)); return ret; -- 2.52.0 >From 6739caf91863d8f63815fb5ac6640f93aa7f8944 Mon Sep 17 00:00:00 2001 From: Michael Niedermayer <[email protected]> Date: Mon, 12 Oct 2026 02:03:27 +0200 Subject: [PATCH 02/24] avutil/opt: do not store a color that failed to parse Fixes: use of uninitialized memory Fixes: f78pyZFASSy9 Regression since: bd68a61304 Found during triage of the review of https://code.ffmpeg.org/FFmpeg/FFmpeg/pulls/24757 Use of uninitialized memory Replicated through UnModified FFmpeg with Valgrind --- libavutil/opt.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/libavutil/opt.c b/libavutil/opt.c index 041ad30280..0f69e04b3b 100644 --- a/libavutil/opt.c +++ b/libavutil/opt.c @@ -565,8 +565,10 @@ static int set_string_color(void *obj, const AVOption *o, const char *val, uint8 } else { uint8_t tmp[4]; ret = av_parse_color(tmp, val, -1, obj); - if (ret < 0) + if (ret < 0) { av_log(logctx, AV_LOG_ERROR, "Unable to parse \"%s\" option value \"%s\" as color\n", o->name, val); + return ret; + } if (dst) memcpy(dst, tmp, sizeof(tmp)); return ret; -- 2.52.0 >From 08cc9134ecfeadde105b90d46a258b17786c8c28 Mon Sep 17 00:00:00 2001 From: Michael Niedermayer <[email protected]> Date: Mon, 12 Oct 2026 02:04:57 +0200 Subject: [PATCH 03/24] avcodec/aac: do not keep the frame pointer after decoding Fixes: use after free Fixes: MbYbttK2ue35 Regression since: eee5fa0808 Found during triage of the review of https://code.ffmpeg.org/FFmpeg/FFmpeg/pulls/24678 Use after free Replicated through UnModified FFmpeg with ASAN --- libavcodec/aac/aacdec.c | 1 + libavcodec/aac/aacdec_latm.h | 1 + 2 files changed, 2 insertions(+) diff --git a/libavcodec/aac/aacdec.c b/libavcodec/aac/aacdec.c index 66ab648016..700f16c56a 100644 --- a/libavcodec/aac/aacdec.c +++ b/libavcodec/aac/aacdec.c @@ -2612,6 +2612,7 @@ static int aac_decode_frame(AVCodecContext *avctx, AVFrame *frame, default: err = aac_decode_frame_int(avctx, frame, got_frame_ptr, &gb, avpkt); } + ac->frame = NULL; if (err < 0) return err; diff --git a/libavcodec/aac/aacdec_latm.h b/libavcodec/aac/aacdec_latm.h index 398d40741b..d9e836e949 100644 --- a/libavcodec/aac/aacdec_latm.h +++ b/libavcodec/aac/aacdec_latm.h @@ -308,6 +308,7 @@ static int latm_decode_frame(AVCodecContext *avctx, AVFrame *out, default: err = aac_decode_frame_int(avctx, out, got_frame_ptr, &gb, avpkt); } + latmctx->aac_ctx.frame = NULL; if (err < 0) return err; -- 2.52.0 >From db07e7b2196f043c5db4b9e09677fc736f24f63c Mon Sep 17 00:00:00 2001 From: Michael Niedermayer <[email protected]> Date: Mon, 12 Oct 2026 02:06:36 +0200 Subject: [PATCH 04/24] avcodec/ratecontrol: check the picture number in ff_get_2pass_fcode() Fixes: out of array read Fixes: H7ATVBRB6ALZ Found during the review of https://code.ffmpeg.org/FFmpeg/FFmpeg/pulls/24758 Out of array read Replicated through UnModified FFmpeg with ASAN --- libavcodec/mpegvideo_enc.c | 4 +++- libavcodec/ratecontrol.c | 11 +++++++++-- libavcodec/ratecontrol.h | 2 +- 3 files changed, 13 insertions(+), 4 deletions(-) diff --git a/libavcodec/mpegvideo_enc.c b/libavcodec/mpegvideo_enc.c index 3908628504..3a7d1e2749 100644 --- a/libavcodec/mpegvideo_enc.c +++ b/libavcodec/mpegvideo_enc.c @@ -3706,7 +3706,9 @@ static int encode_picture(MPVMainEncContext *const m, const AVPacket *pkt) ret = estimate_qp(m, 1); if (ret < 0) return ret; - ff_get_2pass_fcode(m); + ret = ff_get_2pass_fcode(m); + if (ret < 0) + return ret; } else if (!(s->c.avctx->flags & AV_CODEC_FLAG_QSCALE)) { if (s->c.pict_type == AV_PICTURE_TYPE_B) s->lambda = m->last_lambda_for[s->c.pict_type]; diff --git a/libavcodec/ratecontrol.c b/libavcodec/ratecontrol.c index 397a235821..130f09b9b7 100644 --- a/libavcodec/ratecontrol.c +++ b/libavcodec/ratecontrol.c @@ -900,14 +900,21 @@ static void adaptive_quantization(RateControlContext *const rcc, } } -void ff_get_2pass_fcode(MPVMainEncContext *const m) +int ff_get_2pass_fcode(MPVMainEncContext *const m) { MPVEncContext *const s = &m->s; const RateControlContext *rcc = &m->rc_context; - const RateControlEntry *rce = &rcc->entry[s->picture_number]; + const RateControlEntry *rce; + + if (s->picture_number >= rcc->num_entries) { + av_log(s->c.avctx, AV_LOG_ERROR, "Input is longer than 2-pass log file\n"); + return AVERROR(EINVAL); + } + rce = &rcc->entry[s->picture_number]; s->f_code = rce->f_code; s->b_code = rce->b_code; + return 0; } // FIXME rd or at least approx for dquant diff --git a/libavcodec/ratecontrol.h b/libavcodec/ratecontrol.h index 3bcfa5658a..f4f8af5bf5 100644 --- a/libavcodec/ratecontrol.h +++ b/libavcodec/ratecontrol.h @@ -100,7 +100,7 @@ int ff_rate_control_init(MPVMainEncContext *m); float ff_rate_estimate_qscale(MPVMainEncContext *m, int dry_run); void ff_write_pass1_stats(MPVMainEncContext *m); int ff_vbv_update(MPVMainEncContext *m, int frame_size); -void ff_get_2pass_fcode(MPVMainEncContext *m); +int ff_get_2pass_fcode(MPVMainEncContext *m); void ff_rate_control_uninit(RateControlContext *rcc); #endif /* AVCODEC_RATECONTROL_H */ -- 2.52.0 >From fa13733064f4b3fb2881b81cd2da3281a2d5f99a Mon Sep 17 00:00:00 2001 From: Michael Niedermayer <[email protected]> Date: Mon, 12 Oct 2026 02:07:46 +0200 Subject: [PATCH 05/24] avcodec/ratecontrol: check the fcode and bcode of the 2-pass log Fixes: out of array access Fixes: DY618nKRv9YY Found during triage of the review of https://code.ffmpeg.org/FFmpeg/FFmpeg/pulls/24758 Out of array access Replicated through UnModified FFmpeg with ASAN --- libavcodec/ratecontrol.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/libavcodec/ratecontrol.c b/libavcodec/ratecontrol.c index 130f09b9b7..98e05601da 100644 --- a/libavcodec/ratecontrol.c +++ b/libavcodec/ratecontrol.c @@ -635,6 +635,11 @@ av_cold int ff_rate_control_init(MPVMainEncContext *const m) rce->pict_type, i); return -1; } + if ((unsigned)rce->f_code > MAX_FCODE || (unsigned)rce->b_code > MAX_FCODE) { + av_log(avctx, AV_LOG_ERROR, "invalid fcode %d / bcode %d at line %d\n", + rce->f_code, rce->b_code, i); + return -1; + } p = next; } -- 2.52.0 >From ec3bf2499c942b7cf6bccea7148ed6732a56225b Mon Sep 17 00:00:00 2001 From: Michael Niedermayer <[email protected]> Date: Mon, 12 Oct 2026 02:09:06 +0200 Subject: [PATCH 06/24] avformat/mov: saturate the fragment timestamp arithmetic in mov_read_trun() Fixes: signed integer overflow Fixes: 5NVcwD9UoHmO Found during triage of the review of https://code.ffmpeg.org/FFmpeg/FFmpeg/pulls/24878 Signed integer overflow Replicated through UnModified FFmpeg with UBSAN --- libavformat/mov.c | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/libavformat/mov.c b/libavformat/mov.c index 90decf17f5..fab34da3a7 100644 --- a/libavformat/mov.c +++ b/libavformat/mov.c @@ -6301,7 +6301,7 @@ static int mov_read_trun(MOVContext *c, AVIOContext *pb, MOVAtom atom) frag_stream_info = get_current_frag_stream_info(&c->frag_index); if (frag_stream_info) { if (frag_stream_info->next_trun_dts != AV_NOPTS_VALUE) { - dts = frag_stream_info->next_trun_dts - sc->time_offset; + dts = av_sat_sub64(frag_stream_info->next_trun_dts, sc->time_offset); } else if (frag_stream_info->first_tfra_pts != AV_NOPTS_VALUE && c->use_mfra_for == FF_MOV_FLAG_MFRA_PTS) { pts = frag_stream_info->first_tfra_pts; @@ -6326,7 +6326,7 @@ static int mov_read_trun(MOVContext *c, AVIOContext *pb, MOVAtom atom) } if (has_tfdt && c->use_tfdt || fallback_tfdt) { - dts = frag_stream_info->tfdt_dts - sc->time_offset; + dts = av_sat_sub64(frag_stream_info->tfdt_dts, sc->time_offset); av_log(c->fc, AV_LOG_DEBUG, "found tfdt time %"PRId64 ", using it for dts\n", dts); } else if (has_sidx && !c->use_tfdt || fallback_sidx) { @@ -6336,13 +6336,13 @@ static int mov_read_trun(MOVContext *c, AVIOContext *pb, MOVAtom atom) av_log(c->fc, AV_LOG_DEBUG, "found sidx time %"PRId64 ", using it for dts\n", frag_stream_info->sidx_pts); } else { - dts = sc->track_end - sc->time_offset; + dts = av_sat_sub64(sc->track_end, sc->time_offset); av_log(c->fc, AV_LOG_DEBUG, "found track end time %"PRId64 ", using it for dts\n", dts); } } } else { - dts = sc->track_end - sc->time_offset; + dts = av_sat_sub64(sc->track_end, sc->time_offset); av_log(c->fc, AV_LOG_DEBUG, "found track end time %"PRId64 ", using it for dts\n", dts); } @@ -6432,11 +6432,11 @@ static int mov_read_trun(MOVContext *c, AVIOContext *pb, MOVAtom atom) mov_update_dts_shift(sc, ctts_duration, c->fc); if (pts != AV_NOPTS_VALUE) { - dts = pts - sc->dts_shift; + dts = av_sat_sub64(pts, sc->dts_shift); if (flags & MOV_TRUN_SAMPLE_CTS) { - dts -= ctts_duration; + dts = av_sat_sub64(dts, ctts_duration); } else { - dts -= sc->time_offset; + dts = av_sat_sub64(dts, sc->time_offset); } av_log(c->fc, AV_LOG_DEBUG, "pts %"PRId64" calculated dts %"PRId64 @@ -6490,7 +6490,7 @@ static int mov_read_trun(MOVContext *c, AVIOContext *pb, MOVAtom atom) } } if (frag_stream_info) - frag_stream_info->next_trun_dts = dts + sc->time_offset; + frag_stream_info->next_trun_dts = av_sat_add64(dts, sc->time_offset); if (i < entries) { // EOF found before reading all entries. Fix the hole this would // leave in index_entries and tts_data @@ -6537,7 +6537,7 @@ static int mov_read_trun(MOVContext *c, AVIOContext *pb, MOVAtom atom) frag->implicit_offset = offset; - sc->track_end = dts + sc->time_offset; + sc->track_end = av_sat_add64(dts, sc->time_offset); if (st->duration < sc->track_end) st->duration = sc->track_end; -- 2.52.0 >From e5c6a32385caab6d469f8e370beb8a388fa945b2 Mon Sep 17 00:00:00 2001 From: Michael Niedermayer <[email protected]> Date: Mon, 12 Oct 2026 02:10:17 +0200 Subject: [PATCH 07/24] avformat/hls: saturate the timestamps of ID3 timestamped streams Fixes: signed integer overflow Fixes: CniIhjP8pfgr Found during triage of the review of https://code.ffmpeg.org/FFmpeg/FFmpeg/pulls/24873 Signed integer overflow Replicated through UnModified FFmpeg with UBSAN --- libavformat/hls.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/libavformat/hls.c b/libavformat/hls.c index 506c8c0f49..b1793cc1c8 100644 --- a/libavformat/hls.c +++ b/libavformat/hls.c @@ -2661,12 +2661,12 @@ static int recheck_discard_flags(AVFormatContext *s, int first) static void fill_timing_for_id3_timestamped_stream(struct playlist *pls) { if (pls->id3_offset >= 0) { - pls->pkt->dts = pls->id3_mpegts_timestamp + - av_rescale_q(pls->id3_offset, - pls->ctx->streams[pls->pkt->stream_index]->time_base, - MPEG_TIME_BASE_Q); + pls->pkt->dts = av_sat_add64(pls->id3_mpegts_timestamp, + av_rescale_q(pls->id3_offset, + pls->ctx->streams[pls->pkt->stream_index]->time_base, + MPEG_TIME_BASE_Q)); if (pls->pkt->duration) - pls->id3_offset += pls->pkt->duration; + pls->id3_offset = av_sat_add64(pls->id3_offset, pls->pkt->duration); else pls->id3_offset = -1; } else { -- 2.52.0 >From 117224293ac7495933038c4ba257ff64fdac14aa Mon Sep 17 00:00:00 2001 From: Michael Niedermayer <[email protected]> Date: Mon, 12 Oct 2026 02:11:45 +0200 Subject: [PATCH 08/24] avformat/hls: saturate the playlist timestamp offset arithmetic Fixes: signed integer overflow Fixes: 2PuIAHF3wU0b Regression since: e27ad5760c Found during triage of the review of https://code.ffmpeg.org/FFmpeg/FFmpeg/pulls/24873 Signed integer overflow Replicated through UnModified FFmpeg with UBSAN --- libavformat/hls.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/libavformat/hls.c b/libavformat/hls.c index b1793cc1c8..bb57488234 100644 --- a/libavformat/hls.c +++ b/libavformat/hls.c @@ -2637,8 +2637,8 @@ static int recheck_discard_flags(AVFormatContext *s, int first) pls->pb.pub.eof_reached = 0; if (c->cur_timestamp != AV_NOPTS_VALUE) { /* catch up */ - pls->seek_timestamp = c->cur_timestamp + - (pls->ts_offset != AV_NOPTS_VALUE ? pls->ts_offset : 0); + pls->seek_timestamp = av_sat_add64(c->cur_timestamp, + pls->ts_offset != AV_NOPTS_VALUE ? pls->ts_offset : 0); pls->seek_flags = AVSEEK_FLAG_ANY; pls->seek_stream_index = -1; } @@ -2769,7 +2769,7 @@ static int hls_read_packet(AVFormatContext *s, AVPacket *pkt) get_timebase(pls), AV_TIME_BASE_Q); for (int64_t k = 0; k < seg_idx && k < pls->n_segments; k++) - ts -= pls->segments[k]->duration; + ts = av_sat_sub64(ts, pls->segments[k]->duration); if (c->first_timestamp == AV_NOPTS_VALUE) { c->first_timestamp = ts; @@ -2780,19 +2780,19 @@ static int hls_read_packet(AVFormatContext *s, AVPacket *pkt) * order, but another stream in the same segment may * start earlier. Lower the estimate while packets of * that segment are still arriving. */ - int64_t delta = c->first_timestamp - ts; + int64_t delta = av_sat_sub64(c->first_timestamp, ts); if (delta > 0 && delta <= pls->target_duration) { c->first_timestamp = ts; for (int k = 0; k < c->n_playlists; k++) if (c->playlists[k]->ts_offset != AV_NOPTS_VALUE) - c->playlists[k]->ts_offset += delta; + c->playlists[k]->ts_offset = av_sat_add64(c->playlists[k]->ts_offset, delta); adjusted = 1; } } if (pls->ts_offset == AV_NOPTS_VALUE) - pls->ts_offset = ts - c->first_timestamp; + pls->ts_offset = av_sat_sub64(ts, c->first_timestamp); if (adjusted) { for (unsigned k = 0; k < s->nb_streams; k++) @@ -3058,7 +3058,7 @@ static int hls_read_seek(AVFormatContext *s, int stream_index, * have different DTS baselines, so translate the threshold onto this * playlist's own baseline using its captured offset. */ if (pls->ts_offset != AV_NOPTS_VALUE) - pls->seek_timestamp = seek_timestamp + pls->ts_offset; + pls->seek_timestamp = av_sat_add64(seek_timestamp, pls->ts_offset); else pls->seek_timestamp = seek_timestamp; pls->seek_flags = flags; -- 2.52.0 >From 68a89f59626678f9e7aa8cfa43839db708d28e1f Mon Sep 17 00:00:00 2001 From: Michael Niedermayer <[email protected]> Date: Mon, 12 Oct 2026 02:15:55 +0200 Subject: [PATCH 09/24] avfilter/af_sofalizer: reject SOFA files with an IR length of 0 Fixes: undefined clz of 0 Fixes: jj9j0M05l3SP Regression since: 7ea4b928a2 Found during the review of https://code.ffmpeg.org/FFmpeg/FFmpeg/pulls/24624 Undefined clz of 0 Replicated through UnModified FFmpeg with UBSAN --- libavfilter/af_sofalizer.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/libavfilter/af_sofalizer.c b/libavfilter/af_sofalizer.c index 01278c2d42..e1670d08e7 100644 --- a/libavfilter/af_sofalizer.c +++ b/libavfilter/af_sofalizer.c @@ -153,6 +153,11 @@ static int preload_sofa(AVFilterContext *ctx, char *filename, int *samplingrate) return ret; } + if (!mysofa->N) { + av_log(ctx, AV_LOG_ERROR, "Selected SOFA file has inconsistent dimensions.\n"); + return AVERROR_INVALIDDATA; + } + if (s->normalize) mysofa_loudness(s->sofa.hrtf); -- 2.52.0 >From d86a85cf53768770ad8ced3da21b62a784028d5b Mon Sep 17 00:00:00 2001 From: Michael Niedermayer <[email protected]> Date: Mon, 12 Oct 2026 02:16:17 +0200 Subject: [PATCH 10/24] avfilter/af_sofalizer: check the IR length against the IR data Fixes: out of array read Fixes: 65nc8s5OIq4Z Regression since: 4096c670ab Found during triage of the review of https://code.ffmpeg.org/FFmpeg/FFmpeg/pulls/24624 Out of array read Replicated through UnModified FFmpeg with ASAN --- libavfilter/af_sofalizer.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libavfilter/af_sofalizer.c b/libavfilter/af_sofalizer.c index e1670d08e7..caf833c19a 100644 --- a/libavfilter/af_sofalizer.c +++ b/libavfilter/af_sofalizer.c @@ -153,7 +153,7 @@ static int preload_sofa(AVFilterContext *ctx, char *filename, int *samplingrate) return ret; } - if (!mysofa->N) { + if (!mysofa->N || mysofa->DataIR.elements / mysofa->M / mysofa->R < mysofa->N) { av_log(ctx, AV_LOG_ERROR, "Selected SOFA file has inconsistent dimensions.\n"); return AVERROR_INVALIDDATA; } -- 2.52.0 >From b02d7163974eaf5125a8fd185a67345f430490cb Mon Sep 17 00:00:00 2001 From: Michael Niedermayer <[email protected]> Date: Mon, 12 Oct 2026 02:16:53 +0200 Subject: [PATCH 11/24] avfilter/af_sofalizer: check the size of the delay data Fixes: NULL pointer dereference Fixes: d80uw1EIP3Pa Regression since: ee64b64c02 Found during triage of the review of https://code.ffmpeg.org/FFmpeg/FFmpeg/pulls/24624 NULL pointer dereference Replicated through UnModified FFmpeg with ASAN --- libavfilter/af_sofalizer.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/libavfilter/af_sofalizer.c b/libavfilter/af_sofalizer.c index caf833c19a..fa15937402 100644 --- a/libavfilter/af_sofalizer.c +++ b/libavfilter/af_sofalizer.c @@ -153,7 +153,8 @@ static int preload_sofa(AVFilterContext *ctx, char *filename, int *samplingrate) return ret; } - if (!mysofa->N || mysofa->DataIR.elements / mysofa->M / mysofa->R < mysofa->N) { + if (!mysofa->N || mysofa->DataIR.elements / mysofa->M / mysofa->R < mysofa->N || + (mysofa->DataDelay.elements != mysofa->R && mysofa->DataDelay.elements / mysofa->R < mysofa->M)) { av_log(ctx, AV_LOG_ERROR, "Selected SOFA file has inconsistent dimensions.\n"); return AVERROR_INVALIDDATA; } -- 2.52.0 >From 941bac1a438225a6c33f978d3c4628cd980f2692 Mon Sep 17 00:00:00 2001 From: Michael Niedermayer <[email protected]> Date: Mon, 12 Oct 2026 02:17:45 +0200 Subject: [PATCH 12/24] avfilter/vidstabutils: do not offer packed RGB formats Fixes: assertion failure Fixes: CSKmF1Dx1jig Found during the review of https://code.ffmpeg.org/FFmpeg/FFmpeg/pulls/24608 Assertion failure Replicated through UnModified FFmpeg Crash Replicated through UnModified FFmpeg with ASAN --- libavfilter/vidstabutils.c | 4 ---- 1 file changed, 4 deletions(-) diff --git a/libavfilter/vidstabutils.c b/libavfilter/vidstabutils.c index a0c1fc990e..7c87477f3f 100644 --- a/libavfilter/vidstabutils.c +++ b/libavfilter/vidstabutils.c @@ -25,7 +25,6 @@ const enum AVPixelFormat ff_vidstab_pix_fmts[] = { AV_PIX_FMT_YUV444P, AV_PIX_FMT_YUV422P, AV_PIX_FMT_YUV420P, AV_PIX_FMT_YUV411P, AV_PIX_FMT_YUV410P, AV_PIX_FMT_YUVA420P, AV_PIX_FMT_YUV440P, AV_PIX_FMT_GRAY8, - AV_PIX_FMT_RGB24, AV_PIX_FMT_BGR24, AV_PIX_FMT_RGBA, AV_PIX_FMT_NONE }; @@ -41,9 +40,6 @@ VSPixelFormat ff_av2vs_pixfmt(AVFilterContext *ctx, enum AVPixelFormat pf) case AV_PIX_FMT_YUV440P: return PF_YUV440P; case AV_PIX_FMT_YUVA420P: return PF_YUVA420P; case AV_PIX_FMT_GRAY8: return PF_GRAY8; - case AV_PIX_FMT_RGB24: return PF_RGB24; - case AV_PIX_FMT_BGR24: return PF_BGR24; - case AV_PIX_FMT_RGBA: return PF_RGBA; default: av_log(ctx, AV_LOG_ERROR, "cannot deal with pixel format %i\n", pf); return PF_NONE; -- 2.52.0 >From 934a0d0883e1673c749c89b202751f1795da619d Mon Sep 17 00:00:00 2001 From: Michael Niedermayer <[email protected]> Date: Mon, 12 Oct 2026 02:25:23 +0200 Subject: [PATCH 13/24] avfilter/vf_libopencv: reject shapes too big for OpenCV Fixes: out of array write Fixes: EVA3Y4e693ul Found during the review of https://code.ffmpeg.org/FFmpeg/FFmpeg/pulls/24753 Out of array write Replicated through UnModified FFmpeg with ASAN --- libavfilter/vf_libopencv.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/libavfilter/vf_libopencv.c b/libavfilter/vf_libopencv.c index cdfa678860..e34bcb9da7 100644 --- a/libavfilter/vf_libopencv.c +++ b/libavfilter/vf_libopencv.c @@ -240,6 +240,12 @@ static int parse_iplconvkernel(IplConvKernel **kernel, char *buf, void *log_ctx) goto out; } + if (rows > (INT_MAX - sizeof(IplConvKernel) - 32) / sizeof(int) / cols) { + av_log(log_ctx, AV_LOG_ERROR, "Shape size %dx%d is too big\n", cols, rows); + ret = AVERROR(EINVAL); + goto out; + } + if (anchor_x < 0 || anchor_y < 0 || anchor_x >= cols || anchor_y >= rows) { av_log(log_ctx, AV_LOG_ERROR, "Shape anchor %dx%d is not inside the rectangle with size %dx%d.\n", -- 2.52.0 >From a8509fe4a75231d7cefe1ee21c31a68183e4c3be Mon Sep 17 00:00:00 2001 From: Michael Niedermayer <[email protected]> Date: Mon, 12 Oct 2026 02:27:49 +0200 Subject: [PATCH 14/24] avfilter/vf_deshake: use the linesize of the reference frame Fixes: out of array read Fixes: Au41rSBM5kGS Found during triage of the review of https://code.ffmpeg.org/FFmpeg/FFmpeg/pulls/24765 Out of array read Replicated through UnModified FFmpeg with ASAN --- libavfilter/vf_deshake.c | 25 +++++++++++++------------ 1 file changed, 13 insertions(+), 12 deletions(-) diff --git a/libavfilter/vf_deshake.c b/libavfilter/vf_deshake.c index afd0989e05..8a2dbe2fa5 100644 --- a/libavfilter/vf_deshake.c +++ b/libavfilter/vf_deshake.c @@ -171,16 +171,16 @@ static double clean_mean(double *values, int count) * chooses the most likely shift by the smallest difference in blocks. */ static void find_block_motion(DeshakeContext *deshake, uint8_t *src1, - uint8_t *src2, int cx, int cy, int stride, - IntMotionVector *mv) + uint8_t *src2, int cx, int cy, int stride1, + int stride2, IntMotionVector *mv) { int x, y; int diff; int smallest = INT_MAX; int tmp, tmp2; - #define CMP(i, j) deshake->sad(src1 + cy * stride + cx, stride,\ - src2 + (j) * stride + (i), stride) + #define CMP(i, j) deshake->sad(src1 + cy * stride1 + cx, stride1,\ + src2 + (j) * stride2 + (i), stride2) if (deshake->search == EXHAUSTIVE) { // Compare every possible position - this is sloooow! @@ -285,7 +285,7 @@ static double block_angle(int x, int y, int cx, int cy, IntMotionVector *shift) * motion vector (1, -2). */ static void find_motion(DeshakeContext *deshake, uint8_t *src1, uint8_t *src2, - int width, int height, int stride, Transform *t) + int width, int height, int stride1, int stride2, Transform *t) { int x, y; IntMotionVector mv = {0, 0}; @@ -312,10 +312,10 @@ static void find_motion(DeshakeContext *deshake, uint8_t *src1, uint8_t *src2, for (x = deshake->rx; x < width - deshake->rx - 16; x += 16) { // If the contrast is too low, just skip this block as it probably // won't be very useful to us. - contrast = block_contrast(src2, x, y, stride, deshake->blocksize); + contrast = block_contrast(src2, x, y, stride2, deshake->blocksize); if (contrast > deshake->contrast) { //av_log(NULL, AV_LOG_ERROR, "%d\n", contrast); - find_block_motion(deshake, src1, src2, x, y, stride, &mv); + find_block_motion(deshake, src1, src2, x, y, stride1, stride2, &mv); if (mv.x != -1 && mv.y != -1) { deshake->counts[mv.x + deshake->rx][mv.y + deshake->ry] += 1; if (x > deshake->rx && y > deshake->ry) @@ -476,7 +476,8 @@ static int filter_frame(AVFilterLink *link, AVFrame *in) } av_frame_copy_props(out, in); - aligned = !((intptr_t)in->data[0] & 15 | in->linesize[0] & 15); + const AVFrame *ref = deshake->ref ? deshake->ref : in; + aligned = !((intptr_t)ref->data[0] & 15 | ref->linesize[0] & 15); deshake->sad = av_pixelutils_get_sad_fn(4, 4, aligned, deshake); // 16x16, 2nd source unaligned if (!deshake->sad) { ret = AVERROR(EINVAL); @@ -485,9 +486,9 @@ static int filter_frame(AVFilterLink *link, AVFrame *in) if (deshake->cx < 0 || deshake->cy < 0 || deshake->cw < 0 || deshake->ch < 0) { // Find the most likely global motion for the current frame - find_motion(deshake, (deshake->ref == NULL) ? in->data[0] : deshake->ref->data[0], in->data[0], link->w, link->h, in->linesize[0], &t); + find_motion(deshake, ref->data[0], in->data[0], link->w, link->h, ref->linesize[0], in->linesize[0], &t); } else { - uint8_t *src1 = (deshake->ref == NULL) ? in->data[0] : deshake->ref->data[0]; + uint8_t *src1 = ref->data[0]; uint8_t *src2 = in->data[0]; deshake->cx = FFMIN(deshake->cx, link->w); @@ -499,10 +500,10 @@ static int filter_frame(AVFilterLink *link, AVFrame *in) // Quadword align right margin deshake->cw &= ~15; - src1 += deshake->cy * in->linesize[0] + deshake->cx; + src1 += deshake->cy * ref->linesize[0] + deshake->cx; src2 += deshake->cy * in->linesize[0] + deshake->cx; - find_motion(deshake, src1, src2, deshake->cw, deshake->ch, in->linesize[0], &t); + find_motion(deshake, src1, src2, deshake->cw, deshake->ch, ref->linesize[0], in->linesize[0], &t); } -- 2.52.0 >From ee7fe63d02253059738243b725e0e556507c76c4 Mon Sep 17 00:00:00 2001 From: Michael Niedermayer <[email protected]> Date: Mon, 12 Oct 2026 02:28:10 +0200 Subject: [PATCH 15/24] avfilter/vf_idet: use the linesize of the previous and next frame Fixes: out of array read Fixes: Au41rSBM5kGS Found during triage of the review of https://code.ffmpeg.org/FFmpeg/FFmpeg/pulls/24765 Out of array read Replicated through UnModified FFmpeg with ASAN --- libavfilter/vf_idet.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libavfilter/vf_idet.c b/libavfilter/vf_idet.c index c217021ae9..02dc14fb7a 100644 --- a/libavfilter/vf_idet.c +++ b/libavfilter/vf_idet.c @@ -156,9 +156,9 @@ static void filter(AVFilterContext *ctx) } for (y = 2; y < h - 2; y++) { - uint8_t *prev = &idet->prev->data[i][y*refs]; + uint8_t *prev = &idet->prev->data[i][y*idet->prev->linesize[i]]; uint8_t *cur = &idet->cur ->data[i][y*refs]; - uint8_t *next = &idet->next->data[i][y*refs]; + uint8_t *next = &idet->next->data[i][y*idet->next->linesize[i]]; alpha[ y &1] += filter_line(cur-refs, prev, cur+refs, w); alpha[(y^1)&1] += filter_line(cur-refs, next, cur+refs, w); delta += filter_line(cur-refs, cur, cur+refs, w); -- 2.52.0 >From b7951aa4b07aa2e7ef243beb0d1a453dc7bcaa89 Mon Sep 17 00:00:00 2001 From: Michael Niedermayer <[email protected]> Date: Mon, 12 Oct 2026 02:28:42 +0200 Subject: [PATCH 16/24] avfilter/vf_photosensitivity: blend only the visible part of the lines Fixes: out of array read Fixes: Au41rSBM5kGS Found during triage of the review of https://code.ffmpeg.org/FFmpeg/FFmpeg/pulls/24765 Out of array read Replicated through UnModified FFmpeg with ASAN --- libavfilter/vf_photosensitivity.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libavfilter/vf_photosensitivity.c b/libavfilter/vf_photosensitivity.c index 3f040f8c89..97347ad2c9 100644 --- a/libavfilter/vf_photosensitivity.c +++ b/libavfilter/vf_photosensitivity.c @@ -152,12 +152,12 @@ static int blend_frame_partial(AVFilterContext *ctx, void *arg, int jobnr, int n const uint16_t t_mul = 0x100 - s_mul; const int slice_start = ff_slice_pos(td->target->height, jobnr, nb_jobs); const int slice_end = ff_slice_pos(td->target->height, jobnr + 1, nb_jobs); - const int linesize = td->target->linesize[0]; + const int width = td->target->width * NUM_CHANNELS; for (y = slice_start; y < slice_end; y++) { t = td->target->data[0] + y * td->target->linesize[0]; s = td->source->data[0] + y * td->source->linesize[0]; - for (x = 0; x < linesize; x++) { + for (x = 0; x < width; x++) { *t = (*t * t_mul + *s * s_mul) >> 8; t++; s++; } -- 2.52.0 >From 30ed485715e9fe7c848ffce7234f571a3b7c0efc Mon Sep 17 00:00:00 2001 From: Michael Niedermayer <[email protected]> Date: Mon, 12 Oct 2026 02:30:15 +0200 Subject: [PATCH 17/24] avfilter/motion_estimation: use separate linesizes for the current and reference frame Fixes: out of array read Fixes: Au41rSBM5kGS Found during triage of the review of https://code.ffmpeg.org/FFmpeg/FFmpeg/pulls/24765 Out of array read Replicated through UnModified FFmpeg with ASAN --- libavfilter/motion_estimation.c | 9 +++++---- libavfilter/motion_estimation.h | 2 +- libavfilter/vf_mestimate.c | 5 +++-- libavfilter/vf_minterpolate.c | 25 +++++++++++++++---------- 4 files changed, 24 insertions(+), 17 deletions(-) diff --git a/libavfilter/motion_estimation.c b/libavfilter/motion_estimation.c index 2bf5ce6155..a275e2bd6f 100644 --- a/libavfilter/motion_estimation.c +++ b/libavfilter/motion_estimation.c @@ -59,18 +59,19 @@ void ff_me_init_context(AVMotionEstContext *me_ctx, int mb_size, int search_para uint64_t ff_me_cmp_sad(AVMotionEstContext *me_ctx, int x_mb, int y_mb, int x_mv, int y_mv) { - const int linesize = me_ctx->linesize; + const int linesize_ref = me_ctx->linesize_ref; + const int linesize_cur = me_ctx->linesize_cur; uint8_t *data_ref = me_ctx->data_ref; uint8_t *data_cur = me_ctx->data_cur; uint64_t sad = 0; int i, j; - data_ref += y_mv * linesize; - data_cur += y_mb * linesize; + data_ref += y_mv * linesize_ref; + data_cur += y_mb * linesize_cur; for (j = 0; j < me_ctx->mb_size; j++) for (i = 0; i < me_ctx->mb_size; i++) - sad += FFABS(data_ref[x_mv + i + j * linesize] - data_cur[x_mb + i + j * linesize]); + sad += FFABS(data_ref[x_mv + i + j * linesize_ref] - data_cur[x_mb + i + j * linesize_cur]); return sad; } diff --git a/libavfilter/motion_estimation.h b/libavfilter/motion_estimation.h index be627ec3b0..e5f69bec4a 100644 --- a/libavfilter/motion_estimation.h +++ b/libavfilter/motion_estimation.h @@ -40,7 +40,7 @@ typedef struct AVMotionEstPredictor { typedef struct AVMotionEstContext { uint8_t *data_cur, *data_ref; - int linesize; + int linesize_cur, linesize_ref; int mb_size; int search_param; diff --git a/libavfilter/vf_mestimate.c b/libavfilter/vf_mestimate.c index 759883df45..6c71a309f0 100644 --- a/libavfilter/vf_mestimate.c +++ b/libavfilter/vf_mestimate.c @@ -184,10 +184,11 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *frame) } me_ctx->data_cur = s->cur->data[0]; - me_ctx->linesize = s->cur->linesize[0]; + me_ctx->linesize_cur = s->cur->linesize[0]; for (dir = 0; dir < nb_dirs; dir++) { - me_ctx->data_ref = (dir ? s->next : s->prev)->data[0]; + me_ctx->data_ref = (dir ? s->next : s->prev)->data[0]; + me_ctx->linesize_ref = (dir ? s->next : s->prev)->linesize[0]; if (s->method == AV_ME_METHOD_DS) SEARCH_MV(ds); diff --git a/libavfilter/vf_minterpolate.c b/libavfilter/vf_minterpolate.c index c996713553..75bffd4bf5 100644 --- a/libavfilter/vf_minterpolate.c +++ b/libavfilter/vf_minterpolate.c @@ -251,7 +251,8 @@ static uint64_t get_sbad(AVMotionEstContext *me_ctx, int x, int y, int x_mv, int { uint8_t *data_cur = me_ctx->data_cur; uint8_t *data_next = me_ctx->data_ref; - int linesize = me_ctx->linesize; + int linesize_cur = me_ctx->linesize_cur; + int linesize_next = me_ctx->linesize_ref; int mv_x1 = x_mv - x; int mv_y1 = y_mv - y; int mv_x, mv_y, i, j; @@ -262,12 +263,12 @@ static uint64_t get_sbad(AVMotionEstContext *me_ctx, int x, int y, int x_mv, int mv_x = av_clip(x_mv - x, -FFMIN(x - me_ctx->x_min, me_ctx->x_max - x), FFMIN(x - me_ctx->x_min, me_ctx->x_max - x)); mv_y = av_clip(y_mv - y, -FFMIN(y - me_ctx->y_min, me_ctx->y_max - y), FFMIN(y - me_ctx->y_min, me_ctx->y_max - y)); - data_cur += (y + mv_y) * linesize; - data_next += (y - mv_y) * linesize; + data_cur += (y + mv_y) * linesize_cur; + data_next += (y - mv_y) * linesize_next; for (j = 0; j < me_ctx->mb_size; j++) for (i = 0; i < me_ctx->mb_size; i++) - sbad += FFABS(data_cur[x + mv_x + i + j * linesize] - data_next[x - mv_x + i + j * linesize]); + sbad += FFABS(data_cur[x + mv_x + i + j * linesize_cur] - data_next[x - mv_x + i + j * linesize_next]); return sbad + (FFABS(mv_x1 - me_ctx->pred_x) + FFABS(mv_y1 - me_ctx->pred_y)) * COST_PRED_SCALE; } @@ -276,7 +277,8 @@ static uint64_t get_sbad_ob(AVMotionEstContext *me_ctx, int x, int y, int x_mv, { uint8_t *data_cur = me_ctx->data_cur; uint8_t *data_next = me_ctx->data_ref; - int linesize = me_ctx->linesize; + int linesize_cur = me_ctx->linesize_cur; + int linesize_next = me_ctx->linesize_ref; int x_min = me_ctx->x_min + me_ctx->mb_size / 2; int x_max = me_ctx->x_max - me_ctx->mb_size / 2; int y_min = me_ctx->y_min + me_ctx->mb_size / 2; @@ -293,7 +295,7 @@ static uint64_t get_sbad_ob(AVMotionEstContext *me_ctx, int x, int y, int x_mv, for (j = -me_ctx->mb_size / 2; j < me_ctx->mb_size * 3 / 2; j++) for (i = -me_ctx->mb_size / 2; i < me_ctx->mb_size * 3 / 2; i++) - sbad += FFABS(data_cur[x + mv_x + i + (y + mv_y + j) * linesize] - data_next[x - mv_x + i + (y - mv_y + j) * linesize]); + sbad += FFABS(data_cur[x + mv_x + i + (y + mv_y + j) * linesize_cur] - data_next[x - mv_x + i + (y - mv_y + j) * linesize_next]); return sbad + (FFABS(mv_x1 - me_ctx->pred_x) + FFABS(mv_y1 - me_ctx->pred_y)) * COST_PRED_SCALE; } @@ -302,7 +304,8 @@ static uint64_t get_sad_ob(AVMotionEstContext *me_ctx, int x, int y, int x_mv, i { uint8_t *data_ref = me_ctx->data_ref; uint8_t *data_cur = me_ctx->data_cur; - int linesize = me_ctx->linesize; + int linesize_ref = me_ctx->linesize_ref; + int linesize_cur = me_ctx->linesize_cur; int x_min = me_ctx->x_min + me_ctx->mb_size / 2; int x_max = me_ctx->x_max - me_ctx->mb_size / 2; int y_min = me_ctx->y_min + me_ctx->mb_size / 2; @@ -319,7 +322,7 @@ static uint64_t get_sad_ob(AVMotionEstContext *me_ctx, int x, int y, int x_mv, i for (j = -me_ctx->mb_size / 2; j < me_ctx->mb_size * 3 / 2; j++) for (i = -me_ctx->mb_size / 2; i < me_ctx->mb_size * 3 / 2; i++) - sad += FFABS(data_ref[x_mv + i + (y_mv + j) * linesize] - data_cur[x + i + (y + j) * linesize]); + sad += FFABS(data_ref[x_mv + i + (y_mv + j) * linesize_ref] - data_cur[x + i + (y + j) * linesize_cur]); return sad + (FFABS(mv_x - me_ctx->pred_x) + FFABS(mv_y - me_ctx->pred_y)) * COST_PRED_SCALE; } @@ -753,7 +756,8 @@ static int inject_frame(AVFilterLink *inlink, AVFrame *avf_in) if (mi_ctx->frames[1].avf) { for (dir = 0; dir < 2; dir++) { - mi_ctx->me_ctx.linesize = mi_ctx->frames[2].avf->linesize[0]; + mi_ctx->me_ctx.linesize_cur = mi_ctx->frames[2].avf->linesize[0]; + mi_ctx->me_ctx.linesize_ref = mi_ctx->frames[dir ? 3 : 1].avf->linesize[0]; mi_ctx->me_ctx.data_cur = mi_ctx->frames[2].avf->data[0]; mi_ctx->me_ctx.data_ref = mi_ctx->frames[dir ? 3 : 1].avf->data[0]; @@ -770,7 +774,8 @@ static int inject_frame(AVFilterLink *inlink, AVFrame *avf_in) if (!mi_ctx->frames[0].avf) return 0; - mi_ctx->me_ctx.linesize = mi_ctx->frames[0].avf->linesize[0]; + mi_ctx->me_ctx.linesize_cur = mi_ctx->frames[1].avf->linesize[0]; + mi_ctx->me_ctx.linesize_ref = mi_ctx->frames[2].avf->linesize[0]; mi_ctx->me_ctx.data_cur = mi_ctx->frames[1].avf->data[0]; mi_ctx->me_ctx.data_ref = mi_ctx->frames[2].avf->data[0]; -- 2.52.0 >From a39ea8d56ec644201b142e782ae2a13b07dbd7ca Mon Sep 17 00:00:00 2001 From: Michael Niedermayer <[email protected]> Date: Mon, 12 Oct 2026 02:32:19 +0200 Subject: [PATCH 18/24] avfilter/vf_drawbox: check the expression results before converting them to int Fixes: out of range float to int conversion Fixes: signed integer overflow Fixes: 4jtp2TTOoEsQ Found during triage of the review of https://code.ffmpeg.org/FFmpeg/FFmpeg/pulls/24765 Out of range float to int conversion Replicated through UnModified FFmpeg with UBSAN Signed integer overflow Replicated through UnModified FFmpeg with UBSAN --- libavfilter/vf_drawbox.c | 26 +++++++++++++++++++------- 1 file changed, 19 insertions(+), 7 deletions(-) diff --git a/libavfilter/vf_drawbox.c b/libavfilter/vf_drawbox.c index ec409603d3..cd2b55a7c7 100644 --- a/libavfilter/vf_drawbox.c +++ b/libavfilter/vf_drawbox.c @@ -309,37 +309,49 @@ static int config_input(AVFilterLink *inlink) var_names, var_values, NULL, NULL, NULL, NULL, NULL, 0, ctx)) < 0 && i == NUM_EXPR_EVALS) goto fail; - s->x = var_values[VAR_X] = res; + var_values[VAR_X] = res; var_values[VAR_MAX] = inlink->h; if ((ret = av_expr_parse_and_eval(&res, (expr = s->y_expr), var_names, var_values, NULL, NULL, NULL, NULL, NULL, 0, ctx)) < 0 && i == NUM_EXPR_EVALS) goto fail; - s->y = var_values[VAR_Y] = res; + var_values[VAR_Y] = res; - var_values[VAR_MAX] = inlink->w - s->x; + var_values[VAR_MAX] = inlink->w - trunc(var_values[VAR_X]); if ((ret = av_expr_parse_and_eval(&res, (expr = s->w_expr), var_names, var_values, NULL, NULL, NULL, NULL, NULL, 0, ctx)) < 0 && i == NUM_EXPR_EVALS) goto fail; - s->w = var_values[VAR_W] = res; + var_values[VAR_W] = res; - var_values[VAR_MAX] = inlink->h - s->y; + var_values[VAR_MAX] = inlink->h - trunc(var_values[VAR_Y]); if ((ret = av_expr_parse_and_eval(&res, (expr = s->h_expr), var_names, var_values, NULL, NULL, NULL, NULL, NULL, 0, ctx)) < 0 && i == NUM_EXPR_EVALS) goto fail; - s->h = var_values[VAR_H] = res; + var_values[VAR_H] = res; var_values[VAR_MAX] = INT_MAX; if ((ret = av_expr_parse_and_eval(&res, (expr = s->t_expr), var_names, var_values, NULL, NULL, NULL, NULL, NULL, 0, ctx)) < 0 && i == NUM_EXPR_EVALS) goto fail; - s->thickness = var_values[VAR_T] = res; + var_values[VAR_T] = res; } + if (!(fabs(var_values[VAR_X]) <= INT_MAX / 4 && fabs(var_values[VAR_Y]) <= INT_MAX / 4 && + fabs(var_values[VAR_W]) <= INT_MAX / 4 && fabs(var_values[VAR_H]) <= INT_MAX / 4 && + fabs(var_values[VAR_T]) <= INT_MAX)) { + av_log(ctx, AV_LOG_ERROR, "Position, size or thickness out of range.\n"); + return AVERROR(EINVAL); + } + s->x = var_values[VAR_X]; + s->y = var_values[VAR_Y]; + s->w = var_values[VAR_W]; + s->h = var_values[VAR_H]; + s->thickness = var_values[VAR_T]; + /* if w or h are zero, use the input w/h */ s->w = (s->w > 0) ? s->w : inlink->w; s->h = (s->h > 0) ? s->h : inlink->h; -- 2.52.0 >From 642bbfacde9ac93bfa8bb85b5fdbe8f1eaa26e35 Mon Sep 17 00:00:00 2001 From: Michael Niedermayer <[email protected]> Date: Mon, 12 Oct 2026 02:41:46 +0200 Subject: [PATCH 19/24] avfilter/dnn_backend_openvino: set the number of outputs together with the output ports Fixes: NULL pointer dereference Fixes: gJMHsT6GErl5 Regression since: 22652b576c Found during triage of the review of https://code.ffmpeg.org/FFmpeg/FFmpeg/pulls/24617 NULL pointer dereference Replicated through UnModified FFmpeg with ASAN --- libavfilter/dnn/dnn_backend_openvino.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libavfilter/dnn/dnn_backend_openvino.c b/libavfilter/dnn/dnn_backend_openvino.c index 4a372f5f54..9eea57b596 100644 --- a/libavfilter/dnn/dnn_backend_openvino.c +++ b/libavfilter/dnn/dnn_backend_openvino.c @@ -682,7 +682,6 @@ static int init_model_ov(OVModel *ov_model, const char *input_name, const char * } nb_outputs = output_size; } - ov_model->nb_outputs = nb_outputs; for (int i = 0; i < nb_outputs; i++) { if (output_names) status = ov_preprocess_prepostprocessor_get_output_info_by_name( @@ -764,6 +763,7 @@ static int init_model_ov(OVModel *ov_model, const char *input_name, const char * ret = AVERROR(ENOMEM); goto err; } + ov_model->nb_outputs = nb_outputs; } else for (int i = 0; i < nb_outputs; i++) { ov_output_const_port_free(ov_model->output_ports[i]); -- 2.52.0 >From 126bf8599176340a56d7de063d2405de7da7a364 Mon Sep 17 00:00:00 2001 From: Michael Niedermayer <[email protected]> Date: Mon, 12 Oct 2026 02:42:03 +0200 Subject: [PATCH 20/24] avfilter/dnn_backend_openvino: do not free the model when updating it fails Fixes: double free Fixes: QIOnvFKEz80N Regression since: 22652b576c Found during triage of the review of https://code.ffmpeg.org/FFmpeg/FFmpeg/pulls/24617 Double free Replicated through UnModified FFmpeg with ASAN --- libavfilter/dnn/dnn_backend_openvino.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/libavfilter/dnn/dnn_backend_openvino.c b/libavfilter/dnn/dnn_backend_openvino.c index 9eea57b596..808adc0b35 100644 --- a/libavfilter/dnn/dnn_backend_openvino.c +++ b/libavfilter/dnn/dnn_backend_openvino.c @@ -749,8 +749,6 @@ static int init_model_ov(OVModel *ov_model, const char *input_name, const char * status = ov_preprocess_prepostprocessor_build(ov_model->preprocess, &ov_model->ov_model); if (status != OK) { av_log(ctx, AV_LOG_ERROR, "Failed to update OV model\n"); - ov_model_free(tmp_ov_model); - tmp_ov_model = NULL; ret = ov2_map_error(status, NULL); goto err; } -- 2.52.0 >From 101ab7ff65c74fe4e879b8d9e0264b72c4cb808c Mon Sep 17 00:00:00 2001 From: Michael Niedermayer <[email protected]> Date: Mon, 12 Oct 2026 02:48:35 +0200 Subject: [PATCH 21/24] avutil/hwcontext_cuda: copy only the bytes of the visible rows Fixes: out of array access Fixes: ZqshmgSdN2Q2 Found during triage of the review of https://code.ffmpeg.org/FFmpeg/FFmpeg/pulls/24595 Out of array read and write Replicated through API with ASAN Out of array read Replicated through UnModified FFmpeg with a guard page allocator --- libavutil/hwcontext_cuda.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/libavutil/hwcontext_cuda.c b/libavutil/hwcontext_cuda.c index 0ee6bb4945..776c321652 100644 --- a/libavutil/hwcontext_cuda.c +++ b/libavutil/hwcontext_cuda.c @@ -567,10 +567,16 @@ static int cuda_transfer_data(AVHWFramesContext *ctx, AVFrame *dst, int src_is_nonplanar_cuarray = 0; int dst_is_nonplanar_cuarray = 0; + int bytewidth = av_image_get_linesize(ctx->sw_format, src->width, i); + if (bytewidth < 0) { + ret = bytewidth; + goto fail; + } + CUDA_MEMCPY2D cpy = { .srcPitch = src->linesize[i], .dstPitch = dst->linesize[i], - .WidthInBytes = FFMIN(src->linesize[i], dst->linesize[i]), + .WidthInBytes = bytewidth, .Height = AV_CEIL_RSHIFT(src->height, ((i == 0 || i == 3) ? 0 : priv->shift_height)), }; -- 2.52.0 >From c98957e999084dc05d3e3e24bb2434b0982f59db Mon Sep 17 00:00:00 2001 From: Michael Niedermayer <[email protected]> Date: Mon, 12 Oct 2026 03:52:42 +0200 Subject: [PATCH 22/24] avcodec: declare support for parameter changes in the rawvideo and wrapped_avframe encoders Both encoders take the size and format of every frame from the frame itself. --- libavcodec/rawenc.c | 2 +- libavcodec/wrapped_avframe.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/libavcodec/rawenc.c b/libavcodec/rawenc.c index 8c577006d9..97726db599 100644 --- a/libavcodec/rawenc.c +++ b/libavcodec/rawenc.c @@ -87,7 +87,7 @@ const FFCodec ff_rawvideo_encoder = { .p.type = AVMEDIA_TYPE_VIDEO, .p.id = AV_CODEC_ID_RAWVIDEO, .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_FRAME_THREADS | - AV_CODEC_CAP_ENCODER_REORDERED_OPAQUE, + AV_CODEC_CAP_ENCODER_REORDERED_OPAQUE | AV_CODEC_CAP_PARAM_CHANGE, .init = raw_encode_init, FF_CODEC_ENCODE_CB(raw_encode), }; diff --git a/libavcodec/wrapped_avframe.c b/libavcodec/wrapped_avframe.c index a513bb3d39..751ab4f346 100644 --- a/libavcodec/wrapped_avframe.c +++ b/libavcodec/wrapped_avframe.c @@ -108,7 +108,7 @@ const FFCodec ff_wrapped_avframe_encoder = { CODEC_LONG_NAME("AVFrame to AVPacket passthrough"), .p.type = AVMEDIA_TYPE_VIDEO, .p.id = AV_CODEC_ID_WRAPPED_AVFRAME, - .p.capabilities = AV_CODEC_CAP_ENCODER_REORDERED_OPAQUE, + .p.capabilities = AV_CODEC_CAP_ENCODER_REORDERED_OPAQUE | AV_CODEC_CAP_PARAM_CHANGE, FF_CODEC_ENCODE_CB(wrapped_avframe_encode), }; -- 2.52.0 >From 8bf6bdd78dcdf8152d586c5ed4ee6c1a55b83fe8 Mon Sep 17 00:00:00 2001 From: Michael Niedermayer <[email protected]> Date: Mon, 12 Oct 2026 04:01:02 +0200 Subject: [PATCH 23/24] avcodec/encode: reject video frames that do not match the encoder Fixes: out of array read Fixes: DdI1HfjoEG1l Found during triage of the review of https://code.ffmpeg.org/FFmpeg/FFmpeg/pulls/24765 Out of array read Replicated through UnModified FFmpeg with ASAN --- libavcodec/encode.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/libavcodec/encode.c b/libavcodec/encode.c index 6fbbe86d8f..fd503f01e1 100644 --- a/libavcodec/encode.c +++ b/libavcodec/encode.c @@ -518,6 +518,15 @@ static int encode_send_frame_internal(AVCodecContext *avctx, const AVFrame *src) } } } + } else if (!(avctx->codec->capabilities & AV_CODEC_CAP_PARAM_CHANGE)) { + const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(src->format); + + if (!(desc && desc->flags & AV_PIX_FMT_FLAG_HWACCEL) && + (src->format != avctx->pix_fmt || + src->width < avctx->width || src->height < avctx->height)) { + av_log(avctx, AV_LOG_ERROR, "Frame size or pixel format does not match the encoder\n"); + return AVERROR(EINVAL); + } } ret = av_frame_ref(dst, src); -- 2.52.0 >From 52da53a88c569c90a7e4e3e11f0c209980d30cd6 Mon Sep 17 00:00:00 2001 From: Michael Niedermayer <[email protected]> Date: Mon, 12 Oct 2026 04:06:17 +0200 Subject: [PATCH 24/24] swscale: reject planes whose size does not fit in int Fixes: signed integer overflow Fixes: out of array access Fixes: pdA1vTaOO5Be Found during the review of https://code.ffmpeg.org/FFmpeg/FFmpeg/pulls/24851 Signed integer overflow Replicated through API with UBSAN Out of array access Replicated through API with ASAN --- libswscale/swscale.c | 25 +++++++++++++++++++------ 1 file changed, 19 insertions(+), 6 deletions(-) diff --git a/libswscale/swscale.c b/libswscale/swscale.c index 070b0f5939..1ed59c4bad 100644 --- a/libswscale/swscale.c +++ b/libswscale/swscale.c @@ -726,7 +726,7 @@ static void reset_ptr(const uint8_t *src[], enum AVPixelFormat format) } static int check_image_pointers(const uint8_t * const data[4], enum AVPixelFormat pix_fmt, - const int linesizes[4]) + const int linesizes[4], int h) { const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(pix_fmt); int i; @@ -735,7 +735,7 @@ static int check_image_pointers(const uint8_t * const data[4], enum AVPixelForma for (i = 0; i < 4; i++) { int plane = desc->comp[i].plane; - if (!data[plane] || !linesizes[plane]) + if (!data[plane] || !linesizes[plane] || FFABS((int64_t)linesizes[plane]) * h > INT_MAX) return 0; } @@ -1060,12 +1060,12 @@ static int scale_internal(SwsContext *sws, return AVERROR(EINVAL); } - if (!check_image_pointers(srcSlice, sws->src_format, srcStride)) { - av_log(c, AV_LOG_ERROR, "bad src image pointers\n"); + if (!check_image_pointers(srcSlice, sws->src_format, srcStride, sws->src_h)) { + av_log(c, AV_LOG_ERROR, "bad src image pointers or strides\n"); return AVERROR(EINVAL); } - if (!check_image_pointers((const uint8_t* const*)dstSlice, sws->dst_format, dstStride)) { - av_log(c, AV_LOG_ERROR, "bad dst image pointers\n"); + if (!check_image_pointers((const uint8_t* const*)dstSlice, sws->dst_format, dstStride, sws->dst_h)) { + av_log(c, AV_LOG_ERROR, "bad dst image pointers or strides\n"); return AVERROR(EINVAL); } @@ -1402,6 +1402,14 @@ int sws_receive_slice(SwsContext *sws, unsigned int slice_start, dst, c->frame_dst->linesize, slice_start, slice_height); } +static int frame_strides_fit(const AVFrame *frame) +{ + for (int i = 0; i < FF_ARRAY_ELEMS(frame->linesize); i++) + if (FFABS((int64_t)frame->linesize[i]) * frame->height > INT_MAX) + return 0; + return 1; +} + int sws_scale_frame(SwsContext *sws, AVFrame *dst, const AVFrame *src) { int ret, allocated = 0; @@ -1432,6 +1440,11 @@ int sws_scale_frame(SwsContext *sws, AVFrame *dst, const AVFrame *src) if (!src->data[0]) return 0; + if (!frame_strides_fit(src) || !frame_strides_fit(dst)) { + av_log(sws, AV_LOG_ERROR, "Frame planes larger than INT_MAX bytes are not supported\n"); + return AVERROR(EINVAL); + } + const SwsGraph *top = c->graph[FIELD_TOP]; const SwsGraph *bot = c->graph[FIELD_BOTTOM]; if (dst->data[0]) /* user-provided buffers */ -- 2.52.0 _______________________________________________ ffmpeg-devel mailing list -- [email protected] To unsubscribe send an email to [email protected]
