diff --git a/NEWS b/NEWS index 1fe13d57..59c28d10 100644 --- a/NEWS +++ b/NEWS @@ -2,7 +2,8 @@ TagLib 1.11 (Jan 30, 2016) ========================== * Better handling of PCM WAV files with a 'fact' chunk. - + * Better handling of corrupted APE tags. + 1.11 BETA: * New API for creating FileRef from IOStream. diff --git a/taglib/ape/apeitem.cpp b/taglib/ape/apeitem.cpp index ebfb13df..86d1af97 100644 --- a/taglib/ape/apeitem.cpp +++ b/taglib/ape/apeitem.cpp @@ -34,7 +34,9 @@ using namespace APE; class APE::Item::ItemPrivate { public: - ItemPrivate() : type(Text), readOnly(false) {} + ItemPrivate() : + type(Text), + readOnly(false) {} Item::ItemTypes type; String key; @@ -74,8 +76,9 @@ APE::Item::Item(const String &key, const ByteVector &value, bool binary) : d->type = Binary; d->value = value; } - else + else { d->text.append(value); + } } APE::Item::Item(const Item &item) : @@ -181,9 +184,8 @@ void APE::Item::appendValues(const StringList &values) int APE::Item::size() const { - // SFB: Why is d->key.size() used when size() returns the length in UniChars and not UTF-8? - int result = 8 + d->key.size() /* d->key.data(String::UTF8).size() */ + 1; - switch (d->type) { + int result = 8 + d->key.size() + 1; + switch(d->type) { case Text: if(!d->text.isEmpty()) { StringList::ConstIterator it = d->text.begin(); @@ -250,7 +252,9 @@ void APE::Item::parse(const ByteVector &data) const unsigned int valueLength = data.toUInt(0, false); const unsigned int flags = data.toUInt(4, false); - d->key = String(data.mid(8), String::UTF8); + // An item key can contain ASCII characters from 0x20 up to 0x7E, not UTF-8. + + d->key = String(data.mid(8), String::Latin1); const ByteVector value = data.mid(8 + d->key.size() + 1, valueLength); @@ -288,7 +292,7 @@ ByteVector APE::Item::render() const data.append(ByteVector::fromUInt(value.size(), false)); data.append(ByteVector::fromUInt(flags, false)); - data.append(d->key.data(String::UTF8)); + data.append(d->key.data(String::Latin1)); data.append(ByteVector('\0')); data.append(value); diff --git a/taglib/ape/apetag.cpp b/taglib/ape/apetag.cpp index 4b020413..6109d139 100644 --- a/taglib/ape/apetag.cpp +++ b/taglib/ape/apetag.cpp @@ -43,6 +43,20 @@ using namespace TagLib; using namespace APE; +namespace +{ + inline bool isValidItemKey(const String &key) + { + for(String::ConstIterator it = key.begin(); it != key.end(); ++it) { + const int c = static_cast(*it); + if(c < 0x20 || 0x7E < c) + return false; + } + + return true; + } +} + class APE::Tag::TagPrivate { public: @@ -381,7 +395,8 @@ void APE::Tag::parse(const ByteVector &data) APE::Item item; item.parse(data.mid(pos)); - d->itemListMap.insert(item.key().upper(), item); + if(isValidItemKey(item.key())) + d->itemListMap.insert(item.key().upper(), item); pos += item.size(); }