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]

Reply via email to