cas: validate shared buffer size before using -- DO NOT MERGE

bug: 67962232

test:
cts MediaCasTest

Change-Id: I6bafa324fe6bca5c6a172cc4f9f724ba9f44b7ba
diff --git a/drm/libmediadrm/DescramblerImpl.cpp b/drm/libmediadrm/DescramblerImpl.cpp
index 94e09e2..5764669 100644
--- a/drm/libmediadrm/DescramblerImpl.cpp
+++ b/drm/libmediadrm/DescramblerImpl.cpp
@@ -20,8 +20,9 @@
 #include <media/cas/DescramblerAPI.h>
 #include <media/DescramblerImpl.h>
 #include <media/SharedLibrary.h>
-#include <utils/Log.h>
+#include <media/stagefright/foundation/AUtils.h>
 #include <binder/IMemory.h>
+#include <utils/Log.h>
 
 namespace android {
 
@@ -74,10 +75,57 @@
     return getBinderStatus(OK);
 }
 
+static inline bool validateRangeForSize(
+        uint64_t offset, uint64_t length, uint64_t size) {
+    return isInRange<uint64_t, uint64_t>(0, size, offset, length);
+}
+
 Status DescramblerImpl::descramble(
         const DescrambleInfo& info, int32_t *result) {
     ALOGV("descramble");
 
+    if (info.srcMem == NULL || info.srcMem->pointer() == NULL) {
+        ALOGE("srcMem is invalid");
+        return getBinderStatus(BAD_VALUE);
+    }
+
+    // use 64-bit here to catch bad subsample size that might be overflowing.
+    uint64_t totalBytesInSubSamples = 0;
+    for (size_t i = 0; i < info.numSubSamples; i++) {
+        totalBytesInSubSamples += (uint64_t)info.subSamples[i].mNumBytesOfClearData +
+                info.subSamples[i].mNumBytesOfEncryptedData;
+    }
+    // validate if the specified srcOffset and requested total subsample size
+    // is consistent with the source shared buffer size.
+    if (!validateRangeForSize(info.srcOffset, totalBytesInSubSamples, info.srcMem->size())) {
+        ALOGE("Invalid srcOffset and subsample size: "
+                "srcOffset %llu, totalBytesInSubSamples %llu, srcMem size %llu",
+                (unsigned long long) info.srcOffset,
+                (unsigned long long) totalBytesInSubSamples,
+                (unsigned long long) info.srcMem->size());
+        android_errorWriteLog(0x534e4554, "67962232");
+        return getBinderStatus(BAD_VALUE);
+    }
+    void *dstPtr = NULL;
+    if (info.dstType == DescrambleInfo::kDestinationTypeVmPointer) {
+        // When using shared memory, src buffer is also used as dst
+        dstPtr = info.srcMem->pointer();
+
+        // In this case the dst and src would be the same buffer, need to validate
+        // dstOffset against the buffer size too.
+        if (!validateRangeForSize(info.dstOffset, totalBytesInSubSamples, info.srcMem->size())) {
+            ALOGE("Invalid dstOffset and subsample size: "
+                    "dstOffset %llu, totalBytesInSubSamples %llu, srcBuffer size %llu",
+                    (unsigned long long) info.dstOffset,
+                    (unsigned long long) totalBytesInSubSamples,
+                    (unsigned long long) info.srcMem->size());
+            android_errorWriteLog(0x534e4554, "67962232");
+            return getBinderStatus(BAD_VALUE);
+        }
+    } else {
+        dstPtr = info.dstPtr;
+    }
+
     *result = mPlugin->descramble(
             info.dstType != DescrambleInfo::kDestinationTypeVmPointer,
             info.scramblingControl,
@@ -85,8 +133,7 @@
             info.subSamples,
             info.srcMem->pointer(),
             info.srcOffset,
-            info.dstType == DescrambleInfo::kDestinationTypeVmPointer ?
-                    info.srcMem->pointer() : info.dstPtr,
+            dstPtr,
             info.dstOffset,
             NULL);