[FFmpeg-devel] [PATCH] avformat/id3v2: support buggy id3v2.3 tag length in id3v2.4
Benoit Fouet
benoit.fouet at free.fr
Thu Oct 16 11:44:47 CEST 2014
Some encoders do not use syncsafe sizes in v2.4 id3 tags. Check the next
tag to try to choose between the two.
Fixes ticket #4003
---
libavformat/id3v2.c | 42 +++++++++++++++++++++++++++++++++++++++++-
1 file changed, 41 insertions(+), 1 deletion(-)
diff --git a/libavformat/id3v2.c b/libavformat/id3v2.c
index 5469e0a..3bccd76 100644
--- a/libavformat/id3v2.c
+++ b/libavformat/id3v2.c
@@ -170,6 +170,23 @@ static unsigned int get_size(AVIOContext *s, int len)
return v;
}
+/* No real verification, only check that the tag consists of
+ * a combination of capital alpha-numerical characters */
+static int is_tag(const char *buf, int len)
+{
+ if (!len)
+ return 0;
+
+ while (len--)
+ if ((buf[len] < 'A' ||
+ buf[len] > 'Z') &&
+ (buf[len] < '0' ||
+ buf[len] > '9'))
+ return 0;
+
+ return 1;
+}
+
/**
* Free GEOB type extra metadata.
*/
@@ -734,8 +751,31 @@ static void id3v2_parse(AVIOContext *pb, AVDictionary **metadata,
tag[4] = 0;
if (version == 3) {
tlen = avio_rb32(pb);
- } else
+ } else {
tlen = get_size(pb, 4);
+ if (tlen > 0x7f) {
+ /* some encoders incorrectly uses v3 sizes instead of syncsafe ones
+ * so check the next tag to see which one to use */
+ int64_t cur = avio_tell(pb);
+ char next_tag[5];
+
+ next = cur + 2 /* tflags */ + tlen;
+ avio_seek(pb, next, SEEK_SET);
+ if (avio_read(pb, next_tag, 4) < 4)
+ break;
+ if (AV_RB32(next_tag) && !is_tag(next_tag, 4)) {
+ avio_seek(pb, cur - 4, SEEK_SET);
+ tlen = avio_rb32(pb);
+ next = cur + 2 + tlen;
+ avio_seek(pb, next, SEEK_SET);
+ if (avio_read(pb, next_tag, 4) < 4)
+ break;
+ if (AV_RB32(next_tag) && !is_tag(next_tag, 4))
+ break;
+ }
+ avio_seek(pb, cur, SEEK_SET);
+ }
+ }
tflags = avio_rb16(pb);
tunsync = tflags & ID3v2_FLAG_UNSYNCH;
} else {
--
2.1.2.443.g670a3c1
More information about the ffmpeg-devel
mailing list