From: Steve Lhomme <slhomme@matroska.org>
Date: Tue, 23 Jan 2018 15:28:09 +0100
Subject: Rework the way we look at the end boundary when looking an element
 in a parent

The test `MaxDataSize >= (PossibleID_Length + PossibleSizeLength + SizeFound)`
is incorrect when there was garbage data skipped inside the PossibleIdNLength
table.

Now we keep track of how many memmove we had to do to know the real position of
the PossibleIdNLength data since we started reading. That allows a proper check
on the end value since that start.
---
 src/EbmlElement.cpp | 12 ++++++++----
 1 file changed, 8 insertions(+), 4 deletions(-)

diff --git a/src/EbmlElement.cpp b/src/EbmlElement.cpp
index 1e35f29..fba29fa 100644
--- a/src/EbmlElement.cpp
+++ b/src/EbmlElement.cpp
@@ -366,11 +366,12 @@ EbmlElement * EbmlElement::FindNextElement(IOCallback & DataStream, const EbmlSe
   int PossibleSizeLength;
   uint64 SizeUnknown;
   int ReadIndex = 0; // trick for the algo, start index at 0
-  uint32 ReadSize = 0;
+  uint32 ReadSize = 0, IdStart = 0;
   uint64 SizeFound;
   int SizeIdx;
   bool bFound;
   int UpperLevel_original = UpperLevel;
+  uint64 ParseStart = DataStream.getFilePointer();
 
   do {
     // read a potential ID
@@ -396,6 +397,7 @@ EbmlElement * EbmlElement::FindNextElement(IOCallback & DataStream, const EbmlSe
         // ID not found
         // shift left the read octets
         memmove(&PossibleIdNSize[0],&PossibleIdNSize[1], --ReadIndex);
+        IdStart++;
       }
 
       if (MaxDataSize <= ReadSize)
@@ -450,10 +452,11 @@ EbmlElement * EbmlElement::FindNextElement(IOCallback & DataStream, const EbmlSe
           //  0 : child
           //  1 : same level
           //  + : further parent
-          if (Result->ValidateSize() && (SizeFound == SizeUnknown || UpperLevel > 0 || MaxDataSize == 0 || MaxDataSize >= (PossibleID_Length + PossibleSizeLength + SizeFound))) {
+          if (Result->ValidateSize() && (SizeFound == SizeUnknown || UpperLevel > 0 || MaxDataSize == 0 ||
+                                         MaxDataSize >= (IdStart + PossibleID_Length + _SizeLength + SizeFound))) {
             if (SizeFound != SizeUnknown || Result->SetSizeInfinite()) {
-              Result->SizePosition = DataStream.getFilePointer() - SizeIdx + EBML_ID_LENGTH(PossibleID);
-              Result->ElementPosition = Result->SizePosition - EBML_ID_LENGTH(PossibleID);
+              Result->ElementPosition = ParseStart + IdStart;
+              Result->SizePosition = Result->ElementPosition + PossibleID_Length;
               // place the file at the beggining of the data
               DataStream.setFilePointer(Result->SizePosition + _SizeLength);
               return Result;
@@ -467,6 +470,7 @@ EbmlElement * EbmlElement::FindNextElement(IOCallback & DataStream, const EbmlSe
     // recover all the data in the buffer minus one byte
     ReadIndex = SizeIdx - 1;
     memmove(&PossibleIdNSize[0], &PossibleIdNSize[1], ReadIndex);
+    IdStart++;
     UpperLevel = UpperLevel_original;
   } while ( MaxDataSize >= ReadSize );
 
