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 <dtar...@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 <dtar...@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-@CDR_MAJOR_VERSION@.@CDR_MINOR_VERSION@.la libcdr_@CDR_MAJOR_VERSION@_@CDR_MINOR_VERSION@_includedir = $(includedir)/libcdr-@CDR_MAJOR_VERSION@.@CDR_MINOR_VERSION@/libcdr libcdr_@CDR_MAJOR_VERSION@_@CDR_MINOR_VERSION@_include_HEADERS = \ @@ -14,13 +15,16 @@ libcdr_@CDR_MAJOR_VERSION@_@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_@CDR_MAJOR_VERSION@_@CDR_MINOR_VERSION@_la_LIBADD = $(REVENGE_LIBS) $(LCMS2_LIBS) $(ZLIB_LIBS) $(ICU_LIBS) @LIBCDR_WIN32_RESOURCE@ -libcdr_@CDR_MAJOR_VERSION@_@CDR_MINOR_VERSION@_la_DEPENDENCIES = @LIBCDR_WIN32_RESOURCE@ +libcdr_@CDR_MAJOR_VERSION@_@CDR_MINOR_VERSION@_la_LIBADD = libcdr-internal.la $(REVENGE_LIBS) $(LCMS2_LIBS) $(ZLIB_LIBS) $(ICU_LIBS) @LIBCDR_WIN32_RESOURCE@ +libcdr_@CDR_MAJOR_VERSION@_@CDR_MINOR_VERSION@_la_DEPENDENCIES = libcdr-internal.la @LIBCDR_WIN32_RESOURCE@ libcdr_@CDR_MAJOR_VERSION@_@CDR_MINOR_VERSION@_la_LDFLAGS = $(version_info) -export-dynamic -no-undefined libcdr_@CDR_MAJOR_VERSION@_@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_@CDR_MAJOR_VERSION@_@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 <dtar...@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 <dtar...@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) { _______________________________________________ Libreoffice-commits mailing list libreoffice-comm...@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/libreoffice-commits