src/lib/CDRContentCollector.cpp | 39 ++++++++++++++++++++++++++++------- src/lib/CDRParser.cpp | 44 +++++++++++++++++++++++++++++++++------- src/lib/libcdr_utils.cpp | 5 ++++ src/lib/libcdr_utils.h | 1 4 files changed, 74 insertions(+), 15 deletions(-)
New commits: commit 518a4c52ff5bb841f74339ead214f544ec9f1dde Author: David Tardon <dtar...@redhat.com> Date: Mon Aug 17 20:49:45 2015 +0200 afl: avoid infinite loop with big numbers ... for which x - 1.0 == x due to rounding. Change-Id: I98930077a5b47dc9e49ae6ac78e6b19177c7b56c diff --git a/src/lib/CDRContentCollector.cpp b/src/lib/CDRContentCollector.cpp index c3d1c22..ae51b44 100644 --- a/src/lib/CDRContentCollector.cpp +++ b/src/lib/CDRContentCollector.cpp @@ -27,6 +27,35 @@ #define DUMP_VECT 0 #endif +namespace libcdr +{ +namespace +{ + +/// Move the number into [0;1] range. +void normalize(double &d) +{ + if (d < 0.0) + { + const double n = d + static_cast<unsigned long>(-d) + 1.0; + if ((n < 0.0) || (n > 1.0)) + d = 0.0; // The number was too big, thus rounded. Just pick a value. + else + d = n; + } + if (d > 1.0) + { + const double n = d - static_cast<unsigned long>(d); + if ((n < 0.0) || (n > 1.0)) + d = 0.0; // The number was too big, thus rounded. Just pick a value. + else + d = n; + } +} + +} +} + libcdr::CDRContentCollector::CDRContentCollector(libcdr::CDRParserState &ps, librevenge::RVNGDrawingInterface *painter) : m_painter(painter), m_isDocumentStarted(false), m_isPageProperties(false), m_isPageStarted(false), m_ignorePage(false), @@ -773,19 +802,13 @@ void libcdr::CDRContentCollector::_fillProperties(librevenge::RVNGPropertyList & if (m_fillTransforms.getTranslateX() != 0.0) { double xOffset = m_fillTransforms.getTranslateX() / m_currentFillStyle.imageFill.width; - while (xOffset < 0.0) - xOffset += 1.0; - while (xOffset > 1.0) - xOffset -= 1.0; + normalize(xOffset); propList.insert("draw:fill-image-ref-point-x", xOffset, librevenge::RVNG_PERCENT); } if (m_fillTransforms.getTranslateY() != 0.0) { double yOffset = m_fillTransforms.getTranslateY() / m_currentFillStyle.imageFill.width; - while (yOffset < 0.0) - yOffset += 1.0; - while (yOffset > 1.0) - yOffset -= 1.0; + normalize(yOffset); propList.insert("draw:fill-image-ref-point-y", 1.0 - yOffset, librevenge::RVNG_PERCENT); } } commit e13f0f01b29d4487525998f9f0ff0dc895155f4b Author: David Tardon <dtar...@redhat.com> Date: Mon Aug 17 20:13:06 2015 +0200 afl: postpone alloc. till we get the data Change-Id: Ic54f3b1e7e4f08d23a44ad65e855286ebf659fb2 diff --git a/src/lib/CDRParser.cpp b/src/lib/CDRParser.cpp index 5decfdb..36fbe01 100644 --- a/src/lib/CDRParser.cpp +++ b/src/lib/CDRParser.cpp @@ -2360,12 +2360,12 @@ void libcdr::CDRParser::readWaldoBmpf(librevenge::RVNGInputStream *input, unsign return; input->seek(4, librevenge::RVNG_SEEK_CUR); unsigned dataSize = readU32(input); - std::vector<unsigned char> pattern(dataSize); unsigned long tmpNumBytesRead = 0; input->seek(24, librevenge::RVNG_SEEK_CUR); // TODO: is this empirical experience universal??? const unsigned char *tmpBuffer = input->read(dataSize, tmpNumBytesRead); if (dataSize != tmpNumBytesRead) return; + std::vector<unsigned char> pattern(dataSize); memcpy(&pattern[0], tmpBuffer, dataSize); m_collector->collectBmpf(id, width, height, pattern); } commit 334a6c12f3466828a3acb384d9b8bcac664b555f Author: David Tardon <dtar...@redhat.com> Date: Mon Aug 17 20:12:11 2015 +0200 afl: postpone alloc. till we get the data Change-Id: I10412cb64fea97a7271abc8d1cd721c09cfad423 diff --git a/src/lib/CDRParser.cpp b/src/lib/CDRParser.cpp index 4274165..5decfdb 100644 --- a/src/lib/CDRParser.cpp +++ b/src/lib/CDRParser.cpp @@ -2300,11 +2300,11 @@ void libcdr::CDRParser::readBmp(librevenge::RVNGInputStream *input, unsigned len } if (bmpsize == 0) return; - std::vector<unsigned char> bitmap(bmpsize); unsigned long tmpNumBytesRead = 0; const unsigned char *tmpBuffer = input->read(bmpsize, tmpNumBytesRead); if (bmpsize != tmpNumBytesRead) return; + std::vector<unsigned char> bitmap(bmpsize); memcpy(&bitmap[0], tmpBuffer, bmpsize); m_collector->collectBmp(imageId, colorModel, width, height, bpp, palette, bitmap); } commit 47d2e94deb1e633a15e31ffd3345895bcb80cdb6 Author: David Tardon <dtar...@redhat.com> Date: Mon Aug 17 20:07:15 2015 +0200 afl: sanitize size before using it to alloc. a vector Change-Id: I83086ec45babe6fc908b1aa658cdae06e8e241dc diff --git a/src/lib/CDRParser.cpp b/src/lib/CDRParser.cpp index 0b3d0f2..4274165 100644 --- a/src/lib/CDRParser.cpp +++ b/src/lib/CDRParser.cpp @@ -3066,6 +3066,8 @@ void libcdr::CDRParser::readTxsm16(librevenge::RVNGInputStream *input) } unsigned numChars = readU32(input); + if (numChars > getRemainingLength(input) / 8) + numChars = getRemainingLength(input) / 8; std::vector<unsigned char> charDescriptions(numChars); for (i=0; i<numChars; ++i) { commit 0fa9c7c9678a3d3ca797217db013e6290de7bcdb Author: David Tardon <dtar...@redhat.com> Date: Mon Aug 17 20:03:59 2015 +0200 afl: postpone alloc. till we get the data Change-Id: I8b4471f3b8846a92f6b0e71e4e9372471fc2cb35 diff --git a/src/lib/CDRParser.cpp b/src/lib/CDRParser.cpp index fbceb75..0b3d0f2 100644 --- a/src/lib/CDRParser.cpp +++ b/src/lib/CDRParser.cpp @@ -2338,11 +2338,11 @@ void libcdr::CDRParser::readBmpf(librevenge::RVNGInputStream *input, unsigned le if (dataSize == 0) return; input->seek(length - dataSize - 28, librevenge::RVNG_SEEK_CUR); - std::vector<unsigned char> pattern(dataSize); unsigned long tmpNumBytesRead = 0; const unsigned char *tmpBuffer = input->read(dataSize, tmpNumBytesRead); if (dataSize != tmpNumBytesRead) return; + std::vector<unsigned char> pattern(dataSize); memcpy(&pattern[0], tmpBuffer, dataSize); m_collector->collectBmpf(patternId, width, height, pattern); } commit 11a9e1bf12237d983f606826c444973e54bf879e Author: David Tardon <dtar...@redhat.com> Date: Mon Aug 17 19:37:30 2015 +0200 afl: sanitize size before using it to alloc. a vector Change-Id: Ie4eac6f2c72f192716d48c2f593666b5d65a7cab diff --git a/src/lib/CDRParser.cpp b/src/lib/CDRParser.cpp index f438ed0..fbceb75 100644 --- a/src/lib/CDRParser.cpp +++ b/src/lib/CDRParser.cpp @@ -2951,6 +2951,9 @@ void libcdr::CDRParser::readTxsm(librevenge::RVNGInputStream *input, unsigned le charStyles[2*i] = charStyle; } unsigned numChars = readU32(input); + const unsigned charSize = m_version >= 1200 ? 8 : 4; + if (numChars > getRemainingLength(input) / charSize) + numChars = getRemainingLength(input) / charSize; std::vector<unsigned char> charDescriptions(numChars); for (i=0; i<numChars; ++i) { commit 6775c795d1930ef8c585ed972c96b862aa8d31bc Author: David Tardon <dtar...@redhat.com> Date: Mon Aug 17 19:29:32 2015 +0200 afl: sanitize length before reading string This avoids potential creation and manipulation of large buffers. Change-Id: Iac2fa879a65bc2ec2a91c191398e4181f0aa9fd1 diff --git a/src/lib/CDRParser.cpp b/src/lib/CDRParser.cpp index ef449fc..f438ed0 100644 --- a/src/lib/CDRParser.cpp +++ b/src/lib/CDRParser.cpp @@ -3368,6 +3368,13 @@ void libcdr::CDRParser::readParagraphText(librevenge::RVNGInputStream *input) void libcdr::CDRParser::_readX6StyleString(librevenge::RVNGInputStream *input, unsigned length, libcdr::CDRCharacterStyle &style) { + if (length > getRemainingLength(input)) + { + length = getRemainingLength(input); + if ((m_version < 1700) && (length & 1)) + --length; // the length must be even + } + std::vector<unsigned char> styleBuffer(length); unsigned long numBytesRead = 0; const unsigned char *tmpBuffer = input->read(length, numBytesRead); diff --git a/src/lib/libcdr_utils.cpp b/src/lib/libcdr_utils.cpp index d4b8116..e4f2fcc 100644 --- a/src/lib/libcdr_utils.cpp +++ b/src/lib/libcdr_utils.cpp @@ -295,6 +295,11 @@ unsigned long libcdr::getLength(librevenge::RVNGInputStream *const input) return static_cast<unsigned long>(end); } +unsigned long libcdr::getRemainingLength(librevenge::RVNGInputStream *const input) +{ + return getLength(input) - static_cast<unsigned long>(input->tell()); +} + int libcdr::cdr_round(double d) { return (d>0) ? int(d+0.5) : int(d-0.5); diff --git a/src/lib/libcdr_utils.h b/src/lib/libcdr_utils.h index d26f06a..273b0e9 100644 --- a/src/lib/libcdr_utils.h +++ b/src/lib/libcdr_utils.h @@ -90,6 +90,7 @@ double readDouble(librevenge::RVNGInputStream *input, bool bigEndian=false); double readFixedPoint(librevenge::RVNGInputStream *input, bool bigEndian=false); unsigned long getLength(librevenge::RVNGInputStream *input); +unsigned long getRemainingLength(librevenge::RVNGInputStream *input); int cdr_round(double d); commit bf32c68489887f2a1c10a93630bd3b6409ae9d8d Author: David Tardon <dtar...@redhat.com> Date: Mon Aug 17 19:16:47 2015 +0200 use stricter checks in Styd parser too Change-Id: Ib28e586f8569d85264d3c64d2de661a527f97a8b diff --git a/src/lib/CDRParser.cpp b/src/lib/CDRParser.cpp index a501591..ef449fc 100644 --- a/src/lib/CDRParser.cpp +++ b/src/lib/CDRParser.cpp @@ -3256,12 +3256,21 @@ void libcdr::CDRParser::readStyd(librevenge::RVNGInputStream *input) } unsigned styleId = readU16(input); long startPosition = input->tell(); + const unsigned long maxLength = getLength(input); + if (startPosition >= long(maxLength)) + return; unsigned chunkLength = readUnsigned(input); + if ((chunkLength > maxLength) || (long(maxLength - chunkLength) < startPosition)) + chunkLength = unsigned(maxLength - static_cast<unsigned long>(startPosition)); // sanitize length unsigned numOfArgs = readUnsigned(input); - if (numOfArgs > chunkLength / 4) // avoid extra big allocation in case of a broken file - numOfArgs = chunkLength / 4; unsigned startOfArgs = readUnsigned(input); + if (startOfArgs >= chunkLength) + return; unsigned startOfArgTypes = readUnsigned(input); + if (startOfArgTypes >= chunkLength) + return; + if (numOfArgs > (chunkLength - startOfArgs) / 4) // avoid extra big allocation in case of a broken file + numOfArgs = (chunkLength - startOfArgs) / 4; CDRCharacterStyle charStyle; charStyle.m_parentId = readUnsigned(input); std::vector<unsigned> argOffsets(numOfArgs, 0); commit 5d204827bbcb4466d3845bb7655d74531094b901 Author: David Tardon <dtar...@redhat.com> Date: Mon Aug 17 19:14:03 2015 +0200 use stricter checks in Loda parser too Change-Id: I73f566ea7fab30d04510a0eb41bd6c314feff4b9 diff --git a/src/lib/CDRParser.cpp b/src/lib/CDRParser.cpp index 101d9bf..a501591 100644 --- a/src/lib/CDRParser.cpp +++ b/src/lib/CDRParser.cpp @@ -2052,12 +2052,21 @@ void libcdr::CDRParser::readLoda(librevenge::RVNGInputStream *input, unsigned le if (!_redirectX6Chunk(&input, length)) throw GenericException(); long startPosition = input->tell(); + const unsigned long maxLength = getLength(input); + if (startPosition >= long(maxLength)) + return; + if ((length > maxLength) || (long(maxLength - length) < startPosition)) + length = unsigned(maxLength - static_cast<unsigned long>(startPosition)); // sanitize length unsigned chunkLength = readUnsigned(input); unsigned numOfArgs = readUnsigned(input); - if (numOfArgs > length / 4) // avoid extra big allocation in case of a broken file - numOfArgs = length / 4; unsigned startOfArgs = readUnsigned(input); + if (startOfArgs >= length) + return; unsigned startOfArgTypes = readUnsigned(input); + if (startOfArgTypes >= length) + return; + if (numOfArgs > (length - startOfArgs) / 4) // avoid extra big allocation in case of a broken file + numOfArgs = (length - startOfArgs) / 4; unsigned chunkType = readUnsigned(input); if (chunkType == 0x26) m_collector->collectSpline(); _______________________________________________ Libreoffice-commits mailing list libreoffice-comm...@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/libreoffice-commits