diff options
Diffstat (limited to 'CPP/7zip/Archive/7z/7zIn.cpp')
-rwxr-xr-x | CPP/7zip/Archive/7z/7zIn.cpp | 493 |
1 files changed, 239 insertions, 254 deletions
diff --git a/CPP/7zip/Archive/7z/7zIn.cpp b/CPP/7zip/Archive/7z/7zIn.cpp index f892e0cd..6cf3fdf6 100755 --- a/CPP/7zip/Archive/7z/7zIn.cpp +++ b/CPP/7zip/Archive/7z/7zIn.cpp @@ -6,13 +6,17 @@ #include "7zDecode.h" #include "../../Common/StreamObjects.h" #include "../../Common/StreamUtils.h" -extern "C" -{ -#include "../../../../C/7zCrc.h" -#include "../../../../C/CpuArch.h" +extern "C" +{ + #include "../../../../C/7zCrc.h" + #include "../../../../C/CpuArch.h" } -// define FORMAT_7Z_RECOVERY if you want to recover multivolume archives with empty StartHeader +#define Get16(p) GetUi16(p) +#define Get32(p) GetUi32(p) +#define Get64(p) GetUi64(p) + +// define FORMAT_7Z_RECOVERY if you want to recover multivolume archives with empty StartHeader #ifndef _SFX #define FORMAT_7Z_RECOVERY #endif @@ -36,7 +40,7 @@ public: { kUnsupportedVersion = 0, kUnsupported, - kIncorrect, + kIncorrect, kEndOfData, } Cause; CInArchiveException(CCauseType cause): Cause(cause) {}; @@ -97,16 +101,6 @@ void CStreamSwitch::Set(CInArchive *archive, const CObjectVector<CByteBuffer> *d } } -#ifdef LITTLE_ENDIAN_UNALIGN -static inline UInt16 GetUInt16FromMem(const Byte *p) { return *(const UInt16 *)p; } -static inline UInt32 GetUInt32FromMem(const Byte *p) { return *(const UInt32 *)p; } -static inline UInt64 GetUInt64FromMem(const Byte *p) { return *(const UInt64 *)p; } -#else -static inline UInt16 GetUInt16FromMem(const Byte *p) { return p[0] | ((UInt16)p[1] << 8); } -static inline UInt32 GetUInt32FromMem(const Byte *p) { return p[0] | ((UInt32)p[1] << 8) | ((UInt32)p[2] << 16) | ((UInt32)p[3] << 24); } -static inline UInt64 GetUInt64FromMem(const Byte *p) { return GetUInt32FromMem(p) | ((UInt64)GetUInt32FromMem(p + 4) << 32); } -#endif - Byte CInByte2::ReadByte() { if (_pos >= _size) @@ -126,6 +120,7 @@ void CInByte2::SkeepData(UInt64 size) { if (size > _size - _pos) ThrowEndOfData(); + _pos += (size_t)size; } void CInByte2::SkeepData() @@ -157,8 +152,8 @@ UInt64 CInByte2::ReadNumber() } CNum CInByte2::ReadNum() -{ - UInt64 value = ReadNumber(); +{ + UInt64 value = ReadNumber(); if (value > kNumMax) ThrowUnsupported(); return (CNum)value; @@ -168,7 +163,7 @@ UInt32 CInByte2::ReadUInt32() { if (_pos + 4 > _size) ThrowEndOfData(); - UInt32 res = GetUInt32FromMem(_buffer + _pos); + UInt32 res = Get32(_buffer + _pos); _pos += 4; return res; } @@ -177,7 +172,7 @@ UInt64 CInByte2::ReadUInt64() { if (_pos + 8 > _size) ThrowEndOfData(); - UInt64 res = GetUInt64FromMem(_buffer + _pos); + UInt64 res = Get64(_buffer + _pos); _pos += 8; return res; } @@ -200,9 +195,8 @@ void CInByte2::ReadString(UString &s) ThrowUnsupported(); wchar_t *p = s.GetBuffer(len); int i; - for (i = 0; i < len; i++, buf += 2) - p[i] = (wchar_t)GetUInt16FromMem(buf); - p[i] = 0; + for (i = 0; i < len; i++, buf += 2) + p[i] = (wchar_t)Get16(buf); s.ReleaseBuffer(len); _pos += rem + 2; } @@ -234,23 +228,32 @@ HRESULT CInArchive::FindAndReadSignature(IInStream *stream, const UInt64 *search if (searchHeaderSizeLimit != NULL) if (curTestPos - _arhiveBeginStreamPosition > *searchHeaderSizeLimit) break; - UInt32 numReadBytes = kBufferSize - numPrevBytes; - UInt32 processedSize; - RINOK(stream->Read(buffer + numPrevBytes, numReadBytes, &processedSize)); - UInt32 numBytesInBuffer = numPrevBytes + processedSize; - if (numBytesInBuffer < kHeaderSize) - break; - UInt32 numTests = numBytesInBuffer - kHeaderSize + 1; - for(UInt32 pos = 0; pos < numTests; pos++, curTestPos++) - { + do + { + UInt32 numReadBytes = kBufferSize - numPrevBytes; + UInt32 processedSize; + RINOK(stream->Read(buffer + numPrevBytes, numReadBytes, &processedSize)); + numPrevBytes += processedSize; + if (processedSize == 0) + return S_FALSE; + } + while (numPrevBytes < kHeaderSize); + UInt32 numTests = numPrevBytes - kHeaderSize + 1; + for (UInt32 pos = 0; pos < numTests; pos++) + { + for (; buffer[pos] != '7' && pos < numTests; pos++); + if (pos == numTests) + break; if (TestSignatureCandidate(buffer + pos)) { memcpy(_header, buffer + pos, kHeaderSize); + curTestPos += pos; _arhiveBeginStreamPosition = curTestPos; return stream->Seek(curTestPos + kHeaderSize, STREAM_SEEK_SET, NULL); } } - numPrevBytes = numBytesInBuffer - numTests; + curTestPos += numTests; + numPrevBytes -= numTests; memmove(buffer, buffer + numTests, numPrevBytes); } return S_FALSE; @@ -259,6 +262,7 @@ HRESULT CInArchive::FindAndReadSignature(IInStream *stream, const UInt64 *search // S_FALSE means that file is not archive HRESULT CInArchive::Open(IInStream *stream, const UInt64 *searchHeaderSizeLimit) { + HeadersSize = 0; Close(); RINOK(stream->Seek(0, STREAM_SEEK_CUR, &_arhiveBeginStreamPosition)) RINOK(FindAndReadSignature(stream, searchHeaderSizeLimit)); @@ -338,7 +342,7 @@ void CInArchive::GetNextFolderItem(CFolder &folder) { CBindPair bindPair; bindPair.InIndex = ReadNum(); - bindPair.OutIndex = ReadNum(); + bindPair.OutIndex = ReadNum(); folder.BindPairs.Add(bindPair); } @@ -354,7 +358,7 @@ void CInArchive::GetNextFolderItem(CFolder &folder) } } else - for(i = 0; i < numPackedStreams; i++) + for (i = 0; i < numPackedStreams; i++) folder.PackStreams.Add(ReadNum()); } @@ -372,13 +376,13 @@ void CInArchive::WaitAttribute(UInt64 attribute) } void CInArchive::ReadHashDigests(int numItems, - CRecordVector<bool> &digestsDefined, + CRecordVector<bool> &digestsDefined, CRecordVector<UInt32> &digests) { ReadBoolVector2(numItems, digestsDefined); digests.Clear(); digests.Reserve(numItems); - for(int i = 0; i < numItems; i++) + for (int i = 0; i < numItems; i++) { UInt32 crc = 0; if (digestsDefined[i]) @@ -410,7 +414,7 @@ void CInArchive::ReadPackInfo( break; if (type == NID::kCRC) { - ReadHashDigests(numPackStreams, packCRCsDefined, packCRCs); + ReadHashDigests(numPackStreams, packCRCsDefined, packCRCs); continue; } SkeepData(); @@ -421,7 +425,7 @@ void CInArchive::ReadPackInfo( packCRCsDefined.Clear(); packCRCs.Reserve(numPackStreams); packCRCs.Clear(); - for(CNum i = 0; i < numPackStreams; i++) + for (CNum i = 0; i < numPackStreams; i++) { packCRCsDefined.Add(false); packCRCs.Add(0); @@ -429,7 +433,7 @@ void CInArchive::ReadPackInfo( } } -void CInArchive::ReadUnPackInfo( +void CInArchive::ReadUnpackInfo( const CObjectVector<CByteBuffer> *dataVector, CObjectVector<CFolder> &folders) { @@ -441,23 +445,23 @@ void CInArchive::ReadUnPackInfo( streamSwitch.Set(this, dataVector); folders.Clear(); folders.Reserve(numFolders); - for(CNum i = 0; i < numFolders; i++) + for (CNum i = 0; i < numFolders; i++) { folders.Add(CFolder()); GetNextFolderItem(folders.Back()); } } - WaitAttribute(NID::kCodersUnPackSize); + WaitAttribute(NID::kCodersUnpackSize); CNum i; for (i = 0; i < numFolders; i++) { CFolder &folder = folders[i]; CNum numOutStreams = folder.GetNumOutStreams(); - folder.UnPackSizes.Reserve(numOutStreams); + folder.UnpackSizes.Reserve(numOutStreams); for (CNum j = 0; j < numOutStreams; j++) - folder.UnPackSizes.Add(ReadNumber()); + folder.UnpackSizes.Add(ReadNumber()); } for (;;) @@ -469,12 +473,12 @@ void CInArchive::ReadUnPackInfo( { CRecordVector<bool> crcsDefined; CRecordVector<UInt32> crcs; - ReadHashDigests(numFolders, crcsDefined, crcs); - for(i = 0; i < numFolders; i++) + ReadHashDigests(numFolders, crcsDefined, crcs); + for (i = 0; i < numFolders; i++) { CFolder &folder = folders[i]; - folder.UnPackCRCDefined = crcsDefined[i]; - folder.UnPackCRC = crcs[i]; + folder.UnpackCRCDefined = crcsDefined[i]; + folder.UnpackCRC = crcs[i]; } continue; } @@ -484,21 +488,21 @@ void CInArchive::ReadUnPackInfo( void CInArchive::ReadSubStreamsInfo( const CObjectVector<CFolder> &folders, - CRecordVector<CNum> &numUnPackStreamsInFolders, - CRecordVector<UInt64> &unPackSizes, - CRecordVector<bool> &digestsDefined, + CRecordVector<CNum> &numUnpackStreamsInFolders, + CRecordVector<UInt64> &unpackSizes, + CRecordVector<bool> &digestsDefined, CRecordVector<UInt32> &digests) { - numUnPackStreamsInFolders.Clear(); - numUnPackStreamsInFolders.Reserve(folders.Size()); + numUnpackStreamsInFolders.Clear(); + numUnpackStreamsInFolders.Reserve(folders.Size()); UInt64 type; for (;;) { type = ReadID(); - if (type == NID::kNumUnPackStream) + if (type == NID::kNumUnpackStream) { - for(int i = 0; i < folders.Size(); i++) - numUnPackStreamsInFolders.Add(ReadNum()); + for (int i = 0; i < folders.Size(); i++) + numUnpackStreamsInFolders.Add(ReadNum()); continue; } if (type == NID::kCRC || type == NID::kSize) @@ -508,16 +512,16 @@ void CInArchive::ReadSubStreamsInfo( SkeepData(); } - if (numUnPackStreamsInFolders.IsEmpty()) - for(int i = 0; i < folders.Size(); i++) - numUnPackStreamsInFolders.Add(1); + if (numUnpackStreamsInFolders.IsEmpty()) + for (int i = 0; i < folders.Size(); i++) + numUnpackStreamsInFolders.Add(1); int i; - for(i = 0; i < numUnPackStreamsInFolders.Size(); i++) + for (i = 0; i < numUnpackStreamsInFolders.Size(); i++) { // v3.13 incorrectly worked with empty folders // v4.07: we check that folder is empty - CNum numSubstreams = numUnPackStreamsInFolders[i]; + CNum numSubstreams = numUnpackStreamsInFolders[i]; if (numSubstreams == 0) continue; UInt64 sum = 0; @@ -525,20 +529,20 @@ void CInArchive::ReadSubStreamsInfo( if (type == NID::kSize) { UInt64 size = ReadNumber(); - unPackSizes.Add(size); + unpackSizes.Add(size); sum += size; } - unPackSizes.Add(folders[i].GetUnPackSize() - sum); + unpackSizes.Add(folders[i].GetUnpackSize() - sum); } if (type == NID::kSize) type = ReadID(); int numDigests = 0; int numDigestsTotal = 0; - for(i = 0; i < folders.Size(); i++) + for (i = 0; i < folders.Size(); i++) { - CNum numSubstreams = numUnPackStreamsInFolders[i]; - if (numSubstreams != 1 || !folders[i].UnPackCRCDefined) + CNum numSubstreams = numUnpackStreamsInFolders[i]; + if (numSubstreams != 1 || !folders[i].UnpackCRCDefined) numDigests += numSubstreams; numDigestsTotal += numSubstreams; } @@ -547,18 +551,18 @@ void CInArchive::ReadSubStreamsInfo( { if (type == NID::kCRC) { - CRecordVector<bool> digestsDefined2; + CRecordVector<bool> digestsDefined2; CRecordVector<UInt32> digests2; ReadHashDigests(numDigests, digestsDefined2, digests2); int digestIndex = 0; for (i = 0; i < folders.Size(); i++) { - CNum numSubstreams = numUnPackStreamsInFolders[i]; + CNum numSubstreams = numUnpackStreamsInFolders[i]; const CFolder &folder = folders[i]; - if (numSubstreams == 1 && folder.UnPackCRCDefined) + if (numSubstreams == 1 && folder.UnpackCRCDefined) { digestsDefined.Add(true); - digests.Add(folder.UnPackCRC); + digests.Add(folder.UnpackCRC); } else for (CNum j = 0; j < numSubstreams; j++, digestIndex++) @@ -595,9 +599,9 @@ void CInArchive::ReadStreamsInfo( CRecordVector<bool> &packCRCsDefined, CRecordVector<UInt32> &packCRCs, CObjectVector<CFolder> &folders, - CRecordVector<CNum> &numUnPackStreamsInFolders, - CRecordVector<UInt64> &unPackSizes, - CRecordVector<bool> &digestsDefined, + CRecordVector<CNum> &numUnpackStreamsInFolders, + CRecordVector<UInt64> &unpackSizes, + CRecordVector<bool> &digestsDefined, CRecordVector<UInt32> &digests) { for (;;) @@ -614,15 +618,15 @@ void CInArchive::ReadStreamsInfo( ReadPackInfo(dataOffset, packSizes, packCRCsDefined, packCRCs); break; } - case NID::kUnPackInfo: + case NID::kUnpackInfo: { - ReadUnPackInfo(dataVector, folders); + ReadUnpackInfo(dataVector, folders); break; } case NID::kSubStreamsInfo: { - ReadSubStreamsInfo(folders, numUnPackStreamsInFolders, - unPackSizes, digestsDefined, digests); + ReadSubStreamsInfo(folders, numUnpackStreamsInFolders, + unpackSizes, digestsDefined, digests); break; } default: @@ -637,7 +641,7 @@ void CInArchive::ReadBoolVector(int numItems, CBoolVector &v) v.Reserve(numItems); Byte b = 0; Byte mask = 0; - for(int i = 0; i < numItems; i++) + for (int i = 0; i < numItems; i++) { if (mask == 0) { @@ -663,54 +667,30 @@ void CInArchive::ReadBoolVector2(int numItems, CBoolVector &v) v.Add(true); } -void CInArchive::ReadTime(const CObjectVector<CByteBuffer> &dataVector, - CObjectVector<CFileItem> &files, UInt32 type) +void CInArchive::ReadUInt64DefVector(const CObjectVector<CByteBuffer> &dataVector, + CUInt64DefVector &v, int numFiles) { - CBoolVector boolVector; - ReadBoolVector2(files.Size(), boolVector); + ReadBoolVector2(numFiles, v.Defined); CStreamSwitch streamSwitch; streamSwitch.Set(this, &dataVector); + v.Values.Reserve(numFiles); - for(int i = 0; i < files.Size(); i++) + for (int i = 0; i < numFiles; i++) { - CFileItem &file = files[i]; - CArchiveFileTime fileTime; - fileTime.dwLowDateTime = 0; - fileTime.dwHighDateTime = 0; - bool defined = boolVector[i]; - if (defined) - { - fileTime.dwLowDateTime = ReadUInt32(); - fileTime.dwHighDateTime = ReadUInt32(); - } - switch(type) - { - case NID::kCreationTime: - file.IsCreationTimeDefined = defined; - if (defined) - file.CreationTime = fileTime; - break; - case NID::kLastWriteTime: - file.IsLastWriteTimeDefined = defined; - if (defined) - file.LastWriteTime = fileTime; - break; - case NID::kLastAccessTime: - file.IsLastAccessTimeDefined = defined; - if (defined) - file.LastAccessTime = fileTime; - break; - } + UInt64 t = 0; + if (v.Defined[i]) + t = ReadUInt64(); + v.Values.Add(t); } } HRESULT CInArchive::ReadAndDecodePackedStreams( DECL_EXTERNAL_CODECS_LOC_VARS - UInt64 baseOffset, + UInt64 baseOffset, UInt64 &dataOffset, CObjectVector<CByteBuffer> &dataVector #ifndef _NO_CRYPTO - , ICryptoGetTextPassword *getTextPassword + , ICryptoGetTextPassword *getTextPassword, bool &passwordIsDefined #endif ) { @@ -719,23 +699,23 @@ HRESULT CInArchive::ReadAndDecodePackedStreams( CRecordVector<UInt32> packCRCs; CObjectVector<CFolder> folders; - CRecordVector<CNum> numUnPackStreamsInFolders; - CRecordVector<UInt64> unPackSizes; + CRecordVector<CNum> numUnpackStreamsInFolders; + CRecordVector<UInt64> unpackSizes; CRecordVector<bool> digestsDefined; CRecordVector<UInt32> digests; - ReadStreamsInfo(NULL, + ReadStreamsInfo(NULL, dataOffset, - packSizes, - packCRCsDefined, - packCRCs, + packSizes, + packCRCsDefined, + packCRCs, folders, - numUnPackStreamsInFolders, - unPackSizes, - digestsDefined, + numUnpackStreamsInFolders, + unpackSizes, + digestsDefined, digests); - // database.ArchiveInfo.DataStartPosition2 += database.ArchiveInfo.StartPositionAfterHeader; + // db.ArchiveInfo.DataStartPosition2 += db.ArchiveInfo.StartPositionAfterHeader; CNum packIndex = 0; CDecoder decoder( @@ -746,27 +726,27 @@ HRESULT CInArchive::ReadAndDecodePackedStreams( #endif ); UInt64 dataStartPos = baseOffset + dataOffset; - for(int i = 0; i < folders.Size(); i++) + for (int i = 0; i < folders.Size(); i++) { const CFolder &folder = folders[i]; dataVector.Add(CByteBuffer()); CByteBuffer &data = dataVector.Back(); - UInt64 unPackSize64 = folder.GetUnPackSize(); - size_t unPackSize = (size_t)unPackSize64; - if (unPackSize != unPackSize64) + UInt64 unpackSize64 = folder.GetUnpackSize(); + size_t unpackSize = (size_t)unpackSize64; + if (unpackSize != unpackSize64) ThrowUnsupported(); - data.SetCapacity(unPackSize); + data.SetCapacity(unpackSize); CSequentialOutStreamImp2 *outStreamSpec = new CSequentialOutStreamImp2; CMyComPtr<ISequentialOutStream> outStream = outStreamSpec; - outStreamSpec->Init(data, unPackSize); + outStreamSpec->Init(data, unpackSize); HRESULT result = decoder.Decode( EXTERNAL_CODECS_LOC_VARS - _stream, dataStartPos, + _stream, dataStartPos, &packSizes[packIndex], folder, outStream, NULL #ifndef _NO_CRYPTO - , getTextPassword + , getTextPassword, passwordIsDefined #endif #ifdef COMPRESS_MT , false, 1 @@ -774,20 +754,24 @@ HRESULT CInArchive::ReadAndDecodePackedStreams( ); RINOK(result); - if (folder.UnPackCRCDefined) - if (CrcCalc(data, unPackSize) != folder.UnPackCRC) + if (folder.UnpackCRCDefined) + if (CrcCalc(data, unpackSize) != folder.UnpackCRC) ThrowIncorrect(); - for (int j = 0; j < folder.PackStreams.Size(); j++) - dataStartPos += packSizes[packIndex++]; + for (int j = 0; j < folder.PackStreams.Size(); j++) + { + UInt64 packSize = packSizes[packIndex++]; + dataStartPos += packSize; + HeadersSize += packSize; + } } return S_OK; } HRESULT CInArchive::ReadHeader( DECL_EXTERNAL_CODECS_LOC_VARS - CArchiveDatabaseEx &database + CArchiveDatabaseEx &db #ifndef _NO_CRYPTO - , ICryptoGetTextPassword *getTextPassword + , ICryptoGetTextPassword *getTextPassword, bool &passwordIsDefined #endif ) { @@ -795,7 +779,7 @@ HRESULT CInArchive::ReadHeader( if (type == NID::kArchiveProperties) { - ReadArchiveProperties(database.ArchiveInfo); + ReadArchiveProperties(db.ArchiveInfo); type = ReadID(); } @@ -805,50 +789,50 @@ HRESULT CInArchive::ReadHeader( { HRESULT result = ReadAndDecodePackedStreams( EXTERNAL_CODECS_LOC_VARS - database.ArchiveInfo.StartPositionAfterHeader, - database.ArchiveInfo.DataStartPosition2, + db.ArchiveInfo.StartPositionAfterHeader, + db.ArchiveInfo.DataStartPosition2, dataVector #ifndef _NO_CRYPTO - , getTextPassword + , getTextPassword, passwordIsDefined #endif ); RINOK(result); - database.ArchiveInfo.DataStartPosition2 += database.ArchiveInfo.StartPositionAfterHeader; + db.ArchiveInfo.DataStartPosition2 += db.ArchiveInfo.StartPositionAfterHeader; type = ReadID(); } - CRecordVector<UInt64> unPackSizes; + CRecordVector<UInt64> unpackSizes; CRecordVector<bool> digestsDefined; CRecordVector<UInt32> digests; if (type == NID::kMainStreamsInfo) { ReadStreamsInfo(&dataVector, - database.ArchiveInfo.DataStartPosition, - database.PackSizes, - database.PackCRCsDefined, - database.PackCRCs, - database.Folders, - database.NumUnPackStreamsVector, - unPackSizes, + db.ArchiveInfo.DataStartPosition, + db.PackSizes, + db.PackCRCsDefined, + db.PackCRCs, + db.Folders, + db.NumUnpackStreamsVector, + unpackSizes, digestsDefined, digests); - database.ArchiveInfo.DataStartPosition += database.ArchiveInfo.StartPositionAfterHeader; + db.ArchiveInfo.DataStartPosition += db.ArchiveInfo.StartPositionAfterHeader; type = ReadID(); } else { - for(int i = 0; i < database.Folders.Size(); i++) + for (int i = 0; i < db.Folders.Size(); i++) { - database.NumUnPackStreamsVector.Add(1); - CFolder &folder = database.Folders[i]; - unPackSizes.Add(folder.GetUnPackSize()); - digestsDefined.Add(folder.UnPackCRCDefined); - digests.Add(folder.UnPackCRC); + db.NumUnpackStreamsVector.Add(1); + CFolder &folder = db.Folders[i]; + unpackSizes.Add(folder.GetUnpackSize()); + digestsDefined.Add(folder.UnpackCRCDefined); + digests.Add(folder.UnpackCRC); } } - database.Files.Clear(); + db.Files.Clear(); if (type == NID::kEnd) return S_OK; @@ -856,20 +840,20 @@ HRESULT CInArchive::ReadHeader( ThrowIncorrect(); CNum numFiles = ReadNum(); - database.Files.Reserve(numFiles); + db.Files.Reserve(numFiles); CNum i; - for(i = 0; i < numFiles; i++) - database.Files.Add(CFileItem()); + for (i = 0; i < numFiles; i++) + db.Files.Add(CFileItem()); - database.ArchiveInfo.FileInfoPopIDs.Add(NID::kSize); - if (!database.PackSizes.IsEmpty()) - database.ArchiveInfo.FileInfoPopIDs.Add(NID::kPackInfo); + db.ArchiveInfo.FileInfoPopIDs.Add(NID::kSize); + if (!db.PackSizes.IsEmpty()) + db.ArchiveInfo.FileInfoPopIDs.Add(NID::kPackInfo); if (numFiles > 0 && !digests.IsEmpty()) - database.ArchiveInfo.FileInfoPopIDs.Add(NID::kCRC); + db.ArchiveInfo.FileInfoPopIDs.Add(NID::kCRC); CBoolVector emptyStreamVector; emptyStreamVector.Reserve((int)numFiles); - for(i = 0; i < numFiles; i++) + for (i = 0; i < numFiles; i++) emptyStreamVector.Add(false); CBoolVector emptyFileVector; CBoolVector antiFileVector; @@ -881,6 +865,8 @@ HRESULT CInArchive::ReadHeader( if (type == NID::kEnd) break; UInt64 size = ReadNumber(); + size_t ppp = _inByteBack->_pos; + bool addPropIdToList = true; bool isKnownType = true; if (type > ((UInt32)1 << 30)) isKnownType = false; @@ -890,37 +876,22 @@ HRESULT CInArchive::ReadHeader( { CStreamSwitch streamSwitch; streamSwitch.Set(this, &dataVector); - for(int i = 0; i < database.Files.Size(); i++) - _inByteBack->ReadString(database.Files[i].Name); + for (int i = 0; i < db.Files.Size(); i++) + _inByteBack->ReadString(db.Files[i].Name); break; } case NID::kWinAttributes: { CBoolVector boolVector; - ReadBoolVector2(database.Files.Size(), boolVector); - CStreamSwitch streamSwitch; - streamSwitch.Set(this, &dataVector); - for(i = 0; i < numFiles; i++) - { - CFileItem &file = database.Files[i]; - file.AreAttributesDefined = boolVector[i]; - if (file.AreAttributesDefined) - file.Attributes = ReadUInt32(); - } - break; - } - case NID::kStartPos: - { - CBoolVector boolVector; - ReadBoolVector2(database.Files.Size(), boolVector); + ReadBoolVector2(db.Files.Size(), boolVector); CStreamSwitch streamSwitch; streamSwitch.Set(this, &dataVector); - for(i = 0; i < numFiles; i++) + for (i = 0; i < numFiles; i++) { - CFileItem &file = database.Files[i]; - file.IsStartPosDefined = boolVector[i]; - if (file.IsStartPosDefined) - file.StartPos = ReadUInt64(); + CFileItem &file = db.Files[i]; + file.AttribDefined = boolVector[i]; + if (file.AttribDefined) + file.Attrib = ReadUInt32(); } break; } @@ -939,55 +910,68 @@ HRESULT CInArchive::ReadHeader( } break; } - case NID::kEmptyFile: - { - ReadBoolVector(numEmptyStreams, emptyFileVector); - break; - } - case NID::kAnti: - { - ReadBoolVector(numEmptyStreams, antiFileVector); - break; - } - case NID::kCreationTime: - case NID::kLastWriteTime: - case NID::kLastAccessTime: + case NID::kEmptyFile: ReadBoolVector(numEmptyStreams, emptyFileVector); break; + case NID::kAnti: ReadBoolVector(numEmptyStreams, antiFileVector); break; + case NID::kStartPos: ReadUInt64DefVector(dataVector, db.StartPos, (int)numFiles); break; + case NID::kCTime: ReadUInt64DefVector(dataVector, db.CTime, (int)numFiles); break; + case NID::kATime: ReadUInt64DefVector(dataVector, db.ATime, (int)numFiles); break; + case NID::kMTime: ReadUInt64DefVector(dataVector, db.MTime, (int)numFiles); break; + case NID::kDummy: { - ReadTime(dataVector, database.Files, (UInt32)type); + for (UInt64 j = 0; j < size; j++) + if (ReadByte() != 0) + ThrowIncorrect(); + addPropIdToList = false; break; } default: - isKnownType = false; + addPropIdToList = isKnownType = false; } if (isKnownType) - database.ArchiveInfo.FileInfoPopIDs.Add(type); + { + if(addPropIdToList) + db.ArchiveInfo.FileInfoPopIDs.Add(type); + } else SkeepData(size); + bool checkRecordsSize = (db.ArchiveInfo.Version.Major > 0 || + db.ArchiveInfo.Version.Minor > 2); + if (checkRecordsSize && _inByteBack->_pos - ppp != size) + ThrowIncorrect(); } CNum emptyFileIndex = 0; CNum sizeIndex = 0; - for(i = 0; i < numFiles; i++) + + CNum numAntiItems = 0; + for (i = 0; i < numEmptyStreams; i++) + if (antiFileVector[i]) + numAntiItems++; + + for (i = 0; i < numFiles; i++) { - CFileItem &file = database.Files[i]; + CFileItem &file = db.Files[i]; + bool isAnti; file.HasStream = !emptyStreamVector[i]; - if(file.HasStream) + if (file.HasStream) { - file.IsDirectory = false; - file.IsAnti = false; - file.UnPackSize = unPackSizes[sizeIndex]; - file.FileCRC = digests[sizeIndex]; - file.IsFileCRCDefined = digestsDefined[sizeIndex]; + file.IsDir = false; + isAnti = false; + file.Size = unpackSizes[sizeIndex]; + file.Crc = digests[sizeIndex]; + file.CrcDefined = digestsDefined[sizeIndex]; sizeIndex++; } else { - file.IsDirectory = !emptyFileVector[emptyFileIndex]; - file.IsAnti = antiFileVector[emptyFileIndex]; + file.IsDir = !emptyFileVector[emptyFileIndex]; + isAnti = antiFileVector[emptyFileIndex]; emptyFileIndex++; - file.UnPackSize = 0; - file.IsFileCRCDefined = false; + file.Size = 0; + file.CrcDefined = false; } + if (numAntiItems != 0) + db.IsAnti.Add(isAnti); } return S_OK; } @@ -998,7 +982,7 @@ void CArchiveDatabaseEx::FillFolderStartPackStream() FolderStartPackStreamIndex.Clear(); FolderStartPackStreamIndex.Reserve(Folders.Size()); CNum startPos = 0; - for(int i = 0; i < Folders.Size(); i++) + for (int i = 0; i < Folders.Size(); i++) { FolderStartPackStreamIndex.Add(startPos); startPos += (CNum)Folders[i].PackStreams.Size(); @@ -1010,7 +994,7 @@ void CArchiveDatabaseEx::FillStartPos() PackStreamStartPositions.Clear(); PackStreamStartPositions.Reserve(PackSizes.Size()); UInt64 startPos = 0; - for(int i = 0; i < PackSizes.Size(); i++) + for (int i = 0; i < PackSizes.Size(); i++) { PackStreamStartPositions.Add(startPos); startPos += PackSizes[i]; @@ -1044,7 +1028,7 @@ void CArchiveDatabaseEx::FillFolderStartFileIndex() if (folderIndex >= Folders.Size()) ThrowIncorrect(); FolderStartFileIndex.Add(i); // check it - if (NumUnPackStreamsVector[folderIndex] != 0) + if (NumUnpackStreamsVector[folderIndex] != 0) break; folderIndex++; } @@ -1053,7 +1037,7 @@ void CArchiveDatabaseEx::FillFolderStartFileIndex() if (emptyStream) continue; indexInFolder++; - if (indexInFolder >= NumUnPackStreamsVector[folderIndex]) + if (indexInFolder >= NumUnpackStreamsVector[folderIndex]) { folderIndex++; indexInFolder = 0; @@ -1063,25 +1047,25 @@ void CArchiveDatabaseEx::FillFolderStartFileIndex() HRESULT CInArchive::ReadDatabase2( DECL_EXTERNAL_CODECS_LOC_VARS - CArchiveDatabaseEx &database + CArchiveDatabaseEx &db #ifndef _NO_CRYPTO - , ICryptoGetTextPassword *getTextPassword + , ICryptoGetTextPassword *getTextPassword, bool &passwordIsDefined #endif ) { - database.Clear(); - database.ArchiveInfo.StartPosition = _arhiveBeginStreamPosition; + db.Clear(); + db.ArchiveInfo.StartPosition = _arhiveBeginStreamPosition; - database.ArchiveInfo.Version.Major = _header[6]; - database.ArchiveInfo.Version.Minor = _header[7]; + db.ArchiveInfo.Version.Major = _header[6]; + db.ArchiveInfo.Version.Minor = _header[7]; - if (database.ArchiveInfo.Version.Major != kMajorVersion) + if (db.ArchiveInfo.Version.Major != kMajorVersion) ThrowUnsupportedVersion(); - UInt32 crcFromArchive = GetUInt32FromMem(_header + 8); - UInt64 nextHeaderOffset = GetUInt64FromMem(_header + 0xC); - UInt64 nextHeaderSize = GetUInt64FromMem(_header + 0x14); - UInt32 nextHeaderCRC = GetUInt32FromMem(_header + 0x1C); + UInt32 crcFromArchive = Get32(_header + 8); + UInt64 nextHeaderOffset = Get64(_header + 0xC); + UInt64 nextHeaderSize = Get64(_header + 0x14); + UInt32 nextHeaderCRC = Get32(_header + 0x1C); UInt32 crc = CrcCalc(_header + 0xC, 20); #ifdef FORMAT_7Z_RECOVERY @@ -1097,16 +1081,15 @@ HRESULT CInArchive::ReadDatabase2( checkSize = (int)(cur2 - cur); RINOK(_stream->Seek(-checkSize, STREAM_SEEK_END, &cur2)); - UInt32 realProcessedSize; - RINOK(_stream->Read(buf, (UInt32)kCheckSize, &realProcessedSize)); + RINOK(ReadStream_FALSE(_stream, buf, (size_t)checkSize)); int i; - for (i = (int)realProcessedSize - 2; i >= 0; i--) + for (i = (int)checkSize - 2; i >= 0; i--) if (buf[i] == 0x17 && buf[i + 1] == 0x6 || buf[i] == 0x01 && buf[i + 1] == 0x04) break; if (i < 0) return S_FALSE; - nextHeaderSize = realProcessedSize - i; + nextHeaderSize = checkSize - i; nextHeaderOffset = cur2 - cur + i; nextHeaderCRC = CrcCalc(buf + i, (size_t)nextHeaderSize); RINOK(_stream->Seek(cur, STREAM_SEEK_SET, NULL)); @@ -1117,7 +1100,7 @@ HRESULT CInArchive::ReadDatabase2( crcFromArchive = crc; #endif - database.ArchiveInfo.StartPositionAfterHeader = _arhiveBeginStreamPosition + kHeaderSize; + db.ArchiveInfo.StartPositionAfterHeader = _arhiveBeginStreamPosition + kHeaderSize; if (crc != crcFromArchive) ThrowIncorrect(); @@ -1133,10 +1116,10 @@ HRESULT CInArchive::ReadDatabase2( CByteBuffer buffer2; buffer2.SetCapacity((size_t)nextHeaderSize); - UInt32 realProcessedSize; - RINOK(_stream->Read(buffer2, (UInt32)nextHeaderSize, &realProcessedSize)); - if (realProcessedSize != (UInt32)nextHeaderSize) - return S_FALSE; + RINOK(ReadStream_FALSE(_stream, buffer2, (size_t)nextHeaderSize)); + HeadersSize += kHeaderSize + nextHeaderSize; + db.PhySize = kHeaderSize + nextHeaderOffset + nextHeaderSize; + if (CrcCalc(buffer2, (UInt32)nextHeaderSize) != nextHeaderCRC) ThrowIncorrect(); @@ -1145,20 +1128,18 @@ HRESULT CInArchive::ReadDatabase2( CObjectVector<CByteBuffer> dataVector; - for (;;) + UInt64 type = ReadID(); + if (type != NID::kHeader) { - UInt64 type = ReadID(); - if (type == NID::kHeader) - break; if (type != NID::kEncodedHeader) ThrowIncorrect(); HRESULT result = ReadAndDecodePackedStreams( EXTERNAL_CODECS_LOC_VARS - database.ArchiveInfo.StartPositionAfterHeader, - database.ArchiveInfo.DataStartPosition2, + db.ArchiveInfo.StartPositionAfterHeader, + db.ArchiveInfo.DataStartPosition2, dataVector #ifndef _NO_CRYPTO - , getTextPassword + , getTextPassword, passwordIsDefined #endif ); RINOK(result); @@ -1168,31 +1149,35 @@ HRESULT CInArchive::ReadDatabase2( ThrowIncorrect(); streamSwitch.Remove(); streamSwitch.Set(this, dataVector.Front()); + if (ReadID() != NID::kHeader) + ThrowIncorrect(); } + db.HeadersSize = HeadersSize; + return ReadHeader( EXTERNAL_CODECS_LOC_VARS - database + db #ifndef _NO_CRYPTO - , getTextPassword + , getTextPassword, passwordIsDefined #endif ); } HRESULT CInArchive::ReadDatabase( DECL_EXTERNAL_CODECS_LOC_VARS - CArchiveDatabaseEx &database + CArchiveDatabaseEx &db #ifndef _NO_CRYPTO - , ICryptoGetTextPassword *getTextPassword + , ICryptoGetTextPassword *getTextPassword, bool &passwordIsDefined #endif ) { try { return ReadDatabase2( - EXTERNAL_CODECS_LOC_VARS database + EXTERNAL_CODECS_LOC_VARS db #ifndef _NO_CRYPTO - , getTextPassword + , getTextPassword, passwordIsDefined #endif ); } |