CVE-2015-8792: Improper Restriction of Operations within the Bounds of a Memory Buffer (CWE-119)
value: The KaxInternalBlock::ReadData function in libMatroska before 1.4.4 allows context-dependent attackers to obtain sensitive information from process heap memory via crafted EBML lacing, which triggers an invalid memory access.
CWE description: The product performs operations on a memory buffer, but it reads from or writes to a memory location outside the buffer's intended boundary. This may result in read or write operations on unexpected memory locations that could be linked to other variables, data structures, or internal program data.
CVSS v3 base score: 5.3
Published: 2016-01-29T19:59Z
Repository: https://github.com/Matroska-Org/libmatroska
Language: Other
Files changed: ChangeLog, src/KaxBlock.cpp
Commit date: 2015-10-20 12:00:53 +0200
Commit message: KaxBlockInternal: check EBML lace sizes against available buffer space

Diff: diff --git a/ChangeLog b/ChangeLog
index e260ea1..f61dac0 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,15 @@
+2015-10-20  Moritz Bunkus  <moritz@bunkus.org>
+
+        * KaxInternalBlock::ReadData(): Fixed an invalid memory
+        access. When reading a block group or a simple block that uses
+        EBML lacing the frame sizes indicated in the lacing weren't
+        checked against the available number of bytes. If the indicated
+        frame size was bigger than the whole block's size the parser would
+        read beyond the end of the buffer resulting in a heap information
+        leak.
+
 2015-10-17  Moritz Bunkus  <moritz@bunkus.org>
 
         * Released v1.4.3.
 
 2015-05-02  Daniel Winzen  <d@winzen4.de>
diff --git a/src/KaxBlock.cpp b/src/KaxBlock.cpp
index b59538c..22d2132 100644
--- a/src/KaxBlock.cpp
+++ b/src/KaxBlock.cpp
@@ -527,18 +527,22 @@ filepos_t KaxInternalBlock::ReadData(IOCallback & input, ScopeMode ReadFully)
             SizeList[Index] = LastBufferSize;
             break;
           case LACING_EBML:
             SizeRead = LastBufferSize;
             FrameSize = ReadCodedSizeValue(BufferStart + Mem.GetPosition(), SizeRead, SizeUnknown);
+            if (!FrameSize || (static_cast<uint32>(FrameSize + SizeRead) > LastBufferSize))
+              throw SafeReadIOCallback::EndOfStreamX(SizeRead);
             SizeList[0] = FrameSize;
             Mem.Skip(SizeRead);
             LastBufferSize -= FrameSize + SizeRead;
 
             for (Index=1; Index<FrameNum; Index++) {
               // get the size of the frame
               SizeRead = LastBufferSize;
               FrameSize += ReadCodedSizeSignedValue(BufferStart + Mem.GetPosition(), SizeRead, SizeUnknown);
+              if (!FrameSize || (static_cast<uint32>(FrameSize + SizeRead) > LastBufferSize))
+                throw SafeReadIOCallback::EndOfStreamX(SizeRead);
               SizeList[Index] = FrameSize;
               Mem.Skip(SizeRead);
               LastBufferSize -= FrameSize + SizeRead;
             }
             if (Index <= FrameNum) // Safety check if FrameNum == 0

Fixed code: 2015-10-20  Moritz Bunkus  <moritz@bunkus.org>

        * KaxInternalBlock::ReadData(): Fixed an invalid memory
        access. When reading a block group or a simple block that uses
        EBML lacing the frame sizes indicated in the lacing weren't
        checked against the available number of bytes. If the indicated
        frame size was bigger than the whole block's size the parser would
        read beyond the end of the buffer resulting in a heap information
        leak.

            if (!FrameSize || (static_cast<uint32>(FrameSize + SizeRead) > LastBufferSize))
              throw SafeReadIOCallback::EndOfStreamX(SizeRead);
              if (!FrameSize || (static_cast<uint32>(FrameSize + SizeRead) > LastBufferSize))
                throw SafeReadIOCallback::EndOfStreamX(SizeRead);