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

Both muxers store metadata string lengths in 16 bits and silently truncate them 
for longer strings while writing the full data, producing headers that readers 
misparse.

**ASF**

```
ffmpeg -f lavfi -i sine=duration=0.2 -c:a wmav2 -metadata title=<40001 chars> 
-metadata artist=after out.asf
```

exits 0; `ffprobe` on the result then reports `artist=aaaaaa` (the tail of the 
title). With the patch the muxer fails with "Metadata entry 'title' is too long 
for ASF". ASF writes the descriptor count before the entries, so failing is 
cleaner than skipping.

**FLV**

With a 70000-byte title the AMF0 string length is written as 4464 (70000 & 
0xFFFF), followed by all 70000 bytes, so the metadata array desynchronises. 
With the patch the entry is skipped with a warning; the entry count is written 
after the loop, so it stays consistent.

Note: flvdec separately rejects any metadata string of 1024 bytes or more, so 
the FLV case cannot be checked through ffprobe; the declared length was checked 
in the file directly.

FATE `lavf-asf`, `lavf-flv`, `seek-lavf-asf` and `seek-lavf-flv` pass.

This issue was found by an LLM-Enhanced Static Analysis Engine and verified 
manually.



>From 05ca6bf0e1b83e1bd845125e3d2b1277dd222b87 Mon Sep 17 00:00:00 2001
From: Martin Mirchev <[email protected]>
Date: Sun, 18 Oct 2026 16:07:23 +0800
Subject: [PATCH 1/2] avformat/asfenc: reject metadata too long for 16-bit
 string lengths

ASF stores the UTF-16 byte length of each metadata key and value in a
16-bit field. For longer strings the length was truncated while the full
string was written, producing a header that demuxers misparse; e.g. with
a 40001-character title, reading the file back gives "artist=aaaaaa".

Fail with an error instead of writing a corrupt header.

Signed-off-by: Martin Mirchev <[email protected]>
---
 libavformat/asfenc.c | 16 ++++++++++++++++
 1 file changed, 16 insertions(+)

diff --git a/libavformat/asfenc.c b/libavformat/asfenc.c
index 59638e7b22..6308d1d164 100644
--- a/libavformat/asfenc.c
+++ b/libavformat/asfenc.c
@@ -544,6 +544,22 @@ static int asf_write_header1(AVFormatContext *s, int64_t 
file_size,
     if ((ret = avio_open_dyn_buf(&dyn_buf)) < 0)
         return ret;
 
+    /* ASF stores the UTF-16 length of every string in 16 bits */
+    {
+        const AVDictionaryEntry *tag = NULL;
+        while ((tag = av_dict_iterate(s->metadata, tag))) {
+            int klen = avio_put_str16le(dyn_buf, tag->key);
+            int vlen = avio_put_str16le(dyn_buf, tag->value);
+            ffio_reset_dyn_buf(dyn_buf);
+            if (klen > UINT16_MAX || vlen > UINT16_MAX) {
+                av_log(s, AV_LOG_ERROR,
+                       "Metadata entry '%s' is too long for ASF\n", tag->key);
+                ffio_free_dyn_buf(&dyn_buf);
+                return AVERROR(EINVAL);
+            }
+        }
+    }
+
     /* title and other info */
     if (has_title) {
         uint8_t *buf;
-- 
2.54.0


>From 7ef21533714455e8c55224776b104d55db6442b9 Mon Sep 17 00:00:00 2001
From: Martin Mirchev <[email protected]>
Date: Sun, 18 Oct 2026 16:07:23 +0800
Subject: [PATCH 2/2] avformat/flvenc: skip metadata strings longer than 65535
 bytes

AMF0 strings carry a 16-bit length. For longer onMetaData keys or values
the length was truncated (e.g. 4464 for a 70000-byte title) while the
full string was written, so the metadata array desynchronises.

Skip such entries with a warning; the entry count is written afterwards,
so it stays consistent.

Signed-off-by: Martin Mirchev <[email protected]>
---
 libavformat/flvenc.c | 5 +++++
 1 file changed, 5 insertions(+)

diff --git a/libavformat/flvenc.c b/libavformat/flvenc.c
index 7c8d0a126b..1c5b668923 100644
--- a/libavformat/flvenc.c
+++ b/libavformat/flvenc.c
@@ -403,6 +403,11 @@ static void write_metadata(AVFormatContext *s, unsigned 
int ts)
             av_log(s, AV_LOG_DEBUG, "Ignoring metadata for %s\n", tag->key);
             continue;
         }
+        if (strlen(tag->key) > UINT16_MAX || strlen(tag->value) > UINT16_MAX) {
+            av_log(s, AV_LOG_WARNING,
+                   "Metadata entry '%s' is too long for FLV, skipping\n", 
tag->key);
+            continue;
+        }
         put_amf_string(pb, tag->key);
         avio_w8(pb, AMF_DATA_TYPE_STRING);
         put_amf_string(pb, tag->value);
-- 
2.54.0

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

Reply via email to