[Libreoffice-commits] libcdr.git: 9 commits - src/lib

David Tardon dtardon at redhat.com
Mon Aug 17 12:24:06 PDT 2015


 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 <dtardon at 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 <dtardon at 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 <dtardon at 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 <dtardon at 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 <dtardon at 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 <dtardon at 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 <dtardon at 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 <dtardon at 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 <dtardon at 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();


More information about the Libreoffice-commits mailing list