Bug 1149605 - Avoid potential integers overflow. r=kentuckyfriedtakahe, a=abillings
authorJean-Yves Avenard <jyavenard@mozilla.com>
Sun, 26 Apr 2015 14:42:37 +1000
changeset 260320 fcfec0caa7be
parent 260319 daaa2c27b89f
child 260321 0a1accb16d39
push id747
push userryanvm@gmail.com
push date2015-04-29 13:09 +0000
treeherdermozilla-release@fcfec0caa7be [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerskentuckyfriedtakahe, abillings
bugs1149605
milestone38.0
Bug 1149605 - Avoid potential integers overflow. r=kentuckyfriedtakahe, a=abillings
media/libstagefright/frameworks/av/media/libstagefright/SampleTable.cpp
--- a/media/libstagefright/frameworks/av/media/libstagefright/SampleTable.cpp
+++ b/media/libstagefright/frameworks/av/media/libstagefright/SampleTable.cpp
@@ -23,29 +23,34 @@
 #include "include/SampleIterator.h"
 
 #include <arpa/inet.h>
 
 #include <media/stagefright/foundation/ADebug.h>
 #include <media/stagefright/DataSource.h>
 #include <media/stagefright/Utils.h>
 
+#include <stdint.h>
+
 namespace stagefright {
 
 // static
 const uint32_t SampleTable::kChunkOffsetType32 = FOURCC('s', 't', 'c', 'o');
 // static
 const uint32_t SampleTable::kChunkOffsetType64 = FOURCC('c', 'o', '6', '4');
 // static
 const uint32_t SampleTable::kSampleSizeType32 = FOURCC('s', 't', 's', 'z');
 // static
 const uint32_t SampleTable::kSampleSizeTypeCompact = FOURCC('s', 't', 'z', '2');
 
 const uint32_t kAuxTypeCenc = FOURCC('c', 'e', 'n', 'c');
 
+static const uint32_t kMAX_ALLOCATION =
+    (SIZE_MAX < INT32_MAX ? SIZE_MAX : INT32_MAX) - 128;
+
 ////////////////////////////////////////////////////////////////////////////////
 
 struct SampleTable::CompositionDeltaLookup {
     CompositionDeltaLookup();
 
     void setEntries(
             const uint32_t *deltaEntries, size_t numDeltaEntries);
 
@@ -200,21 +205,21 @@ status_t SampleTable::setChunkOffsetPara
     if (U32_AT(header) != 0) {
         // Expected version = 0, flags = 0.
         return ERROR_MALFORMED;
     }
 
     mNumChunkOffsets = U32_AT(&header[4]);
 
     if (mChunkOffsetType == kChunkOffsetType32) {
-        if (data_size < 8 + mNumChunkOffsets * 4) {
+        if (data_size < 8 + (uint64_t)mNumChunkOffsets * 4) {
             return ERROR_MALFORMED;
         }
     } else {
-        if (data_size < 8 + mNumChunkOffsets * 8) {
+        if (data_size < 8 + (uint64_t)mNumChunkOffsets * 8) {
             return ERROR_MALFORMED;
         }
     }
 
     return OK;
 }
 
 status_t SampleTable::setSampleToChunkParams(
@@ -237,17 +242,17 @@ status_t SampleTable::setSampleToChunkPa
 
     if (U32_AT(header) != 0) {
         // Expected version = 0, flags = 0.
         return ERROR_MALFORMED;
     }
 
     mNumSampleToChunkOffsets = U32_AT(&header[4]);
 
-    if (data_size < 8 + mNumSampleToChunkOffsets * 12) {
+    if (data_size < 8 + (uint64_t)mNumSampleToChunkOffsets * 12) {
         return ERROR_MALFORMED;
     }
 
     mSampleToChunkEntries =
         new SampleToChunkEntry[mNumSampleToChunkOffsets];
 
     for (uint32_t i = 0; i < mNumSampleToChunkOffsets; ++i) {
         uint8_t buffer[12];
@@ -301,34 +306,34 @@ status_t SampleTable::setSampleSizeParam
 
     if (type == kSampleSizeType32) {
         mSampleSizeFieldSize = 32;
 
         if (mDefaultSampleSize != 0) {
             return OK;
         }
 
-        if (data_size < 12 + mNumSampleSizes * 4) {
+        if (data_size < 12 + (uint64_t)mNumSampleSizes * 4) {
             return ERROR_MALFORMED;
         }
     } else {
         if ((mDefaultSampleSize & 0xffffff00) != 0) {
             // The high 24 bits are reserved and must be 0.
             return ERROR_MALFORMED;
         }
 
         mSampleSizeFieldSize = mDefaultSampleSize & 0xff;
         mDefaultSampleSize = 0;
 
         if (mSampleSizeFieldSize != 4 && mSampleSizeFieldSize != 8
             && mSampleSizeFieldSize != 16) {
             return ERROR_MALFORMED;
         }
 
-        if (data_size < 12 + (mNumSampleSizes * mSampleSizeFieldSize + 4) / 8) {
+        if (data_size < 12 + ((uint64_t)mNumSampleSizes * mSampleSizeFieldSize + 4) / 8) {
             return ERROR_MALFORMED;
         }
     }
 
     return OK;
 }
 
 status_t SampleTable::setTimeToSampleParams(
@@ -344,16 +349,20 @@ status_t SampleTable::setTimeToSamplePar
     }
 
     if (U32_AT(header) != 0) {
         // Expected version = 0, flags = 0.
         return ERROR_MALFORMED;
     }
 
     mTimeToSampleCount = U32_AT(&header[4]);
+    if (mTimeToSampleCount > kMAX_ALLOCATION / 2 / sizeof(uint32_t)) {
+        // Avoid later overflow.
+        return ERROR_MALFORMED;
+    }
     mTimeToSample = new uint32_t[mTimeToSampleCount * 2];
 
     size_t size = sizeof(uint32_t) * mTimeToSampleCount * 2;
     if (mDataSource->readAt(
                 data_offset + 8, mTimeToSample, size) < (ssize_t)size) {
         return ERROR_IO;
     }
 
@@ -379,19 +388,19 @@ status_t SampleTable::setCompositionTime
         return ERROR_IO;
     }
 
     if (U32_AT(header) != 0) {
         // Expected version = 0, flags = 0.
         return ERROR_MALFORMED;
     }
 
-    size_t numEntries = U32_AT(&header[4]);
+    uint32_t numEntries = U32_AT(&header[4]);
 
-    if (data_size != (numEntries + 1) * 8) {
+    if (data_size != ((uint64_t)numEntries + 1) * 8) {
         return ERROR_MALFORMED;
     }
 
     mNumCompositionTimeDeltaEntries = numEntries;
     mCompositionTimeDeltaEntries = new uint32_t[2 * numEntries];
 
     if (mDataSource->readAt(
                 data_offset + 8, mCompositionTimeDeltaEntries, numEntries * 8)
@@ -426,16 +435,20 @@ status_t SampleTable::setSyncSampleParam
     }
 
     if (U32_AT(header) != 0) {
         // Expected version = 0, flags = 0.
         return ERROR_MALFORMED;
     }
 
     mNumSyncSamples = U32_AT(&header[4]);
+    if (mNumSyncSamples > kMAX_ALLOCATION / sizeof(uint32_t)) {
+        // Avoid later overflow.
+        return ERROR_MALFORMED;
+    }
 
     if (mNumSyncSamples < 2) {
         ALOGV("Table of sync samples is empty or has only a single entry!");
     }
 
     mSyncSamples = new uint32_t[mNumSyncSamples];
     size_t size = mNumSyncSamples * sizeof(uint32_t);
     if (mDataSource->readAt(mSyncSampleOffset + 8, mSyncSamples, size)
@@ -602,16 +615,21 @@ SampleTable::parseSampleCencInfo() {
         return OK;
     }
 
     if (!mCencSizes.isEmpty() && mCencOffsets.size() > 1 &&
         mCencSizes.size() != mCencOffsets.size()) {
         return ERROR_MALFORMED;
     }
 
+    if (mCencInfoCount > kMAX_ALLOCATION / sizeof(SampleCencInfo)) {
+        // Avoid future OOM.
+        return ERROR_MALFORMED;
+    }
+
     mCencInfo = new SampleCencInfo[mCencInfoCount];
     for (uint32_t i = 0; i < mCencInfoCount; i++) {
         mCencInfo[i].mSubsamples = NULL;
     }
 
     uint64_t nextOffset = mCencOffsets[0];
     for (uint32_t i = 0; i < mCencInfoCount; i++) {
         uint8_t size = mCencDefaultSize ? mCencDefaultSize : mCencSizes[i];