PR #25551 opened by Romain Beauxis (toots)
URL: https://code.ffmpeg.org/FFmpeg/FFmpeg/pulls/25551
Patch URL: https://code.ffmpeg.org/FFmpeg/FFmpeg/pulls/25551.patch


>From 279e039ef21aa9eb504985f35b5bfd71815bca24 Mon Sep 17 00:00:00 2001
From: Martin Mirchev <[email protected]>
Date: Tue, 27 Oct 2026 11:49:49 +0800
Subject: [PATCH 1/2] avformat/oggparsevorbis: fix chained streams with headers
 over 64 KiB

When a chained Vorbis stream starts, its three header packets are
packed into new extradata with 16-bit size prefixes. A header larger
than 65535 bytes, typically a comment header with embedded cover art,
gets its size truncated, so the Vorbis parser cannot be reinitialized
and demuxing fails with "Failed to re-initialize Vorbis parser". The
audio of the new chained stream and everything after it is lost.

Use Xiph lacing instead, as vorbis_header() already does for the
initial extradata.

Signed-off-by: Martin Mirchev <[email protected]>
(cherry picked from commit 94110fbc39a85f442530fc73d5c9b906d2551244)
---
 libavformat/oggparsevorbis.c | 29 ++++++++++++++++++++---------
 1 file changed, 20 insertions(+), 9 deletions(-)

diff --git a/libavformat/oggparsevorbis.c b/libavformat/oggparsevorbis.c
index 3ad72cd69a4..18160ec3ddb 100644
--- a/libavformat/oggparsevorbis.c
+++ b/libavformat/oggparsevorbis.c
@@ -463,7 +463,6 @@ static int vorbis_packet(AVFormatContext *s, int idx)
     int duration, flags = 0;
     int bos, skip_packet = 0;
     int ret, new_extradata_size;
-    PutByteContext pb;
 
     if (os->psize == 0)
         return AVERROR_INVALIDDATA;
@@ -609,20 +608,32 @@ static int vorbis_packet(AVFormatContext *s, int idx)
     /* All three headers for the new chained stream have been collected;
      * pack them into new extradata to be attached to the next data packet. */
     if (priv->header && priv->comment && priv->setup) {
-        new_extradata_size = priv->header_size + priv->comment_size + 
priv->setup_size + 6;
+        uint64_t total_size = (uint64_t)priv->header_size + priv->comment_size 
+
+                              priv->setup_size;
+        uint8_t *p;
+
+        /* Use Xiph lacing like vorbis_header() does: 16-bit sizes cannot
+         * describe headers larger than 64 KiB, e.g. a comment header with
+         * embedded cover art. */
+        if (total_size + total_size / 255 + 3 > INT_MAX)
+            return AVERROR_INVALIDDATA;
+        new_extradata_size = 1 + priv->header_size / 255 + 1 +
+                             priv->comment_size / 255 + 1 + total_size;
 
         ret = av_reallocp(&os->new_extradata, new_extradata_size);
         if (ret < 0)
             return ret;
 
         os->new_extradata_size = new_extradata_size;
-        bytestream2_init_writer(&pb, os->new_extradata, new_extradata_size);
-        bytestream2_put_be16(&pb, priv->header_size);
-        bytestream2_put_buffer(&pb, priv->header, priv->header_size);
-        bytestream2_put_be16(&pb, priv->comment_size);
-        bytestream2_put_buffer(&pb, priv->comment, priv->comment_size);
-        bytestream2_put_be16(&pb, priv->setup_size);
-        bytestream2_put_buffer(&pb, priv->setup, priv->setup_size);
+        p     = os->new_extradata;
+        *p++  = 2;
+        p    += av_xiphlacing(p, priv->header_size);
+        p    += av_xiphlacing(p, priv->comment_size);
+        memcpy(p, priv->header, priv->header_size);
+        p    += priv->header_size;
+        memcpy(p, priv->comment, priv->comment_size);
+        p    += priv->comment_size;
+        memcpy(p, priv->setup, priv->setup_size);
 
         av_freep(&priv->header);
         priv->header_size = 0;
-- 
2.54.0


>From c13899aa707ed2c1299599fa18e210d6245556a8 Mon Sep 17 00:00:00 2001
From: Martin Mirchev <[email protected]>
Date: Tue, 27 Oct 2026 11:49:49 +0800
Subject: [PATCH 2/2] fate/ogg-vorbis: add a test for a chained stream with a
 large comment

Remux two short streams from an existing sample, the second one with a
70000-byte comment header, and demux their concatenation.

Signed-off-by: Martin Mirchev <[email protected]>
(cherry picked from commit 0718c6e195e4554c8c87712c3c3dc6004d35be8c)
---
 tests/fate/ogg-vorbis.mak                     | 13 +++++
 .../ref/fate/ogg-vorbis-chained-large-comment | 58 +++++++++++++++++++
 2 files changed, 71 insertions(+)
 create mode 100644 tests/ref/fate/ogg-vorbis-chained-large-comment

diff --git a/tests/fate/ogg-vorbis.mak b/tests/fate/ogg-vorbis.mak
index e9151b63157..51d6a9e4d6a 100644
--- a/tests/fate/ogg-vorbis.mak
+++ b/tests/fate/ogg-vorbis.mak
@@ -7,6 +7,19 @@ fate-ogg-vorbis-copy-chained-meta: 
$(APITESTSDIR)/api-dump-stream-meta-test$(EXE
 fate-ogg-vorbis-copy-chained-meta: REF = 
$(SRC_PATH)/tests/ref/fate/ogg-vorbis-chained-meta.txt
 fate-ogg-vorbis-copy-chained-meta: CMD = run_with_temp "$(FFMPEG) -nostdin 
-hide_banner -loglevel quiet -i $(TARGET_SAMPLES)/ogg-vorbis/chained-meta.ogg 
-c copy -f ogg -y" "$(APITESTSDIR)/api-dump-stream-meta-test$(EXESUF)" ogg
 
+# Chain two streams cut from the same sample, the second one with a comment
+# header larger than 64 KiB (as with embedded cover art).
+FATE_OGG_COPY_VORBIS-$(call FRAMECRC, OGG FFMETADATA, VORBIS, OGG_MUXER 
CONCAT_PROTOCOL) += fate-ogg-vorbis-chained-large-comment
+fate-ogg-vorbis-chained-large-comment: CMD = \
+    cleanfiles="$${cleanfiles} $${outfile}.txt $${outfile}.1.ogg 
$${outfile}.2.ogg"; \
+    printf ";FFMETADATA1\ncomment=%070000d\n" 0 > "$${outfile}.txt" && \
+    ffmpeg -i $(TARGET_SAMPLES)/vorbis/moog_small.ogg -c copy -t 0.5 -fflags 
+bitexact \
+        -y "$$(target_path "$${outfile}.1.ogg")" && \
+    ffmpeg -i $(TARGET_SAMPLES)/vorbis/moog_small.ogg -i "$$(target_path 
"$${outfile}.txt")" \
+        -map 0 -map_metadata 1 -c copy -t 0.5 -fflags +bitexact -serial_offset 
1 \
+        -y "$$(target_path "$${outfile}.2.ogg")" && \
+    framecrc -i "concat:$$(target_path "$${outfile}.1.ogg")|$$(target_path 
"$${outfile}.2.ogg")" -c copy
+
 FATE_OGG_VORBIS_PROBE-$(call DEMDEC, OGG, VORBIS) += 
fate-ogg-vorbis-initial-padding-chained
 fate-ogg-vorbis-initial-padding-chained: CMD = ffprobe_demux -of default 
-show_entries stream=codec_name,initial_padding 
$(TARGET_SAMPLES)/ogg-vorbis/chained-meta.ogg
 
diff --git a/tests/ref/fate/ogg-vorbis-chained-large-comment 
b/tests/ref/fate/ogg-vorbis-chained-large-comment
new file mode 100644
index 00000000000..20ca11e82cd
--- /dev/null
+++ b/tests/ref/fate/ogg-vorbis-chained-large-comment
@@ -0,0 +1,58 @@
+#extradata 0:    12456, 0xa1161932
+#tb 0: 1/44100
+#media_type 0: audio
+#codec_id 0: vorbis
+#sample_rate 0: 44100
+#channel_layout_name 0: stereo
+0,       -128,       -128,      128,        3, 0x00000000, S=1, Strings 
Metadata,      106, 0xe088249e
+0,          0,          0,      576,        4, 0x0028000a
+0,        576,        576,     1024,        4, 0x0038000e
+0,       1600,       1600,     1024,        4, 0x0038000e
+0,       2624,       2624,     1024,        4, 0x00180006
+0,       3648,       3648,      576,        3, 0x00000000
+0,       4224,       4224,      128,       54, 0x014c1a96
+0,       4352,       4352,      128,       55, 0x2f911b84
+0,       4480,       4480,      576,      420, 0xf6dbdbbc
+0,       5056,       5056,     1024,      387, 0x0c56c7ba
+0,       6080,       6080,     1024,      393, 0x6327c817
+0,       7104,       7104,     1024,      358, 0x578bb0b5
+0,       8128,       8128,     1024,      301, 0x3f658f2f
+0,       9152,       9152,     1024,      303, 0xe1a2955f
+0,      10176,      10176,     1024,      311, 0x4f829c54
+0,      11200,      11200,     1024,      308, 0x1d1a9ae7
+0,      12224,      12224,     1024,      282, 0x10428728
+0,      13248,      13248,     1024,      274, 0xd201846b
+0,      14272,      14272,     1024,      297, 0x688a8dee
+0,      15296,      15296,     1024,      279, 0x01fc85c1
+0,      16320,      16320,     1024,      299, 0xeb658ff2
+0,      17344,      17344,     1024,      286, 0x01569307
+0,      18368,      18368,     1024,      307, 0x331a8a6a
+0,      19392,      19392,     1024,      293, 0x59eb908a
+0,      20416,      20416,     1024,      294, 0x11dc9474
+0,      21440,      21440,     1024,      300, 0x7c9d9254, S=1, Skip Samples,  
     10, 0x03000080
+0,      22464,      22464,      128,        3, 0x00000000, S=2, Strings 
Metadata,    70115, 0xf8df6f8e, New Extradata,    82871, 0x33479e75
+0,      22592,      22592,      576,        4, 0x0028000a
+0,      23168,      23168,     1024,        4, 0x0038000e
+0,      24192,      24192,     1024,        4, 0x0038000e
+0,      25216,      25216,     1024,        4, 0x00180006
+0,      26240,      26240,      576,        3, 0x00000000
+0,      26816,      26816,      128,       54, 0x014c1a96
+0,      26944,      26944,      128,       55, 0x2f911b84
+0,      27072,      27072,      576,      420, 0xf6dbdbbc
+0,      27648,      27648,     1024,      387, 0x0c56c7ba
+0,      28672,      28672,     1024,      393, 0x6327c817
+0,      29696,      29696,     1024,      358, 0x578bb0b5
+0,      30720,      30720,     1024,      301, 0x3f658f2f
+0,      31744,      31744,     1024,      303, 0xe1a2955f
+0,      32768,      32768,     1024,      311, 0x4f829c54
+0,      33792,      33792,     1024,      308, 0x1d1a9ae7
+0,      34816,      34816,     1024,      282, 0x10428728
+0,      35840,      35840,     1024,      274, 0xd201846b
+0,      36864,      36864,     1024,      297, 0x688a8dee
+0,      37888,      37888,     1024,      279, 0x01fc85c1
+0,      38912,      38912,     1024,      299, 0xeb658ff2
+0,      39936,      39936,     1024,      286, 0x01569307
+0,      40960,      40960,     1024,      307, 0x331a8a6a
+0,      41984,      41984,     1024,      293, 0x59eb908a
+0,      43008,      43008,     1024,      294, 0x11dc9474
+0,      44032,      44032,     1024,      300, 0x7c9d9254, S=1, Skip Samples,  
     10, 0x03000080
-- 
2.54.0

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

Reply via email to