]> granicus.if.org Git - taglib/commitdiff
APE item keys should be ASCII between 0x20 and 0x7E, not UTF-8.
authorTsuda Kageyu <tsuda.kageyu@gmail.com>
Mon, 1 Feb 2016 13:19:43 +0000 (22:19 +0900)
committerTsuda Kageyu <tsuda.kageyu@gmail.com>
Mon, 1 Feb 2016 13:19:43 +0000 (22:19 +0900)
NEWS
taglib/ape/apeitem.cpp
taglib/ape/apetag.cpp

diff --git a/NEWS b/NEWS
index 1fe13d57f7f33a091cfb94e3b32b4907ac9c3541..59c28d106bf9ca534cd7a6d4011508833991b6bf 100644 (file)
--- 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.
index ebfb13df548eedab26669c25182d91a528ecbd60..86d1af97d156ab16eea4ec05e8d9074073d01b31 100644 (file)
@@ -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);
 
index 4b0204135ab786c10cb34eff213b7ba45c3c5e75..6109d1395c161249edaf693dbaeace849df0f327 100644 (file)
 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<unsigned short>(*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();
   }