diff options
author | Igor Pavlov <ipavlov@users.sourceforge.net> | 2015-11-19 03:00:00 +0300 |
---|---|---|
committer | Kornel LesiĆski <kornel@geekhood.net> | 2016-05-28 02:16:57 +0300 |
commit | e24f7fba53cc8f28d74b5039f7279d9bf945ff25 (patch) | |
tree | 52cf49d97bf4436151ec824ec7fbbf9d567578ff /CPP/7zip/Archive | |
parent | 7c8a265a15125b64808e695882acd2a0298ebce4 (diff) |
15.1115.11
Diffstat (limited to 'CPP/7zip/Archive')
-rw-r--r-- | CPP/7zip/Archive/7z/7zIn.h | 2 | ||||
-rw-r--r-- | CPP/7zip/Archive/DllExports2.cpp | 2 | ||||
-rw-r--r-- | CPP/7zip/Archive/Rar/Rar5Handler.cpp | 18 | ||||
-rw-r--r-- | CPP/7zip/Archive/Rar/RarHandler.cpp | 23 | ||||
-rw-r--r-- | CPP/7zip/Archive/Rar/RarHandler.h | 1 | ||||
-rw-r--r-- | CPP/7zip/Archive/Udf/UdfHandler.cpp | 1 | ||||
-rw-r--r-- | CPP/7zip/Archive/Udf/UdfIn.cpp | 58 | ||||
-rw-r--r-- | CPP/7zip/Archive/Udf/UdfIn.h | 1 | ||||
-rw-r--r-- | CPP/7zip/Archive/Zip/ZipIn.cpp | 34 |
9 files changed, 117 insertions, 23 deletions
diff --git a/CPP/7zip/Archive/7z/7zIn.h b/CPP/7zip/Archive/7z/7zIn.h index ad8ceba5..3592e99b 100644 --- a/CPP/7zip/Archive/7z/7zIn.h +++ b/CPP/7zip/Archive/7z/7zIn.h @@ -87,6 +87,8 @@ struct CFolders return PackPositions[index + 1] - PackPositions[index]; } + CFolders(): NumPackStreams(0), NumFolders(0) {} + void Clear() { NumPackStreams = 0; diff --git a/CPP/7zip/Archive/DllExports2.cpp b/CPP/7zip/Archive/DllExports2.cpp index 979b4bf9..10889e75 100644 --- a/CPP/7zip/Archive/DllExports2.cpp +++ b/CPP/7zip/Archive/DllExports2.cpp @@ -26,6 +26,7 @@ HINSTANCE g_hInstance; #define NT_CHECK_FAIL_ACTION return FALSE; +#ifdef _WIN32 extern "C" BOOL WINAPI DllMain( #ifdef UNDER_CE @@ -49,6 +50,7 @@ BOOL WINAPI DllMain( */ return TRUE; } +#endif DEFINE_GUID(CLSID_CArchiveHandler, k_7zip_GUID_Data1, diff --git a/CPP/7zip/Archive/Rar/Rar5Handler.cpp b/CPP/7zip/Archive/Rar/Rar5Handler.cpp index dff327f2..131f2c9b 100644 --- a/CPP/7zip/Archive/Rar/Rar5Handler.cpp +++ b/CPP/7zip/Archive/Rar/Rar5Handler.cpp @@ -1825,6 +1825,8 @@ HRESULT CHandler::Open2(IInStream *stream, int prevSplitFile = -1; int prevMainFile = -1; + bool nextVol_is_Required = false; + CInArchive arch; for (;;) @@ -1861,7 +1863,8 @@ HRESULT CHandler::Open2(IInStream *stream, if (!inStream || result != S_OK) { - _missingVolName = volName; + if (nextVol_is_Required) + _missingVolName = volName; break; } } @@ -2111,11 +2114,18 @@ HRESULT CHandler::Open2(IInStream *stream, } curBytes += endPos; + + nextVol_is_Required = false; + if (!arcInfo.IsVolume()) break; - if (arcInfo.EndOfArchive_was_Read - && !arcInfo.AreMoreVolumes()) - break; + + if (arcInfo.EndOfArchive_was_Read) + { + if (!arcInfo.AreMoreVolumes()) + break; + nextVol_is_Required = true; + } } FillLinks(); diff --git a/CPP/7zip/Archive/Rar/RarHandler.cpp b/CPP/7zip/Archive/Rar/RarHandler.cpp index 31c06d96..3b5924b4 100644 --- a/CPP/7zip/Archive/Rar/RarHandler.cpp +++ b/CPP/7zip/Archive/Rar/RarHandler.cpp @@ -640,6 +640,7 @@ HRESULT CInArchive::GetNextItem(CItem &item, ICryptoGetTextPassword *getTextPass { ArcInfo.EndFlags = m_BlockHeader.Flags; UInt32 offset = 7; + if (m_BlockHeader.Flags & NHeader::NArchive::kEndOfArc_Flags_DataCRC) { if (processed < offset + 4) @@ -648,6 +649,7 @@ HRESULT CInArchive::GetNextItem(CItem &item, ICryptoGetTextPassword *getTextPass ArcInfo.DataCRC = Get32(m_FileHeaderData + offset); offset += 4; } + if (m_BlockHeader.Flags & NHeader::NArchive::kEndOfArc_Flags_VolNumber) { if (processed < offset + 2) @@ -657,6 +659,7 @@ HRESULT CInArchive::GetNextItem(CItem &item, ICryptoGetTextPassword *getTextPass ArcInfo.EndOfArchive_was_Read = true; } + m_Position += processed; FinishCryptoBlock(); ArcInfo.EndPos = m_Position; @@ -699,11 +702,13 @@ HRESULT CInArchive::GetNextItem(CItem &item, ICryptoGetTextPassword *getTextPass continue; */ } + if (m_CryptoMode && m_BlockHeader.HeadSize > (1 << 10)) { error = k_ErrorType_DecryptionError; return S_OK; } + if ((m_BlockHeader.Flags & NHeader::NBlock::kLongBlock) != 0) { if (m_FileHeaderData.Size() < 7 + 4) @@ -1032,7 +1037,10 @@ HRESULT CHandler::Open2(IInStream *stream, openCallback->QueryInterface(IID_ICryptoGetTextPassword, (void **)&getTextPassword); } + bool nextVol_is_Required = false; + CInArchive archive; + for (;;) { CMyComPtr<IInStream> inStream; @@ -1072,7 +1080,8 @@ HRESULT CHandler::Open2(IInStream *stream, if (!inStream || result != S_OK) { - _missingVolName = volName; + if (nextVol_is_Required) + _missingVolName = volName; break; } } @@ -1191,6 +1200,18 @@ HRESULT CHandler::Open2(IInStream *stream, arc.PhySize = archive.ArcInfo.GetPhySize(); arc.Stream = inStream; } + + nextVol_is_Required = false; + + if (!archive.ArcInfo.IsVolume()) + break; + + if (archive.ArcInfo.EndOfArchive_was_Read) + { + if (!archive.ArcInfo.AreMoreVolumes()) + break; + nextVol_is_Required = true; + } } } diff --git a/CPP/7zip/Archive/Rar/RarHandler.h b/CPP/7zip/Archive/Rar/RarHandler.h index 9e6fb5cb..e280eb57 100644 --- a/CPP/7zip/Archive/Rar/RarHandler.h +++ b/CPP/7zip/Archive/Rar/RarHandler.h @@ -45,6 +45,7 @@ struct CInArcInfo bool IsEncryptOld() const { return (!IsThereEncryptVer() || EncryptVersion < 36); } + bool AreMoreVolumes() const { return (EndFlags & NHeader::NArchive::kEndOfArc_Flags_NextVol) != 0; } bool Is_VolNumber_Defined() const { return (EndFlags & NHeader::NArchive::kEndOfArc_Flags_VolNumber) != 0; } bool Is_DataCRC_Defined() const { return (EndFlags & NHeader::NArchive::kEndOfArc_Flags_DataCRC) != 0; } }; diff --git a/CPP/7zip/Archive/Udf/UdfHandler.cpp b/CPP/7zip/Archive/Udf/UdfHandler.cpp index 876482d1..74ec0beb 100644 --- a/CPP/7zip/Archive/Udf/UdfHandler.cpp +++ b/CPP/7zip/Archive/Udf/UdfHandler.cpp @@ -98,6 +98,7 @@ STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value) if (!_archive.IsArc) v |= kpv_ErrorFlags_IsNotArc; if (_archive.Unsupported) v |= kpv_ErrorFlags_UnsupportedFeature; if (_archive.UnexpectedEnd) v |= kpv_ErrorFlags_UnexpectedEnd; + if (_archive.NoEndAnchor) v |= kpv_ErrorFlags_HeadersError; prop = v; break; } diff --git a/CPP/7zip/Archive/Udf/UdfIn.cpp b/CPP/7zip/Archive/Udf/UdfIn.cpp index 6be035cb..a051a271 100644 --- a/CPP/7zip/Archive/Udf/UdfIn.cpp +++ b/CPP/7zip/Archive/Udf/UdfIn.cpp @@ -610,6 +610,7 @@ API_FUNC_IsArc IsArc_Udf(const Byte *p, size_t size) } } + HRESULT CInArchive::Open2() { Clear(); @@ -644,8 +645,10 @@ HRESULT CInArchive::Open2() CExtent extentVDS; extentVDS.Parse(buf + i + 16); */ + const size_t kBufSize = 1 << 11; Byte buf[kBufSize]; + for (SecLogSize = 11;; SecLogSize -= 3) { if (SecLogSize < 8) @@ -665,6 +668,7 @@ HRESULT CInArchive::Open2() break; } } + PhySize = (UInt32)(256 + 1) << SecLogSize; IsArc = true; @@ -946,28 +950,63 @@ HRESULT CInArchive::Open2() } { - UInt32 secMask = ((UInt32)1 << SecLogSize) - 1; + const UInt32 secMask = ((UInt32)1 << SecLogSize) - 1; PhySize = (PhySize + secMask) & ~(UInt64)secMask; } + + NoEndAnchor = true; + if (PhySize < fileSize) { + UInt64 rem = fileSize - PhySize; + const size_t secSize = (size_t)1 << SecLogSize; + RINOK(_stream->Seek(PhySize, STREAM_SEEK_SET, NULL)); - size_t bufSize = (UInt32)1 << SecLogSize; - size_t readSize = bufSize; - RINOK(ReadStream(_stream, buf, &readSize)); - if (readSize == bufSize) + + // some UDF images contain ZEROs before "Anchor Volume Descriptor Pointer" at the end + + for (unsigned sec = 0; sec < 1024; sec++) { - CTag tag; - if (tag.Parse(buf, readSize) == S_OK) - if (tag.Id == DESC_TYPE_AnchorVolPtr) + if (rem == 0) + break; + + size_t readSize = secSize; + if (readSize > rem) + readSize = (size_t)rem; + + RINOK(ReadStream(_stream, buf, &readSize)); + + if (readSize == 0) + break; + + if (readSize == secSize && NoEndAnchor) + { + CTag tag; + if (tag.Parse(buf, readSize) == S_OK && + tag.Id == DESC_TYPE_AnchorVolPtr) { - PhySize += bufSize; + NoEndAnchor = false; + rem -= readSize; + PhySize = fileSize - rem; + continue; } + } + + size_t i; + for (i = 0; i < readSize && buf[i] == 0; i++); + if (i != readSize) + break; + rem -= readSize; } + + if (rem == 0) + PhySize = fileSize; } + return S_OK; } + HRESULT CInArchive::Open(IInStream *inStream, CProgressVirt *progress) { _progress = progress; @@ -1000,6 +1039,7 @@ void CInArchive::Clear() IsArc = false; Unsupported = false; UnexpectedEnd = false; + NoEndAnchor = false; PhySize = 0; FileSize = 0; diff --git a/CPP/7zip/Archive/Udf/UdfIn.h b/CPP/7zip/Archive/Udf/UdfIn.h index 3851062e..f7379401 100644 --- a/CPP/7zip/Archive/Udf/UdfIn.h +++ b/CPP/7zip/Archive/Udf/UdfIn.h @@ -370,6 +370,7 @@ public: bool IsArc; bool Unsupported; bool UnexpectedEnd; + bool NoEndAnchor; void UpdatePhySize(UInt64 val) { diff --git a/CPP/7zip/Archive/Zip/ZipIn.cpp b/CPP/7zip/Archive/Zip/ZipIn.cpp index f72e7f8c..77ca89ea 100644 --- a/CPP/7zip/Archive/Zip/ZipIn.cpp +++ b/CPP/7zip/Archive/Zip/ZipIn.cpp @@ -188,9 +188,9 @@ API_FUNC_IsArc IsArc_Zip(const Byte *p, size_t size) // Crc = Get32(p + 10); // PackSize = Get32(p + 14); // Size = Get32(p + 18); - unsigned nameSize = Get16(p + 22); + const unsigned nameSize = Get16(p + 22); unsigned extraSize = Get16(p + 24); - UInt32 extraOffset = kLocalHeaderSize + (UInt32)nameSize; + const UInt32 extraOffset = kLocalHeaderSize + (UInt32)nameSize; if (extraOffset + extraSize > (1 << 16)) return k_IsArc_Res_NO; @@ -562,13 +562,21 @@ bool CInArchive::ReadLocalItem(CItemEx &item) // return false; } } + if (!CheckDosTime(item.Time)) { HeadersWarning = true; // return false; } + if (item.Name.Len() != nameSize) - return false; + { + // we support "bad" archives with null-terminated name. + if (item.Name.Len() + 1 != nameSize) + return false; + HeadersWarning = true; + } + return item.LocalFullHeaderSize <= ((UInt32)1 << 16); } @@ -782,9 +790,9 @@ HRESULT CInArchive::ReadCdItem(CItemEx &item) item.Crc = Get32(p + 12); item.PackSize = Get32(p + 16); item.Size = Get32(p + 20); - unsigned nameSize = Get16(p + 24); - UInt16 extraSize = Get16(p + 26); - UInt16 commentSize = Get16(p + 28); + const unsigned nameSize = Get16(p + 24); + const unsigned extraSize = Get16(p + 26); + const unsigned commentSize = Get16(p + 28); UInt32 diskNumberStart = Get16(p + 30); item.InternalAttrib = Get16(p + 32); item.ExternalAttrib = Get32(p + 34); @@ -961,7 +969,7 @@ HRESULT CInArchive::TryReadCd(CObjectVector<CItemEx> &items, UInt64 cdOffset, UI CItemEx cdItem; RINOK(ReadCdItem(cdItem)); items.Add(cdItem); - if (progress && items.Size() % 1 == 0) + if (progress && (items.Size() & 0xFFF) == 0) RINOK(progress->SetCompletedCD(items.Size())); } return (m_Position - cdOffset == cdSize) ? S_OK : S_FALSE; @@ -1009,6 +1017,7 @@ bool IsStrangeItem(const CItem &item) return item.Name.Len() > (1 << 14) || item.Method > (1 << 8); } + HRESULT CInArchive::ReadLocals( CObjectVector<CItemEx> &items, CProgressVirt *progress) { @@ -1037,7 +1046,8 @@ HRESULT CInArchive::ReadLocals( return S_FALSE; throw; } - if (progress && items.Size() % 1 == 0) + + if (progress && (items.Size() & 0xFF) == 0) RINOK(progress->SetCompletedLocal(items.Size(), item.LocalHeaderPos)); } @@ -1154,15 +1164,17 @@ HRESULT CInArchive::ReadHeaders2(CObjectVector<CItemEx> &items, CProgressVirt *p HeadersError = true; return S_OK; } + _inBufMode = true; _inBuffer.Init(); cdAbsOffset = m_Position - 4; + for (;;) { CItemEx cdItem; RINOK(ReadCdItem(cdItem)); cdItems.Add(cdItem); - if (progress && cdItems.Size() % 1 == 0) + if (progress && (cdItems.Size() & 0xFFF) == 0) RINOK(progress->SetCompletedCD(items.Size())); m_Signature = ReadUInt32(); if (m_Signature != NSignature::kCentralFileHeader) @@ -1183,6 +1195,7 @@ HRESULT CInArchive::ReadHeaders2(CObjectVector<CItemEx> &items, CProgressVirt *p CEcd64 ecd64; bool isZip64 = false; UInt64 ecd64AbsOffset = m_Position - 4; + if (m_Signature == NSignature::kEcd64) { IsZip64 = isZip64 = true; @@ -1213,6 +1226,7 @@ HRESULT CInArchive::ReadHeaders2(CObjectVector<CItemEx> &items, CProgressVirt *p (!items.IsEmpty()))) return S_FALSE; } + if (m_Signature == NSignature::kEcd64Locator) { if (!isZip64) @@ -1224,6 +1238,7 @@ HRESULT CInArchive::ReadHeaders2(CObjectVector<CItemEx> &items, CProgressVirt *p return S_FALSE; m_Signature = ReadUInt32(); } + if (m_Signature != NSignature::kEcd) return S_FALSE; @@ -1323,6 +1338,7 @@ HRESULT CInArchive::ReadHeaders2(CObjectVector<CItemEx> &items, CProgressVirt *p return S_OK; } + HRESULT CInArchive::ReadHeaders(CObjectVector<CItemEx> &items, CProgressVirt *progress) { HRESULT res; |