Bug 1346648 - Better pointer checks. r=cpearce
authorGerald Squelart <gsquelart@mozilla.com>
Tue, 14 Mar 2017 09:33:16 +1100
changeset 501793 d45b0f72d98aba5c55ac3ad4b5fc548edbeb30f4
parent 501792 083daa40d2d70bad15dd135276905f8ed9c08b51
child 501794 dfa17169cf1f69da44edf276b420eb6af4d0bbef
push id50127
push userna-g@nostrum.com
push dateTue, 21 Mar 2017 00:09:45 +0000
reviewerscpearce
bugs1346648
milestone55.0a1
Bug 1346648 - Better pointer checks. r=cpearce MozReview-Commit-ID: BjYCYS4h5qN
media/gmp-clearkey/0.1/ClearKeyDecryptionManager.cpp
--- a/media/gmp-clearkey/0.1/ClearKeyDecryptionManager.cpp
+++ b/media/gmp-clearkey/0.1/ClearKeyDecryptionManager.cpp
@@ -18,16 +18,18 @@
 
 #include "psshparser/PsshParser.h"
 
 #include <assert.h>
 #include <string.h>
 #include <vector>
 #include <algorithm>
 
+#include "mozilla/CheckedInt.h"
+
 using namespace cdm;
 
 bool AllZero(const std::vector<uint32_t>& aBytes)
 {
   return all_of(aBytes.begin(), aBytes.end(), [](uint32_t b) { return b == 0; });
 }
 
 class ClearKeyDecryptor : public RefCounted
@@ -206,29 +208,38 @@ ClearKeyDecryptor::Decrypt(uint8_t* aBuf
   CK_LOGD("ClearKeyDecryptor::Decrypt");
   // If the sample is split up into multiple encrypted subsamples, we need to
   // stitch them into one continuous buffer for decryption.
   std::vector<uint8_t> tmp(aBufferSize);
 
   if (aMetadata.NumSubsamples()) {
     // Take all encrypted parts of subsamples and stitch them into one
     // continuous encrypted buffer.
-    uint8_t* data = aBuffer;
+    static_assert(sizeof(uintptr_t) == sizeof(uint8_t*),
+                  "We need uintptr_t to be exactly the same size as a pointer");
+    mozilla::CheckedInt<uintptr_t> data = reinterpret_cast<uintptr_t>(aBuffer);
+    const uintptr_t endBuffer =
+      reinterpret_cast<uintptr_t>(aBuffer + aBufferSize);
     uint8_t* iter = &tmp[0];
     for (size_t i = 0; i < aMetadata.NumSubsamples(); i++) {
       data += aMetadata.mClearBytes[i];
-      uint32_t cipherBytes = aMetadata.mCipherBytes[i];
-      if (data + cipherBytes > aBuffer + aBufferSize) {
+      if (!data.isValid() || data.value() > endBuffer) {
+        // Trying to read past the end of the buffer!
+        return Status::kDecryptError;
+      }
+      const uint32_t& cipherBytes = aMetadata.mCipherBytes[i];
+      mozilla::CheckedInt<uintptr_t> dataAfterCipher = data + cipherBytes;
+      if (!dataAfterCipher.isValid() || dataAfterCipher.value() > endBuffer) {
         // Trying to read past the end of the buffer!
         return Status::kDecryptError;
       }
 
-      memcpy(iter, data, cipherBytes);
+      memcpy(iter, reinterpret_cast<uint8_t*>(data.value()), cipherBytes);
 
-      data += cipherBytes;
+      data = dataAfterCipher;
       iter += cipherBytes;
     }
 
     tmp.resize((size_t)(iter - &tmp[0]));
   } else {
     memcpy(&tmp[0], aBuffer, aBufferSize);
   }