[Libreoffice-commits] core.git: cppcanvas/source vcl/qa vcl/source

Mike Kaganski mike.kaganski at collabora.com
Mon Aug 31 12:01:46 PDT 2015


 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 daecb93affd5e5ec89eec0d18f433a296b9aed1d
Author: Mike Kaganski <mike.kaganski at 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 <ci at libreoffice.org>
    Reviewed-by: Andras Timar <andras.timar at collabora.com>

diff --git a/cppcanvas/source/mtfrenderer/emfplus.cxx b/cppcanvas/source/mtfrenderer/emfplus.cxx
index cd09430..e26e8f9 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 (const_cast<sal_uInt8 *>(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 03d1f90..89e92fd 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()


More information about the Libreoffice-commits mailing list