1 /*
2  * Copyright (C) 2010 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 //#define LOG_NDEBUG 0
18 #define LOG_TAG "ID3"
19 #include <utils/Log.h>
20 
21 #include "../include/ID3.h"
22 
23 #include <media/DataSource.h>
24 #include <media/MediaExtractorPluginApi.h>
25 #include <media/MediaExtractorPluginHelper.h>
26 #include <media/stagefright/foundation/ADebug.h>
27 #include <media/stagefright/foundation/ByteUtils.h>
28 #include <utils/String8.h>
29 #include <byteswap.h>
30 
31 namespace android {
32 
33 static const size_t kMaxMetadataSize = 3 * 1024 * 1024;
34 
35 struct ID3::MemorySource : public DataSourceBase {
MemorySourceandroid::ID3::MemorySource36     MemorySource(const uint8_t *data, size_t size)
37         : mData(data),
38           mSize(size) {
39     }
40 
initCheckandroid::ID3::MemorySource41     virtual status_t initCheck() const {
42         return OK;
43     }
44 
readAtandroid::ID3::MemorySource45     virtual ssize_t readAt(off64_t offset, void *data, size_t size) {
46         off64_t available = (offset >= (off64_t)mSize) ? 0LL : mSize - offset;
47 
48         size_t copy = (available > (off64_t)size) ? size : available;
49         memcpy(data, mData + offset, copy);
50 
51         return copy;
52     }
53 
54 private:
55     const uint8_t *mData;
56     size_t mSize;
57 
58     DISALLOW_EVIL_CONSTRUCTORS(MemorySource);
59 };
60 
61 class ID3::DataSourceUnwrapper : public DataSourceBase {
62 
63 public:
DataSourceUnwrapper(DataSourceHelper * sourcehelper)64     explicit DataSourceUnwrapper(DataSourceHelper *sourcehelper) {
65         mSource = sourcehelper;
66     }
initCheck() const67     virtual status_t initCheck() const { return OK; }
68 
69     // Returns the number of bytes read, or -1 on failure. It's not an error if
70     // this returns zero; it just means the given offset is equal to, or
71     // beyond, the end of the source.
readAt(off64_t offset,void * data,size_t size)72     virtual ssize_t readAt(off64_t offset, void *data, size_t size) {
73         return mSource->readAt(offset, data, size);
74     }
75 
76     // May return ERROR_UNSUPPORTED.
getSize(off64_t * size)77     virtual status_t getSize(off64_t *size) {
78         return mSource->getSize(size);
79     }
80 
getUri(char *,size_t)81     virtual bool getUri(char * /*uriString*/, size_t /*bufferSize*/) {
82         return false;
83     }
84 
flags()85     virtual uint32_t flags() {
86         return 0;
87     }
88 
close()89     virtual void close() {};
90 private:
91     DataSourceHelper *mSource;
92 };
93 
94 
ID3(DataSourceHelper * sourcehelper,bool ignoreV1,off64_t offset)95 ID3::ID3(DataSourceHelper *sourcehelper, bool ignoreV1, off64_t offset)
96     : mIsValid(false),
97       mData(NULL),
98       mSize(0),
99       mFirstFrameOffset(0),
100       mVersion(ID3_UNKNOWN),
101       mRawSize(0) {
102     DataSourceUnwrapper source(sourcehelper);
103     mIsValid = parseV2(&source, offset);
104 
105     if (!mIsValid && !ignoreV1) {
106         mIsValid = parseV1(&source);
107     }
108 }
109 
ID3(const uint8_t * data,size_t size,bool ignoreV1)110 ID3::ID3(const uint8_t *data, size_t size, bool ignoreV1)
111     : mIsValid(false),
112       mData(NULL),
113       mSize(0),
114       mFirstFrameOffset(0),
115       mVersion(ID3_UNKNOWN),
116       mRawSize(0) {
117     MemorySource *source = new (std::nothrow) MemorySource(data, size);
118 
119     if (source == NULL)
120         return;
121 
122     mIsValid = parseV2(source, 0);
123 
124     if (!mIsValid && !ignoreV1) {
125         mIsValid = parseV1(source);
126     }
127     delete source;
128 }
129 
~ID3()130 ID3::~ID3() {
131     if (mData) {
132         free(mData);
133         mData = NULL;
134     }
135 }
136 
isValid() const137 bool ID3::isValid() const {
138     return mIsValid;
139 }
140 
version() const141 ID3::Version ID3::version() const {
142     return mVersion;
143 }
144 
145 // static
ParseSyncsafeInteger(const uint8_t encoded[4],size_t * x)146 bool ID3::ParseSyncsafeInteger(const uint8_t encoded[4], size_t *x) {
147     *x = 0;
148     for (int32_t i = 0; i < 4; ++i) {
149         if (encoded[i] & 0x80) {
150             return false;
151         }
152 
153         *x = ((*x) << 7) | encoded[i];
154     }
155 
156     return true;
157 }
158 
parseV2(DataSourceBase * source,off64_t offset)159 bool ID3::parseV2(DataSourceBase *source, off64_t offset) {
160 struct id3_header {
161     char id[3];
162     uint8_t version_major;
163     uint8_t version_minor;
164     uint8_t flags;
165     uint8_t enc_size[4];
166     };
167 
168     id3_header header;
169     if (source->readAt(
170                 offset, &header, sizeof(header)) != (ssize_t)sizeof(header)) {
171         return false;
172     }
173 
174     if (memcmp(header.id, "ID3", 3)) {
175         return false;
176     }
177 
178     if (header.version_major == 0xff || header.version_minor == 0xff) {
179         return false;
180     }
181 
182     if (header.version_major == 2) {
183         if (header.flags & 0x3f) {
184             // We only support the 2 high bits, if any of the lower bits are
185             // set, we cannot guarantee to understand the tag format.
186             return false;
187         }
188 
189         if (header.flags & 0x40) {
190             // No compression scheme has been decided yet, ignore the
191             // tag if compression is indicated.
192 
193             return false;
194         }
195     } else if (header.version_major == 3) {
196         if (header.flags & 0x1f) {
197             // We only support the 3 high bits, if any of the lower bits are
198             // set, we cannot guarantee to understand the tag format.
199             return false;
200         }
201     } else if (header.version_major == 4) {
202         if (header.flags & 0x0f) {
203             // The lower 4 bits are undefined in this spec.
204             return false;
205         }
206     } else {
207         return false;
208     }
209 
210     size_t size;
211     if (!ParseSyncsafeInteger(header.enc_size, &size)) {
212         return false;
213     }
214 
215     if (size > kMaxMetadataSize) {
216         ALOGE("skipping huge ID3 metadata of size %zu", size);
217         return false;
218     }
219 
220     mData = (uint8_t *)malloc(size);
221 
222     if (mData == NULL) {
223         return false;
224     }
225 
226     mSize = size;
227     mRawSize = mSize + sizeof(header);
228 
229     if (source->readAt(offset + sizeof(header), mData, mSize) != (ssize_t)mSize) {
230         free(mData);
231         mData = NULL;
232 
233         return false;
234     }
235 
236     // first handle global unsynchronization
237     if (header.flags & 0x80) {
238         ALOGV("removing unsynchronization");
239 
240         removeUnsynchronization();
241     }
242 
243     // handle extended header, if present
244     mFirstFrameOffset = 0;
245     if (header.version_major == 3 && (header.flags & 0x40)) {
246         // Version 2.3 has an optional extended header.
247 
248         if (mSize < 4) {
249             free(mData);
250             mData = NULL;
251 
252             return false;
253         }
254 
255         // v2.3 does not have syncsafe integers
256         size_t extendedHeaderSize = U32_AT(&mData[0]);
257         if (extendedHeaderSize > SIZE_MAX - 4) {
258             free(mData);
259             mData = NULL;
260             ALOGE("b/24623447, extendedHeaderSize is too large");
261             return false;
262         }
263         extendedHeaderSize += 4;
264 
265         if (extendedHeaderSize > mSize) {
266             free(mData);
267             mData = NULL;
268 
269             return false;
270         }
271 
272         mFirstFrameOffset = extendedHeaderSize;
273 
274         uint16_t extendedFlags = 0;
275         if (extendedHeaderSize >= 6) {
276             extendedFlags = U16_AT(&mData[4]);
277 
278             if (extendedHeaderSize >= 10) {
279                 size_t paddingSize = U32_AT(&mData[6]);
280 
281                 if (paddingSize > SIZE_MAX - mFirstFrameOffset) {
282                     ALOGE("b/24623447, paddingSize is too large");
283                 }
284                 if (paddingSize > mSize - mFirstFrameOffset) {
285                     free(mData);
286                     mData = NULL;
287 
288                     return false;
289                 }
290 
291                 mSize -= paddingSize;
292             }
293 
294             if (extendedFlags & 0x8000) {
295                 ALOGV("have crc");
296             }
297         }
298     } else if (header.version_major == 4 && (header.flags & 0x40)) {
299         // Version 2.4 has an optional extended header, that's different
300         // from Version 2.3's...
301 
302         if (mSize < 4) {
303             free(mData);
304             mData = NULL;
305 
306             return false;
307         }
308 
309         size_t ext_size;
310         if (!ParseSyncsafeInteger(mData, &ext_size)) {
311             free(mData);
312             mData = NULL;
313 
314             return false;
315         }
316 
317         if (ext_size < 6 || ext_size > mSize) {
318             free(mData);
319             mData = NULL;
320 
321             return false;
322         }
323 
324         mFirstFrameOffset = ext_size;
325     }
326 
327     // Handle any v2.4 per-frame unsynchronization
328     // The id3 spec isn't clear about what should happen if the global
329     // unsynchronization flag is combined with per-frame unsynchronization,
330     // or whether that's even allowed, so this code assumes id3 writing
331     // tools do the right thing and not apply double-unsynchronization,
332     // but will honor the flags if they are set.
333     if (header.version_major == 4) {
334         void *copy = malloc(size);
335         if (copy == NULL) {
336             free(mData);
337             mData = NULL;
338             ALOGE("b/24623447, no more memory");
339             return false;
340         }
341 
342         memcpy(copy, mData, size);
343 
344         bool success = removeUnsynchronizationV2_4(false /* iTunesHack */);
345         if (!success) {
346             memcpy(mData, copy, size);
347             mSize = size;
348 
349             success = removeUnsynchronizationV2_4(true /* iTunesHack */);
350 
351             if (success) {
352                 ALOGV("Had to apply the iTunes hack to parse this ID3 tag");
353             }
354         }
355 
356         free(copy);
357         copy = NULL;
358 
359         if (!success) {
360             free(mData);
361             mData = NULL;
362 
363             return false;
364         }
365     }
366 
367 
368 
369     if (header.version_major == 2) {
370         mVersion = ID3_V2_2;
371     } else if (header.version_major == 3) {
372         mVersion = ID3_V2_3;
373     } else {
374         CHECK_EQ(header.version_major, 4);
375         mVersion = ID3_V2_4;
376     }
377 
378     return true;
379 }
380 
removeUnsynchronization()381 void ID3::removeUnsynchronization() {
382 
383     // This file has "unsynchronization", so we have to replace occurrences
384     // of 0xff 0x00 with just 0xff in order to get the real data.
385 
386     size_t writeOffset = 1;
387     for (size_t readOffset = 1; readOffset < mSize; ++readOffset) {
388         if (mData[readOffset - 1] == 0xff && mData[readOffset] == 0x00) {
389             continue;
390         }
391         // Only move data if there's actually something to move.
392         // This handles the special case of the data being only [0xff, 0x00]
393         // which should be converted to just 0xff if unsynchronization is on.
394         mData[writeOffset++] = mData[readOffset];
395     }
396 
397     if (writeOffset < mSize) {
398         mSize = writeOffset;
399     }
400 
401 }
402 
WriteSyncsafeInteger(uint8_t * dst,size_t x)403 static void WriteSyncsafeInteger(uint8_t *dst, size_t x) {
404     for (size_t i = 0; i < 4; ++i) {
405         dst[3 - i] = (x & 0x7f);
406         x >>= 7;
407     }
408 }
409 
removeUnsynchronizationV2_4(bool iTunesHack)410 bool ID3::removeUnsynchronizationV2_4(bool iTunesHack) {
411     size_t oldSize = mSize;
412 
413     size_t offset = mFirstFrameOffset;
414     while (mSize >= 10 && offset <= mSize - 10) {
415         if (!memcmp(&mData[offset], "\0\0\0\0", 4)) {
416             break;
417         }
418 
419         size_t dataSize;
420         if (iTunesHack) {
421             dataSize = U32_AT(&mData[offset + 4]);
422         } else if (!ParseSyncsafeInteger(&mData[offset + 4], &dataSize)) {
423             return false;
424         }
425 
426         if (dataSize > mSize - 10 - offset) {
427             return false;
428         }
429 
430         uint16_t flags = U16_AT(&mData[offset + 8]);
431         uint16_t prevFlags = flags;
432 
433         if (flags & 1) {
434             // Strip data length indicator
435 
436             if (mSize < 14 || mSize - 14 < offset || dataSize < 4) {
437                 return false;
438             }
439             memmove(&mData[offset + 10], &mData[offset + 14], mSize - offset - 14);
440             mSize -= 4;
441             dataSize -= 4;
442 
443             flags &= ~1;
444         }
445 
446         if ((flags & 2) && (dataSize >= 2)) {
447             // This frame has "unsynchronization", so we have to replace occurrences
448             // of 0xff 0x00 with just 0xff in order to get the real data.
449 
450             size_t readOffset = offset + 11;
451             size_t writeOffset = offset + 11;
452             for (size_t i = 0; i + 1 < dataSize; ++i) {
453                 if (mData[readOffset - 1] == 0xff
454                         && mData[readOffset] == 0x00) {
455                     ++readOffset;
456                     --mSize;
457                     --dataSize;
458                 }
459                 if (i + 1 < dataSize) {
460                     // Only move data if there's actually something to move.
461                     // This handles the special case of the data being only [0xff, 0x00]
462                     // which should be converted to just 0xff if unsynchronization is on.
463                     mData[writeOffset++] = mData[readOffset++];
464                 }
465             }
466             // move the remaining data following this frame
467             if (readOffset <= oldSize) {
468                 memmove(&mData[writeOffset], &mData[readOffset], oldSize - readOffset);
469             } else {
470                 ALOGE("b/34618607 (%zu %zu %zu %zu)", readOffset, writeOffset, oldSize, mSize);
471                 android_errorWriteLog(0x534e4554, "34618607");
472             }
473 
474         }
475         flags &= ~2;
476         if (flags != prevFlags || iTunesHack) {
477             WriteSyncsafeInteger(&mData[offset + 4], dataSize);
478             mData[offset + 8] = flags >> 8;
479             mData[offset + 9] = flags & 0xff;
480         }
481 
482         offset += 10 + dataSize;
483     }
484 
485     memset(&mData[mSize], 0, oldSize - mSize);
486 
487     return true;
488 }
489 
Iterator(const ID3 & parent,const char * id)490 ID3::Iterator::Iterator(const ID3 &parent, const char *id)
491     : mParent(parent),
492       mID(NULL),
493       mOffset(mParent.mFirstFrameOffset),
494       mFrameData(NULL),
495       mFrameSize(0) {
496     if (id) {
497         mID = strdup(id);
498     }
499 
500     findFrame();
501 }
502 
~Iterator()503 ID3::Iterator::~Iterator() {
504     if (mID) {
505         free(mID);
506         mID = NULL;
507     }
508 }
509 
done() const510 bool ID3::Iterator::done() const {
511     return mFrameData == NULL;
512 }
513 
next()514 void ID3::Iterator::next() {
515     if (mFrameData == NULL) {
516         return;
517     }
518 
519     mOffset += mFrameSize;
520 
521     findFrame();
522 }
523 
getID(String8 * id) const524 void ID3::Iterator::getID(String8 *id) const {
525     id->setTo("");
526 
527     if (mFrameData == NULL) {
528         return;
529     }
530 
531     if (mParent.mVersion == ID3_V2_2) {
532         id->setTo((const char *)&mParent.mData[mOffset], 3);
533     } else if (mParent.mVersion == ID3_V2_3 || mParent.mVersion == ID3_V2_4) {
534         id->setTo((const char *)&mParent.mData[mOffset], 4);
535     } else {
536         CHECK(mParent.mVersion == ID3_V1 || mParent.mVersion == ID3_V1_1);
537 
538         switch (mOffset) {
539             case 3:
540                 id->setTo("TT2");
541                 break;
542             case 33:
543                 id->setTo("TP1");
544                 break;
545             case 63:
546                 id->setTo("TAL");
547                 break;
548             case 93:
549                 id->setTo("TYE");
550                 break;
551             case 97:
552                 id->setTo("COM");
553                 break;
554             case 126:
555                 id->setTo("TRK");
556                 break;
557             case 127:
558                 id->setTo("TCO");
559                 break;
560             default:
561                 CHECK(!"should not be here.");
562                 break;
563         }
564     }
565 }
566 
567 
568 // the 2nd argument is used to get the data following the \0 in a comment field
getString(String8 * id,String8 * comment) const569 void ID3::Iterator::getString(String8 *id, String8 *comment) const {
570     getstring(id, false);
571     if (comment != NULL) {
572         getstring(comment, true);
573     }
574 }
575 
576 // comment fields (COM/COMM) contain an initial short descriptor, followed by \0,
577 // followed by more data. The data following the \0 can be retrieved by setting
578 // "otherdata" to true.
getstring(String8 * id,bool otherdata) const579 void ID3::Iterator::getstring(String8 *id, bool otherdata) const {
580     id->setTo("");
581 
582     const uint8_t *frameData = mFrameData;
583     if (frameData == NULL) {
584         return;
585     }
586 
587     uint8_t encoding = *frameData;
588 
589     if (mParent.mVersion == ID3_V1 || mParent.mVersion == ID3_V1_1) {
590         if (mOffset == 126 || mOffset == 127) {
591             // Special treatment for the track number and genre.
592             char tmp[16];
593             snprintf(tmp, sizeof(tmp), "%d", (int)*frameData);
594 
595             id->setTo(tmp);
596             return;
597         }
598 
599         // this is supposed to be ISO-8859-1, but pass it up as-is to the caller, who will figure
600         // out the real encoding
601         id->setTo((const char*)frameData, mFrameSize);
602         return;
603     }
604 
605     if (mFrameSize < getHeaderLength() + 1) {
606         return;
607     }
608     size_t n = mFrameSize - getHeaderLength() - 1;
609     if (otherdata) {
610         if (n < 5) {
611             return;
612         }
613         // skip past the encoding, language, and the 0 separator
614         frameData += 4;
615         int32_t i = n - 4;
616         while(--i >= 0 && *++frameData != 0) ;
617         int skipped = (frameData - mFrameData);
618         if (skipped >= (int)n) {
619             return;
620         }
621         n -= skipped;
622     }
623 
624     if (n <= 0) {
625        return;
626     }
627 
628     if (encoding == 0x00) {
629         // supposedly ISO 8859-1
630         id->setTo((const char*)frameData + 1, n);
631     } else if (encoding == 0x03) {
632         // supposedly UTF-8
633         id->setTo((const char *)(frameData + 1), n);
634     } else if (encoding == 0x02) {
635         // supposedly UTF-16 BE, no byte order mark.
636         // API wants number of characters, not number of bytes...
637         int len = n / 2;
638         const char16_t *framedata = (const char16_t *) (frameData + 1);
639         char16_t *framedatacopy = NULL;
640 #if BYTE_ORDER == LITTLE_ENDIAN
641         if (len > 0) {
642             framedatacopy = new (std::nothrow) char16_t[len];
643             if (framedatacopy == NULL) {
644                 return;
645             }
646             for (int i = 0; i < len; i++) {
647                 framedatacopy[i] = bswap_16(framedata[i]);
648             }
649             framedata = framedatacopy;
650         }
651 #endif
652         id->setTo(framedata, len);
653         if (framedatacopy != NULL) {
654             delete[] framedatacopy;
655         }
656     } else if (encoding == 0x01) {
657         // UCS-2
658         // API wants number of characters, not number of bytes...
659         int len = n / 2;
660         if (len == 0) {
661             return;
662         }
663         const char16_t *framedata = (const char16_t *) (frameData + 1);
664         char16_t *framedatacopy = NULL;
665         if (*framedata == 0xfffe) {
666             // endianness marker != host endianness, convert & skip
667             if (len <= 1) {
668                 return;         // nothing after the marker
669             }
670             framedatacopy = new (std::nothrow) char16_t[len];
671             if (framedatacopy == NULL) {
672                 return;
673             }
674             for (int i = 0; i < len; i++) {
675                 framedatacopy[i] = bswap_16(framedata[i]);
676             }
677             framedata = framedatacopy;
678             // and skip over the marker
679             framedata++;
680             len--;
681         } else if (*framedata == 0xfeff) {
682             // endianness marker == host endianness, skip it
683             if (len <= 1) {
684                 return;         // nothing after the marker
685             }
686             framedata++;
687             len--;
688         }
689 
690         // check if the resulting data consists entirely of 8-bit values
691         bool eightBit = true;
692         for (int i = 0; i < len; i++) {
693             if (framedata[i] > 0xff) {
694                 eightBit = false;
695                 break;
696             }
697         }
698         if (eightBit) {
699             // collapse to 8 bit, then let the media scanner client figure out the real encoding
700             char *frame8 = new (std::nothrow) char[len];
701             if (frame8 != NULL) {
702                 for (int i = 0; i < len; i++) {
703                     frame8[i] = framedata[i];
704                 }
705                 id->setTo(frame8, len);
706                 delete [] frame8;
707             } else {
708                 id->setTo(framedata, len);
709             }
710         } else {
711             id->setTo(framedata, len);
712         }
713 
714         if (framedatacopy != NULL) {
715             delete[] framedatacopy;
716         }
717     }
718 }
719 
getData(size_t * length) const720 const uint8_t *ID3::Iterator::getData(size_t *length) const {
721     *length = 0;
722 
723     if (mFrameData == NULL) {
724         return NULL;
725     }
726 
727     // Prevent integer underflow
728     if (mFrameSize < getHeaderLength()) {
729         return NULL;
730     }
731 
732     *length = mFrameSize - getHeaderLength();
733 
734     return mFrameData;
735 }
736 
getHeaderLength() const737 size_t ID3::Iterator::getHeaderLength() const {
738     if (mParent.mVersion == ID3_V2_2) {
739         return 6;
740     } else if (mParent.mVersion == ID3_V2_3 || mParent.mVersion == ID3_V2_4) {
741         return 10;
742     } else {
743         CHECK(mParent.mVersion == ID3_V1 || mParent.mVersion == ID3_V1_1);
744         return 0;
745     }
746 }
747 
findFrame()748 void ID3::Iterator::findFrame() {
749     for (;;) {
750         mFrameData = NULL;
751         mFrameSize = 0;
752 
753         if (mParent.mVersion == ID3_V2_2) {
754             if (mOffset + 6 > mParent.mSize) {
755                 return;
756             }
757 
758             if (!memcmp(&mParent.mData[mOffset], "\0\0\0", 3)) {
759                 return;
760             }
761 
762             mFrameSize =
763                 (mParent.mData[mOffset + 3] << 16)
764                 | (mParent.mData[mOffset + 4] << 8)
765                 | mParent.mData[mOffset + 5];
766 
767             if (mFrameSize == 0) {
768                 return;
769             }
770             mFrameSize += 6; // add tag id and size field
771 
772             // Prevent integer overflow in validation
773             if (SIZE_MAX - mOffset <= mFrameSize) {
774                 return;
775             }
776 
777             if (mOffset + mFrameSize > mParent.mSize) {
778                 ALOGV("partial frame at offset %zu (size = %zu, bytes-remaining = %zu)",
779                     mOffset, mFrameSize, mParent.mSize - mOffset - (size_t)6);
780                 return;
781             }
782 
783             mFrameData = &mParent.mData[mOffset + 6];
784 
785             if (!mID) {
786                 break;
787             }
788 
789             char id[4];
790             memcpy(id, &mParent.mData[mOffset], 3);
791             id[3] = '\0';
792 
793             if (!strcmp(id, mID)) {
794                 break;
795             }
796         } else if (mParent.mVersion == ID3_V2_3
797                 || mParent.mVersion == ID3_V2_4) {
798             if (mOffset + 10 > mParent.mSize) {
799                 return;
800             }
801 
802             if (!memcmp(&mParent.mData[mOffset], "\0\0\0\0", 4)) {
803                 return;
804             }
805 
806             size_t baseSize = 0;
807             if (mParent.mVersion == ID3_V2_4) {
808                 if (!ParseSyncsafeInteger(
809                             &mParent.mData[mOffset + 4], &baseSize)) {
810                     return;
811                 }
812             } else {
813                 baseSize = U32_AT(&mParent.mData[mOffset + 4]);
814             }
815 
816             if (baseSize == 0) {
817                 return;
818             }
819 
820             // Prevent integer overflow when adding
821             if (SIZE_MAX - 10 <= baseSize) {
822                 return;
823             }
824 
825             mFrameSize = 10 + baseSize; // add tag id, size field and flags
826 
827             // Prevent integer overflow in validation
828             if (SIZE_MAX - mOffset <= mFrameSize) {
829                 return;
830             }
831 
832             if (mOffset + mFrameSize > mParent.mSize) {
833                 ALOGV("partial frame at offset %zu (size = %zu, bytes-remaining = %zu)",
834                     mOffset, mFrameSize, mParent.mSize - mOffset - (size_t)10);
835                 return;
836             }
837 
838             uint16_t flags = U16_AT(&mParent.mData[mOffset + 8]);
839 
840             if ((mParent.mVersion == ID3_V2_4 && (flags & 0x000c))
841                 || (mParent.mVersion == ID3_V2_3 && (flags & 0x00c0))) {
842                 // Compression or encryption are not supported at this time.
843                 // Per-frame unsynchronization and data-length indicator
844                 // have already been taken care of.
845 
846                 ALOGV("Skipping unsupported frame (compression, encryption "
847                      "or per-frame unsynchronization flagged");
848 
849                 mOffset += mFrameSize;
850                 continue;
851             }
852 
853             mFrameData = &mParent.mData[mOffset + 10];
854 
855             if (!mID) {
856                 break;
857             }
858 
859             char id[5];
860             memcpy(id, &mParent.mData[mOffset], 4);
861             id[4] = '\0';
862 
863             if (!strcmp(id, mID)) {
864                 break;
865             }
866         } else {
867             CHECK(mParent.mVersion == ID3_V1 || mParent.mVersion == ID3_V1_1);
868 
869             if (mOffset >= mParent.mSize) {
870                 return;
871             }
872 
873             mFrameData = &mParent.mData[mOffset];
874 
875             switch (mOffset) {
876                 case 3:
877                 case 33:
878                 case 63:
879                     mFrameSize = 30;
880                     break;
881                 case 93:
882                     mFrameSize = 4;
883                     break;
884                 case 97:
885                     if (mParent.mVersion == ID3_V1) {
886                         mFrameSize = 30;
887                     } else {
888                         mFrameSize = 29;
889                     }
890                     break;
891                 case 126:
892                     mFrameSize = 1;
893                     break;
894                 case 127:
895                     mFrameSize = 1;
896                     break;
897                 default:
898                     CHECK(!"Should not be here, invalid offset.");
899                     break;
900             }
901 
902             if (!mID) {
903                 break;
904             }
905 
906             String8 id;
907             getID(&id);
908 
909             if (id == mID) {
910                 break;
911             }
912         }
913 
914         mOffset += mFrameSize;
915     }
916 }
917 
918 // return includes terminator;  if unterminated, returns > limit
StringSize(const uint8_t * start,size_t limit,uint8_t encoding)919 static size_t StringSize(const uint8_t *start, size_t limit, uint8_t encoding) {
920 
921     if (encoding == 0x00 || encoding == 0x03) {
922         // ISO 8859-1 or UTF-8
923         return strnlen((const char *)start, limit) + 1;
924     }
925 
926     // UCS-2
927     size_t n = 0;
928     while ((n+1 < limit) && (start[n] != '\0' || start[n + 1] != '\0')) {
929         n += 2;
930     }
931     n += 2;
932     return n;
933 }
934 
935 const void *
getAlbumArt(size_t * length,String8 * mime) const936 ID3::getAlbumArt(size_t *length, String8 *mime) const {
937     *length = 0;
938     mime->setTo("");
939 
940     Iterator it(
941             *this,
942             (mVersion == ID3_V2_3 || mVersion == ID3_V2_4) ? "APIC" : "PIC");
943 
944     while (!it.done()) {
945         size_t size;
946         const uint8_t *data = it.getData(&size);
947         if (!data) {
948             return NULL;
949         }
950 
951         if (mVersion == ID3_V2_3 || mVersion == ID3_V2_4) {
952             uint8_t encoding = data[0];
953             size_t consumed = 1;
954 
955             // *always* in an 8-bit encoding
956             size_t mimeLen = StringSize(&data[consumed], size - consumed, 0x00);
957             if (mimeLen > size - consumed) {
958                 ALOGW("bogus album art size: mime");
959                 return NULL;
960             }
961             mime->setTo((const char *)&data[consumed]);
962             consumed += mimeLen;
963 
964 #if 0
965             uint8_t picType = data[consumed];
966             if (picType != 0x03) {
967                 // Front Cover Art
968                 it.next();
969                 continue;
970             }
971 #endif
972 
973             consumed++;
974             if (consumed >= size) {
975                 ALOGW("bogus album art size: pic type");
976                 return NULL;
977             }
978 
979             size_t descLen = StringSize(&data[consumed], size - consumed, encoding);
980             consumed += descLen;
981 
982             if (consumed >= size) {
983                 ALOGW("bogus album art size: description");
984                 return NULL;
985             }
986 
987             *length = size - consumed;
988 
989             return &data[consumed];
990         } else {
991             uint8_t encoding = data[0];
992 
993             if (size <= 5) {
994                 return NULL;
995             }
996 
997             if (!memcmp(&data[1], "PNG", 3)) {
998                 mime->setTo("image/png");
999             } else if (!memcmp(&data[1], "JPG", 3)) {
1000                 mime->setTo("image/jpeg");
1001             } else if (!memcmp(&data[1], "-->", 3)) {
1002                 mime->setTo("text/plain");
1003             } else {
1004                 return NULL;
1005             }
1006 
1007 #if 0
1008             uint8_t picType = data[4];
1009             if (picType != 0x03) {
1010                 // Front Cover Art
1011                 it.next();
1012                 continue;
1013             }
1014 #endif
1015 
1016             size_t descLen = StringSize(&data[5], size - 5, encoding);
1017             if (descLen > size - 5) {
1018                 return NULL;
1019             }
1020 
1021             *length = size - 5 - descLen;
1022 
1023             return &data[5 + descLen];
1024         }
1025     }
1026 
1027     return NULL;
1028 }
1029 
parseV1(DataSourceBase * source)1030 bool ID3::parseV1(DataSourceBase *source) {
1031     const size_t V1_TAG_SIZE = 128;
1032 
1033     off64_t size;
1034     if (source->getSize(&size) != OK || size < (off64_t)V1_TAG_SIZE) {
1035         return false;
1036     }
1037 
1038     mData = (uint8_t *)malloc(V1_TAG_SIZE);
1039     if (source->readAt(size - V1_TAG_SIZE, mData, V1_TAG_SIZE)
1040             != (ssize_t)V1_TAG_SIZE) {
1041         free(mData);
1042         mData = NULL;
1043 
1044         return false;
1045     }
1046 
1047     if (memcmp("TAG", mData, 3)) {
1048         free(mData);
1049         mData = NULL;
1050 
1051         return false;
1052     }
1053 
1054     mSize = V1_TAG_SIZE;
1055     mFirstFrameOffset = 3;
1056 
1057     if (mData[V1_TAG_SIZE - 3] != 0) {
1058         mVersion = ID3_V1;
1059     } else {
1060         mVersion = ID3_V1_1;
1061     }
1062 
1063     return true;
1064 }
1065 
1066 }  // namespace android
1067