Bug 1140797 - Prevent fatal assert when doing base64 decode in gmp-clearkey. r=edwin
authorChris Pearce <cpearce@mozilla.com>
Mon, 09 Mar 2015 08:27:18 +1300
changeset 232476 cd14abe258462fc2b835469a513a8b826e6cc14f
parent 232475 58d2dbe695c43162703d882bf8c49b78c1cb7a71
child 232477 8d6612e510fc6279fd91cc7a2f3fb8b0626078a3
push id28384
push usercbook@mozilla.com
push dateMon, 09 Mar 2015 12:46:25 +0000
treeherdermozilla-central@23f1f0369df5 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersedwin
bugs1140797
milestone39.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1140797 - Prevent fatal assert when doing base64 decode in gmp-clearkey. r=edwin
media/gmp-clearkey/0.1/ClearKeyUtils.cpp
--- a/media/gmp-clearkey/0.1/ClearKeyUtils.cpp
+++ b/media/gmp-clearkey/0.1/ClearKeyUtils.cpp
@@ -390,45 +390,51 @@ Decode6Bit(string& aStr)
       break;
     }
   }
 
   return true;
 }
 
 static bool
-DecodeBase64(string& aEncoded, vector<uint8_t>& aOutDecoded)
+DecodeBase64KeyOrId(string& aEncoded, vector<uint8_t>& aOutDecoded)
 {
-  if (!Decode6Bit(aEncoded)) {
+  if (aEncoded.size() != 22 || // Can't decode to 16 byte CENC key or keyId.
+      !Decode6Bit(aEncoded)) {
     return false;
   }
 
   // The number of bytes we haven't yet filled in the current byte, mod 8.
   int shift = 0;
 
-  aOutDecoded.resize(aEncoded.length() * 6 / 8);
-  aOutDecoded.reserve(aEncoded.length() * 6 / 8 + 1);
-  auto out = aOutDecoded.begin();
+  aOutDecoded.resize(16);
+  vector<uint8_t>::iterator out = aOutDecoded.begin();
   for (size_t i = 0; i < aEncoded.length(); i++) {
     if (!shift) {
       *out = aEncoded[i] << 2;
     } else {
       *out |= aEncoded[i] >> (6 - shift);
-      *(++out) = aEncoded[i] << (shift + 2);
+      out++;
+      if (out == aOutDecoded.end()) {
+        // Hit last 6bit octed in encoded, which is padding and can be ignored.
+        break;
+      }
+      *out = aEncoded[i] << (shift + 2);
     }
     shift = (shift + 2) % 8;
   }
 
   return true;
 }
 
 static bool
 DecodeKey(string& aEncoded, Key& aOutDecoded)
 {
-  return DecodeBase64(aEncoded, aOutDecoded) &&
+  return
+    DecodeBase64KeyOrId(aEncoded, aOutDecoded) &&
     // Key should be 128 bits long.
     aOutDecoded.size() == CLEARKEY_KEY_LEN;
 }
 
 static bool
 ParseKeyObject(ParserContext& aCtx, KeyIdPair& aOutKey)
 {
   EXPECT_SYMBOL(aCtx, '{');
@@ -472,17 +478,17 @@ ParseKeyObject(ParserContext& aCtx, KeyI
     if (!sym || sym == '}') {
       break;
     }
     EXPECT_SYMBOL(aCtx, ',');
   }
 
   return !key.empty() &&
          !keyId.empty() &&
-         DecodeBase64(keyId, aOutKey.mKeyId) &&
+         DecodeBase64KeyOrId(keyId, aOutKey.mKeyId) &&
          DecodeKey(key, aOutKey.mKey) &&
          GetNextSymbol(aCtx) == '}';
 }
 
 static bool
 ParseKeys(ParserContext& aCtx, vector<KeyIdPair>& aOutKeys)
 {
   // Consume start of array.