cppcanvas/source/mtfrenderer/emfplus.cxx | 33 +++++++++++++++++++++---------- vcl/qa/cppunit/wmf/data/tdf93750.emf |binary vcl/qa/cppunit/wmf/wmfimporttest.cxx | 17 +++++++++++++++ vcl/source/filter/wmf/enhwmf.cxx | 10 ++++----- 4 files changed, 45 insertions(+), 15 deletions(-)
New commits: commit 975ab665df3158799cbde1146e124d8c08b4d9df Author: Mike Kaganski <mike.kagan...@collabora.com> Date: Sat Aug 29 00:57:20 2015 +1000 tdf#93750 allow for EMF+ record padding up to 11 bytes When an array of EMF+ has extra bytes in the end, that are less than 12, they should not be treated as another EMF+ record, but simply ignored. Change-Id: I34701c00916812c8a6a4b69730f602da81719b35 Reviewed-on: https://gerrit.libreoffice.org/18110 Tested-by: Jenkins <c...@libreoffice.org> Reviewed-by: Andras Timar <andras.ti...@collabora.com> (cherry picked from commit daecb93affd5e5ec89eec0d18f433a296b9aed1d) Reviewed-on: https://gerrit.libreoffice.org/18200 Reviewed-by: Miklos Vajna <vmik...@collabora.co.uk> diff --git a/cppcanvas/source/mtfrenderer/emfplus.cxx b/cppcanvas/source/mtfrenderer/emfplus.cxx index b8480b8..0562e43 100644 --- a/cppcanvas/source/mtfrenderer/emfplus.cxx +++ b/cppcanvas/source/mtfrenderer/emfplus.cxx @@ -1111,31 +1111,35 @@ namespace cppcanvas void Read (SvMemoryStream &s, sal_uInt32 dataSize, bool bUseWholeStream) { - sal_uInt32 header, unknown; + sal_uInt32 header, bitmapType; s.ReadUInt32( header ).ReadUInt32( type ); SAL_INFO("cppcanvas.emf", "EMF+\timage\nEMF+\theader: 0x" << std::hex << header << " type: " << type << std::dec ); if (type == 1) { // bitmap - s.ReadInt32( width ).ReadInt32( height ).ReadInt32( stride ).ReadInt32( pixelFormat ).ReadUInt32( unknown ); + s.ReadInt32( width ).ReadInt32( height ).ReadInt32( stride ).ReadInt32( pixelFormat ).ReadUInt32( bitmapType ); SAL_INFO("cppcanvas.emf", "EMF+\tbitmap width: " << width << " height: " << height << " stride: " << stride << " pixelFormat: 0x" << std::hex << pixelFormat << std::dec); - if (width == 0) { // non native formats + if ((bitmapType != 0) || (width == 0)) { // non native formats GraphicFilter filter; filter.ImportGraphic (graphic, OUString(), s); SAL_INFO("cppcanvas.emf", "EMF+\tbitmap width: " << graphic.GetBitmap().GetSizePixel().Width() << " height: " << graphic.GetBitmap().GetSizePixel().Height()); } - } else if (type == 2) { + } else if (type == 2) { // metafile sal_Int32 mfType, mfSize; s.ReadInt32( mfType ).ReadInt32( mfSize ); - SAL_INFO("cppcanvas.emf", "EMF+\tmetafile type: " << mfType << " dataSize: " << mfSize << " real size calculated from record dataSize: " << dataSize - 16); + if (bUseWholeStream) + dataSize = s.remainingSize(); + else + dataSize -= 16; + SAL_INFO("cppcanvas.emf", "EMF+\tmetafile type: " << mfType << " dataSize: " << mfSize << " real size calculated from record dataSize: " << dataSize); GraphicFilter filter; // workaround buggy metafiles, which have wrong mfSize set (n#705956 for example) - SvMemoryStream mfStream (const_cast<char *>(static_cast<char const *>(s.GetData()) + s.Tell()), bUseWholeStream ? s.remainingSize() : dataSize - 16, StreamMode::READ); + SvMemoryStream mfStream (const_cast<char *>(static_cast<char const *>(s.GetData()) + s.Tell()), dataSize, StreamMode::READ); filter.ImportGraphic (graphic, OUString(), mfStream); @@ -1810,9 +1814,12 @@ namespace cppcanvas sal_uInt32 length = pAct->GetDataSize (); SvMemoryStream rMF ((void*) pAct->GetData (), length, StreamMode::READ); - length -= 4; + if (length < 12) { + SAL_INFO("cppcanvas.emf", "length is less than required header size"); + } - while (length > 0) { + // 12 is minimal valid EMF+ record size; remaining bytes are padding + while (length >= 12) { sal_uInt16 type, flags; sal_uInt32 size, dataSize; sal_Size next; @@ -1823,6 +1830,11 @@ namespace cppcanvas if (size < 12) { SAL_INFO("cppcanvas.emf", "Size field is less than 12 bytes"); + } else if (size > length) { + SAL_INFO("cppcanvas.emf", "Size field is greater than bytes left"); + } + if (dataSize > (size-12)) { + SAL_INFO("cppcanvas.emf", "DataSize field is greater than Size-12"); } SAL_INFO("cppcanvas.emf", "EMF+ record size: " << size << " type: " << emfTypeToName(type) << " flags: " << flags << " data size: " << dataSize); @@ -1834,14 +1846,15 @@ namespace cppcanvas mMStream.Seek(0); } - // 1st 4 bytes are unknown + OSL_ENSURE(dataSize >= 4, "No room for TotalObjectSize in EmfPlusContinuedObjectRecord"); + // 1st 4 bytes are TotalObjectSize mMStream.Write (static_cast<const char *>(rMF.GetData()) + rMF.Tell() + 4, dataSize - 4); SAL_INFO("cppcanvas.emf", "EMF+ read next object part size: " << size << " type: " << type << " flags: " << flags << " data size: " << dataSize); } else { if (mbMultipart) { SAL_INFO("cppcanvas.emf", "EMF+ multipart record flags: " << mMFlags); mMStream.Seek (0); - processObjectRecord (mMStream, mMFlags, dataSize, true); + processObjectRecord (mMStream, mMFlags, 0, true); } mbMultipart = false; } diff --git a/vcl/qa/cppunit/wmf/data/tdf93750.emf b/vcl/qa/cppunit/wmf/data/tdf93750.emf new file mode 100644 index 0000000..3c4c415 Binary files /dev/null and b/vcl/qa/cppunit/wmf/data/tdf93750.emf differ diff --git a/vcl/qa/cppunit/wmf/wmfimporttest.cxx b/vcl/qa/cppunit/wmf/wmfimporttest.cxx index 3cee5fe..6e595c0 100644 --- a/vcl/qa/cppunit/wmf/wmfimporttest.cxx +++ b/vcl/qa/cppunit/wmf/wmfimporttest.cxx @@ -44,12 +44,14 @@ public: void testSine(); void testEmfProblem(); void testWorldTransformFontSize(); + void testTdf93750(); CPPUNIT_TEST_SUITE(WmfTest); CPPUNIT_TEST(testNonPlaceableWmf); CPPUNIT_TEST(testSine); CPPUNIT_TEST(testEmfProblem); CPPUNIT_TEST(testWorldTransformFontSize); + CPPUNIT_TEST(testTdf93750); CPPUNIT_TEST_SUITE_END(); }; @@ -148,6 +150,21 @@ void WmfTest::testWorldTransformFontSize() assertXPath(pDoc, "/metafile/font[3]", "weight", "normal"); } +void WmfTest::testTdf93750() +{ + SvFileStream aFileStream(getFullUrl("tdf93750.emf"), StreamMode::READ); + GDIMetaFile aGDIMetaFile; + ReadWindowMetafile(aFileStream, aGDIMetaFile); + + MetafileXmlDump dumper; + xmlDocPtr pDoc = dumper.dumpAndParse(aGDIMetaFile); + + CPPUNIT_ASSERT (pDoc); + + assertXPath(pDoc, "/metafile/push[1]/comment[2]", "datasize", "28"); + assertXPath(pDoc, "/metafile/push[1]/comment[3]", "datasize", "72"); +} + CPPUNIT_TEST_SUITE_REGISTRATION(WmfTest); CPPUNIT_PLUGIN_IMPLEMENT(); diff --git a/vcl/source/filter/wmf/enhwmf.cxx b/vcl/source/filter/wmf/enhwmf.cxx index 87d492d6..a59d684 100644 --- a/vcl/source/filter/wmf/enhwmf.cxx +++ b/vcl/source/filter/wmf/enhwmf.cxx @@ -433,10 +433,8 @@ void EnhWMFReader::ReadEMFPlusComment(sal_uInt32 length, bool& bHaveDC) bHaveDC = false; - OSL_ASSERT(length >= 4); - // reduce by 32bit length itself, skip in SeekRel if - // impossibly unavailable - sal_uInt32 nRemainder = length >= 4 ? length-4 : length; + // skip in SeekRel if impossibly unavailable + sal_uInt32 nRemainder = length; const size_t nRequiredHeaderSize = 12; while (nRemainder >= nRequiredHeaderSize) @@ -682,7 +680,9 @@ bool EnhWMFReader::ReadEnhWMF() // EMF+ comment (FIXME: BE?) if( id == 0x2B464D45 && nRecSize >= 12 ) - ReadEMFPlusComment( length, bHaveDC ); + // [MS-EMF] 2.3.3: DataSize includes both CommentIdentifier and CommentRecordParm fields. + // We have already read 4-byte CommentIdentifier, so reduce length appropriately + ReadEMFPlusComment( length-4, bHaveDC ); // GDIC comment, doesn't do anything useful yet else if( id == 0x43494447 && nRecSize >= 12 ) { // TODO: ReadGDIComment() _______________________________________________ Libreoffice-commits mailing list libreoffice-comm...@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/libreoffice-commits