filter/source/graphicfilter/ieps/ieps.cxx | 355 +++++++++++++++--------------- 1 file changed, 183 insertions(+), 172 deletions(-)
New commits: commit e7c76d604a4694e6568bf10c2a06a786f1096319 Author: Caolán McNamara <caol...@redhat.com> AuthorDate: Tue Dec 22 10:27:38 2020 +0000 Commit: Caolán McNamara <caol...@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 <caol...@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; _______________________________________________ Libreoffice-commits mailing list libreoffice-comm...@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/libreoffice-commits