[FFmpeg-devel] [PATCH] avformat/id3v2: support buggy id3v2.3 tag length in id3v2.4
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 | 64 +++-- 1 file changed, 62 insertions(+), 2 deletions(-) diff --git a/libavformat/id3v2.c b/libavformat/id3v2.c index 44df4ff..3e54620 100644 --- a/libavformat/id3v2.c +++ b/libavformat/id3v2.c @@ -170,6 +170,48 @@ static unsigned int get_size(AVIOContext *s, int len) return v; } +static unsigned int size_to_syncsafe(unsigned int size) +{ +return (((size) (0x7f 0)) 0) + + (((size) (0x7f 8)) 1) + + (((size) (0x7f 16)) 2) + + (((size) (0x7f 24)) 3); +} + +/* No real verification, only check that the tag consists of + * a combination of capital alpha-numerical characters */ +static int is_tag(const char *buf, unsigned 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; +} + +/** + * Return 1 if the tag of length len at the given offset is valid, 0 if not, -1 on error + */ +static int check_tag(AVIOContext *s, int offset, unsigned int len) +{ +char tag[4]; + +if (len 4 || +avio_seek(s, offset, SEEK_SET) 0 || +avio_read(s, tag, len) len) +return -1; +else if (!AV_RB32(tag) || is_tag(tag, len)) +return 1; + +return 0; +} + /** * Free GEOB type extra metadata. */ @@ -734,8 +776,26 @@ static void id3v2_parse(AVIOContext *pb, AVDictionary **metadata, tag[4] = 0; if (version == 3) { tlen = avio_rb32(pb); -} else -tlen = get_size(pb, 4); +} else { +/* some encoders incorrectly uses v3 sizes instead of syncsafe ones + * so check the next tag to see which one to use */ +tlen = avio_rb32(pb); +if (tlen 0x7f) { +if (tlen len) { +int64_t cur = avio_tell(pb); + +if (ffio_ensure_seekback(pb, 2 /* tflags */ + tlen + 4 /* next tag */)) +break; + +if (check_tag(pb, cur + 2 + size_to_syncsafe(tlen), 4) == 1) +tlen = size_to_syncsafe(tlen); +else if (check_tag(pb, cur + 2 + tlen, 4) != 1) +break; +avio_seek(pb, cur, SEEK_SET); +} else +tlen = size_to_syncsafe(tlen); +} +} tflags = avio_rb16(pb); tunsync = tflags ID3v2_FLAG_UNSYNCH; } else { -- 2.1.2.443.g670a3c1 ___ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org http://ffmpeg.org/mailman/listinfo/ffmpeg-devel
Re: [FFmpeg-devel] [PATCH] avformat/id3v2: support buggy id3v2.3 tag length in id3v2.4
On Fri, Oct 17, 2014 at 10:56:59AM +0200, Benoit Fouet wrote: 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 | 64 +++-- 1 file changed, 62 insertions(+), 2 deletions(-) applied thanks [...] -- Michael GnuPG fingerprint: 9FF2128B147EF6730BADF133611EC787040B0FAB I do not agree with what you have to say, but I'll defend to the death your right to say it. -- Voltaire signature.asc Description: Digital signature ___ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org http://ffmpeg.org/mailman/listinfo/ffmpeg-devel
[FFmpeg-devel] [PATCH] avformat/id3v2: support buggy id3v2.3 tag length in id3v2.4
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 ___ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org http://ffmpeg.org/mailman/listinfo/ffmpeg-devel
Re: [FFmpeg-devel] [PATCH] avformat/id3v2: support buggy id3v2.3 tag length in id3v2.4
On Thu, Oct 16, 2014 at 11:44:47AM +0200, Benoit Fouet wrote: 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) { i think that check isnt sufficient to detect that the 2 readings differ. For example 0xFF would be read as 0xFF by one and 0x7F by the other and would not trigger this also maybe len could be used to distingish a subset of cases and there is the problem with seekable=0 streams where seeking back might fail, not sure what to do in that case ... [...] -- Michael GnuPG fingerprint: 9FF2128B147EF6730BADF133611EC787040B0FAB He who knows, does not speak. He who speaks, does not know. -- Lao Tsu signature.asc Description: Digital signature ___ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org http://ffmpeg.org/mailman/listinfo/ffmpeg-devel
Re: [FFmpeg-devel] [PATCH] avformat/id3v2: support buggy id3v2.3 tag length in id3v2.4
Hi, On 16 October 2014 17:10:38 CEST, Michael Niedermayer michae...@gmx.at wrote: On Thu, Oct 16, 2014 at 11:44:47AM +0200, Benoit Fouet wrote: 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) { i think that check isnt sufficient to detect that the 2 readings differ. For example 0xFF would be read as 0xFF by one and 0x7F by the other and would not trigger this True, although I guess that could be handled by just making this test a = instead of . also maybe len could be used to distingish a subset of cases Not sure I understand what you mean here... The tlen check seems to be enough to me. and there is the problem with seekable=0 streams where seeking back might fail, not sure what to do in that case ... We could theoretically buffer the data instead of seeking back, as the syncsafe size will always be smaller than the other one. Is this something that we want? I can work on something like that. -- Ben ___ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org http://ffmpeg.org/mailman/listinfo/ffmpeg-devel
Re: [FFmpeg-devel] [PATCH] avformat/id3v2: support buggy id3v2.3 tag length in id3v2.4
On Thu, Oct 16, 2014 at 06:06:39PM +0200, Benoit Fouet wrote: Hi, On 16 October 2014 17:10:38 CEST, Michael Niedermayer michae...@gmx.at wrote: On Thu, Oct 16, 2014 at 11:44:47AM +0200, Benoit Fouet wrote: 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) { i think that check isnt sufficient to detect that the 2 readings differ. For example 0xFF would be read as 0xFF by one and 0x7F by the other and would not trigger this True, although I guess that could be handled by just making this test a = instead of . that wouldnt work with 0x81 also maybe len could be used to distingish a subset of cases Not sure I understand what you mean here... The tlen check seems to be enough to me. i was thinking of avoiding the seek for cases where one is clearly invalid like tlen len IIRC the variable names and there is the problem with seekable=0 streams where seeking back might fail, not sure what to do in that case ... We could theoretically buffer the data instead of seeking back, as the syncsafe size will always be smaller than the other one. Is this something that we want? I can work on something like that. probably that is needed, also see ffio_ensure_seekback() [...] -- Michael GnuPG fingerprint: 9FF2128B147EF6730BADF133611EC787040B0FAB When the tyrant has disposed of foreign enemies by conquest or treaty, and there is nothing more to fear from them, then he is always stirring up some war or other, in order that the people may require a leader. -- Plato signature.asc Description: Digital signature ___ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org http://ffmpeg.org/mailman/listinfo/ffmpeg-devel