[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index] [Thread Index]

Bug#932241: patch for CVE-2019-13615



This patch is just "git diff d559b0d..534dfdb" on the upstream libebml
repository, refreshed with quilt. It's an amalgamation of a series of
related changes that fix this bug. With this patch, VLC no longer
segfaults reading heap-over-flow.mp4 from the upstream bugtracker.


diff --git a/src/EbmlElement.cpp b/src/EbmlElement.cpp
index 143f439..871247c 100644
--- a/src/EbmlElement.cpp
+++ b/src/EbmlElement.cpp
@@ -372,11 +372,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
@@ -402,14 +403,17 @@ 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)
+        break;
      if (DataStream.read(&PossibleIdNSize[ReadIndex++], 1) == 0) {
        return NULL; // no more data ?
      }
      ReadSize++;

-    } while (!bFound && MaxDataSize > ReadSize);
+    } while (!bFound);

    if (!bFound)
      // we reached the maximum we could read without a proper ID
@@ -432,6 +436,10 @@ EbmlElement * EbmlElement::FindNextElement(IOCallback & DataStream, const EbmlSe
        bFound = false;
        break;
      }
+      if (MaxDataSize <= ReadSize) {
+        bFound = false;
+        break;
+      }
      if( DataStream.read( &PossibleIdNSize[SizeIdx++], 1 ) == 0 ) {
        return NULL; // no more data ?
      }
@@ -454,16 +462,15 @@ 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 (SizeFound == SizeUnknown) {
-              Result->SetSizeInfinite();
+          if (Result->ValidateSize() && (SizeFound == SizeUnknown || UpperLevel > 0 || MaxDataSize == 0 ||
+                                         MaxDataSize >= (IdStart + PossibleID_Length + _SizeLength + SizeFound))) {
+            if (SizeFound != SizeUnknown || Result->SetSizeInfinite()) {
+              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;
            }
-
-            Result->SizePosition = DataStream.getFilePointer() - SizeIdx + EBML_ID_LENGTH(PossibleID);
-            Result->ElementPosition = Result->SizePosition - EBML_ID_LENGTH(PossibleID);
-            // place the file at the beggining of the data
-            DataStream.setFilePointer(Result->SizePosition + _SizeLength);
-            return Result;
          }
        }
        delete Result;
@@ -473,8 +480,9 @@ 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 > DataStream.getFilePointer() - SizeIdx + PossibleID_Length );
+  } while ( MaxDataSize >= ReadSize );

  return NULL;
}


Reply to: