Bug 1329480: [MSE] Do not reject partial boxes. r?gerald draft
authorJean-Yves Avenard <jyavenard@mozilla.com>
Fri, 13 Jan 2017 17:38:40 +0100
changeset 461276 e591349ab55b2963b85cec4ac6c24bfeac4865fa
parent 460682 8ee0791fa82773daa0a8c3287df3718f7eebb751
child 464349 0cd2906de9ad0be7139faf71c42ab84b9fdd2eb8
push id41627
push userbmo:jyavenard@mozilla.com
push dateMon, 16 Jan 2017 09:48:37 +0000
reviewersgerald
bugs1329480
milestone53.0a1
Bug 1329480: [MSE] Do not reject partial boxes. r?gerald Partial content less than 8 bytes long was incorrectly rejected. We now assume that content is valid unless it is explicitly incorrect (bad box type) MozReview-Commit-ID: 8L32mNVjzxh
dom/media/mediasource/ContainerParser.cpp
--- a/dom/media/mediasource/ContainerParser.cpp
+++ b/dom/media/mediasource/ContainerParser.cpp
@@ -15,16 +15,17 @@
 #include "MediaData.h"
 #ifdef MOZ_FMP4
 #include "MP4Stream.h"
 #include "mp4_demuxer/AtomType.h"
 #include "mp4_demuxer/ByteReader.h"
 #endif
 #include "nsAutoPtr.h"
 #include "SourceBufferResource.h"
+#include <algorithm>
 
 extern mozilla::LogModule* GetMediaSourceSamplesLog();
 
 #define STRINGIFY(x) #x
 #define TOSTRING(x) STRINGIFY(x)
 #define MSE_DEBUG(name, arg, ...) MOZ_LOG(GetMediaSourceSamplesLog(), mozilla::LogLevel::Debug, (TOSTRING(name) "(%p:%s)::%s: " arg, this, mType.get(), __func__, ##__VA_ARGS__))
 #define MSE_DEBUGV(name, arg, ...) MOZ_LOG(GetMediaSourceSamplesLog(), mozilla::LogLevel::Verbose, (TOSTRING(name) "(%p:%s)::%s: " arg, this, mType.get(), __func__, ##__VA_ARGS__))
 
@@ -343,27 +344,33 @@ public:
   {}
 
   MediaResult IsInitSegmentPresent(MediaByteBuffer* aData) override
   {
     ContainerParser::IsInitSegmentPresent(aData);
     // Each MP4 atom has a chunk size and chunk type. The root chunk in an MP4
     // file is the 'ftyp' atom followed by a file type. We just check for a
     // vaguely valid 'ftyp' atom.
+    if (aData->Length() < 8) {
+      return NS_ERROR_NOT_AVAILABLE;
+    }
     AtomParser parser(mType, aData);
     if (!parser.IsValid()) {
       return MediaResult(
         NS_ERROR_FAILURE,
         RESULT_DETAIL("Invalid Top-Level Box:%s", parser.LastInvalidBox()));
     }
     return parser.StartWithInitSegment() ? NS_OK : NS_ERROR_NOT_AVAILABLE;
   }
 
   MediaResult IsMediaSegmentPresent(MediaByteBuffer* aData) override
   {
+    if (aData->Length() < 8) {
+      return NS_ERROR_NOT_AVAILABLE;
+    }
     AtomParser parser(mType, aData);
     if (!parser.IsValid()) {
       return MediaResult(
         NS_ERROR_FAILURE,
         RESULT_DETAIL("Invalid Box:%s", parser.LastInvalidBox()));
     }
     return parser.StartWithMediaSegment() ? NS_OK : NS_ERROR_NOT_AVAILABLE;
   }
@@ -391,30 +398,25 @@ private:
 
       while (reader.Remaining() >= 8) {
         uint64_t size = reader.ReadU32();
         const uint8_t* typec = reader.Peek(4);
         mp4_demuxer::AtomType type(reader.ReadU32());
         MSE_DEBUGV(AtomParser ,"Checking atom:'%c%c%c%c' @ %u",
                    typec[0], typec[1], typec[2], typec[3],
                    (uint32_t)reader.Offset() - 8);
-
-        for (const auto& boxType : validBoxes) {
-          if (type == boxType) {
-            mValid = true;
-            break;
-          }
-        }
-        if (!mValid) {
-          // No point continuing.
+        if (std::find(std::begin(validBoxes), std::end(validBoxes), type)
+            == std::end(validBoxes)) {
+          // No valid box found, no point continuing.
           mLastInvalidBox[0] = typec[0];
           mLastInvalidBox[1] = typec[1];
           mLastInvalidBox[2] = typec[2];
           mLastInvalidBox[3] = typec[3];
           mLastInvalidBox[4] = '\0';
+          mValid = false;
           break;
         }
         if (mInitOffset.isNothing() &&
             mp4_demuxer::AtomType(type) == initAtom) {
           mInitOffset = Some(reader.Offset());
         }
         if (mMediaOffset.isNothing() &&
             mp4_demuxer::AtomType(type) == mediaAtom) {
@@ -453,17 +455,17 @@ private:
       return mMediaOffset.isSome() &&
         (mInitOffset.isNothing() || mMediaOffset.ref() < mInitOffset.ref());
     }
     bool IsValid() const { return mValid; }
     const char* LastInvalidBox() const { return mLastInvalidBox; }
   private:
     Maybe<size_t> mInitOffset;
     Maybe<size_t> mMediaOffset;
-    bool mValid = false;
+    bool mValid = true;
     char mLastInvalidBox[5];
   };
 
 public:
   MediaResult ParseStartAndEndTimestamps(MediaByteBuffer* aData,
                                          int64_t& aStart,
                                          int64_t& aEnd) override
   {