Bug 1158568 - Fix potential size overflow. r=kentuckyfriedtakahe, a=abillings
authorJean-Yves Avenard <jyavenard@mozilla.com>
Sun, 26 Apr 2015 16:05:10 +1000
changeset 260332 8a61f534f496
parent 260331 b9f3bdfbf395
child 260333 28521384c589
push id754
push userryanvm@gmail.com
push date2015-04-30 21:03 +0000
treeherdermozilla-release@d262c6789549 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerskentuckyfriedtakahe, abillings
bugs1158568
milestone38.0
Bug 1158568 - Fix potential size overflow. r=kentuckyfriedtakahe, a=abillings
media/libstagefright/frameworks/av/media/libstagefright/MPEG4Extractor.cpp
--- a/media/libstagefright/frameworks/av/media/libstagefright/MPEG4Extractor.cpp
+++ b/media/libstagefright/frameworks/av/media/libstagefright/MPEG4Extractor.cpp
@@ -35,16 +35,19 @@
 #include <media/stagefright/foundation/AMessage.h>
 #include <media/stagefright/MediaBuffer.h>
 #include <media/stagefright/MediaDefs.h>
 #include <media/stagefright/MediaSource.h>
 #include <media/stagefright/MetaData.h>
 #include <utils/String8.h>
 #include "nsTArray.h"
 
+static const uint32_t kMAX_ALLOCATION =
+    (SIZE_MAX < INT32_MAX ? SIZE_MAX : INT32_MAX) - 128;
+
 namespace stagefright {
 
 class MPEG4Source : public MediaSource {
 public:
     // Caller retains ownership of both "dataSource" and "sampleTable".
     MPEG4Source(const sp<MetaData> &format,
                 const sp<DataSource> &dataSource,
                 int32_t timeScale,
@@ -759,16 +762,21 @@ status_t MPEG4Extractor::parseChunk(off6
             // The smallest valid chunk is 16 bytes long in this case.
             return ERROR_MALFORMED;
         }
     } else if (chunk_size < 8) {
         // The smallest valid chunk is 8 bytes long.
         return ERROR_MALFORMED;
     }
 
+    if (chunk_size >= kMAX_ALLOCATION) {
+        // Could cause an overflow later. Abort.
+        return ERROR_MALFORMED;
+    }
+
     char chunk[5];
     MakeFourCCString(chunk_type, chunk);
     ALOGV("chunk: %s @ %lld, %d", chunk, *offset, depth);
 
 #if 0
     static const char kWhitespace[] = "                                        ";
     const char *indent = &kWhitespace[sizeof(kWhitespace) - 1 - 2 * depth];
     printf("%sfound chunk '%s' of size %lld\n", indent, chunk, chunk_size);
@@ -1839,17 +1847,17 @@ status_t MPEG4Extractor::parseChunk(off6
             const void *data;
             size_t size = 0;
             if (!mLastTrack->meta->findData(
                     kKeyTextFormatData, &type, &data, &size)) {
                 size = 0;
             }
 
             // Make sure (size + chunk_size) isn't going to overflow.
-            if (size > (size_t)-1 - chunk_size) {
+            if (size >= kMAX_ALLOCATION - chunk_size) {
                 return ERROR_MALFORMED;
             }
             uint8_t *buffer = new uint8_t[size + chunk_size];
 
             if (size > 0) {
                 memcpy(buffer, data, size);
             }
 
@@ -2192,22 +2200,25 @@ status_t MPEG4Extractor::parseTrackHeade
     return OK;
 }
 
 status_t MPEG4Extractor::parseMetaData(off64_t offset, size_t size) {
     if (size < 4) {
         return ERROR_MALFORMED;
     }
 
-    uint8_t *buffer = new uint8_t[size + 1];
+    FallibleTArray<uint8_t> bufferBackend;
+    if (!bufferBackend.SetLength(size + 1)) {
+        // OOM ignore metadata.
+        return OK;
+    }
+
+    uint8_t *buffer = bufferBackend.Elements();
     if (mDataSource->readAt(
                 offset, buffer, size) != (ssize_t)size) {
-        delete[] buffer;
-        buffer = NULL;
-
         return ERROR_IO;
     }
 
     uint32_t flags = U32_AT(buffer);
 
     uint32_t metadataKey = 0;
     char chunk[5];
     MakeFourCCString(mPath[4], chunk);
@@ -2368,19 +2379,16 @@ status_t MPEG4Extractor::parseMetaData(o
         } else {
             buffer[size] = '\0';
 
             mFileMetaData->setCString(
                     metadataKey, (const char *)buffer + 8);
         }
     }
 
-    delete[] buffer;
-    buffer = NULL;
-
     return OK;
 }
 
 sp<MediaSource> MPEG4Extractor::getTrack(size_t index) {
     status_t err;
     if ((err = readMetaData()) != OK) {
         return NULL;
     }
@@ -2688,17 +2696,17 @@ status_t MPEG4Source::parseChunk(off64_t
             // The smallest valid chunk is 16 bytes long in this case.
             return ERROR_MALFORMED;
         }
     } else if (chunk_size < 8) {
         // The smallest valid chunk is 8 bytes long.
         return ERROR_MALFORMED;
     }
 
-    if (chunk_size >= INT32_MAX - 128) {
+    if (chunk_size >= kMAX_ALLOCATION) {
         // Could cause an overflow later. Abort.
         return ERROR_MALFORMED;
     }
 
     char chunk[5];
     MakeFourCCString(chunk_type, chunk);
     ALOGV("MPEG4Source chunk %s @ %llx", chunk, *offset);