[Libreoffice-commits] libcdr.git: 4 commits - configure.ac src/lib src/Makefile.am src/test

David Tardon dtardon at redhat.com
Mon Aug 17 09:08:10 PDT 2015


 configure.ac                       |   17 +++++
 src/Makefile.am                    |    4 +
 src/lib/CDRContentCollector.cpp    |    5 +
 src/lib/CDRInternalStream.cpp      |    2 
 src/lib/CDRParser.cpp              |   11 +++
 src/lib/Makefile.am                |   11 ++-
 src/lib/libcdr_utils.cpp           |   32 +++++++++++
 src/lib/libcdr_utils.h             |    2 
 src/test/.gitignore                |   10 +++
 src/test/CDRInternalStreamTest.cpp |  106 +++++++++++++++++++++++++++++++++++++
 src/test/Makefile.am               |   33 +++++++++++
 src/test/test.cpp                  |   46 ++++++++++++++++
 12 files changed, 272 insertions(+), 7 deletions(-)

New commits:
commit 6611e91b52506820b9ded09f0c45810ab7c4ad98
Author: David Tardon <dtardon at redhat.com>
Date:   Mon Aug 17 16:58:21 2015 +0200

    afl: improve sanity check
    
    Change-Id: I58d8100c4e6e5d15464df6868625fffe8b51d947

diff --git a/src/lib/CDRParser.cpp b/src/lib/CDRParser.cpp
index c6eabc9..101d9bf 100644
--- a/src/lib/CDRParser.cpp
+++ b/src/lib/CDRParser.cpp
@@ -1636,11 +1636,18 @@ void libcdr::CDRParser::readTrfd(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;
+  if (numOfArgs > (length - startOfArgs) / 4) // avoid extra big allocation in case of a broken file
+    numOfArgs = (length - startOfArgs) / 4;
   std::vector<unsigned> argOffsets(numOfArgs, 0);
   unsigned i = 0;
   input->seek(startPosition+startOfArgs, librevenge::RVNG_SEEK_SET);
diff --git a/src/lib/libcdr_utils.cpp b/src/lib/libcdr_utils.cpp
index 45eeb73..d4b8116 100644
--- a/src/lib/libcdr_utils.cpp
+++ b/src/lib/libcdr_utils.cpp
@@ -7,6 +7,7 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
  */
 
+#include <cassert>
 #include <string.h>
 
 #include "libcdr_utils.h"
@@ -263,6 +264,37 @@ double libcdr::readFixedPoint(librevenge::RVNGInputStream *input, bool bigEndian
   return ((double)fixedPointNumberIntegerPart + fixedPointNumberFractionalPart);
 }
 
+unsigned long libcdr::getLength(librevenge::RVNGInputStream *const input)
+{
+  if (!input)
+    throw EndOfStreamException();
+
+  const long orig = input->tell();
+  long end = 0;
+
+  if (input->seek(0, librevenge::RVNG_SEEK_END) == 0)
+  {
+    end = input->tell();
+  }
+  else
+  {
+    // RVNG_SEEK_END does not work. Use the harder way.
+    if (input->seek(0, librevenge::RVNG_SEEK_SET) != 0)
+      throw EndOfStreamException();
+    while (!input->isEnd())
+    {
+      readU8(input);
+      ++end;
+    }
+  }
+  assert(end >= 0);
+
+  if (input->seek(orig, librevenge::RVNG_SEEK_SET) != 0)
+    throw EndOfStreamException();
+
+  return static_cast<unsigned long>(end);
+}
+
 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 2349e37..d26f06a 100644
--- a/src/lib/libcdr_utils.h
+++ b/src/lib/libcdr_utils.h
@@ -89,6 +89,8 @@ double readDouble(librevenge::RVNGInputStream *input, bool bigEndian=false);
 
 double readFixedPoint(librevenge::RVNGInputStream *input, bool bigEndian=false);
 
+unsigned long getLength(librevenge::RVNGInputStream *input);
+
 int cdr_round(double d);
 
 void writeU16(librevenge::RVNGBinaryData &buffer, const int value);
commit 65d6b995beb37236301edd9ecdaab9161e58eb96
Author: David Tardon <dtardon at redhat.com>
Date:   Mon Aug 17 17:23:29 2015 +0200

    add unit test for the internal stream
    
    Change-Id: I2811ea0fcf013882af202a39cd0664f81b2ef1d3

diff --git a/configure.ac b/configure.ac
index 2bbf072..b6285ab 100644
--- a/configure.ac
+++ b/configure.ac
@@ -294,6 +294,21 @@ AS_IF([test "x$enable_debug" = "xyes"], [
 ])
 AC_SUBST(DEBUG_CXXFLAGS)
 
+# ==========
+# Unit tests
+# ==========
+AC_ARG_ENABLE([tests],
+    [AS_HELP_STRING([--enable-tests], [Build and run unit tests])],
+    [enable_tests="$enableval"],
+    [enable_tests=yes]
+)
+AS_IF([test "x$enable_tests" = "xyes"], [
+    PKG_CHECK_MODULES([CPPUNIT], [cppunit])
+], [])
+AC_SUBST([CPPUNIT_CFLAGS])
+AC_SUBST([CPPUNIT_LIBS])
+AM_CONDITIONAL([BUILD_TESTS], [test "x$enable_tests" = "xyes"])
+
 # =============
 # Documentation
 # =============
@@ -332,6 +347,7 @@ src/conv/text/cdr2text.rc
 src/conv/text/cmx2text.rc
 src/lib/Makefile
 src/lib/libcdr.rc
+src/test/Makefile
 build/Makefile
 build/win32/Makefile
 docs/Makefile
@@ -350,6 +366,7 @@ AC_MSG_NOTICE([
 Build configuration:
 	debug:           ${enable_debug}
 	docs:            ${build_docs}
+	tests:           ${enable_tests}
 	tools:           ${enable_tools}
 	werror:          ${enable_werror}
 ==============================================================================
diff --git a/src/Makefile.am b/src/Makefile.am
index 64fd45e..513f18b 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -3,3 +3,7 @@ SUBDIRS = lib
 if BUILD_TOOLS
 SUBDIRS += conv
 endif
+
+if BUILD_TESTS
+SUBDIRS += test
+endif
diff --git a/src/lib/Makefile.am b/src/lib/Makefile.am
index b3613d7..f8065a8 100644
--- a/src/lib/Makefile.am
+++ b/src/lib/Makefile.am
@@ -4,6 +4,7 @@ else
 version_info = -version-info $(LT_CURRENT):$(LT_REVISION):$(LT_AGE)
 endif
 
+noinst_LTLIBRARIES = libcdr-internal.la
 lib_LTLIBRARIES = libcdr- at CDR_MAJOR_VERSION@. at CDR_MINOR_VERSION@.la
 libcdr_ at CDR_MAJOR_VERSION@_ at CDR_MINOR_VERSION@_includedir = $(includedir)/libcdr- at CDR_MAJOR_VERSION@. at CDR_MINOR_VERSION@/libcdr
 libcdr_ at CDR_MAJOR_VERSION@_ at CDR_MINOR_VERSION@_include_HEADERS = \
@@ -14,13 +15,16 @@ libcdr_ at CDR_MAJOR_VERSION@_ at CDR_MINOR_VERSION@_include_HEADERS = \
 
 AM_CXXFLAGS = -I$(top_srcdir)/inc $(REVENGE_CFLAGS) $(LCMS2_CFLAGS) $(ZLIB_CFLAGS) $(ICU_CFLAGS) $(DEBUG_CXXFLAGS) -DLIBCDR_BUILD=1
 
-libcdr_ at CDR_MAJOR_VERSION@_ at CDR_MINOR_VERSION@_la_LIBADD  = $(REVENGE_LIBS) $(LCMS2_LIBS) $(ZLIB_LIBS) $(ICU_LIBS) @LIBCDR_WIN32_RESOURCE@
-libcdr_ at CDR_MAJOR_VERSION@_ at CDR_MINOR_VERSION@_la_DEPENDENCIES = @LIBCDR_WIN32_RESOURCE@
+libcdr_ at CDR_MAJOR_VERSION@_ at CDR_MINOR_VERSION@_la_LIBADD  = libcdr-internal.la $(REVENGE_LIBS) $(LCMS2_LIBS) $(ZLIB_LIBS) $(ICU_LIBS) @LIBCDR_WIN32_RESOURCE@
+libcdr_ at CDR_MAJOR_VERSION@_ at CDR_MINOR_VERSION@_la_DEPENDENCIES = libcdr-internal.la @LIBCDR_WIN32_RESOURCE@
 libcdr_ at CDR_MAJOR_VERSION@_ at CDR_MINOR_VERSION@_la_LDFLAGS = $(version_info) -export-dynamic -no-undefined
 libcdr_ at CDR_MAJOR_VERSION@_ at CDR_MINOR_VERSION@_la_SOURCES = \
+	CDRDocument.cpp \
+	CMXDocument.cpp
+
+libcdr_internal_la_SOURCES = \
 	CDRCollector.cpp \
 	CDRContentCollector.cpp \
-	CDRDocument.cpp \
 	CDRInternalStream.cpp \
 	CDROutputElementList.cpp \
 	CDRParser.cpp \
@@ -28,7 +32,6 @@ libcdr_ at CDR_MAJOR_VERSION@_ at CDR_MINOR_VERSION@_la_SOURCES = \
 	CDRStylesCollector.cpp \
 	CDRTransforms.cpp \
 	CDRTypes.cpp \
-	CMXDocument.cpp \
 	CMXParser.cpp \
 	CommonParser.cpp \
 	libcdr_utils.cpp \
diff --git a/src/test/.gitignore b/src/test/.gitignore
new file mode 100644
index 0000000..7742c8b
--- /dev/null
+++ b/src/test/.gitignore
@@ -0,0 +1,10 @@
+Makefile
+Makefile.in
+test
+.libs
+.deps
+*.lo
+*.log
+*.o
+*.trs
+*~
diff --git a/src/test/CDRInternalStreamTest.cpp b/src/test/CDRInternalStreamTest.cpp
new file mode 100644
index 0000000..f3d24b3
--- /dev/null
+++ b/src/test/CDRInternalStreamTest.cpp
@@ -0,0 +1,106 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/*
+ * This file is part of the libcdr project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#include <algorithm>
+
+#include <cppunit/TestFixture.h>
+#include <cppunit/extensions/HelperMacros.h>
+
+#include <librevenge-stream/librevenge-stream.h>
+
+#include "CDRInternalStream.h"
+
+namespace test
+{
+
+using libcdr::CDRInternalStream;
+
+class CDRInternalStreamTest : public CPPUNIT_NS::TestFixture
+{
+public:
+  virtual void setUp();
+  virtual void tearDown();
+
+private:
+  CPPUNIT_TEST_SUITE(CDRInternalStreamTest);
+  CPPUNIT_TEST(testRead);
+  CPPUNIT_TEST(testSeek);
+  CPPUNIT_TEST_SUITE_END();
+
+private:
+  void testRead();
+  void testSeek();
+};
+
+void CDRInternalStreamTest::setUp()
+{
+}
+
+void CDRInternalStreamTest::tearDown()
+{
+}
+
+void CDRInternalStreamTest::testRead()
+{
+  const unsigned char data[] = "abc dee fgh";
+  CDRInternalStream strm(std::vector<unsigned char>(data, data + sizeof(data)));
+
+  CPPUNIT_ASSERT_MESSAGE("stream is already exhausted before starting to read", !strm.isEnd());
+
+  for (int i = 0; sizeof(data) != i; ++i)
+  {
+    unsigned long readBytes = 0;
+    const unsigned char *s = strm.read(1, readBytes);
+
+    CPPUNIT_ASSERT(1 == readBytes);
+    CPPUNIT_ASSERT_EQUAL(data[i], s[0]);
+    CPPUNIT_ASSERT(((sizeof(data) - 1) == i) || !strm.isEnd());
+  }
+
+  CPPUNIT_ASSERT_MESSAGE("reading did not exhaust the stream", strm.isEnd());
+
+  strm.seek(0, librevenge::RVNG_SEEK_SET);
+
+  unsigned long readBytes = 0;
+  const unsigned char *s = strm.read(sizeof(data), readBytes);
+  CPPUNIT_ASSERT(sizeof(data) == readBytes);
+  CPPUNIT_ASSERT(std::equal(data, data + sizeof(data), s));
+}
+
+void CDRInternalStreamTest::testSeek()
+{
+  const unsigned char data[] = "abc dee fgh";
+  CDRInternalStream strm(std::vector<unsigned char>(data, data + sizeof(data)));
+
+  strm.seek(0, librevenge::RVNG_SEEK_SET);
+  CPPUNIT_ASSERT(0 == strm.tell());
+  strm.seek(2, librevenge::RVNG_SEEK_SET);
+  CPPUNIT_ASSERT(2 == strm.tell());
+
+  strm.seek(1, librevenge::RVNG_SEEK_CUR);
+  CPPUNIT_ASSERT(3 == strm.tell());
+  strm.seek(-2, librevenge::RVNG_SEEK_CUR);
+  CPPUNIT_ASSERT(1 == strm.tell());
+
+  CPPUNIT_ASSERT(!strm.isEnd());
+  CPPUNIT_ASSERT(0 == strm.seek(0, librevenge::RVNG_SEEK_END));
+  CPPUNIT_ASSERT(strm.isEnd());
+  CPPUNIT_ASSERT(sizeof(data) == strm.tell());
+  CPPUNIT_ASSERT(0 != strm.seek(1, librevenge::RVNG_SEEK_END)); // cannot seek after the end
+  CPPUNIT_ASSERT(strm.isEnd());
+  CPPUNIT_ASSERT(0 == strm.seek(-1, librevenge::RVNG_SEEK_END)); // but can seek before it
+  CPPUNIT_ASSERT(!strm.isEnd());
+  CPPUNIT_ASSERT((sizeof(data) - 1) == strm.tell());
+}
+
+CPPUNIT_TEST_SUITE_REGISTRATION(CDRInternalStreamTest);
+
+}
+
+/* vim:set shiftwidth=2 softtabstop=2 expandtab: */
diff --git a/src/test/Makefile.am b/src/test/Makefile.am
new file mode 100644
index 0000000..68c7514
--- /dev/null
+++ b/src/test/Makefile.am
@@ -0,0 +1,33 @@
+## -*- Mode: make; tab-width: 4; indent-tabs-mode: tabs -*-
+
+target_test = test
+
+check_PROGRAMS = $(target_test)
+
+AM_CXXFLAGS = \
+	-I$(top_srcdir)/inc \
+	-I$(top_srcdir)/src/lib \
+	$(CPPUNIT_CFLAGS) \
+	$(LCMS2_CFLAGS) \
+	$(REVENGE_CFLAGS) \
+	$(REVENGE_STREAM_CFLAGS) \
+	$(BOOST_CFLAGS) \
+	$(DEBUG_CXXFLAGS)
+
+test_LDFLAGS = -L$(top_srcdir)/src/lib
+test_LDADD = \
+	$(top_builddir)/src/lib/libcdr-internal.la \
+	$(CPPUNIT_LIBS) \
+	$(ICU_LIBS) \
+	$(LCMS2_LIBS) \
+	$(REVENGE_LIBS) \
+	$(REVENGE_STREAM_LIBS) \
+	$(ZLIB_LIBS)
+
+test_SOURCES = \
+	CDRInternalStreamTest.cpp \
+	test.cpp
+
+TESTS = $(target_test)
+
+## vim:set shiftwidth=4 tabstop=4 noexpandtab:
diff --git a/src/test/test.cpp b/src/test/test.cpp
new file mode 100644
index 0000000..96a6769
--- /dev/null
+++ b/src/test/test.cpp
@@ -0,0 +1,46 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/*
+ * This file is part of the libcdr project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#include <iostream>
+
+#include <cppunit/BriefTestProgressListener.h>
+#include <cppunit/CompilerOutputter.h>
+#include <cppunit/TestResult.h>
+#include <cppunit/TestResultCollector.h>
+#include <cppunit/TestRunner.h>
+
+#include <cppunit/extensions/TestFactoryRegistry.h>
+
+int main()
+{
+  // Create the event manager and test controller
+  CPPUNIT_NS::TestResult controller;
+
+  // Add a listener that colllects test result
+  CPPUNIT_NS::TestResultCollector result;
+  controller.addListener(&result);
+
+  // Add a listener that print dots as test run.
+  CPPUNIT_NS::BriefTestProgressListener progress;
+  controller.addListener(&progress);
+
+  // Add the top suite to the test runner
+  CPPUNIT_NS::TestRunner runner;
+  runner.addTest(CPPUNIT_NS::TestFactoryRegistry::getRegistry().makeTest());
+  runner.run(controller);
+
+  // output
+  CPPUNIT_NS::CompilerOutputter outputter(&result, std::cerr);
+  outputter.write();
+
+  // return status code
+  return result.wasSuccessful() ? 0 : 1;
+}
+
+/* vim:set shiftwidth=2 softtabstop=2 expandtab: */
commit b6a295e599f93f6ff6fcda489c1c34479c846728
Author: David Tardon <dtardon at redhat.com>
Date:   Mon Aug 17 17:05:27 2015 +0200

    impl. seek-to-end in internal stream
    
    Change-Id: Id2401fd09bd2d4a5c54caeb2502932969d9e61f8

diff --git a/src/lib/CDRInternalStream.cpp b/src/lib/CDRInternalStream.cpp
index 11ecb0f..b1e5520 100644
--- a/src/lib/CDRInternalStream.cpp
+++ b/src/lib/CDRInternalStream.cpp
@@ -126,6 +126,8 @@ int libcdr::CDRInternalStream::seek(long offset, librevenge::RVNG_SEEK_TYPE seek
     m_offset += offset;
   else if (seekType == librevenge::RVNG_SEEK_SET)
     m_offset = offset;
+  else if (seekType == librevenge::RVNG_SEEK_END)
+    m_offset = long(static_cast<unsigned long>(m_buffer.size())) + offset;
 
   if (m_offset < 0)
   {
commit 5ce6bb2daefef06139073a257d54843705eb9993
Author: David Tardon <dtardon at redhat.com>
Date:   Fri Aug 14 15:16:04 2015 +0200

    afl: avoid out-of-bounds access to vector
    
    Change-Id: I0356716036eb9c32a87c7a376488037abe9c5eab

diff --git a/src/lib/CDRContentCollector.cpp b/src/lib/CDRContentCollector.cpp
index 06df33b..c3d1c22 100644
--- a/src/lib/CDRContentCollector.cpp
+++ b/src/lib/CDRContentCollector.cpp
@@ -1129,7 +1129,10 @@ void libcdr::CDRContentCollector::_generateBitmapFromPattern(librevenge::RVNGBin
     while (i <lineWidth && k < width)
     {
       unsigned l = 0;
-      unsigned char c = pattern.pattern[(j-1)*lineWidth+i];
+      unsigned char c = 0;
+      const unsigned index = (j-1)*lineWidth+i;
+      if (index < pattern.pattern.size())
+        c = pattern.pattern[index];
       i++;
       while (k < width && l < 8)
       {


More information about the Libreoffice-commits mailing list