Bug 1282214 - Make mp4parse read buffer fallible. r=kinetik, a=lizzard
authorRalph Giles <giles@mozilla.com>
Wed, 29 Jun 2016 13:05:00 +0200
changeset 339813 c86c60043a9ef8fb983ab6db054d53acf04d037b
parent 339812 49b4519a8d2e21e42649c9317e1d687af949bffd
child 339814 87af6e5c29e8934bba32a702c0f0b9dd255a75de
push id6249
push userjlund@mozilla.com
push dateMon, 01 Aug 2016 13:59:36 +0000
treeherdermozilla-beta@bad9d4f5bf7e [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerskinetik, lizzard
bugs1282214
milestone49.0a2
Bug 1282214 - Make mp4parse read buffer fallible. r=kinetik, a=lizzard The rust mp4parse demuxer allocates a temporary buffer for the container header. The size of this buffer is clipped to 1 MB but we've seen some crashes in low memory conditions. Presumedly the system is too fragmented to allocate the buffer. In that case playing the video is probably impossible, but it's better to return an error rather than crash. Replace the std::vector instance with an nsTArray so we can check for allocation failure. MozReview-Commit-ID: 23QG28VxkPk
media/libstagefright/binding/MP4Metadata.cpp
--- a/media/libstagefright/binding/MP4Metadata.cpp
+++ b/media/libstagefright/binding/MP4Metadata.cpp
@@ -451,47 +451,50 @@ MP4MetadataStagefright::HasCompleteMetad
 MP4MetadataStagefright::Metadata(Stream* aSource)
 {
   auto parser = mozilla::MakeUnique<MoofParser>(aSource, 0, false);
   return parser->Metadata();
 }
 
 #ifdef MOZ_RUST_MP4PARSE
 static int32_t
-read_source(RefPtr<Stream> aSource, std::vector<uint8_t>& aBuffer)
+read_source(RefPtr<Stream> aSource, nsTArray<uint8_t>& aBuffer)
 {
   static LazyLogModule sLog("MP4Metadata");
   int64_t length;
   if (!aSource->Length(&length) || length <= 0) {
     MOZ_LOG(sLog, LogLevel::Warning, ("Couldn't get source length"));
     return MP4PARSE_ERROR_IO;
   }
   MOZ_LOG(sLog, LogLevel::Debug,
          ("Source length %d bytes\n", (long long int)length));
   length = std::min<int64_t>(length, 1024 * 1024); // Don't read the entire file.
-  aBuffer.resize(length);
+  if (!aBuffer.SetLength(length, mozilla::fallible)) {
+    MOZ_LOG(sLog, LogLevel::Warning, ("Couldn't allocate temporary buffer"));
+    return MP4PARSE_ERROR_IO;
+  }
   size_t bytes_read = 0;
-  bool rv = aSource->ReadAt(0, aBuffer.data(), aBuffer.size(), &bytes_read);
+  bool rv = aSource->ReadAt(0, aBuffer.Elements(), aBuffer.Length(), &bytes_read);
   if (!rv || bytes_read != size_t(length)) {
     MOZ_LOG(sLog, LogLevel::Warning, ("Error copying mp4 data"));
     return MP4PARSE_ERROR_IO;
   }
   return MP4PARSE_OK;
 }
 
 MP4MetadataRust::MP4MetadataRust(Stream* aSource)
   : mSource(aSource)
   , mRustState(mp4parse_new())
 {
   static LazyLogModule sLog("MP4Metadata");
 
-  std::vector<uint8_t> buffer;
+  nsTArray<uint8_t> buffer;
   int32_t rv = read_source(mSource, buffer);
   if (rv == MP4PARSE_OK) {
-    rv = mp4parse_read(mRustState.get(), buffer.data(), buffer.size());
+    rv = mp4parse_read(mRustState.get(), buffer.Elements(), buffer.Length());
   }
   MOZ_LOG(sLog, LogLevel::Debug, ("rust parser returned %d\n", rv));
   Telemetry::Accumulate(Telemetry::MEDIA_RUST_MP4PARSE_SUCCESS,
                         rv == MP4PARSE_OK);
   if (rv != MP4PARSE_OK) {
     MOZ_ASSERT(rv > 0);
     Telemetry::Accumulate(Telemetry::MEDIA_RUST_MP4PARSE_ERROR_CODE,
                           rv);