Do not loop endlessly if id3v2 tag size is negative / too large.
[ffmpeg.git] / libavformat / id3v2.c
1 /*
2  * ID3v2 header parser
3  * Copyright (c) 2003 Fabrice Bellard
4  *
5  * This file is part of FFmpeg.
6  *
7  * FFmpeg is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU Lesser General Public
9  * License as published by the Free Software Foundation; either
10  * version 2.1 of the License, or (at your option) any later version.
11  *
12  * FFmpeg is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15  * Lesser General Public License for more details.
16  *
17  * You should have received a copy of the GNU Lesser General Public
18  * License along with FFmpeg; if not, write to the Free Software
19  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20  */
21
22 #include "id3v2.h"
23 #include "id3v1.h"
24 #include "libavutil/avstring.h"
25 #include "libavutil/intreadwrite.h"
26 #include "metadata.h"
27 #include "avio_internal.h"
28
29 int ff_id3v2_match(const uint8_t *buf, const char * magic)
30 {
31     return  buf[0]         == magic[0] &&
32             buf[1]         == magic[1] &&
33             buf[2]         == magic[2] &&
34             buf[3]         != 0xff &&
35             buf[4]         != 0xff &&
36            (buf[6] & 0x80) ==    0 &&
37            (buf[7] & 0x80) ==    0 &&
38            (buf[8] & 0x80) ==    0 &&
39            (buf[9] & 0x80) ==    0;
40 }
41
42 int ff_id3v2_tag_len(const uint8_t * buf)
43 {
44     int len = ((buf[6] & 0x7f) << 21) +
45               ((buf[7] & 0x7f) << 14) +
46               ((buf[8] & 0x7f) << 7) +
47                (buf[9] & 0x7f) +
48               ID3v2_HEADER_SIZE;
49     if (buf[5] & 0x10)
50         len += ID3v2_HEADER_SIZE;
51     return len;
52 }
53
54 static unsigned int get_size(AVIOContext *s, int len)
55 {
56     int v = 0;
57     while (len--)
58         v = (v << 7) + (avio_r8(s) & 0x7F);
59     return v;
60 }
61
62 static void read_ttag(AVFormatContext *s, AVIOContext *pb, int taglen, const char *key)
63 {
64     char *q, dst[512];
65     const char *val = NULL;
66     int len, dstlen = sizeof(dst) - 1;
67     unsigned genre;
68     unsigned int (*get)(AVIOContext*) = avio_rb16;
69
70     dst[0] = 0;
71     if (taglen < 1)
72         return;
73
74     taglen--; /* account for encoding type byte */
75
76     switch (avio_r8(pb)) { /* encoding type */
77
78     case ID3v2_ENCODING_ISO8859:
79         q = dst;
80         while (taglen-- && q - dst < dstlen - 7) {
81             uint8_t tmp;
82             PUT_UTF8(avio_r8(pb), tmp, *q++ = tmp;)
83         }
84         *q = 0;
85         break;
86
87     case ID3v2_ENCODING_UTF16BOM:
88         taglen -= 2;
89         switch (avio_rb16(pb)) {
90         case 0xfffe:
91             get = avio_rl16;
92         case 0xfeff:
93             break;
94         default:
95             av_log(s, AV_LOG_ERROR, "Incorrect BOM value in tag %s.\n", key);
96             return;
97         }
98         // fall-through
99
100     case ID3v2_ENCODING_UTF16BE:
101         q = dst;
102         while (taglen > 1 && q - dst < dstlen - 7) {
103             uint32_t ch;
104             uint8_t tmp;
105
106             GET_UTF16(ch, ((taglen -= 2) >= 0 ? get(pb) : 0), break;)
107             PUT_UTF8(ch, tmp, *q++ = tmp;)
108         }
109         *q = 0;
110         break;
111
112     case ID3v2_ENCODING_UTF8:
113         len = FFMIN(taglen, dstlen);
114         avio_read(pb, dst, len);
115         dst[len] = 0;
116         break;
117     default:
118         av_log(s, AV_LOG_WARNING, "Unknown encoding in tag %s\n.", key);
119     }
120
121     if (!(strcmp(key, "TCON") && strcmp(key, "TCO"))
122         && (sscanf(dst, "(%d)", &genre) == 1 || sscanf(dst, "%d", &genre) == 1)
123         && genre <= ID3v1_GENRE_MAX)
124         val = ff_id3v1_genre_str[genre];
125     else if (!(strcmp(key, "TXXX") && strcmp(key, "TXX"))) {
126         /* dst now contains two 0-terminated strings */
127         dst[dstlen] = 0;
128         len = strlen(dst);
129         key = dst;
130         val = dst + FFMIN(len + 1, dstlen);
131     }
132     else if (*dst)
133         val = dst;
134
135     if (val)
136         av_metadata_set2(&s->metadata, key, val, AV_METADATA_DONT_OVERWRITE);
137 }
138
139 static void ff_id3v2_parse(AVFormatContext *s, int len, uint8_t version, uint8_t flags)
140 {
141     int isv34, unsync;
142     unsigned tlen;
143     char tag[5];
144     int64_t next;
145     int taghdrlen;
146     const char *reason;
147     AVIOContext pb;
148     unsigned char *buffer = NULL;
149     int buffer_size = 0;
150
151     switch (version) {
152     case 2:
153         if (flags & 0x40) {
154             reason = "compression";
155             goto error;
156         }
157         isv34 = 0;
158         taghdrlen = 6;
159         break;
160
161     case 3:
162     case 4:
163         isv34 = 1;
164         taghdrlen = 10;
165         break;
166
167     default:
168         reason = "version";
169         goto error;
170     }
171
172     unsync = flags & 0x80;
173
174     if (isv34 && flags & 0x40) /* Extended header present, just skip over it */
175         avio_seek(s->pb, get_size(s->pb, 4), SEEK_CUR);
176
177     while (len >= taghdrlen) {
178         unsigned int tflags;
179         int tunsync = 0;
180
181         if (isv34) {
182             avio_read(s->pb, tag, 4);
183             tag[4] = 0;
184             if(version==3){
185                 tlen = avio_rb32(s->pb);
186             }else
187                 tlen = get_size(s->pb, 4);
188             tflags = avio_rb16(s->pb);
189             tunsync = tflags & ID3v2_FLAG_UNSYNCH;
190         } else {
191             avio_read(s->pb, tag, 3);
192             tag[3] = 0;
193             tlen = avio_rb24(s->pb);
194         }
195         if (tlen > (1<<28))
196             break;
197         len -= taghdrlen + tlen;
198
199         if (len < 0)
200             break;
201
202         next = avio_tell(s->pb) + tlen;
203
204         if (tflags & ID3v2_FLAG_DATALEN) {
205             avio_rb32(s->pb);
206             tlen -= 4;
207         }
208
209         if (tflags & (ID3v2_FLAG_ENCRYPTION | ID3v2_FLAG_COMPRESSION)) {
210             av_log(s, AV_LOG_WARNING, "Skipping encrypted/compressed ID3v2 frame %s.\n", tag);
211             avio_seek(s->pb, tlen, SEEK_CUR);
212         } else if (tag[0] == 'T') {
213             if (unsync || tunsync) {
214                 int i, j;
215                 av_fast_malloc(&buffer, &buffer_size, tlen);
216                 for (i = 0, j = 0; i < tlen; i++, j++) {
217                     buffer[j] = avio_r8(s->pb);
218                     if (j > 0 && !buffer[j] && buffer[j - 1] == 0xff) {
219                         /* Unsynchronised byte, skip it */
220                         j--;
221                     }
222                 }
223                 ffio_init_context(&pb, buffer, j, 0, NULL, NULL, NULL, NULL);
224                 read_ttag(s, &pb, j, tag);
225             } else {
226                 read_ttag(s, s->pb, tlen, tag);
227             }
228         }
229         else if (!tag[0]) {
230             if (tag[1])
231                 av_log(s, AV_LOG_WARNING, "invalid frame id, assuming padding");
232             avio_seek(s->pb, tlen, SEEK_CUR);
233             break;
234         }
235         /* Skip to end of tag */
236         avio_seek(s->pb, next, SEEK_SET);
237     }
238
239     if (len > 0) {
240         /* Skip padding */
241         avio_seek(s->pb, len, SEEK_CUR);
242     }
243     if (version == 4 && flags & 0x10) /* Footer preset, always 10 bytes, skip over it */
244         avio_seek(s->pb, 10, SEEK_CUR);
245
246     av_free(buffer);
247     return;
248
249   error:
250     av_log(s, AV_LOG_INFO, "ID3v2.%d tag skipped, cannot handle %s\n", version, reason);
251     avio_seek(s->pb, len, SEEK_CUR);
252     av_free(buffer);
253 }
254
255 void ff_id3v2_read(AVFormatContext *s, const char *magic)
256 {
257     int len, ret;
258     uint8_t buf[ID3v2_HEADER_SIZE];
259     int     found_header;
260     int64_t off;
261
262     do {
263         /* save the current offset in case there's nothing to read/skip */
264         off = avio_tell(s->pb);
265         ret = avio_read(s->pb, buf, ID3v2_HEADER_SIZE);
266         if (ret != ID3v2_HEADER_SIZE)
267             break;
268             found_header = ff_id3v2_match(buf, magic);
269             if (found_header) {
270             /* parse ID3v2 header */
271             len = ((buf[6] & 0x7f) << 21) |
272                   ((buf[7] & 0x7f) << 14) |
273                   ((buf[8] & 0x7f) << 7) |
274                    (buf[9] & 0x7f);
275             ff_id3v2_parse(s, len, buf[3], buf[5]);
276         } else {
277             avio_seek(s->pb, off, SEEK_SET);
278         }
279     } while (found_header);
280     ff_metadata_conv(&s->metadata, NULL, ff_id3v2_34_metadata_conv);
281     ff_metadata_conv(&s->metadata, NULL, ff_id3v2_2_metadata_conv);
282     ff_metadata_conv(&s->metadata, NULL, ff_id3v2_4_metadata_conv);
283 }
284
285 const AVMetadataConv ff_id3v2_34_metadata_conv[] = {
286     { "TALB", "album"},
287     { "TCOM", "composer"},
288     { "TCON", "genre"},
289     { "TCOP", "copyright"},
290     { "TENC", "encoded_by"},
291     { "TIT2", "title"},
292     { "TLAN", "language"},
293     { "TPE1", "artist"},
294     { "TPE2", "album_artist"},
295     { "TPE3", "performer"},
296     { "TPOS", "disc"},
297     { "TPUB", "publisher"},
298     { "TRCK", "track"},
299     { "TSSE", "encoder"},
300     { 0 }
301 };
302
303 const AVMetadataConv ff_id3v2_4_metadata_conv[] = {
304     { "TDRL", "date"},
305     { "TDRC", "date"},
306     { "TDEN", "creation_time"},
307     { "TSOA", "album-sort"},
308     { "TSOP", "artist-sort"},
309     { "TSOT", "title-sort"},
310     { 0 }
311 };
312
313 const AVMetadataConv ff_id3v2_2_metadata_conv[] = {
314     { "TAL",  "album"},
315     { "TCO",  "genre"},
316     { "TT2",  "title"},
317     { "TEN",  "encoded_by"},
318     { "TP1",  "artist"},
319     { "TP2",  "album_artist"},
320     { "TP3",  "performer"},
321     { "TRK",  "track"},
322     { 0 }
323 };
324
325
326 const char ff_id3v2_tags[][4] = {
327    "TALB", "TBPM", "TCOM", "TCON", "TCOP", "TDLY", "TENC", "TEXT",
328    "TFLT", "TIT1", "TIT2", "TIT3", "TKEY", "TLAN", "TLEN", "TMED",
329    "TOAL", "TOFN", "TOLY", "TOPE", "TOWN", "TPE1", "TPE2", "TPE3",
330    "TPE4", "TPOS", "TPUB", "TRCK", "TRSN", "TRSO", "TSRC", "TSSE",
331    { 0 },
332 };
333
334 const char ff_id3v2_4_tags[][4] = {
335    "TDEN", "TDOR", "TDRC", "TDRL", "TDTG", "TIPL", "TMCL", "TMOO",
336    "TPRO", "TSOA", "TSOP", "TSOT", "TSST",
337    { 0 },
338 };
339
340 const char ff_id3v2_3_tags[][4] = {
341    "TDAT", "TIME", "TORY", "TRDA", "TSIZ", "TYER",
342    { 0 },
343 };