From 1194dc935382931bbfdd4e49004bd755e6165df1 Mon Sep 17 00:00:00 2001 From: Igor Pavlov Date: Sun, 28 Nov 2021 19:03:01 -0800 Subject: 21.04 --- CPP/7zip/Archive/Zip/ZipHandler.cpp | 2 +- CPP/7zip/Archive/Zip/ZipIn.cpp | 51 ++++++++++++++++++++++++++----------- CPP/7zip/Archive/Zip/ZipIn.h | 2 +- CPP/7zip/Archive/Zip/ZipUpdate.cpp | 46 +++++++++++++++++++++++++++++---- 4 files changed, 79 insertions(+), 22 deletions(-) (limited to 'CPP/7zip/Archive/Zip') diff --git a/CPP/7zip/Archive/Zip/ZipHandler.cpp b/CPP/7zip/Archive/Zip/ZipHandler.cpp index 72a77cb7..d8168bbe 100644 --- a/CPP/7zip/Archive/Zip/ZipHandler.cpp +++ b/CPP/7zip/Archive/Zip/ZipHandler.cpp @@ -1665,7 +1665,7 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems, m_Archive, item, realOutStream, extractCallback, progress, #ifndef _7ZIP_ST - _props._numThreads, _props._memUsage, + _props._numThreads, _props._memUsage_Decompress, #endif res); diff --git a/CPP/7zip/Archive/Zip/ZipIn.cpp b/CPP/7zip/Archive/Zip/ZipIn.cpp index 880ff218..076d6bb5 100644 --- a/CPP/7zip/Archive/Zip/ZipIn.cpp +++ b/CPP/7zip/Archive/Zip/ZipIn.cpp @@ -989,7 +989,8 @@ bool CInArchive::ReadFileName(unsigned size, AString &s) bool CInArchive::ReadExtra(const CLocalItem &item, unsigned extraSize, CExtraBlock &extra, - UInt64 &unpackSize, UInt64 &packSize, UInt64 &localOffset, UInt32 &disk) + UInt64 &unpackSize, UInt64 &packSize, + CItem *cdItem) { extra.Clear(); @@ -1017,18 +1018,40 @@ bool CInArchive::ReadExtra(const CLocalItem &item, unsigned extraSize, CExtraBlo { extra.IsZip64 = true; bool isOK = true; + + if (!cdItem + && size == 16 + && !ZIP64_IS_32_MAX(unpackSize) + && !ZIP64_IS_32_MAX(packSize)) + { + /* Win10 Explorer's "Send to Zip" for big (3500 MiB) files + creates Zip64 Extra in local file header. + But if both uncompressed and compressed sizes are smaller than 4 GiB, + Win10 doesn't store 0xFFFFFFFF in 32-bit fields as expected by zip specification. + 21.04: we ignore these minor errors in Win10 zip archives. */ + if (ReadUInt64() != unpackSize) + isOK = false; + if (ReadUInt64() != packSize) + isOK = false; + size = 0; + } + else + { + if (ZIP64_IS_32_MAX(unpackSize)) + { if (size < 8) isOK = false; else { size -= 8; unpackSize = ReadUInt64(); }} - if (ZIP64_IS_32_MAX(unpackSize)) - { if (size < 8) isOK = false; else { size -= 8; unpackSize = ReadUInt64(); }} - - if (isOK && ZIP64_IS_32_MAX(packSize)) - { if (size < 8) isOK = false; else { size -= 8; packSize = ReadUInt64(); }} - - if (isOK && ZIP64_IS_32_MAX(localOffset)) - { if (size < 8) isOK = false; else { size -= 8; localOffset = ReadUInt64(); }} + if (isOK && ZIP64_IS_32_MAX(packSize)) + { if (size < 8) isOK = false; else { size -= 8; packSize = ReadUInt64(); }} - if (isOK && ZIP64_IS_16_MAX(disk)) - { if (size < 4) isOK = false; else { size -= 4; disk = ReadUInt32(); }} + if (cdItem) + { + if (isOK && ZIP64_IS_32_MAX(cdItem->LocalHeaderPos)) + { if (size < 8) isOK = false; else { size -= 8; cdItem->LocalHeaderPos = ReadUInt64(); }} + + if (isOK && ZIP64_IS_16_MAX(cdItem->Disk)) + { if (size < 4) isOK = false; else { size -= 4; cdItem->Disk = ReadUInt32(); }} + } + } if (!isOK || size != 0) { @@ -1100,9 +1123,7 @@ bool CInArchive::ReadLocalItem(CItemEx &item) if (extraSize > 0) { - UInt64 localOffset = 0; - UInt32 disk = 0; - if (!ReadExtra(item, extraSize, item.LocalExtra, item.Size, item.PackSize, localOffset, disk)) + if (!ReadExtra(item, extraSize, item.LocalExtra, item.Size, item.PackSize, NULL)) { /* Most of archives are OK for Extra. But there are some rare cases that have error. And if error in first item, it can't open archive. @@ -1557,7 +1578,7 @@ HRESULT CInArchive::ReadCdItem(CItemEx &item) ReadFileName(nameSize, item.Name); if (extraSize > 0) - ReadExtra(item, extraSize, item.CentralExtra, item.Size, item.PackSize, item.LocalHeaderPos, item.Disk); + ReadExtra(item, extraSize, item.CentralExtra, item.Size, item.PackSize, &item); // May be these strings must be deleted /* diff --git a/CPP/7zip/Archive/Zip/ZipIn.h b/CPP/7zip/Archive/Zip/ZipIn.h index 31e524b6..1498afed 100644 --- a/CPP/7zip/Archive/Zip/ZipIn.h +++ b/CPP/7zip/Archive/Zip/ZipIn.h @@ -312,7 +312,7 @@ class CInArchive bool ReadFileName(unsigned nameSize, AString &dest); bool ReadExtra(const CLocalItem &item, unsigned extraSize, CExtraBlock &extra, - UInt64 &unpackSize, UInt64 &packSize, UInt64 &localOffset, UInt32 &disk); + UInt64 &unpackSize, UInt64 &packSize, CItem *cdItem); bool ReadLocalItem(CItemEx &item); HRESULT FindDescriptor(CItemEx &item, unsigned numFiles); HRESULT ReadCdItem(CItemEx &item); diff --git a/CPP/7zip/Archive/Zip/ZipUpdate.cpp b/CPP/7zip/Archive/Zip/ZipUpdate.cpp index 4468c7c5..26636c78 100644 --- a/CPP/7zip/Archive/Zip/ZipUpdate.cpp +++ b/CPP/7zip/Archive/Zip/ZipUpdate.cpp @@ -773,7 +773,7 @@ static HRESULT Update2( if (numThreads < 1) numThreads = 1; - const size_t kMemPerThread = (size_t)1 << 25; + const size_t kMemPerThread = (size_t)sizeof(size_t) << 23; const size_t kBlockSize = 1 << 16; bool mtMode = (numThreads > 1); @@ -791,6 +791,7 @@ static HRESULT Update2( if (onem.FindProp(NCoderPropID::kNumThreads) < 0) { + // fixme: we should check the number of threads for xz mehod also // fixed for 9.31. bzip2 default is just one thread. onem.AddProp_NumThreads(numThreads); } @@ -801,8 +802,8 @@ static HRESULT Update2( if (method == NFileHeader::NCompressionMethod::kStore && !options.PasswordIsDefined) numThreads = 1; - if (oneMethodMain) - { + if (oneMethodMain) + { if (method == NFileHeader::NCompressionMethod::kBZip2) { @@ -828,6 +829,7 @@ static HRESULT Update2( int numXzThreads = oneMethodMain->Get_Xz_NumThreads(numLzmaThreads); if (numXzThreads < 0) { + // numXzThreads is unknown const UInt64 averageSize = numBytesToCompress / numFilesToCompress; const UInt64 blockSize = oneMethodMain->Get_Xz_BlockSize(); UInt64 averageNumberOfBlocks = 1; @@ -844,18 +846,52 @@ static HRESULT Update2( } numThreads /= (unsigned)numXzThreads; } + else if ( + method == NFileHeader::NCompressionMethod::kDeflate + || method == NFileHeader::NCompressionMethod::kDeflate64 + || method == NFileHeader::NCompressionMethod::kPPMd) + { + if (numThreads > 1 + && options._memUsage_WasSet + && !options._numThreads_WasForced) + { + UInt64 methodMemUsage; + if (method == NFileHeader::NCompressionMethod::kPPMd) + methodMemUsage = oneMethodMain->Get_Ppmd_MemSize(); + else + methodMemUsage = (4 << 20); // for deflate + const UInt64 threadMemUsage = kMemPerThread + methodMemUsage; + const UInt64 numThreads64 = options._memUsage_Compress / threadMemUsage; + if (numThreads64 < numThreads) + numThreads = (UInt32)numThreads64; + } + } else if (method == NFileHeader::NCompressionMethod::kLZMA) { // we suppose that default LZMA is 2 thread. So we don't change it - UInt32 numLZMAThreads = oneMethodMain->Get_Lzma_NumThreads(); + const UInt32 numLZMAThreads = oneMethodMain->Get_Lzma_NumThreads(); numThreads /= numLZMAThreads; + + if (numThreads > 1 + && options._memUsage_WasSet + && !options._numThreads_WasForced) + { + const UInt64 methodMemUsage = oneMethodMain->Get_Lzma_MemUsage(true); + const UInt64 threadMemUsage = kMemPerThread + methodMemUsage; + const UInt64 numThreads64 = options._memUsage_Compress / threadMemUsage; + if (numThreads64 < numThreads) + numThreads = (UInt32)numThreads64; + } } - } + } // (oneMethodMain) if (numThreads > numFilesToCompress) numThreads = (UInt32)numFilesToCompress; if (numThreads <= 1) + { mtMode = false; + numThreads = 1; + } } // mtMode = true; // to test mtMode for seqMode -- cgit v1.2.3