[Libreoffice-commits] core.git: filter/source

Caolán McNamara (via logerrit) logerrit at kemper.freedesktop.org
Tue Dec 22 12:58:36 UTC 2020


 filter/source/graphicfilter/ieps/ieps.cxx |  355 +++++++++++++++---------------
 1 file changed, 183 insertions(+), 172 deletions(-)

New commits:
commit e7c76d604a4694e6568bf10c2a06a786f1096319
Author:     Caolán McNamara <caolanm at redhat.com>
AuthorDate: Tue Dec 22 10:27:38 2020 +0000
Commit:     Caolán McNamara <caolanm at redhat.com>
CommitDate: Tue Dec 22 13:57:43 2020 +0100

    oss-fuzz: epsfuzzer doesn't pass sanity check
    
    Step #5:     #6 0x640b42f in __cxa_throw (/tmp/not-out/epsfuzzer+0x640b42f)
    Step #5:     #7 0x5413d9 in SvStream::ReadUInt32(unsigned int&) (/tmp/not-out/epsfuzzer+0x5413d9)
    Step #5:     #8 0x1dd29b1 in ipsGraphicImport (/tmp/not-out/epsfuzzer+0x1dd29b1)
    
    Change-Id: Ieab45edabd5f13d07359be558618ff65badfde2e
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/108156
    Tested-by: Jenkins
    Reviewed-by: Caolán McNamara <caolanm at redhat.com>

diff --git a/filter/source/graphicfilter/ieps/ieps.cxx b/filter/source/graphicfilter/ieps/ieps.cxx
index 4bb06962ed0d..e5753510bbd9 100644
--- a/filter/source/graphicfilter/ieps/ieps.cxx
+++ b/filter/source/graphicfilter/ieps/ieps.cxx
@@ -592,227 +592,238 @@ ipsGraphicImport( SvStream & rStream, Graphic & rGraphic, FilterConfigItem* )
     sal_uInt32  nPosWMF = 0;
     sal_uInt32  nSizeTIFF = 0;
     sal_uInt32  nPosTIFF = 0;
-    sal_uInt32  nOrigPos = nPSStreamPos = rStream.Tell();
+
+    auto nOrigPos = nPSStreamPos = rStream.Tell();
     SvStreamEndian nOldFormat = rStream.GetEndian();
-    rStream.SetEndian( SvStreamEndian::LITTLE );
-    rStream.ReadUInt32( nSignature );
-    if ( nSignature == 0xc6d3d0c5 )
+
+    try
     {
-        rStream.ReadUInt32( nPSStreamPos ).ReadUInt32( nPSSize ).ReadUInt32( nPosWMF ).ReadUInt32( nSizeWMF );
+        rStream.SetEndian( SvStreamEndian::LITTLE );
+        rStream.ReadUInt32( nSignature );
+        if ( nSignature == 0xc6d3d0c5 )
+        {
+            rStream.ReadUInt32( nPSStreamPos ).ReadUInt32( nPSSize ).ReadUInt32( nPosWMF ).ReadUInt32( nSizeWMF );
 
-        // first we try to get the metafile grafix
+            // first we try to get the metafile grafix
 
-        if ( nSizeWMF )
-        {
-            if (nPosWMF && checkSeek(rStream, nOrigPos + nPosWMF))
+            if ( nSizeWMF )
             {
-                if (GraphicConverter::Import(rStream, aGraphic, ConvertDataFormat::WMF) == ERRCODE_NONE)
-                    bHasPreview = bRetValue = true;
+                if (nPosWMF && checkSeek(rStream, nOrigPos + nPosWMF))
+                {
+                    if (GraphicConverter::Import(rStream, aGraphic, ConvertDataFormat::WMF) == ERRCODE_NONE)
+                        bHasPreview = bRetValue = true;
+                }
             }
-        }
-        else
-        {
-            rStream.ReadUInt32( nPosTIFF ).ReadUInt32( nSizeTIFF );
+            else
+            {
+                rStream.ReadUInt32( nPosTIFF ).ReadUInt32( nSizeTIFF );
 
-            // else we have to get the tiff grafix
+                // else we have to get the tiff grafix
 
-            if (nPosTIFF && nSizeTIFF && checkSeek(rStream, nOrigPos + nPosTIFF))
-            {
-                if ( GraphicConverter::Import( rStream, aGraphic, ConvertDataFormat::TIF ) == ERRCODE_NONE )
+                if (nPosTIFF && nSizeTIFF && checkSeek(rStream, nOrigPos + nPosTIFF))
                 {
-                    MakeAsMeta(aGraphic);
-                    rStream.Seek( nOrigPos + nPosTIFF );
-                    bHasPreview = bRetValue = true;
+                    if ( GraphicConverter::Import( rStream, aGraphic, ConvertDataFormat::TIF ) == ERRCODE_NONE )
+                    {
+                        MakeAsMeta(aGraphic);
+                        rStream.Seek( nOrigPos + nPosTIFF );
+                        bHasPreview = bRetValue = true;
+                    }
                 }
             }
         }
-    }
-    else
-    {
-        nPSStreamPos = nOrigPos;            // no preview available _>so we must get the size manually
-        nPSSize = rStream.Seek( STREAM_SEEK_TO_END ) - nOrigPos;
-    }
-
-    std::unique_ptr<sal_uInt8[]> pHeader( new sal_uInt8[ 22 ] );
-    rStream.Seek( nPSStreamPos );
-    rStream.ReadBytes(pHeader.get(), 22); // check PostScript header
-    bool bOk = ImplSearchEntry(pHeader.get(), reinterpret_cast<sal_uInt8 const *>("%!PS-Adobe"), 10, 10) &&
-               ImplSearchEntry(&pHeader[ 15 ], reinterpret_cast<sal_uInt8 const *>("EPS"), 3, 3);
-    if (bOk)
-    {
-        rStream.Seek(nPSStreamPos);
-        bOk = rStream.remainingSize() >= nPSSize;
-        SAL_WARN_IF(!bOk, "filter.eps", "eps claims to be: " << nPSSize << " in size, but only " << rStream.remainingSize() << " remains");
-    }
-    if (bOk)
-    {
-        std::unique_ptr<sal_uInt8[]> pBuf( new sal_uInt8[ nPSSize ] );
+        else
+        {
+            nPSStreamPos = nOrigPos;            // no preview available _>so we must get the size manually
+            nPSSize = rStream.Seek( STREAM_SEEK_TO_END ) - nOrigPos;
+        }
 
-        sal_uInt32 nBufStartPos = rStream.Tell();
-        sal_uInt32 nBytesRead = rStream.ReadBytes(pBuf.get(), nPSSize);
-        if ( nBytesRead == nPSSize )
+        std::unique_ptr<sal_uInt8[]> pHeader( new sal_uInt8[ 22 ] );
+        rStream.Seek( nPSStreamPos );
+        rStream.ReadBytes(pHeader.get(), 22); // check PostScript header
+        bool bOk = ImplSearchEntry(pHeader.get(), reinterpret_cast<sal_uInt8 const *>("%!PS-Adobe"), 10, 10) &&
+                   ImplSearchEntry(&pHeader[ 15 ], reinterpret_cast<sal_uInt8 const *>("EPS"), 3, 3);
+        if (bOk)
         {
-            sal_uInt32 nSecurityCount = 32;
-            // if there is no tiff/wmf preview, we will parse for a preview in
-            // the eps prolog
-            if (!bHasPreview && nBytesRead >= nSecurityCount)
+            rStream.Seek(nPSStreamPos);
+            bOk = rStream.remainingSize() >= nPSSize;
+            SAL_WARN_IF(!bOk, "filter.eps", "eps claims to be: " << nPSSize << " in size, but only " << rStream.remainingSize() << " remains");
+        }
+        if (bOk)
+        {
+            std::unique_ptr<sal_uInt8[]> pBuf( new sal_uInt8[ nPSSize ] );
+
+            sal_uInt32 nBufStartPos = rStream.Tell();
+            sal_uInt32 nBytesRead = rStream.ReadBytes(pBuf.get(), nPSSize);
+            if ( nBytesRead == nPSSize )
             {
-                sal_uInt8* pDest = ImplSearchEntry( pBuf.get(), reinterpret_cast<sal_uInt8 const *>("%%BeginPreview:"), nBytesRead - nSecurityCount, 15 );
-                sal_uInt32 nRemainingBytes = pDest ? (nBytesRead - (pDest - pBuf.get())) : 0;
-                if (nRemainingBytes >= 15)
+                sal_uInt32 nSecurityCount = 32;
+                // if there is no tiff/wmf preview, we will parse for a preview in
+                // the eps prolog
+                if (!bHasPreview && nBytesRead >= nSecurityCount)
                 {
-                    pDest += 15;
-                    nSecurityCount = nRemainingBytes - 15;
-                    tools::Long nWidth = ImplGetNumber(pDest, nSecurityCount);
-                    tools::Long nHeight = ImplGetNumber(pDest, nSecurityCount);
-                    tools::Long nBitDepth = ImplGetNumber(pDest, nSecurityCount);
-                    tools::Long nScanLines = ImplGetNumber(pDest, nSecurityCount);
-                    pDest = ImplSearchEntry(pDest, reinterpret_cast<sal_uInt8 const *>("%"), nSecurityCount, 1);       // go to the first Scanline
-                    bOk = pDest && nWidth > 0 && nHeight > 0 && ( ( nBitDepth == 1 ) || ( nBitDepth == 8 ) ) && nScanLines;
-                    if (bOk)
+                    sal_uInt8* pDest = ImplSearchEntry( pBuf.get(), reinterpret_cast<sal_uInt8 const *>("%%BeginPreview:"), nBytesRead - nSecurityCount, 15 );
+                    sal_uInt32 nRemainingBytes = pDest ? (nBytesRead - (pDest - pBuf.get())) : 0;
+                    if (nRemainingBytes >= 15)
                     {
-                        tools::Long nResult;
-                        bOk = !o3tl::checked_multiply(nWidth, nHeight, nResult) && nResult <= SAL_MAX_INT32/2/3;
-                    }
-                    if (bOk)
-                    {
-                        rStream.Seek( nBufStartPos + ( pDest - pBuf.get() ) );
-
-                        vcl::bitmap::RawBitmap aBitmap( Size( nWidth, nHeight ), 24 );
+                        pDest += 15;
+                        nSecurityCount = nRemainingBytes - 15;
+                        tools::Long nWidth = ImplGetNumber(pDest, nSecurityCount);
+                        tools::Long nHeight = ImplGetNumber(pDest, nSecurityCount);
+                        tools::Long nBitDepth = ImplGetNumber(pDest, nSecurityCount);
+                        tools::Long nScanLines = ImplGetNumber(pDest, nSecurityCount);
+                        pDest = ImplSearchEntry(pDest, reinterpret_cast<sal_uInt8 const *>("%"), nSecurityCount, 1);       // go to the first Scanline
+                        bOk = pDest && nWidth > 0 && nHeight > 0 && ( ( nBitDepth == 1 ) || ( nBitDepth == 8 ) ) && nScanLines;
+                        if (bOk)
                         {
-                            bool bIsValid = true;
-                            sal_uInt8 nDat = 0;
-                            char nByte;
-                            for (tools::Long y = 0; bIsValid && y < nHeight; ++y)
+                            tools::Long nResult;
+                            bOk = !o3tl::checked_multiply(nWidth, nHeight, nResult) && nResult <= SAL_MAX_INT32/2/3;
+                        }
+                        if (bOk)
+                        {
+                            rStream.Seek( nBufStartPos + ( pDest - pBuf.get() ) );
+
+                            vcl::bitmap::RawBitmap aBitmap( Size( nWidth, nHeight ), 24 );
                             {
-                                int nBitsLeft = 0;
-                                for (tools::Long x = 0; x < nWidth; ++x)
+                                bool bIsValid = true;
+                                sal_uInt8 nDat = 0;
+                                char nByte;
+                                for (tools::Long y = 0; bIsValid && y < nHeight; ++y)
                                 {
-                                    if ( --nBitsLeft < 0 )
+                                    int nBitsLeft = 0;
+                                    for (tools::Long x = 0; x < nWidth; ++x)
                                     {
-                                        while ( bIsValid && ( nBitsLeft != 7 ) )
+                                        if ( --nBitsLeft < 0 )
                                         {
-                                            rStream.ReadChar(nByte);
-                                            bIsValid = rStream.good();
-                                            if (!bIsValid)
-                                                break;
-                                            switch (nByte)
+                                            while ( bIsValid && ( nBitsLeft != 7 ) )
                                             {
-                                                case 0x0a :
-                                                    if ( --nScanLines < 0 )
-                                                        bIsValid = false;
+                                                rStream.ReadChar(nByte);
+                                                bIsValid = rStream.good();
+                                                if (!bIsValid)
                                                     break;
-                                                case 0x09 :
-                                                case 0x0d :
-                                                case 0x20 :
-                                                case 0x25 :
-                                                break;
-                                                default:
+                                                switch (nByte)
                                                 {
-                                                    if ( nByte >= '0' )
+                                                    case 0x0a :
+                                                        if ( --nScanLines < 0 )
+                                                            bIsValid = false;
+                                                        break;
+                                                    case 0x09 :
+                                                    case 0x0d :
+                                                    case 0x20 :
+                                                    case 0x25 :
+                                                    break;
+                                                    default:
                                                     {
-                                                        if ( nByte > '9' )
+                                                        if ( nByte >= '0' )
                                                         {
-                                                            nByte &=~0x20;  // case none sensitive for hexadecimal values
-                                                            nByte -= ( 'A' - 10 );
-                                                            if ( nByte > 15 )
-                                                                bIsValid = false;
+                                                            if ( nByte > '9' )
+                                                            {
+                                                                nByte &=~0x20;  // case none sensitive for hexadecimal values
+                                                                nByte -= ( 'A' - 10 );
+                                                                if ( nByte > 15 )
+                                                                    bIsValid = false;
+                                                            }
+                                                            else
+                                                                nByte -= '0';
+                                                            nBitsLeft += 4;
+                                                            nDat <<= 4;
+                                                            nDat |= ( nByte ^ 0xf ); // in epsi a zero bit represents white color
                                                         }
                                                         else
-                                                            nByte -= '0';
-                                                        nBitsLeft += 4;
-                                                        nDat <<= 4;
-                                                        nDat |= ( nByte ^ 0xf ); // in epsi a zero bit represents white color
+                                                            bIsValid = false;
                                                     }
-                                                    else
-                                                        bIsValid = false;
+                                                    break;
                                                 }
-                                                break;
                                             }
                                         }
-                                    }
-                                    if (!bIsValid)
-                                        break;
-                                    if ( nBitDepth == 1 )
-                                        aBitmap.SetPixel( y, x, Color(static_cast<sal_uInt8>(nDat >> nBitsLeft) & 1) );
-                                    else
-                                    {
-                                        aBitmap.SetPixel( y, x, nDat ? COL_WHITE : COL_BLACK );  // nBitDepth == 8
-                                        nBitsLeft = 0;
+                                        if (!bIsValid)
+                                            break;
+                                        if ( nBitDepth == 1 )
+                                            aBitmap.SetPixel( y, x, Color(static_cast<sal_uInt8>(nDat >> nBitsLeft) & 1) );
+                                        else
+                                        {
+                                            aBitmap.SetPixel( y, x, nDat ? COL_WHITE : COL_BLACK );  // nBitDepth == 8
+                                            nBitsLeft = 0;
+                                        }
                                     }
                                 }
-                            }
-                            if (bIsValid)
-                            {
-                                ScopedVclPtrInstance<VirtualDevice> pVDev;
-                                GDIMetaFile     aMtf;
-                                Size            aSize( nWidth, nHeight );
-                                pVDev->EnableOutput( false );
-                                aMtf.Record( pVDev );
-                                aSize = OutputDevice::LogicToLogic(aSize, MapMode(), MapMode(MapUnit::Map100thMM));
-                                pVDev->DrawBitmapEx( Point(), aSize, vcl::bitmap::CreateFromData(std::move(aBitmap)) );
-                                aMtf.Stop();
-                                aMtf.WindStart();
-                                aMtf.SetPrefMapMode(MapMode(MapUnit::Map100thMM));
-                                aMtf.SetPrefSize( aSize );
-                                aGraphic = aMtf;
-                                bHasPreview = bRetValue = true;
+                                if (bIsValid)
+                                {
+                                    ScopedVclPtrInstance<VirtualDevice> pVDev;
+                                    GDIMetaFile     aMtf;
+                                    Size            aSize( nWidth, nHeight );
+                                    pVDev->EnableOutput( false );
+                                    aMtf.Record( pVDev );
+                                    aSize = OutputDevice::LogicToLogic(aSize, MapMode(), MapMode(MapUnit::Map100thMM));
+                                    pVDev->DrawBitmapEx( Point(), aSize, vcl::bitmap::CreateFromData(std::move(aBitmap)) );
+                                    aMtf.Stop();
+                                    aMtf.WindStart();
+                                    aMtf.SetPrefMapMode(MapMode(MapUnit::Map100thMM));
+                                    aMtf.SetPrefSize( aSize );
+                                    aGraphic = aMtf;
+                                    bHasPreview = bRetValue = true;
+                                }
                             }
                         }
                     }
                 }
-            }
 
-            sal_uInt8* pDest = ImplSearchEntry( pBuf.get(), reinterpret_cast<sal_uInt8 const *>("%%BoundingBox:"), nBytesRead, 14 );
-            sal_uInt32 nRemainingBytes = pDest ? (nBytesRead - (pDest - pBuf.get())) : 0;
-            if (nRemainingBytes >= 14)
-            {
-                pDest += 14;
-                nSecurityCount = std::min<sal_uInt32>(nRemainingBytes - 14, 100);
-                tools::Long nNumb[4];
-                nNumb[0] = nNumb[1] = nNumb[2] = nNumb[3] = 0;
-                for ( int i = 0; ( i < 4 ) && nSecurityCount; i++ )
-                {
-                    nNumb[ i ] = ImplGetNumber(pDest, nSecurityCount);
-                }
-                bool bFail = nSecurityCount == 0;
-                tools::Long nWidth(0), nHeight(0);
-                if (!bFail)
-                    bFail = o3tl::checked_sub(nNumb[2], nNumb[0], nWidth) || o3tl::checked_add(nWidth, tools::Long(1), nWidth);
-                if (!bFail)
-                    bFail = o3tl::checked_sub(nNumb[3], nNumb[1], nHeight) || o3tl::checked_add(nHeight, tools::Long(1), nHeight);
-                if (!bFail && nWidth > 0 && nHeight > 0)
+                sal_uInt8* pDest = ImplSearchEntry( pBuf.get(), reinterpret_cast<sal_uInt8 const *>("%%BoundingBox:"), nBytesRead, 14 );
+                sal_uInt32 nRemainingBytes = pDest ? (nBytesRead - (pDest - pBuf.get())) : 0;
+                if (nRemainingBytes >= 14)
                 {
-                    GDIMetaFile aMtf;
-
-                    // if there is no preview -> try with gs to make one
-                    if (!bHasPreview && !utl::ConfigManager::IsFuzzing())
+                    pDest += 14;
+                    nSecurityCount = std::min<sal_uInt32>(nRemainingBytes - 14, 100);
+                    tools::Long nNumb[4];
+                    nNumb[0] = nNumb[1] = nNumb[2] = nNumb[3] = 0;
+                    for ( int i = 0; ( i < 4 ) && nSecurityCount; i++ )
                     {
-                        bHasPreview = RenderAsEMF(pBuf.get(), nBytesRead, aGraphic);
-                        if (!bHasPreview)
-                            bHasPreview = RenderAsBMP(pBuf.get(), nBytesRead, aGraphic);
+                        nNumb[ i ] = ImplGetNumber(pDest, nSecurityCount);
                     }
-
-                    // if there is no preview -> make a red box
-                    if( !bHasPreview )
+                    bool bFail = nSecurityCount == 0;
+                    tools::Long nWidth(0), nHeight(0);
+                    if (!bFail)
+                        bFail = o3tl::checked_sub(nNumb[2], nNumb[0], nWidth) || o3tl::checked_add(nWidth, tools::Long(1), nWidth);
+                    if (!bFail)
+                        bFail = o3tl::checked_sub(nNumb[3], nNumb[1], nHeight) || o3tl::checked_add(nHeight, tools::Long(1), nHeight);
+                    if (!bFail && nWidth > 0 && nHeight > 0)
                     {
-                        MakePreview(pBuf.get(), nBytesRead, nWidth, nHeight,
-                            aGraphic);
-                    }
+                        GDIMetaFile aMtf;
+
+                        // if there is no preview -> try with gs to make one
+                        if (!bHasPreview && !utl::ConfigManager::IsFuzzing())
+                        {
+                            bHasPreview = RenderAsEMF(pBuf.get(), nBytesRead, aGraphic);
+                            if (!bHasPreview)
+                                bHasPreview = RenderAsBMP(pBuf.get(), nBytesRead, aGraphic);
+                        }
 
-                    GfxLink     aGfxLink( std::move(pBuf), nPSSize, GfxLinkType::EpsBuffer ) ;
-                    aMtf.AddAction( static_cast<MetaAction*>( new MetaEPSAction( Point(), Size( nWidth, nHeight ),
-                                                                      aGfxLink, aGraphic.GetGDIMetaFile() ) ) );
-                    CreateMtfReplacementAction( aMtf, rStream, nOrigPos, nPSSize, nPosWMF, nSizeWMF, nPosTIFF, nSizeTIFF );
-                    aMtf.WindStart();
-                    aMtf.SetPrefMapMode(MapMode(MapUnit::MapPoint));
-                    aMtf.SetPrefSize( Size( nWidth, nHeight ) );
-                    rGraphic = aMtf;
-                    bRetValue = true;
+                        // if there is no preview -> make a red box
+                        if( !bHasPreview )
+                        {
+                            MakePreview(pBuf.get(), nBytesRead, nWidth, nHeight,
+                                aGraphic);
+                        }
+
+                        GfxLink     aGfxLink( std::move(pBuf), nPSSize, GfxLinkType::EpsBuffer ) ;
+                        aMtf.AddAction( static_cast<MetaAction*>( new MetaEPSAction( Point(), Size( nWidth, nHeight ),
+                                                                          aGfxLink, aGraphic.GetGDIMetaFile() ) ) );
+                        CreateMtfReplacementAction( aMtf, rStream, nOrigPos, nPSSize, nPosWMF, nSizeWMF, nPosTIFF, nSizeTIFF );
+                        aMtf.WindStart();
+                        aMtf.SetPrefMapMode(MapMode(MapUnit::MapPoint));
+                        aMtf.SetPrefSize( Size( nWidth, nHeight ) );
+                        rGraphic = aMtf;
+                        bRetValue = true;
+                    }
                 }
             }
         }
     }
+    catch (const SvStreamEOFException&)
+    {
+        SAL_WARN("filter.eps", "EOF");
+        bRetValue = false;
+    }
+
     rStream.SetEndian(nOldFormat);
     rStream.Seek( nOrigPos );
     return bRetValue;


More information about the Libreoffice-commits mailing list