PR #23997 opened by akshaver
URL: https://code.ffmpeg.org/FFmpeg/FFmpeg/pulls/23997
Patch URL: https://code.ffmpeg.org/FFmpeg/FFmpeg/pulls/23997.patch

Backport six CVE fixes from master to release/8.1. Every commit is a plain
`git cherry-pick -x` of a commit already in the tree — no code was adapted, and
all six apply to `release/8.1` with zero conflicts and zero fuzz
(`patch --fuzz=0`, exact context match).

| CVE | Component | master | release/9.0 |
| --- | --- | --- | --- |
| CVE-2026-64830 | vobsub demuxer (`libavformat/mpeg.c`) | `dbd495f066` | 
`dcf8ce2802` |
| CVE-2026-64831 | Vulkan HEVC hwaccel | `92737390dc` | `3d129a4a85` |
| CVE-2026-64832 | NVDEC double-free (`libavcodec/nvdec.c`) | `4c6217477f` | 
`3d5ad47c40` |
| CVE-2026-64833 | S/PDIF muxer (`libavformat/spdifenc.c`) | `6f80e27654` | 
`385ac2fadc` |
| CVE-2026-64834 | RTP/ASF demuxer (`libavformat/rtpdec_asf.c`) | `11d5f475be` 
| `3c441711a3` |
| CVE-2026-64835 | ADX decoder (`libavcodec/adxdec.c`) | `1836ef9684` | 
`c10e7f5dc1` |

The `release/9.0` commit is the one cherry-picked here; each carries both
`(cherry picked from commit ...)` trailers, so the full provenance chain back to
master is in the commit messages.

### Why release/8.1

All six advisories are scoped "through 8.1.2", and 8.1.2 is the current 8.1
point release, so the whole 8.1 line is affected. The fixes reached master
between 2026-07-02 and 2026-07-05 and were backported to `release/9.0`, but
`release/8.1` has not picked them up.

Against `doc/developer.texi` "Criteria for Point Releases", the rule being
(1 OR 2 OR 3) AND 4:

* **(1)** each fixes a security issue identified by a CVE number;
* **(4)** source and binary compatibility are retained — these are bounds and
  state checks in existing functions, no public interface changes, and the
  `LIBAV*_VERSION_*` macros are untouched, so SONAMEs do not move.

### Size

Small and defensive rather than structural — four are five added lines or
fewer, and 0003 is a net deletion:

| Patch | Δ |
| --- | --- |
| 0001 vobsub | +16 −2 |
| 0002 vulkan_hevc | +3 −0 |
| 0003 nvdec | +1 −5 |
| 0004 spdifenc | +1 −1 |
| 0005 rtpdec_asf | +2 −0 |
| 0006 adxdec | +5 −0 |

### Testing

`release/8.1` + these six configures and builds cleanly (Debian bookworm, gcc
12, `--disable-x86asm --enable-demuxers --enable-muxers --enable-decoders
--enable-parsers`).

I have also been running the equivalent patch set on top of the 8.1.2 release
tarball in a downstream product build, on both x86_64 and aarch64, with the
component set unchanged and audio decode verified end to end.



From 4fe710047d633ddd7a126352ce0f5f505a0fe843 Mon Sep 17 00:00:00 2001
From: Pavel Kohout <[email protected]>
Date: Mon, 29 Jun 2026 23:30:41 +0200
Subject: [PATCH 1/6] avformat/vobsub: reuse subtitle streams and bound the
 stream count

Fixes: heap buffer overflow
Fixes: lqaO5R1BaZGO
Fixes: dbfe61100b (avformat/vobsub: fix several issues.)
Found-by: Pavel Kohout (Aisle Research)
Signed-off-by: Michael Niedermayer <[email protected]>
(cherry picked from commit dbd495f066a85ba96b17433f4306582aa37c3951)
Signed-off-by: Michael Niedermayer <[email protected]>
(cherry picked from commit dcf8ce2802bf2be1b0c6b8d4996abca7b669978d)
Signed-off-by: Adam Shaver <[email protected]>
---
 libavformat/mpeg.c | 18 ++++++++++++++++--
 1 file changed, 16 insertions(+), 2 deletions(-)

diff --git a/libavformat/mpeg.c b/libavformat/mpeg.c
index a7a2ef78e6..1ce4bf9d46 100644
--- a/libavformat/mpeg.c
+++ b/libavformat/mpeg.c
@@ -841,6 +841,20 @@ static int vobsub_read_header(AVFormatContext *s)
             }
 
             if (!st || st->id != stream_id) {
+                st = NULL;
+                for (i = 0; i < s->nb_streams; i++) {
+                    if (s->streams[i]->id == stream_id) {
+                        st = s->streams[i];
+                        break;
+                    }
+                }
+            }
+            if (!st) {
+                if (s->nb_streams >= FF_ARRAY_ELEMS(vobsub->q)) {
+                    av_log(s, AV_LOG_ERROR, "Maximum number of subtitle 
streams reached\n");
+                    ret = AVERROR_INVALIDDATA;
+                    goto end;
+                }
                 st = avformat_new_stream(s, NULL);
                 if (!st) {
                     ret = AVERROR(ENOMEM);
@@ -865,14 +879,14 @@ static int vobsub_read_header(AVFormatContext *s)
             timestamp = (hh*3600LL + mm*60LL + ss) * 1000LL + ms + delay;
             timestamp = av_rescale_q(timestamp, av_make_q(1, 1000), 
st->time_base);
 
-            sub = ff_subtitles_queue_insert(&vobsub->q[s->nb_streams - 1], "", 
0, 0);
+            sub = ff_subtitles_queue_insert(&vobsub->q[st->index], "", 0, 0);
             if (!sub) {
                 ret = AVERROR(ENOMEM);
                 goto end;
             }
             sub->pos = pos;
             sub->pts = timestamp;
-            sub->stream_index = s->nb_streams - 1;
+            sub->stream_index = st->index;
 
         } else if (!strncmp(line, "alt:", 4)) {
             const char *p = line + 4;
-- 
2.52.0


From 6b3015cd92d4a0f96b0511e8110c50ac0dcc9d3a Mon Sep 17 00:00:00 2001
From: Pavel Kohout <[email protected]>
Date: Tue, 30 Jun 2026 21:55:49 +0200
Subject: [PATCH 2/6] avcodec/vulkan_hevc: reject too many VPS HRD parameter
 sets

Fixes: stack buffer overflow
Fixes: tD7Mj0ST7ND3
Fixes: 82864c21112157951ce91b4430a9018edd02f5ab (vulkan_hevc: use 
VK_KHR_video_maintenance2 if available)
Found-by: Pavel Kohout (Aisle Research)
Signed-off-by: Michael Niedermayer <[email protected]>
(cherry picked from commit 92737390dc133daadce47dd7d2ec8ef3d9ebcbed)
(cherry picked from commit 3d129a4a8531e9f7baa8558c7c994b4dd36bcf04)
Signed-off-by: Adam Shaver <[email protected]>
---
 libavcodec/vulkan_hevc.c | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/libavcodec/vulkan_hevc.c b/libavcodec/vulkan_hevc.c
index 8f0d1f6636..9b9264f1cd 100644
--- a/libavcodec/vulkan_hevc.c
+++ b/libavcodec/vulkan_hevc.c
@@ -875,6 +875,9 @@ static int vk_hevc_end_frame(AVCodecContext *avctx)
                 vksps_p.vcl_hdr, &vksps_p.ptl, &vksps_p.dpbm,
                 &vksps_p.pal, vksps_p.str, &vksps_p.ltr);
 
+        if (sps->vps->vps_num_hrd_parameters > HEVC_MAX_SUB_LAYERS)
+            return AVERROR_INVALIDDATA;
+
         vkvps_p.sls = vkvps_ps;
         set_vps(sps->vps, &vkvps, &vkvps_p.ptl, &vkvps_p.dpbm,
                 vkvps_p.hdr, vkvps_p.sls);
-- 
2.52.0


From 9cbcf979a587a66b280496657d00fabe301bf20f Mon Sep 17 00:00:00 2001
From: Michael Niedermayer <[email protected]>
Date: Tue, 30 Jun 2026 00:24:07 +0200
Subject: [PATCH 3/6] avcodec/nvdec: don't double free the fdd-owned context on
 the sep_ref error path

Fixes: double free
Fixes: rpSz7v3yq2u8
Fixes: 72982f8cb5dad6252a14226d28128313eed4a5ff (avcodec/nvdec: add support for 
separate reference frame)
Found-by: Pavel Kohout (Aisle Research)
Signed-off-by: Michael Niedermayer <[email protected]>
(cherry picked from commit 4c6217477fc64305055b37d9d1d0d76d30e37f97)
Signed-off-by: Michael Niedermayer <[email protected]>
(cherry picked from commit 3d5ad47c40436dbdeaaa6601af0bb4575d5aa3c5)
Signed-off-by: Adam Shaver <[email protected]>
---
 libavcodec/nvdec.c | 6 +-----
 1 file changed, 1 insertion(+), 5 deletions(-)

diff --git a/libavcodec/nvdec.c b/libavcodec/nvdec.c
index 7c29f25718..787a9d7c28 100644
--- a/libavcodec/nvdec.c
+++ b/libavcodec/nvdec.c
@@ -628,8 +628,7 @@ int ff_nvdec_start_frame_sep_ref(AVCodecContext *avctx, 
AVFrame *frame, int has_
             cf->ref_idx_ref = av_refstruct_pool_get(ctx->decoder_pool);
             if (!cf->ref_idx_ref) {
                 av_log(avctx, AV_LOG_ERROR, "No decoder surfaces left\n");
-                ret = AVERROR(ENOMEM);
-                goto fail;
+                return AVERROR(ENOMEM);
             }
         }
         cf->ref_idx = *cf->ref_idx_ref;
@@ -639,9 +638,6 @@ int ff_nvdec_start_frame_sep_ref(AVCodecContext *avctx, 
AVFrame *frame, int has_
     }
 
     return 0;
-fail:
-    nvdec_fdd_priv_free(cf);
-    return ret;
 }
 
 int ff_nvdec_end_frame(AVCodecContext *avctx)
-- 
2.52.0


From 9a92fb0034bc56045e3211a04b08c145a4594eda Mon Sep 17 00:00:00 2001
From: Michael Niedermayer <[email protected]>
Date: Tue, 30 Jun 2026 00:11:50 +0200
Subject: [PATCH 4/6] avformat/spdifenc: bound DTS core_size against the packet
 size in the HD path

Fixes: out of array read
Fixes: yBSax492UIB9
Fixes: 482d98f69b2 (spdifenc: IEC 61937 encapsulation of DTS-HD for HDMI)
Found-by: Pavel Kohout (Aisle Research)
Signed-off-by: Michael Niedermayer <[email protected]>
(cherry picked from commit 6f80e2765492700622596af720534cef33dd31b4)
Signed-off-by: Michael Niedermayer <[email protected]>
(cherry picked from commit 385ac2fadcb4394ec4f65e5c4d3d24003e090f36)
Signed-off-by: Adam Shaver <[email protected]>
---
 libavformat/spdifenc.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/libavformat/spdifenc.c b/libavformat/spdifenc.c
index ab3f73da0d..16eebda01c 100644
--- a/libavformat/spdifenc.c
+++ b/libavformat/spdifenc.c
@@ -225,7 +225,7 @@ static int spdif_header_dts4(AVFormatContext *s, AVPacket 
*pkt, int core_size,
              * (dtshd_fallback == 0) */
             ctx->dtshd_skip = 1;
     }
-    if (ctx->dtshd_skip && core_size) {
+    if (ctx->dtshd_skip && core_size && core_size <= pkt->size) {
         pkt_size = core_size;
         if (ctx->dtshd_fallback >= 0)
             --ctx->dtshd_skip;
-- 
2.52.0


From c26e3cd2f879dc7bea3d0ee00dc5353f7bc9842d Mon Sep 17 00:00:00 2001
From: Pavel Kohout <[email protected]>
Date: Tue, 30 Jun 2026 21:55:16 +0200
Subject: [PATCH 5/6] avformat/rtpdec_asf: reject ASF objects smaller than
 their header

Fixes: infinite loop
Fixes: MzWwJdpZF2Ls
Fixes: c2f3eec445389d67afc8c699ba23915a20cae51c (Implement RTSP-MS/ASF packet 
parsing.)
Found-by: Pavel Kohout (Aisle Research)
Signed-off-by: Michael Niedermayer <[email protected]>
(cherry picked from commit 11d5f475be95d22d5f0692220cc772b116abc632)
Signed-off-by: Michael Niedermayer <[email protected]>
(cherry picked from commit 3c441711a343ccf50196c70a3f0b554b52f8d9de)
Signed-off-by: Adam Shaver <[email protected]>
---
 libavformat/rtpdec_asf.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/libavformat/rtpdec_asf.c b/libavformat/rtpdec_asf.c
index b3b346f3cc..f7fa69e27f 100644
--- a/libavformat/rtpdec_asf.c
+++ b/libavformat/rtpdec_asf.c
@@ -56,6 +56,8 @@ static int rtp_asf_fix_header(uint8_t *buf, int len)
         uint64_t chunksize = AV_RL64(p + sizeof(ff_asf_guid));
         int skip = 6 * 8 + 3 * 4 + sizeof(ff_asf_guid) * 2;
         if (memcmp(p, ff_asf_file_header, sizeof(ff_asf_guid))) {
+            if (chunksize < sizeof(ff_asf_guid) + 8)
+                return -1;
             if (chunksize > end - p)
                 return -1;
             p += chunksize;
-- 
2.52.0


From 852b0552f072826723749db6891928d839f536d8 Mon Sep 17 00:00:00 2001
From: Pavel Kohout <[email protected]>
Date: Mon, 29 Jun 2026 23:46:16 +0200
Subject: [PATCH 6/6] avcodec/adx: sync decoder channel state on NEW_EXTRADATA

Fixes: out of array access
Fixes: heaNtmHvklpe
Fixes: 92396cee602320c714713ca2d93b53684ad57000 (avformat: add CRI AAX demuxer)
Found-by: Pavel Kohout (Aisle Research)
Signed-off-by: Michael Niedermayer <[email protected]>
(cherry picked from commit 1836ef96846937a6cc2443698a693104f5c0b21e)
Signed-off-by: Michael Niedermayer <[email protected]>
(cherry picked from commit c10e7f5dc12367d0dfcc52983d427c6766425fa8)
Signed-off-by: Adam Shaver <[email protected]>
---
 libavcodec/adxdec.c | 5 +++++
 1 file changed, 5 insertions(+)

diff --git a/libavcodec/adxdec.c b/libavcodec/adxdec.c
index 019fc1a90d..a79ae430aa 100644
--- a/libavcodec/adxdec.c
+++ b/libavcodec/adxdec.c
@@ -173,6 +173,7 @@ static int adx_decode_frame(AVCodecContext *avctx, AVFrame 
*frame,
     new_extradata = av_packet_get_side_data(avpkt, AV_PKT_DATA_NEW_EXTRADATA,
                                             &new_extradata_size);
     if (new_extradata && new_extradata_size > 0) {
+        int old_channels = c->channels;
         int header_size;
         if ((ret = adx_decode_header(avctx, new_extradata,
                                      new_extradata_size, &header_size,
@@ -181,6 +182,10 @@ static int adx_decode_frame(AVCodecContext *avctx, AVFrame 
*frame,
             return AVERROR_INVALIDDATA;
         }
 
+        c->channels      = avctx->ch_layout.nb_channels;
+        c->header_parsed = 1;
+        if (old_channels != c->channels)
+            memset(c->prev, 0, sizeof(c->prev));
         c->eof = 0;
     }
 
-- 
2.52.0

_______________________________________________
ffmpeg-devel mailing list -- [email protected]
To unsubscribe send an email to [email protected]

Reply via email to