summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDavid Tardon <dtardon@redhat.com>2017-03-31 15:29:25 +0200
committerDavid Tardon <dtardon@redhat.com>2017-03-31 15:31:24 +0200
commitcf0303b0ca57d3f54aa50686d38aaa149c02d034 (patch)
treea2a06b05af909234e76666b59a7cd183643577b5
parent7d1543b4f7bb4578735767141356bf61565a9fd9 (diff)
oss-fuzz: avoid big allocations
Change-Id: I852f5359241975931b384800042760723db05b3a
-rw-r--r--src/lib/VSDParser.cpp17
-rw-r--r--src/lib/libvisio_utils.cpp27
-rw-r--r--src/lib/libvisio_utils.h2
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, ...);