Bug 1362440 - part1 : add timecode checking for parser draft
authorAlastor Wu <alwu@mozilla.com>
Mon, 30 Oct 2017 15:27:27 +0800
changeset 688587 e8e9d1f2b605e213c873ca4a1280f7e5f494e63f
parent 688337 d3910b7628b8066d3f30d58b17b5824b05768854
child 688588 13aeae76c15a4fd91dba0986154ea70dabd5947b
push id86795
push useralwu@mozilla.com
push dateMon, 30 Oct 2017 09:49:00 +0000
bugs1362440
milestone58.0a1
Bug 1362440 - part1 : add timecode checking for parser The spec [1] defines that "Timecode (e7) MUST appear before Block (a1) or SimpleBlock (a3)". [1] https://www.matroska.org/technical/specs/index.html MozReview-Commit-ID: 7g8lgckuNif
dom/media/webm/WebMBufferedParser.cpp
dom/media/webm/WebMBufferedParser.h
--- a/dom/media/webm/WebMBufferedParser.cpp
+++ b/dom/media/webm/WebMBufferedParser.cpp
@@ -108,24 +108,30 @@ bool WebMBufferedParser::Append(const un
         mClusterOffset = mCurrentOffset + (p - aBuffer) -
                         (mElement.mID.mLength + mElement.mSize.mLength);
         // Handle "unknown" length;
         if (mElement.mSize.mValue + 1 != uint64_t(1) << (mElement.mSize.mLength * 7)) {
           mClusterEndOffset = mClusterOffset + mElement.mID.mLength + mElement.mSize.mLength + mElement.mSize.mValue;
         } else {
           mClusterEndOffset = -1;
         }
+        mGotClusterTimecode = false;
         mState = READ_ELEMENT_ID;
         break;
       case BLOCKGROUP_ID:
         mState = READ_ELEMENT_ID;
         break;
       case SIMPLEBLOCK_ID:
         /* FALLTHROUGH */
       case BLOCK_ID:
+        if (!mGotClusterTimecode) {
+          WEBM_DEBUG("The Timecode element must appear before any Block or "
+                     "SimpleBlock elements in a Cluster");
+          return false;
+        }
         mBlockSize = mElement.mSize.mValue;
         mBlockTimecode = 0;
         mBlockTimecodeLength = BLOCK_TIMECODE_LENGTH;
         mBlockOffset = mCurrentOffset + (p - aBuffer) -
                        (mElement.mID.mLength + mElement.mSize.mLength);
         mState = READ_VINT;
         mNextState = READ_BLOCK_TIMECODE;
         break;
@@ -159,23 +165,25 @@ bool WebMBufferedParser::Append(const un
         mVInt.mValue |= *p++;
         mVIntLeft -= 1;
       } else {
         mState = mNextState;
       }
       break;
     case READ_TIMECODESCALE:
       if (!mGotTimecodeScale) {
+        WEBM_DEBUG("Should get the SegmentInfo first");
         return false;
       }
       mTimecodeScale = mVInt.mValue;
       mState = READ_ELEMENT_ID;
       break;
     case READ_CLUSTER_TIMECODE:
       mClusterTimecode = mVInt.mValue;
+      mGotClusterTimecode = true;
       mState = READ_ELEMENT_ID;
       break;
     case READ_BLOCK_TIMECODE:
       if (mBlockTimecodeLength) {
         mBlockTimecode <<= 8;
         mBlockTimecode |= *p++;
         mBlockTimecodeLength -= 1;
       } else {
@@ -185,16 +193,17 @@ bool WebMBufferedParser::Append(const un
           ReentrantMonitorAutoEnter mon(aReentrantMonitor);
           int64_t endOffset = mBlockOffset + mBlockSize +
                               mElement.mID.mLength + mElement.mSize.mLength;
           uint32_t idx = aMapping.IndexOfFirstElementGt(endOffset);
           if (idx == 0 || aMapping[idx - 1] != endOffset) {
             // Don't insert invalid negative timecodes.
             if (mBlockTimecode >= 0 || mClusterTimecode >= uint16_t(abs(mBlockTimecode))) {
               if (!mGotTimecodeScale) {
+                WEBM_DEBUG("Should get the TimecodeScale first");
                 return false;
               }
               uint64_t absTimecode = mClusterTimecode + mBlockTimecode;
               absTimecode *= mTimecodeScale;
               // Avoid creating an entry if the timecode is out of order
               // (invalid according to the WebM specification) so that
               // ordering invariants of aMapping are not violated.
               if (idx == 0 ||
--- a/dom/media/webm/WebMBufferedParser.h
+++ b/dom/media/webm/WebMBufferedParser.h
@@ -70,16 +70,17 @@ struct WebMBufferedParser
     , mClusterOffset(0)
     , mClusterEndOffset(-1)
     , mBlockOffset(0)
     , mBlockTimecode(0)
     , mBlockTimecodeLength(0)
     , mSkipBytes(0)
     , mTimecodeScale(1000000)
     , mGotTimecodeScale(false)
+    , mGotClusterTimecode(false)
   {
     if (mStartOffset != 0) {
       mState = FIND_CLUSTER_SYNC;
     }
   }
 
   uint32_t GetTimecodeScale() {
     MOZ_ASSERT(mGotTimecodeScale);
@@ -255,16 +256,19 @@ private:
 
   // Timecode scale read from the segment info and used to scale absolute
   // timecodes.
   uint32_t mTimecodeScale;
 
   // True if we read the timecode scale from the segment info or have
   // confirmed that the default value is to be used.
   bool mGotTimecodeScale;
+
+  // True if we've read the cluster time code.
+  bool mGotClusterTimecode;
 };
 
 class WebMBufferedState final
 {
   NS_INLINE_DECL_THREADSAFE_REFCOUNTING(WebMBufferedState)
 
 public:
   WebMBufferedState()