PR #24677 opened by michaelni URL: https://code.ffmpeg.org/FFmpeg/FFmpeg/pulls/24677 Patch URL: https://code.ffmpeg.org/FFmpeg/FFmpeg/pulls/24677.patch
Fixes: stack buffer overflow Fixes: CJwFCf3E6R4m Fixes: ANT-2026-5C280R3A Fixes: ANT-2026-5C280R3A-attack_a.flv Fixes: ANT-2026-5C280R3A-attack_b.flv See: #22956 Regression since: baad75cafa Found-by: Claude and Ada Logics >From 3ffa89e92f76beac513b6491e11aa138ce96755c Mon Sep 17 00:00:00 2001 From: Michael Niedermayer <[email protected]> Date: Thu, 24 Sep 2026 18:47:27 +0200 Subject: [PATCH 1/3] avcodec/aac: export push_output_configuration() and pop_output_configuration() The USAC decoder needs them to make its in-band configuration updates transactional. --- libavcodec/aac/aacdec.c | 16 ++++++++-------- libavcodec/aac/aacdec.h | 3 +++ libavcodec/aac/aacdec_latm.h | 4 ++-- 3 files changed, 13 insertions(+), 10 deletions(-) diff --git a/libavcodec/aac/aacdec.c b/libavcodec/aac/aacdec.c index fdebe139c3..c53a58aa4d 100644 --- a/libavcodec/aac/aacdec.c +++ b/libavcodec/aac/aacdec.c @@ -451,7 +451,7 @@ static void copy_oc(OutputConfiguration *dst, OutputConfiguration *src) /** * Save current output configuration if and only if it has been locked. */ -static int push_output_configuration(AACDecContext *ac) +int ff_aac_push_output_configuration(AACDecContext *ac) { int pushed = 0; @@ -467,7 +467,7 @@ static int push_output_configuration(AACDecContext *ac) * Restore the previous output configuration if and only if the current * configuration is unlocked. */ -static void pop_output_configuration(AACDecContext *ac) +void ff_aac_pop_output_configuration(AACDecContext *ac) { if (ac->oc[1].status != OC_LOCKED && ac->oc[0].status != OC_NONE) { copy_oc(&ac->oc[1], &ac->oc[0]); @@ -632,7 +632,7 @@ ChannelElement *ff_aac_get_che(AACDecContext *ac, int type, int elem_id) ac->oc[1].m4ac.chan_config == 1) { uint8_t layout_map[MAX_ELEM_ID*4][3]; int layout_map_tags; - push_output_configuration(ac); + ff_aac_push_output_configuration(ac); av_log(ac->avctx, AV_LOG_DEBUG, "mono with CPE\n"); @@ -651,7 +651,7 @@ ChannelElement *ff_aac_get_che(AACDecContext *ac, int type, int elem_id) ac->oc[1].m4ac.chan_config == 2) { uint8_t layout_map[MAX_ELEM_ID * 4][3]; int layout_map_tags; - push_output_configuration(ac); + ff_aac_push_output_configuration(ac); av_log(ac->avctx, AV_LOG_DEBUG, "stereo with SCE\n"); @@ -2205,7 +2205,7 @@ static int parse_adts_frame_header(AACDecContext *ac, GetBitContext *gb) "More than one AAC RDB per ADTS frame"); ac->warned_num_aac_frames = 1; } - push_output_configuration(ac); + ff_aac_push_output_configuration(ac); if (hdr_info.chan_config) { ac->oc[1].m4ac.chan_config = hdr_info.chan_config; if ((ret = ff_aac_set_default_channel_config(ac, ac->avctx, @@ -2396,7 +2396,7 @@ static int decode_frame_ga(AVCodecContext *avctx, AACDecContext *ac, uint8_t layout_map[MAX_ELEM_ID*4][3] = {{0}}; int tags; - int pushed = push_output_configuration(ac); + int pushed = ff_aac_push_output_configuration(ac); if (pce_found && !pushed) return AVERROR_INVALIDDATA; @@ -2409,7 +2409,7 @@ static int decode_frame_ga(AVCodecContext *avctx, AACDecContext *ac, if (pce_found) { av_log(avctx, AV_LOG_ERROR, "Not evaluating a further program_config_element as this construct is dubious at best.\n"); - pop_output_configuration(ac); + ff_aac_pop_output_configuration(ac); } else { err = ff_aac_output_configure(ac, layout_map, tags, OC_TRIAL_PCE, 1); if (!err) @@ -2557,7 +2557,7 @@ static int aac_decode_frame_int(AVCodecContext *avctx, AVFrame *frame, return err; fail: - pop_output_configuration(ac); + ff_aac_pop_output_configuration(ac); return err; } diff --git a/libavcodec/aac/aacdec.h b/libavcodec/aac/aacdec.h index 18412fb97a..7588855ae1 100644 --- a/libavcodec/aac/aacdec.h +++ b/libavcodec/aac/aacdec.h @@ -617,4 +617,7 @@ int ff_aac_output_configure(AACDecContext *ac, ChannelElement *ff_aac_get_che(AACDecContext *ac, int type, int elem_id); +int ff_aac_push_output_configuration(AACDecContext *ac); +void ff_aac_pop_output_configuration(AACDecContext *ac); + #endif /* AVCODEC_AAC_AACDEC_H */ diff --git a/libavcodec/aac/aacdec_latm.h b/libavcodec/aac/aacdec_latm.h index 398d40741b..f79996c973 100644 --- a/libavcodec/aac/aacdec_latm.h +++ b/libavcodec/aac/aacdec_latm.h @@ -280,11 +280,11 @@ static int latm_decode_frame(AVCodecContext *avctx, AVFrame *out, *got_frame_ptr = 0; return avpkt->size; } else { - push_output_configuration(&latmctx->aac_ctx); + ff_aac_push_output_configuration(&latmctx->aac_ctx); if ((err = decode_audio_specific_config( &latmctx->aac_ctx, avctx, &latmctx->aac_ctx.oc[1], avctx->extradata, avctx->extradata_size*8LL, 1)) < 0) { - pop_output_configuration(&latmctx->aac_ctx); + ff_aac_pop_output_configuration(&latmctx->aac_ctx); return err; } latmctx->initialized = 1; -- 2.52.0 >From 1c0f645ca1096eccfbafdb5df92ad3ba858bcd60 Mon Sep 17 00:00:00 2001 From: Michael Niedermayer <[email protected]> Date: Thu, 24 Sep 2026 18:47:38 +0200 Subject: [PATCH 2/3] avcodec/aac: restore the previous configuration when an in-band configuration update fails Fixes: stack buffer overflow Fixes: CJwFCf3E6R4m Fixes: ANT-2026-5C280R3A Fixes: ANT-2026-5C280R3A-attack_a.flv Fixes: ANT-2026-5C280R3A-attack_b.flv See: https://code.ffmpeg.org/FFmpeg/FFmpeg/issues/22956 Regression since: baad75cafa Found-by: Claude and Ada Logics --- libavcodec/aac/aacdec.c | 4 ++-- libavcodec/aac/aacdec_usac.c | 3 ++- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/libavcodec/aac/aacdec.c b/libavcodec/aac/aacdec.c index c53a58aa4d..bd4dfc64e5 100644 --- a/libavcodec/aac/aacdec.c +++ b/libavcodec/aac/aacdec.c @@ -2581,12 +2581,12 @@ static int aac_decode_frame(AVCodecContext *avctx, AVFrame *frame, &jp_dualmono_size); if (new_extradata) { - /* discard previous configuration */ - ac->oc[1].status = OC_NONE; + ff_aac_push_output_configuration(ac); err = decode_audio_specific_config(ac, ac->avctx, &ac->oc[1], new_extradata, new_extradata_size * 8LL, 1); if (err < 0) { + ff_aac_pop_output_configuration(ac); return err; } } diff --git a/libavcodec/aac/aacdec_usac.c b/libavcodec/aac/aacdec_usac.c index 00b4d4586d..d3bf09345a 100644 --- a/libavcodec/aac/aacdec_usac.c +++ b/libavcodec/aac/aacdec_usac.c @@ -1904,9 +1904,10 @@ static int parse_audio_preroll(AACDecContext *ac, GetBitContext *gb) /* Implementations are free to pad the config to any length, so use a * different reader for this. */ gbc = *gb; + ff_aac_push_output_configuration(ac); ret = ff_aac_usac_config_decode(ac, ac->avctx, &gbc, oc, m4ac->chan_config); if (ret < 0) { - *m4ac = m4ac_bak; + ff_aac_pop_output_configuration(ac); return ret; } else { ac->oc[1].m4ac.chan_config = 0; -- 2.52.0 >From f2a0e1a4faa89a35995ccf5d42a949d9be1d0134 Mon Sep 17 00:00:00 2001 From: Michael Niedermayer <[email protected]> Date: Thu, 24 Sep 2026 19:17:46 +0200 Subject: [PATCH 3/3] avcodec/aac/aacdec_usac: check the return value of ff_aac_output_configure() ff_aac_usac_decode_frame() went on decoding the frame after the output configuration failed. Found during triage/review of a security report. --- libavcodec/aac/aacdec_usac.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/libavcodec/aac/aacdec_usac.c b/libavcodec/aac/aacdec_usac.c index d3bf09345a..6ba7b7ded1 100644 --- a/libavcodec/aac/aacdec_usac.c +++ b/libavcodec/aac/aacdec_usac.c @@ -2082,8 +2082,10 @@ int ff_aac_usac_decode_frame(AVCodecContext *avctx, AACDecContext *ac, ratio_dec = 1; } - ff_aac_output_configure(ac, ac->oc[1].layout_map, ac->oc[1].layout_map_tags, - ac->oc[1].status, 0); + ret = ff_aac_output_configure(ac, ac->oc[1].layout_map, ac->oc[1].layout_map_tags, + ac->oc[1].status, 0); + if (ret < 0) + return ret; ac->avctx->profile = AV_PROFILE_AAC_USAC; -- 2.52.0 _______________________________________________ ffmpeg-devel mailing list -- [email protected] To unsubscribe send an email to [email protected]
