summaryrefslogtreecommitdiff
path: root/package/source/zipapi/ZipFile.cxx
diff options
context:
space:
mode:
Diffstat (limited to 'package/source/zipapi/ZipFile.cxx')
-rw-r--r--package/source/zipapi/ZipFile.cxx145
1 files changed, 88 insertions, 57 deletions
diff --git a/package/source/zipapi/ZipFile.cxx b/package/source/zipapi/ZipFile.cxx
index 2d8d69c853c7..37907647711b 100644
--- a/package/source/zipapi/ZipFile.cxx
+++ b/package/source/zipapi/ZipFile.cxx
@@ -590,7 +590,8 @@ uno::Reference<io::XInputStream> ZipFile::checkValidPassword(
namespace {
-class XBufferedStream : public cppu::WeakImplHelper<css::io::XInputStream, css::io::XSeekable>
+class XBufferedStream : public cppu::WeakImplHelper<css::io::XInputStream, css::io::XSeekable>,
+ public comphelper::ByteReader
{
std::vector<sal_Int8> maBytes;
size_t mnPos;
@@ -655,6 +656,22 @@ public:
return nReadSize;
}
+ virtual sal_Int32 readSomeBytes(sal_Int8* pData, sal_Int32 nBytesToRead) override
+ {
+ if (!hasBytes())
+ return 0;
+
+ sal_Int32 nReadSize = std::min<sal_Int32>(nBytesToRead, remainingSize());
+ std::vector<sal_Int8>::const_iterator it = maBytes.cbegin();
+ std::advance(it, mnPos);
+ for (sal_Int32 i = 0; i < nReadSize; ++i, ++it)
+ pData[i] = *it;
+
+ mnPos += nReadSize;
+
+ return nReadSize;
+ }
+
virtual sal_Int32 SAL_CALL readSomeBytes( ::css::uno::Sequence<sal_Int8>& rData, sal_Int32 nMaxBytesToRead ) override
{
return readBytes(rData, nMaxBytesToRead);
@@ -918,7 +935,12 @@ sal_uInt64 ZipFile::readLOC(ZipEntry &rEntry)
sal_Int64 nPos = -rEntry.nOffset;
aGrabber.seek(nPos);
- sal_Int32 nTestSig = aGrabber.ReadInt32();
+ std::array<sal_Int8, 30> aHeader;
+ if (aGrabber.readBytes(aHeader.data(), 30) != 30)
+ throw new uno::RuntimeException();
+ MemoryByteGrabber headerMemGrabber(aHeader.data(), 30);
+
+ sal_Int32 nTestSig = headerMemGrabber.ReadInt32();
if (nTestSig != LOCSIG)
throw ZipIOException(u"Invalid LOC header (bad signature)"_ustr );
@@ -927,18 +949,18 @@ sal_uInt64 ZipFile::readLOC(ZipEntry &rEntry)
// Just verify the path and calculate the data offset and otherwise
// rely on the central directory info.
- aGrabber.ReadInt16(); // version - ignore any mismatch (Maven created JARs)
- sal_uInt16 const nLocFlag = aGrabber.ReadUInt16(); // general purpose bit flag
- sal_uInt16 const nLocMethod = aGrabber.ReadUInt16(); // compression method
+ headerMemGrabber.ReadInt16(); // version - ignore any mismatch (Maven created JARs)
+ sal_uInt16 const nLocFlag = headerMemGrabber.ReadUInt16(); // general purpose bit flag
+ sal_uInt16 const nLocMethod = headerMemGrabber.ReadUInt16(); // compression method
// Do *not* compare timestamps, since MSO 2010 can produce documents
// with timestamp difference in the central directory entry and local
// file header.
- aGrabber.ReadInt32(); //time
- sal_uInt32 nLocCrc = aGrabber.ReadUInt32(); //crc
- sal_uInt64 nLocCompressedSize = aGrabber.ReadUInt32(); //compressed size
- sal_uInt64 nLocSize = aGrabber.ReadUInt32(); //size
- sal_Int16 nPathLen = aGrabber.ReadInt16();
- sal_Int16 nExtraLen = aGrabber.ReadInt16();
+ headerMemGrabber.ReadInt32(); //time
+ sal_uInt32 nLocCrc = headerMemGrabber.ReadUInt32(); //crc
+ sal_uInt64 nLocCompressedSize = headerMemGrabber.ReadUInt32(); //compressed size
+ sal_uInt64 nLocSize = headerMemGrabber.ReadUInt32(); //size
+ sal_Int16 nPathLen = headerMemGrabber.ReadInt16();
+ sal_Int16 nExtraLen = headerMemGrabber.ReadInt16();
if (nPathLen < 0)
{
@@ -955,13 +977,13 @@ sal_uInt64 ZipFile::readLOC(ZipEntry &rEntry)
{
// read always in UTF8, some tools seem not to set UTF8 bit
// coverity[tainted_data] - we've checked negative lens, and up to max short is ok here
- uno::Sequence<sal_Int8> aNameBuffer(nPathLen);
- sal_Int32 nRead = aGrabber.readBytes(aNameBuffer, nPathLen);
- if (nRead < aNameBuffer.getLength())
- aNameBuffer.realloc(nRead);
+ std::vector<sal_Int8> aNameBuffer(nPathLen);
+ sal_Int32 nRead = aGrabber.readBytes(aNameBuffer.data(), nPathLen);
+ if (nRead < nPathLen)
+ aNameBuffer.resize(nRead);
- OUString sLOCPath( reinterpret_cast<const char *>(aNameBuffer.getConstArray()),
- aNameBuffer.getLength(),
+ OUString sLOCPath( reinterpret_cast<const char *>(aNameBuffer.data()),
+ nRead,
RTL_TEXTENCODING_UTF8 );
if ( rEntry.nPathLen == -1 ) // the file was created
@@ -980,9 +1002,9 @@ sal_uInt64 ZipFile::readLOC(ZipEntry &rEntry)
::std::optional<sal_uInt64> oOffset64;
if (nExtraLen != 0)
{
- Sequence<sal_Int8> aExtraBuffer;
- aGrabber.readBytes(aExtraBuffer, nExtraLen);
- MemoryByteGrabber extraMemGrabber(aExtraBuffer);
+ std::vector<sal_Int8> aExtraBuffer(nExtraLen);
+ aGrabber.readBytes(aExtraBuffer.data(), nExtraLen);
+ MemoryByteGrabber extraMemGrabber(aExtraBuffer.data(), nExtraLen);
isZip64 = readExtraFields(extraMemGrabber, nExtraLen,
nLocSize, nLocCompressedSize, oOffset64, &sLOCPath);
@@ -1116,7 +1138,7 @@ sal_uInt64 ZipFile::readLOC(ZipEntry &rEntry)
std::tuple<sal_Int64, sal_Int64, sal_Int64> ZipFile::findCentralDirectory()
{
// this method is called in constructor only, no need for mutex
- Sequence < sal_Int8 > aBuffer;
+ std::vector < sal_Int8 > aBuffer;
try
{
sal_Int64 const nLength = aGrabber.getLength();
@@ -1130,10 +1152,11 @@ std::tuple<sal_Int64, sal_Int64, sal_Int64> ZipFile::findCentralDirectory()
aGrabber.seek( nEnd );
auto nSize = nLength - nEnd;
- if (nSize != aGrabber.readBytes(aBuffer, nSize))
+ aBuffer.reserve(nSize);
+ if (nSize != aGrabber.readBytes(aBuffer.data(), nSize))
throw ZipException(u"Zip END signature not found!"_ustr );
- const sal_Int8 *pBuffer = aBuffer.getConstArray();
+ const sal_Int8 *pBuffer = aBuffer.data();
sal_Int64 nEndPos = {};
nPos = nSize - ENDHDR;
@@ -1176,9 +1199,10 @@ std::tuple<sal_Int64, sal_Int64, sal_Int64> ZipFile::findCentralDirectory()
if (20 <= nEndPos)
{
aGrabber.seek(nEndPos - 20);
- Sequence<sal_Int8> aZip64EndLocator;
- aGrabber.readBytes(aZip64EndLocator, 20);
- MemoryByteGrabber loc64Grabber(aZip64EndLocator);
+ std::array<sal_Int8, 20> aZip64EndLocator;
+ if (20 != aGrabber.readBytes(aZip64EndLocator.data(), 20))
+ throw uno::RuntimeException();
+ MemoryByteGrabber loc64Grabber(aZip64EndLocator.data(), 20);
if (loc64Grabber.ReadUInt8() == 'P'
&& loc64Grabber.ReadUInt8() == 'K'
&& loc64Grabber.ReadUInt8() == 6
@@ -1201,9 +1225,9 @@ std::tuple<sal_Int64, sal_Int64, sal_Int64> ZipFile::findCentralDirectory()
throw ZipException(u"invalid Zip64 end locator (number of disks)"_ustr);
}
aGrabber.seek(nLoc64End64Offset);
- Sequence<sal_Int8> aZip64EndDirectory;
- aGrabber.readBytes(aZip64EndDirectory, nEndPos - 20 - nLoc64End64Offset);
- MemoryByteGrabber end64Grabber(aZip64EndDirectory);
+ std::vector<sal_Int8> aZip64EndDirectory(nEndPos - 20 - nLoc64End64Offset);
+ aGrabber.readBytes(aZip64EndDirectory.data(), nEndPos - 20 - nLoc64End64Offset);
+ MemoryByteGrabber end64Grabber(aZip64EndDirectory.data(), nEndPos - 20 - nLoc64End64Offset);
if (end64Grabber.ReadUInt8() != 'P'
|| end64Grabber.ReadUInt8() != 'K'
|| end64Grabber.ReadUInt8() != 6
@@ -1309,12 +1333,12 @@ sal_Int32 ZipFile::readCEN()
throw ZipException(u"central directory too big"_ustr);
aGrabber.seek(nCenPos);
- Sequence<sal_Int8> aCENBuffer(nCenLen);
- sal_Int64 nRead = aGrabber.readBytes ( aCENBuffer, nCenLen );
+ std::vector<sal_Int8> aCENBuffer(nCenLen);
+ sal_Int64 nRead = aGrabber.readBytes ( aCENBuffer.data(), nCenLen );
if (nCenLen != nRead)
throw ZipException (u"Error reading CEN into memory buffer!"_ustr );
- MemoryByteGrabber aMemGrabber(aCENBuffer);
+ MemoryByteGrabber aMemGrabber(aCENBuffer.data(), nCenLen);
ZipEntry aEntry;
sal_Int16 nCommentLen;
@@ -1590,29 +1614,30 @@ void ZipFile::HandlePK34(std::span<const sal_Int8> data, sal_Int64 dataOffset, s
RTL_TEXTENCODING_UTF8);
else
{
- Sequence<sal_Int8> aFileName;
+ std::vector<sal_Int8> aFileName(aEntry.nPathLen);
aGrabber.seek(dataOffset + 30);
- aGrabber.readBytes(aFileName, aEntry.nPathLen);
- aEntry.sPath = OUString(reinterpret_cast<const char*>(aFileName.getConstArray()),
- aFileName.getLength(), RTL_TEXTENCODING_UTF8);
- aEntry.nPathLen = static_cast<sal_Int16>(aFileName.getLength());
+ aGrabber.readBytes(aFileName.data(), aEntry.nPathLen);
+ aEntry.sPath = OUString(reinterpret_cast<const char*>(aFileName.data()),
+ aEntry.nPathLen, RTL_TEXTENCODING_UTF8);
+ aEntry.nPathLen = aEntry.nPathLen;
}
aEntry.sPath = aEntry.sPath.replace('\\', '/');
// read 64bit header
if (aEntry.nExtraLen > 0)
{
- Sequence<sal_Int8> aExtraBuffer;
+ std::vector<sal_Int8> aExtraBuffer(aEntry.nExtraLen);
if (o3tl::make_unsigned(30 + aEntry.nPathLen) + aEntry.nExtraLen <= data.size())
{
- aExtraBuffer = Sequence<sal_Int8>(data.data() + 30 + aEntry.nPathLen, aEntry.nExtraLen);
+ auto it = data.begin() + 30 + aEntry.nPathLen;
+ std::copy(it, it + aEntry.nExtraLen, aExtraBuffer.begin());
}
else
{
aGrabber.seek(dataOffset + 30 + aEntry.nExtraLen);
- aGrabber.readBytes(aExtraBuffer, aEntry.nExtraLen);
+ aGrabber.readBytes(aExtraBuffer.data(), aEntry.nExtraLen);
}
- MemoryByteGrabber aMemGrabberExtra(aExtraBuffer);
+ MemoryByteGrabber aMemGrabberExtra(aExtraBuffer.data(), aEntry.nExtraLen);
if (aEntry.nExtraLen > 0)
{
::std::optional<sal_uInt64> oOffset64;
@@ -1743,7 +1768,9 @@ void ZipFile::recover()
{
::osl::MutexGuard aGuard( m_aMutexHolder->GetMutex() );
- Sequence < sal_Int8 > aBuffer;
+ std::vector < sal_Int8 > aBuffer;
+ const sal_Int64 nToRead = 32000;
+ aBuffer.reserve(nToRead);
try
{
@@ -1753,11 +1780,11 @@ void ZipFile::recover()
aGrabber.seek( 0 );
- const sal_Int64 nToRead = 32000;
- for( sal_Int64 nGenPos = 0; aGrabber.readBytes( aBuffer, nToRead ) && aBuffer.getLength() > 16; )
+ sal_Int32 nRead;
+ for( sal_Int64 nGenPos = 0; (nRead = aGrabber.readBytes( aBuffer.data(), nToRead )) && nRead > 16; )
{
- const sal_Int8 *pBuffer = aBuffer.getConstArray();
- const sal_Int32 nBufSize = aBuffer.getLength();
+ const sal_Int8 *pBuffer = aBuffer.data();
+ const sal_Int32 nBufSize = nRead;
sal_Int64 nPos = 0;
// the buffer should contain at least one header,
@@ -1822,17 +1849,18 @@ sal_Int32 ZipFile::getCRC( sal_Int64 nOffset, sal_Int64 nSize )
{
::osl::MutexGuard aGuard( m_aMutexHolder->GetMutex() );
- Sequence < sal_Int8 > aBuffer;
CRC32 aCRC;
sal_Int64 nBlockSize = ::std::min(nSize, static_cast< sal_Int64 >(32000));
+ std::vector < sal_Int8 > aBuffer;
+ aBuffer.reserve(nBlockSize);
aGrabber.seek( nOffset );
+ sal_Int32 nRead;
for (sal_Int64 ind = 0;
- aGrabber.readBytes( aBuffer, nBlockSize ) && ind * nBlockSize < nSize;
+ (nRead = aGrabber.readBytes( aBuffer.data(), nBlockSize )) && ind * nBlockSize < nSize;
++ind)
{
- sal_Int64 nLen = ::std::min(nBlockSize, nSize - ind * nBlockSize);
- aCRC.updateSegment(aBuffer, static_cast<sal_Int32>(nLen));
+ aCRC.updateSegment(aBuffer.data(), nRead);
}
return aCRC.getValue();
@@ -1842,26 +1870,29 @@ void ZipFile::getSizeAndCRC( sal_Int64 nOffset, sal_Int64 nCompressedSize, sal_I
{
::osl::MutexGuard aGuard( m_aMutexHolder->GetMutex() );
- Sequence < sal_Int8 > aBuffer;
CRC32 aCRC;
sal_Int64 nRealSize = 0;
- Inflater aInflaterLocal( true );
+ ZipUtils::InflaterBytes aInflaterLocal( true );
sal_Int32 nBlockSize = static_cast< sal_Int32 > (::std::min( nCompressedSize, static_cast< sal_Int64 >( 32000 ) ) );
+ std::vector < sal_Int8 > aBuffer(nBlockSize);
+ std::vector< sal_Int8 > aData( nBlockSize );
aGrabber.seek( nOffset );
+ sal_Int32 nRead;
for ( sal_Int64 ind = 0;
- !aInflaterLocal.finished() && aGrabber.readBytes( aBuffer, nBlockSize ) && ind * nBlockSize < nCompressedSize;
+ !aInflaterLocal.finished()
+ && (nRead = aGrabber.readBytes( aBuffer.data(), nBlockSize ))
+ && ind * nBlockSize < nCompressedSize;
ind++ )
{
- Sequence < sal_Int8 > aData( nBlockSize );
sal_Int32 nLastInflated = 0;
sal_Int64 nInBlock = 0;
- aInflaterLocal.setInput( aBuffer );
+ aInflaterLocal.setInput( aBuffer.data(), nRead );
do
{
- nLastInflated = aInflaterLocal.doInflateSegment( aData, 0, nBlockSize );
- aCRC.updateSegment( aData, nLastInflated );
+ nLastInflated = aInflaterLocal.doInflateSegment( aData.data(), nBlockSize, 0, nBlockSize );
+ aCRC.updateSegment( aData.data(), nLastInflated );
nInBlock += nLastInflated;
} while( !aInflater.finished() && nLastInflated );