Vulnerability: The parse function in ogg/xiphcomment.cpp in TagLib 1.7 and earlier allows remote attackers to cause a denial of service (crash) via a crafted vendorLength field in an ogg file.
Vulnerability ID: CVE-2012-1108
CWE: CWE-20
Severity score: 2.9
Project: https://github.com/taglib/taglib
Published: 2012-09-06
File: taglib/ogg/xiphcomment.cpp
Commit message: Be more careful when parsing Vorbis Comments
Commit author: Frank Lai

Vulnerable version (before fix):
 void Ogg::XiphComment::parse(const ByteVector &data)    // Next the number of fields in the comment vector.    int commentFields = data.mid(pos, 4).toUInt(false);   pos += 4;    for(int i = 0; i < commentFields; i++) {      // Each comment field is in the format "KEY=value" in a UTF8 string and has     // 4 bytes before the text starts that gives the length.      int commentLength = data.mid(pos, 4).toUInt(false);     pos += 4;      String comment = String(data.mid(pos, commentLength), String::UTF8);     pos += commentLength;      int commentSeparatorPosition = comment.find("=");      String key = comment.substr(0, commentSeparatorPosition);     String value = comment.substr(commentSeparatorPosition + 1);

Fixed version (after fix):
 void Ogg::XiphComment::parse(const ByteVector &data)    // Next the number of fields in the comment vector.    uint commentFields = data.mid(pos, 4).toUInt(false);   pos += 4;    if(commentFields > (data.size() - 8) / 4) {     return;   }    for(uint i = 0; i < commentFields; i++) {      // Each comment field is in the format "KEY=value" in a UTF8 string and has     // 4 bytes before the text starts that gives the length.      uint commentLength = data.mid(pos, 4).toUInt(false);     pos += 4;      String comment = String(data.mid(pos, commentLength), String::UTF8);     pos += commentLength;     if(pos > data.size()) {       break;     }      int commentSeparatorPosition = comment.find("=");     if(commentSeparatorPosition == -1) {       break;     }      String key = comment.substr(0, commentSeparatorPosition);     String value = comment.substr(commentSeparatorPosition + 1);

Patch:
patch: @@ -295,21 +295,31 @@ void Ogg::XiphComment::parse(const ByteVector &data)
 
   // Next the number of fields in the comment vector.
 
-  int commentFields = data.mid(pos, 4).toUInt(false);
+  uint commentFields = data.mid(pos, 4).toUInt(false);
   pos += 4;
 
-  for(int i = 0; i < commentFields; i++) {
+  if(commentFields > (data.size() - 8) / 4) {
+    return;
+  }
+
+  for(uint i = 0; i < commentFields; i++) {
 
     // Each comment field is in the format "KEY=value" in a UTF8 string and has
     // 4 bytes before the text starts that gives the length.
 
-    int commentLength = data.mid(pos, 4).toUInt(false);
+    uint commentLength = data.mid(pos, 4).toUInt(false);
     pos += 4;
 
     String comment = String(data.mid(pos, commentLength), String::UTF8);
     pos += commentLength;
+    if(pos > data.size()) {
+      break;
+    }
 
     int commentSeparatorPosition = comment.find("=");
+    if(commentSeparatorPosition == -1) {
+      break;
+    }
 
     String key = comment.substr(0, commentSeparatorPosition);
     String value = comment.substr(commentSeparatorPosition + 1);
path: taglib/ogg/xiphcomment.cpp