Bug 1232069 - Check box sizes before alloc&copy. r=jya
authorGerald Squelart <gsquelart@mozilla.com>
Tue, 29 Dec 2015 13:12:14 -0500 (2015-12-29)
changeset 277858 2a57c0a0cf19b32f5fa9cb72c44a92e3319d14a0
parent 277857 0a1ac3ab8cb90dc9d26bd5702e43f6a51ec018d1
child 277859 cf88ad1f476c7f9ed1ee57e41dc27bd5d06c9785
push id29835
push usercbook@mozilla.com
push dateWed, 30 Dec 2015 11:00:19 +0000 (2015-12-30)
treeherdermozilla-central@c690c50b2b54 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjya
bugs1232069
milestone46.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 1232069 - Check box sizes before alloc&copy. r=jya
media/libstagefright/binding/Box.cpp
media/libstagefright/binding/MoofParser.cpp
media/libstagefright/binding/include/mp4_demuxer/Box.h
--- a/media/libstagefright/binding/Box.cpp
+++ b/media/libstagefright/binding/Box.cpp
@@ -8,16 +8,20 @@
 #include "mp4_demuxer/Stream.h"
 #include "mozilla/Endian.h"
 #include <algorithm>
 
 using namespace mozilla;
 
 namespace mp4_demuxer {
 
+// Limit reads to 32MiB max.
+// static
+const uint64_t Box::kMAX_BOX_READ = 32 * 1024 * 1024;
+
 // Returns the offset from the start of the body of a box of type |aType|
 // to the start of its first child.
 static uint32_t
 BoxOffset(AtomType aType)
 {
   const uint32_t FULLBOX_OFFSET = 4;
 
   if (aType == AtomType("mp4a") || aType == AtomType("enca")) {
@@ -144,18 +148,18 @@ Box::Read(nsTArray<uint8_t>* aDest)
 }
 
 bool
 Box::Read(nsTArray<uint8_t>* aDest, const MediaByteRange& aRange)
 {
   int64_t length;
   if (!mContext->mSource->Length(&length)) {
     // The HTTP server didn't give us a length to work with.
-    // Limit the read to 32MiB max.
-    length = std::min(aRange.mEnd - mChildOffset, uint64_t(32 * 1024 * 1024));
+    // Limit the read to kMAX_BOX_READ max.
+    length = std::min(aRange.mEnd - mChildOffset, kMAX_BOX_READ);
   } else {
     length = aRange.mEnd - mChildOffset;
   }
   aDest->SetLength(length);
   size_t bytes;
   if (!mContext->mSource->CachedReadAt(mChildOffset, aDest->Elements(),
                                        aDest->Length(), &bytes) ||
       bytes != aDest->Length()) {
--- a/media/libstagefright/binding/MoofParser.cpp
+++ b/media/libstagefright/binding/MoofParser.cpp
@@ -177,17 +177,19 @@ MoofParser::HasMetadata()
 }
 
 already_AddRefed<mozilla::MediaByteBuffer>
 MoofParser::Metadata()
 {
   MediaByteRange ftyp;
   MediaByteRange moov;
   ScanForMetadata(ftyp, moov);
-  if (!ftyp.Length() || !moov.Length()) {
+  if (!ftyp.Length() || !moov.Length() ||
+      ftyp.Length() > Box::kMAX_BOX_READ || moov.Length() > Box::kMAX_BOX_READ) {
+    // No ftyp or moov, or trying to read bigger-that-readable box (32MB).
     return nullptr;
   }
   RefPtr<MediaByteBuffer> metadata = new MediaByteBuffer();
   if (!metadata->SetLength(ftyp.Length() + moov.Length(), fallible)) {
     // OOM
     return nullptr;
   }
 
--- a/media/libstagefright/binding/include/mp4_demuxer/Box.h
+++ b/media/libstagefright/binding/include/mp4_demuxer/Box.h
@@ -46,16 +46,18 @@ public:
   const Box* Parent() const { return mParent; }
   bool IsType(const char* aType) const { return mType == AtomType(aType); }
 
   Box Next() const;
   Box FirstChild() const;
   bool Read(nsTArray<uint8_t>* aDest);
   bool Read(nsTArray<uint8_t>* aDest, const MediaByteRange& aRange);
 
+  static const uint64_t kMAX_BOX_READ;
+
 private:
   bool Contains(MediaByteRange aRange) const;
   BoxContext* mContext;
   mozilla::MediaByteRange mRange;
   uint64_t mBodyOffset;
   uint64_t mChildOffset;
   AtomType mType;
   const Box* mParent;