Bug 1149278 - Limit box reads to resource length. r=k17e, a=sledru
authorJean-Yves Avenard <jyavenard@mozilla.com>
Tue, 07 Apr 2015 20:33:16 +1000
changeset 258378 de1e5351aad2
parent 258377 4c9214ed82b8
child 258379 68f61e9c41d2
push id4654
push userryanvm@gmail.com
push date2015-04-08 19:02 +0000
treeherdermozilla-beta@01cf08a90d44 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersk17e, sledru
bugs1149278
milestone38.0
Bug 1149278 - Limit box reads to resource length. r=k17e, a=sledru Also, add a safeguard where we will never attempt to read a mp4 box over 32MiB
media/libstagefright/binding/Box.cpp
media/libstagefright/binding/MoofParser.cpp
--- a/media/libstagefright/binding/Box.cpp
+++ b/media/libstagefright/binding/Box.cpp
@@ -2,16 +2,17 @@
 /* vim:set ts=2 sw=2 sts=2 et cindent: */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "mp4_demuxer/Box.h"
 #include "mp4_demuxer/mp4_demuxer.h"
 #include "mozilla/Endian.h"
+#include <algorithm>
 
 using namespace mozilla;
 
 namespace mp4_demuxer {
 
 // 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
@@ -86,21 +87,16 @@ Box::Box(BoxContext* aContext, uint64_t 
 
   MediaByteRange boxRange(aOffset, aOffset + size);
   if (mChildOffset > boxRange.mEnd ||
       (mParent && !mParent->mRange.Contains(boxRange)) ||
       !byteRange->Contains(boxRange)) {
     return;
   }
 
-  nsTArray<uint8_t> content;
-  if (!Read(&content, boxRange)) {
-    return;
-  }
-
   mRange = boxRange;
 }
 
 Box::Box()
   : mContext(nullptr)
 {}
 
 Box
@@ -124,17 +120,25 @@ bool
 Box::Read(nsTArray<uint8_t>* aDest)
 {
   return Read(aDest, mRange);
 }
 
 bool
 Box::Read(nsTArray<uint8_t>* aDest, const MediaByteRange& aRange)
 {
-  aDest->SetLength(aRange.mEnd - mChildOffset);
+  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));
+  } else {
+    length = aRange.mEnd - mChildOffset;
+  }
+  aDest->SetLength(length);
   size_t bytes;
   if (!mContext->mSource->CachedReadAt(mChildOffset, aDest->Elements(),
                                        aDest->Length(), &bytes) ||
       bytes != aDest->Length()) {
     // Byte ranges are being reported incorrectly
     NS_WARNING("Read failed in mp4_demuxer::Box::Read()");
     aDest->Clear();
     return false;
--- a/media/libstagefright/binding/MoofParser.cpp
+++ b/media/libstagefright/binding/MoofParser.cpp
@@ -94,19 +94,20 @@ public:
 
 private:
   nsRefPtr<Stream> mStream;
 };
 
 bool
 MoofParser::BlockingReadNextMoof()
 {
+  int64_t length = std::numeric_limits<int64_t>::max();
+  mSource->Length(&length);
   nsTArray<MediaByteRange> byteRanges;
-  byteRanges.AppendElement(
-    MediaByteRange(0, std::numeric_limits<int64_t>::max()));
+  byteRanges.AppendElement(MediaByteRange(0, length));
   nsRefPtr<mp4_demuxer::BlockingStream> stream = new BlockingStream(mSource);
 
   BoxContext context(stream, byteRanges);
   for (Box box(&context, mOffset); box.IsAvailable(); box = box.Next()) {
     if (box.IsType("moof")) {
       byteRanges.Clear();
       byteRanges.AppendElement(MediaByteRange(mOffset, box.Range().mEnd));
       return RebuildFragmentedIndex(context);