summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDavid Tardon <dtardon@redhat.com>2015-07-21 17:35:13 +0200
committerDavid Tardon <dtardon@redhat.com>2015-07-21 17:59:43 +0200
commit77a88f128700e434c093eb53590be63022edbdea (patch)
tree4dbbaae1f35e081ac85aa109e90fe09c3be1381c
parent2bdd7a9bfd1ed1606b7348602196f0a2baf0c099 (diff)
avoid overflows when reading chunk records
Change-Id: Iea13e63e977348a449b68eca329146ae6f097197
-rw-r--r--src/lib/VSD5Parser.cpp16
1 files changed, 12 insertions, 4 deletions
diff --git a/src/lib/VSD5Parser.cpp b/src/lib/VSD5Parser.cpp
index 00cbf06..79b638b 100644
--- a/src/lib/VSD5Parser.cpp
+++ b/src/lib/VSD5Parser.cpp
@@ -102,7 +102,12 @@ void libvisio::VSD5Parser::handleChunkRecords(librevenge::RVNGInputStream *input
long endPosition = input->tell() + m_header.dataLength;
input->seek(endPosition - 4, librevenge::RVNG_SEEK_SET);
unsigned numRecords = readU16(input);
+ const long headerPosition = endPosition - 4 * (numRecords + 1);
+ if (headerPosition <= startPosition) // no records to read
+ return;
unsigned endOffset = readU16(input);
+ if (long(endOffset) > (headerPosition - startPosition))
+ endOffset = unsigned(headerPosition - startPosition); // try to read something anyway
std::map<unsigned, ChunkHeader> records;
input->seek(endPosition-4*(numRecords+1), librevenge::RVNG_SEEK_SET);
unsigned i = 0;
@@ -114,10 +119,13 @@ void libvisio::VSD5Parser::handleChunkRecords(librevenge::RVNGInputStream *input
unsigned tmpStart = offset;
while (tmpStart % 4)
tmpStart++;
- header.dataLength = endOffset - tmpStart;
- header.level = m_header.level + 1;
- records[tmpStart] = header;
- endOffset = offset;
+ if (tmpStart < endOffset)
+ {
+ header.dataLength = endOffset - tmpStart;
+ header.level = m_header.level + 1;
+ records[tmpStart] = header;
+ endOffset = offset;
+ }
}
i = 0;
for (std::map<unsigned, ChunkHeader>::iterator iter = records.begin(); iter != records.end(); ++iter)