[Libreoffice-commits] libvisio.git: src/lib

David Tardon dtardon at redhat.com
Fri Mar 31 13:32:20 UTC 2017


 src/lib/VSDParser.cpp      |   17 +++++++++++++++++
 src/lib/libvisio_utils.cpp |   27 +++++++++++++++++++++++++++
 src/lib/libvisio_utils.h   |    2 ++
 3 files changed, 46 insertions(+)

New commits:
commit cf0303b0ca57d3f54aa50686d38aaa149c02d034
Author: David Tardon <dtardon at redhat.com>
Date:   Fri Mar 31 15:29:25 2017 +0200

    oss-fuzz: avoid big allocations
    
    Change-Id: I852f5359241975931b384800042760723db05b3a

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, ...);


More information about the Libreoffice-commits mailing list