Bug 1346648 - Better pointer checks. r=cpearce
authorGerald Squelart <gsquelart@mozilla.com>
Tue, 14 Mar 2017 09:33:16 +1100
changeset 348523 d45b0f72d98aba5c55ac3ad4b5fc548edbeb30f4
parent 348522 083daa40d2d70bad15dd135276905f8ed9c08b51
child 348524 dfa17169cf1f69da44edf276b420eb6af4d0bbef
push id31526
push userkwierso@gmail.com
push dateTue, 21 Mar 2017 01:20:02 +0000
treeherdermozilla-central@5fe5dcf1c10a [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerscpearce
bugs1346648
milestone55.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 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);
   }