Bug 1140797 - Prevent fatal assert when doing base64 decode in gmp-clearkey. r=edwin, a=lmandel
authorChris Pearce <cpearce@mozilla.com>
Mon, 09 Mar 2015 08:27:18 +1300
changeset 250436 29333933d6d6
parent 250435 a49b40d229df
child 250437 938177ece421
push id4589
push userryanvm@gmail.com
push date2015-03-19 02:20 +0000
treeherdermozilla-beta@d76c709556bb [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersedwin, lmandel
bugs1140797
milestone37.0
Bug 1140797 - Prevent fatal assert when doing base64 decode in gmp-clearkey. r=edwin, a=lmandel
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.