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: