diff options
author | David Tardon <dtardon@redhat.com> | 2017-03-31 15:29:25 +0200 |
---|---|---|
committer | David Tardon <dtardon@redhat.com> | 2017-03-31 15:31:24 +0200 |
commit | cf0303b0ca57d3f54aa50686d38aaa149c02d034 (patch) | |
tree | a2a06b05af909234e76666b59a7cd183643577b5 | |
parent | 7d1543b4f7bb4578735767141356bf61565a9fd9 (diff) |
oss-fuzz: avoid big allocations
Change-Id: I852f5359241975931b384800042760723db05b3a
-rw-r--r-- | src/lib/VSDParser.cpp | 17 | ||||
-rw-r--r-- | src/lib/libvisio_utils.cpp | 27 | ||||
-rw-r--r-- | src/lib/libvisio_utils.h | 2 |
3 files changed, 46 insertions, 0 deletions
diff --git a/src/lib/VSDParser.cpp b/src/lib/VSDParser.cpp index 8ac21eb..9f87e51 100644 --- a/src/lib/VSDParser.cpp +++ b/src/lib/VSDParser.cpp @@ -21,6 +21,18 @@ #include "VSDStylesCollector.h" #include "VSDMetaData.h" +namespace +{ + +void sanitizeListLength(uint32_t &length, const std::size_t elem, librevenge::RVNGInputStream *const input) +{ + const unsigned long maxLength = libvisio::getRemainingLength(input) / elem; + if (length > maxLength) + length = maxLength; +} + +} + libvisio::VSDParser::VSDParser(librevenge::RVNGInputStream *input, librevenge::RVNGDrawingInterface *painter, librevenge::RVNGInputStream *container) : m_input(input), m_painter(painter), m_container(container), m_header(), m_collector(0), m_shapeList(), m_currentLevel(0), m_stencils(), m_currentStencil(0), m_shape(), m_isStencilStarted(false), m_isInStyles(false), @@ -914,6 +926,7 @@ void libvisio::VSDParser::readGeomList(librevenge::RVNGInputStream *input) uint32_t childrenListLength = readU32(input); input->seek(subHeaderLength, librevenge::RVNG_SEEK_CUR); std::vector<unsigned> geometryOrder; + sanitizeListLength(childrenListLength, 4, input); geometryOrder.reserve(childrenListLength / sizeof(uint32_t)); for (unsigned i = 0; i < (childrenListLength / sizeof(uint32_t)); i++) geometryOrder.push_back(readU32(input)); @@ -938,6 +951,7 @@ void libvisio::VSDParser::readCharList(librevenge::RVNGInputStream *input) uint32_t subHeaderLength = readU32(input); uint32_t childrenListLength = readU32(input); input->seek(subHeaderLength, librevenge::RVNG_SEEK_CUR); + sanitizeListLength(childrenListLength, 4, input); std::vector<unsigned> characterOrder; characterOrder.reserve(childrenListLength / sizeof(uint32_t)); for (unsigned i = 0; i < (childrenListLength / sizeof(uint32_t)); i++) @@ -958,6 +972,7 @@ void libvisio::VSDParser::readParaList(librevenge::RVNGInputStream *input) uint32_t subHeaderLength = readU32(input); uint32_t childrenListLength = readU32(input); input->seek(subHeaderLength, librevenge::RVNG_SEEK_CUR); + sanitizeListLength(childrenListLength, 4, input); std::vector<unsigned> paragraphOrder; paragraphOrder.reserve(childrenListLength / sizeof(uint32_t)); for (unsigned i = 0; i < (childrenListLength / sizeof(uint32_t)); i++) @@ -982,6 +997,7 @@ void libvisio::VSDParser::readTabsDataList(librevenge::RVNGInputStream *input) uint32_t subHeaderLength = readU32(input); uint32_t childrenListLength = readU32(input); input->seek(subHeaderLength, librevenge::RVNG_SEEK_CUR); + sanitizeListLength(childrenListLength, 4, input); std::vector<unsigned> tabsOrder; tabsOrder.reserve(childrenListLength / sizeof(uint32_t)); for (unsigned i = 0; i < (childrenListLength / sizeof(uint32_t)); i++) @@ -1000,6 +1016,7 @@ void libvisio::VSDParser::readLayerList(librevenge::RVNGInputStream *input) uint32_t subHeaderLength = readU32(input); uint32_t childrenListLength = readU32(input); input->seek(subHeaderLength, librevenge::RVNG_SEEK_CUR); + sanitizeListLength(childrenListLength, 4, input); std::vector<unsigned> layerOrder; layerOrder.reserve(childrenListLength / sizeof(uint32_t)); for (unsigned i = 0; i < (childrenListLength / sizeof(uint32_t)); i++) diff --git a/src/lib/libvisio_utils.cpp b/src/lib/libvisio_utils.cpp index 08b5b2d..a46f833 100644 --- a/src/lib/libvisio_utils.cpp +++ b/src/lib/libvisio_utils.cpp @@ -109,6 +109,33 @@ const librevenge::RVNGString libvisio::getColourString(const Colour &c) return sColour; } +unsigned long libvisio::getRemainingLength(librevenge::RVNGInputStream *const input) +{ + if (!input) + throw EndOfStreamException(); + + const unsigned long begin = (unsigned long) input->tell(); + unsigned long end = begin; + + if (0 == input->seek(0, librevenge::RVNG_SEEK_END)) + { + end = (unsigned long) input->tell(); + } + else + { + // librevenge::RVNG_SEEK_END does not work. Use the harder way. + while (!input->isEnd()) + { + readU8(input); + ++end; + } + } + + input->seek(begin, librevenge::RVNG_SEEK_SET); + + return end - begin; +} + void libvisio::appendUCS4(librevenge::RVNGString &text, UChar32 ucs4Character) { // Convert carriage returns to new line characters diff --git a/src/lib/libvisio_utils.h b/src/lib/libvisio_utils.h index 2a4880e..ea63867 100644 --- a/src/lib/libvisio_utils.h +++ b/src/lib/libvisio_utils.h @@ -88,6 +88,8 @@ double readDouble(librevenge::RVNGInputStream *input); const librevenge::RVNGString getColourString(const Colour &c); +unsigned long getRemainingLength(librevenge::RVNGInputStream *input); + void appendUCS4(librevenge::RVNGString &text, UChar32 ucs4Character); void debugPrint(const char *format, ...); |