diff options
author | Igor Pavlov <ipavlov@users.sourceforge.net> | 2021-07-23 01:00:14 +0300 |
---|---|---|
committer | Kornel <kornel@geekhood.net> | 2021-07-23 01:00:14 +0300 |
commit | 585698650f7257d2cefa6a3a2a49d5bbe84fd9b2 (patch) | |
tree | 8900be42e892a440bbd1063804b0557288c2f97f /CPP/7zip/Archive | |
parent | 4a960640a340a848a2d2c27f19b339c2c3d3f734 (diff) |
21.0221.02
Diffstat (limited to 'CPP/7zip/Archive')
104 files changed, 3214 insertions, 1455 deletions
diff --git a/CPP/7zip/Archive/7z/7zCompressionMode.h b/CPP/7zip/Archive/7z/7zCompressionMode.h index 608293d6..44c90226 100644 --- a/CPP/7zip/Archive/7z/7zCompressionMode.h +++ b/CPP/7zip/Archive/7z/7zCompressionMode.h @@ -57,18 +57,20 @@ struct CCompressionMethodMode #endif bool PasswordIsDefined; - UString Password; + UString Password; // _Wipe bool IsEmpty() const { return (Methods.IsEmpty() && !PasswordIsDefined); } CCompressionMethodMode(): - DefaultMethod_was_Inserted(false), - Filter_was_Inserted(false), - PasswordIsDefined(false) + DefaultMethod_was_Inserted(false) + , Filter_was_Inserted(false) #ifndef _7ZIP_ST , NumThreads(1) , MultiThreadMixer(true) #endif + , PasswordIsDefined(false) {} + + ~CCompressionMethodMode() { Password.Wipe_and_Empty(); } }; }} diff --git a/CPP/7zip/Archive/7z/7zDecode.cpp b/CPP/7zip/Archive/7z/7zDecode.cpp index 9df531e0..c27c8fbc 100644 --- a/CPP/7zip/Archive/7z/7zDecode.cpp +++ b/CPP/7zip/Archive/7z/7zDecode.cpp @@ -158,7 +158,7 @@ STDMETHODIMP CLockedSequentialInStreamMT::Read(void *data, UInt32 size, UInt32 * if (_pos != _glob->Pos) { - RINOK(_glob->Stream->Seek(_pos, STREAM_SEEK_SET, NULL)); + RINOK(_glob->Stream->Seek((Int64)_pos, STREAM_SEEK_SET, NULL)); _glob->Pos = _pos; } @@ -200,7 +200,7 @@ STDMETHODIMP CLockedSequentialInStreamST::Read(void *data, UInt32 size, UInt32 * { if (_pos != _glob->Pos) { - RINOK(_glob->Stream->Seek(_pos, STREAM_SEEK_SET, NULL)); + RINOK(_glob->Stream->Seek((Int64)_pos, STREAM_SEEK_SET, NULL)); _glob->Pos = _pos; } @@ -276,6 +276,7 @@ HRESULT CDecoder::Decode( if (!_bindInfoPrev_Defined || !AreBindInfoExEqual(bindInfo, _bindInfoPrev)) { + _bindInfoPrev_Defined = false; _mixerRef.Release(); #ifdef USE_MIXER_MT @@ -348,7 +349,7 @@ HRESULT CDecoder::Decode( _bindInfoPrev_Defined = true; } - _mixer->ReInit(); + RINOK(_mixer->ReInit2()); UInt32 packStreamIndex = 0; UInt32 unpackStreamIndexStart = folders.FoToCoderUnpackSizes[folderIndex]; @@ -396,10 +397,10 @@ HRESULT CDecoder::Decode( if (setDecoderProperties) { const CByteBuffer &props = coderInfo.Props; - size_t size = props.Size(); - if (size > 0xFFFFFFFF) + const UInt32 size32 = (UInt32)props.Size(); + if (props.Size() != size32) return E_NOTIMPL; - HRESULT res = setDecoderProperties->SetDecoderProperties2((const Byte *)props, (UInt32)size); + HRESULT res = setDecoderProperties->SetDecoderProperties2((const Byte *)props, size32); if (res == E_INVALIDARG) res = E_NOTIMPL; RINOK(res); @@ -415,17 +416,17 @@ HRESULT CDecoder::Decode( isEncrypted = true; if (!getTextPassword) return E_NOTIMPL; - CMyComBSTR passwordBSTR; + CMyComBSTR_Wipe passwordBSTR; RINOK(getTextPassword->CryptoGetTextPassword(&passwordBSTR)); passwordIsDefined = true; - password.Empty(); + password.Wipe_and_Empty(); size_t len = 0; if (passwordBSTR) { password = passwordBSTR; len = password.Len(); } - CByteBuffer buffer(len * 2); + CByteBuffer_Wipe buffer(len * 2); for (size_t k = 0; k < len; k++) { wchar_t c = passwordBSTR[k]; @@ -444,7 +445,7 @@ HRESULT CDecoder::Decode( if (setFinishMode) { finishMode = fullUnpack; - RINOK(setFinishMode->SetFinishMode(BoolToInt(finishMode))); + RINOK(setFinishMode->SetFinishMode(BoolToUInt(finishMode))); } } @@ -487,36 +488,49 @@ HRESULT CDecoder::Decode( CLockedInStream *lockedInStreamSpec = new CLockedInStream; CMyComPtr<IUnknown> lockedInStream = lockedInStreamSpec; - bool needMtLock = false; + #ifdef USE_MIXER_MT + #ifdef USE_MIXER_ST + bool needMtLock = _useMixerMT; + #endif + #endif if (folderInfo.PackStreams.Size() > 1) { // lockedInStream.Pos = (UInt64)(Int64)-1; // RINOK(inStream->Seek(0, STREAM_SEEK_CUR, &lockedInStream.Pos)); - RINOK(inStream->Seek(startPos + packPositions[0], STREAM_SEEK_SET, &lockedInStreamSpec->Pos)); + RINOK(inStream->Seek((Int64)(startPos + packPositions[0]), STREAM_SEEK_SET, &lockedInStreamSpec->Pos)); lockedInStreamSpec->Stream = inStream; + #ifdef USE_MIXER_MT #ifdef USE_MIXER_ST - if (_mixer->IsThere_ExternalCoder_in_PackTree(_mixer->MainCoderIndex)) - #endif + /* + For ST-mixer mode: + If parallel input stream reading from pack streams is possible, + we must use MT-lock for packed streams. + Internal decoders in 7-Zip will not read pack streams in parallel in ST-mixer mode. + So we force to needMtLock mode only if there is unknown (external) decoder. + */ + if (!needMtLock && _mixer->IsThere_ExternalCoder_in_PackTree(_mixer->MainCoderIndex)) needMtLock = true; + #endif + #endif } for (unsigned j = 0; j < folderInfo.PackStreams.Size(); j++) { CMyComPtr<ISequentialInStream> packStream; - UInt64 packPos = startPos + packPositions[j]; + const UInt64 packPos = startPos + packPositions[j]; if (folderInfo.PackStreams.Size() == 1) { - RINOK(inStream->Seek(packPos, STREAM_SEEK_SET, NULL)); + RINOK(inStream->Seek((Int64)packPos, STREAM_SEEK_SET, NULL)); packStream = inStream; } else { #ifdef USE_MIXER_MT #ifdef USE_MIXER_ST - if (_useMixerMT || needMtLock) + if (needMtLock) #endif { CLockedSequentialInStreamMT *lockedStreamImpSpec = new CLockedSequentialInStreamMT; @@ -542,7 +556,7 @@ HRESULT CDecoder::Decode( streamSpec->Init(packPositions[j + 1] - packPositions[j]); } - unsigned num = inStreams.Size(); + const unsigned num = inStreams.Size(); CObjArray<ISequentialInStream *> inStreamPointers(num); for (i = 0; i < num; i++) inStreamPointers[i] = inStreams[i]; diff --git a/CPP/7zip/Archive/7z/7zEncode.cpp b/CPP/7zip/Archive/7z/7zEncode.cpp index 7d8270f9..49963241 100644 --- a/CPP/7zip/Archive/7z/7zEncode.cpp +++ b/CPP/7zip/Archive/7z/7zEncode.cpp @@ -158,7 +158,7 @@ HRESULT CEncoder::CreateMixerCoder( { RINOK(CreateCoder_Index( EXTERNAL_CODECS_LOC_VARS - methodFull.CodecIndex, true, cod)); + (unsigned)methodFull.CodecIndex, true, cod)); } else { @@ -215,7 +215,7 @@ HRESULT CEncoder::CreateMixerCoder( if (cryptoSetPassword) { const unsigned sizeInBytes = _options.Password.Len() * 2; - CByteBuffer buffer(sizeInBytes); + CByteBuffer_Wipe buffer(sizeInBytes); for (unsigned i = 0; i < _options.Password.Len(); i++) { wchar_t c = _options.Password[i]; @@ -249,11 +249,12 @@ public: STDMETHODIMP CSequentialOutTempBufferImp2::Write(const void *data, UInt32 size, UInt32 *processed) { - if (!_buf->Write(data, size)) + HRESULT res = _buf->Write_HRESULT(data, size); + if (res != S_OK) { if (processed) *processed = 0; - return E_FAIL; + return res; } if (processed) *processed = size; @@ -309,7 +310,7 @@ HRESULT CEncoder::Encode( RINOK(CreateMixerCoder(EXTERNAL_CODECS_LOC_VARS inSizeForReduce)); } - _mixer->ReInit(); + RINOK(_mixer->ReInit2()); CMtEncMultiProgress *mtProgressSpec = NULL; CMyComPtr<ICompressProgressInfo> mtProgress; @@ -478,7 +479,7 @@ HRESULT CEncoder::Encode( unpackSize = streamSize; } else - streamSize = _mixer->GetBondStreamSize(bond); + streamSize = _mixer->GetBondStreamSize((unsigned)bond); coderUnpackSizes.Add(streamSize); } @@ -609,13 +610,13 @@ HRESULT CEncoder::EncoderConstr() int bond = _bindInfo.FindBond_for_PackStream(outIndex); if (bond >= 0) { - ci = _bindInfo.Bonds[bond].UnpackIndex; + ci = _bindInfo.Bonds[(unsigned)bond].UnpackIndex; continue; } int si = _bindInfo.FindStream_in_PackStreams(outIndex); if (si >= 0) - _bindInfo.PackStreams.MoveToFront(si); + _bindInfo.PackStreams.MoveToFront((unsigned)si); break; } } diff --git a/CPP/7zip/Archive/7z/7zEncode.h b/CPP/7zip/Archive/7z/7zEncode.h index f1a9b5ad..6ea7f276 100644 --- a/CPP/7zip/Archive/7z/7zEncode.h +++ b/CPP/7zip/Archive/7z/7zEncode.h @@ -41,7 +41,7 @@ public: STDMETHOD(SetRatioInfo)(const UInt64 *inSize, const UInt64 *outSize); }; -class CEncoder +class CEncoder MY_UNCOPYABLE { #ifdef USE_MIXER_ST NCoderMixer2::CMixerST *_mixerST; diff --git a/CPP/7zip/Archive/7z/7zExtract.cpp b/CPP/7zip/Archive/7z/7zExtract.cpp index 9ffe2fdc..95eba9af 100644 --- a/CPP/7zip/Archive/7z/7zExtract.cpp +++ b/CPP/7zip/Archive/7z/7zExtract.cpp @@ -217,6 +217,10 @@ HRESULT CFolderOutStream::FlushCorrupted(Int32 callbackOperationResult) STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems, Int32 testModeSpec, IArchiveExtractCallback *extractCallbackSpec) { + // for GCC + // CFolderOutStream *folderOutStream = new CFolderOutStream; + // CMyComPtr<ISequentialOutStream> outStream(folderOutStream); + COM_TRY_BEGIN CMyComPtr<IArchiveExtractCallback> extractCallback = extractCallbackSpec; @@ -350,7 +354,7 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems, #ifndef _NO_CRYPTO bool isEncrypted = false; bool passwordIsDefined = false; - UString password; + UString_Wipe password; #endif @@ -411,7 +415,8 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems, { RINOK(folderOutStream->FlushCorrupted(NExtract::NOperationResult::kDataError)); // continue; - return E_FAIL; + // return E_FAIL; + throw; } } diff --git a/CPP/7zip/Archive/7z/7zHandler.cpp b/CPP/7zip/Archive/7z/7zHandler.cpp index bbb892e7..9e344c34 100644 --- a/CPP/7zip/Archive/7z/7zHandler.cpp +++ b/CPP/7zip/Archive/7z/7zHandler.cpp @@ -107,34 +107,62 @@ static void ConvertMethodIdToString(AString &res, UInt64 id) res += s + len - ConvertMethodIdToString_Back(s + len, id); } -static unsigned GetStringForSizeValue(char *s, UInt32 val) + +static char *GetStringForSizeValue(char *s, UInt32 val) { unsigned i; for (i = 0; i <= 31; i++) if (((UInt32)1 << i) == val) { - if (i < 10) + if (i >= 10) { - s[0] = (char)('0' + i); - s[1] = 0; - return 1; + *s++= (char)('0' + i / 10); + i %= 10; } - if (i < 20) { s[0] = '1'; s[1] = (char)('0' + i - 10); } - else if (i < 30) { s[0] = '2'; s[1] = (char)('0' + i - 20); } - else { s[0] = '3'; s[1] = (char)('0' + i - 30); } - s[2] = 0; - return 2; + *s++ = (char)('0' + i); + *s = 0; + return s; } + char c = 'b'; if ((val & ((1 << 20) - 1)) == 0) { val >>= 20; c = 'm'; } else if ((val & ((1 << 10) - 1)) == 0) { val >>= 10; c = 'k'; } - ::ConvertUInt32ToString(val, s); - unsigned pos = MyStringLen(s); - s[pos++] = c; - s[pos] = 0; - return pos; + s = ConvertUInt32ToString(val, s); + *s++ = c; + *s = 0; + return s; } + +static void GetLzma2String(char *s, unsigned d) +{ + if (d > 40) + { + *s = 0; + return; + // s = MyStpCpy(s, "unsup"); + } + else if ((d & 1) == 0) + d = (d >> 1) + 12; + else + { + // s = GetStringForSizeValue(s, (UInt32)3 << ((d >> 1) + 11)); + d = (d >> 1) + 1; + char c = 'k'; + if (d >= 10) + { + c = 'm'; + d -= 10; + } + s = ConvertUInt32ToString((UInt32)3 << d, s); + *s++ = c; + *s = 0; + return; + } + ConvertUInt32ToString(d, s); +} + + /* static inline void AddHexToString(UString &res, Byte value) { @@ -147,8 +175,7 @@ static char *AddProp32(char *s, const char *name, UInt32 v) { *s++ = ':'; s = MyStpCpy(s, name); - ::ConvertUInt32ToString(v, s); - return s + MyStringLen(s); + return ConvertUInt32ToString(v, s); } void CHandler::AddMethodName(AString &s, UInt64 id) @@ -184,10 +211,7 @@ STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value) if (id == k_LZMA2) { s += "LZMA2:"; - if ((pm.Lzma2Prop & 1) == 0) - ConvertUInt32ToString((pm.Lzma2Prop >> 1) + 12, temp); - else - GetStringForSizeValue(temp, 3 << ((pm.Lzma2Prop >> 1) + 11)); + GetLzma2String(temp, pm.Lzma2Prop); s += temp; } else if (id == k_LZMA) @@ -244,14 +268,13 @@ STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value) break; } } - prop.Detach(value); - return S_OK; + return prop.Detach(value); #ifndef _SFX COM_TRY_END #endif } -static void SetFileTimeProp_From_UInt64Def(PROPVARIANT *prop, const CUInt64DefVector &v, int index) +static void SetFileTimeProp_From_UInt64Def(PROPVARIANT *prop, const CUInt64DefVector &v, unsigned index) { UInt64 value; if (v.GetItem(index, value)) @@ -416,7 +439,7 @@ HRESULT CHandler::SetMethodToProp(CNum folderIndex, PROPVARIANT *prop) const if (propsSize == 5) { UInt32 dicSize = GetUi32((const Byte *)props + 1); - char *dest = s + GetStringForSizeValue(s, dicSize); + char *dest = GetStringForSizeValue(s, dicSize); UInt32 d = props[0]; if (d != 0x5D) { @@ -434,24 +457,16 @@ HRESULT CHandler::SetMethodToProp(CNum folderIndex, PROPVARIANT *prop) const { name = "LZMA2"; if (propsSize == 1) - { - Byte d = props[0]; - if ((d & 1) == 0) - ConvertUInt32ToString((UInt32)((d >> 1) + 12), s); - else - GetStringForSizeValue(s, 3 << ((d >> 1) + 11)); - } + GetLzma2String(s, props[0]); } else if (id == k_PPMD) { name = "PPMD"; if (propsSize == 5) { - Byte order = *props; char *dest = s; *dest++ = 'o'; - ConvertUInt32ToString(order, dest); - dest += MyStringLen(dest); + dest = ConvertUInt32ToString(*props, dest); dest = MyStpCpy(dest, ":mem"); GetStringForSizeValue(dest, GetUi32(props + 1)); } @@ -534,7 +549,7 @@ HRESULT CHandler::SetMethodToProp(CNum folderIndex, PROPVARIANT *prop) const STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *value) { - PropVariant_Clear(value); + RINOK(PropVariant_Clear(value)); // COM_TRY_BEGIN // NCOM::CPropVariant prop; @@ -637,7 +652,7 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val #endif } - // prop.Detach(value); + // return prop.Detach(value); return S_OK; // COM_TRY_END } @@ -708,7 +723,7 @@ STDMETHODIMP CHandler::Close() #ifndef _NO_CRYPTO _isEncrypted = false; _passwordIsDefined = false; - _password.Empty(); + _password.Wipe_and_Empty(); #endif return S_OK; COM_TRY_END diff --git a/CPP/7zip/Archive/7z/7zHandler.h b/CPP/7zip/Archive/7z/7zHandler.h index 99942eb0..cad1ae61 100644 --- a/CPP/7zip/Archive/7z/7zHandler.h +++ b/CPP/7zip/Archive/7z/7zHandler.h @@ -129,6 +129,10 @@ public: DECL_ISetCompressCodecsInfo CHandler(); + ~CHandler() + { + Close(); + } private: CMyComPtr<IInStream> _inStream; @@ -137,7 +141,7 @@ private: #ifndef _NO_CRYPTO bool _isEncrypted; bool _passwordIsDefined; - UString _password; + UString _password; // _Wipe #endif #ifdef EXTRACT_ONLY diff --git a/CPP/7zip/Archive/7z/7zHandlerOut.cpp b/CPP/7zip/Archive/7z/7zHandlerOut.cpp index b6be06a8..b549d94a 100644 --- a/CPP/7zip/Archive/7z/7zHandlerOut.cpp +++ b/CPP/7zip/Archive/7z/7zHandlerOut.cpp @@ -111,7 +111,7 @@ HRESULT CHandler::SetMainMethod( } const UInt64 kSolidBytes_Min = (1 << 24); - const UInt64 kSolidBytes_Max = ((UInt64)1 << 32) - 1; + const UInt64 kSolidBytes_Max = ((UInt64)1 << 32); bool needSolid = false; @@ -140,26 +140,52 @@ HRESULT CHandler::SetMainMethod( case k_LZMA2: dicSize = oneMethodInfo.Get_Lzma_DicSize(); break; case k_PPMD: dicSize = oneMethodInfo.Get_Ppmd_MemSize(); break; case k_Deflate: dicSize = (UInt32)1 << 15; break; + case k_Deflate64: dicSize = (UInt32)1 << 16; break; case k_BZip2: dicSize = oneMethodInfo.Get_BZip2_BlockSize(); break; default: continue; } - - _numSolidBytes = (UInt64)dicSize << 7; - if (_numSolidBytes < kSolidBytes_Min) _numSolidBytes = kSolidBytes_Min; - if (_numSolidBytes > kSolidBytes_Max) _numSolidBytes = kSolidBytes_Max; + + if (methodFull.Id == k_LZMA2) + { + // he we calculate default chunk Size for LZMA2 as defined in LZMA2 encoder code + UInt64 cs = (UInt64)dicSize << 2; + const UInt32 kMinSize = (UInt32)1 << 20; + const UInt32 kMaxSize = (UInt32)1 << 28; + if (cs < kMinSize) cs = kMinSize; + if (cs > kMaxSize) cs = kMaxSize; + if (cs < dicSize) cs = dicSize; + cs += (kMinSize - 1); + cs &= ~(UInt64)(kMinSize - 1); + // we want to use at least 64 chunks (threads) per one solid block. + _numSolidBytes = cs << 6; + const UInt64 kSolidBytes_Lzma2_Max = ((UInt64)1 << 34); + if (_numSolidBytes > kSolidBytes_Lzma2_Max) + _numSolidBytes = kSolidBytes_Lzma2_Max; + } + else + { + _numSolidBytes = (UInt64)dicSize << 7; + if (_numSolidBytes > kSolidBytes_Max) + _numSolidBytes = kSolidBytes_Max; + } + + if (_numSolidBytes < kSolidBytes_Min) + _numSolidBytes = kSolidBytes_Min; _numSolidBytesDefined = true; } if (!_numSolidBytesDefined) + { if (needSolid) _numSolidBytes = kSolidBytes_Max; else _numSolidBytes = 0; + } _numSolidBytesDefined = true; return S_OK; } -static HRESULT GetTime(IArchiveUpdateCallback *updateCallback, int index, PROPID propID, UInt64 &ft, bool &ftDefined) +static HRESULT GetTime(IArchiveUpdateCallback *updateCallback, unsigned index, PROPID propID, UInt64 &ft, bool &ftDefined) { // ft = 0; // ftDefined = false; @@ -289,8 +315,8 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numIt bool need_CTime = (Write_CTime.Def && Write_CTime.Val); bool need_ATime = (Write_ATime.Def && Write_ATime.Val); - bool need_MTime = (Write_MTime.Def && Write_MTime.Val || !Write_MTime.Def); - bool need_Attrib = (Write_Attrib.Def && Write_Attrib.Val || !Write_Attrib.Def); + bool need_MTime = (Write_MTime.Def ? Write_MTime.Val : true); + bool need_Attrib = (Write_Attrib.Def ? Write_Attrib.Val : true); if (db && !db->Files.IsEmpty()) { @@ -313,7 +339,7 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numIt CUpdateItem ui; ui.NewProps = IntToBool(newProps); ui.NewData = IntToBool(newData); - ui.IndexInArchive = indexInArchive; + ui.IndexInArchive = (int)indexInArchive; ui.IndexInClient = i; ui.IsAnti = false; ui.Size = 0; @@ -322,23 +348,23 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numIt // bool isAltStream = false; if (ui.IndexInArchive != -1) { - if (db == 0 || (unsigned)ui.IndexInArchive >= db->Files.Size()) + if (!db || (unsigned)ui.IndexInArchive >= db->Files.Size()) return E_INVALIDARG; - const CFileItem &fi = db->Files[ui.IndexInArchive]; + const CFileItem &fi = db->Files[(unsigned)ui.IndexInArchive]; if (!ui.NewProps) { - _db.GetPath(ui.IndexInArchive, name); + _db.GetPath((unsigned)ui.IndexInArchive, name); } ui.IsDir = fi.IsDir; ui.Size = fi.Size; // isAltStream = fi.IsAltStream; - ui.IsAnti = db->IsItemAnti(ui.IndexInArchive); + ui.IsAnti = db->IsItemAnti((unsigned)ui.IndexInArchive); if (!ui.NewProps) { - ui.CTimeDefined = db->CTime.GetItem(ui.IndexInArchive, ui.CTime); - ui.ATimeDefined = db->ATime.GetItem(ui.IndexInArchive, ui.ATime); - ui.MTimeDefined = db->MTime.GetItem(ui.IndexInArchive, ui.MTime); + ui.CTimeDefined = db->CTime.GetItem((unsigned)ui.IndexInArchive, ui.CTime); + ui.ATimeDefined = db->ATime.GetItem((unsigned)ui.IndexInArchive, ui.ATime); + ui.MTimeDefined = db->MTime.GetItem((unsigned)ui.IndexInArchive, ui.MTime); } } @@ -570,10 +596,10 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numIt updateCallback->QueryInterface(IID_ICryptoGetTextPassword2, (void **)&getPassword2); methodMode.PasswordIsDefined = false; - methodMode.Password.Empty(); + methodMode.Password.Wipe_and_Empty(); if (getPassword2) { - CMyComBSTR password; + CMyComBSTR_Wipe password; Int32 passwordIsDefined; RINOK(getPassword2->CryptoGetTextPassword2(&passwordIsDefined, &password)); methodMode.PasswordIsDefined = IntToBool(passwordIsDefined); @@ -751,7 +777,7 @@ HRESULT COutHandler::SetSolidFromString(const UString &s) _solidExtension = true; continue; } - i += (int)(end - start); + i += (unsigned)(end - start); if (i == s2.Len()) return E_INVALIDARG; wchar_t c = s2[i++]; @@ -829,7 +855,7 @@ HRESULT COutHandler::SetProperty(const wchar_t *nameSpec, const PROPVARIANT &val } UInt32 number; - int index = ParseStringToUInt32(name, number); + unsigned index = ParseStringToUInt32(name, number); // UString realName = name.Ptr(index); if (index == 0) { diff --git a/CPP/7zip/Archive/7z/7zHeader.h b/CPP/7zip/Archive/7z/7zHeader.h index d7f0ae36..e1bbc0aa 100644 --- a/CPP/7zip/Archive/7z/7zHeader.h +++ b/CPP/7zip/Archive/7z/7zHeader.h @@ -108,8 +108,9 @@ const UInt32 k_SWAP4 = 0x20304; const UInt32 k_LZMA = 0x30101; const UInt32 k_PPMD = 0x30401; -const UInt32 k_Deflate = 0x40108; -const UInt32 k_BZip2 = 0x40202; +const UInt32 k_Deflate = 0x40108; +const UInt32 k_Deflate64 = 0x40109; +const UInt32 k_BZip2 = 0x40202; const UInt32 k_BCJ = 0x3030103; const UInt32 k_BCJ2 = 0x303011B; diff --git a/CPP/7zip/Archive/7z/7zIn.cpp b/CPP/7zip/Archive/7z/7zIn.cpp index ab5b5de4..7134595c 100644 --- a/CPP/7zip/Archive/7z/7zIn.cpp +++ b/CPP/7zip/Archive/7z/7zIn.cpp @@ -11,6 +11,8 @@ #include "../../../../C/7zCrc.h" #include "../../../../C/CpuArch.h" +// #include "../../../Common/UTFConvert.h" + #include "../../Common/StreamObjects.h" #include "../../Common/StreamUtils.h" @@ -32,6 +34,7 @@ using namespace NCOM; namespace NArchive { namespace N7z { +unsigned BoolVector_CountSum(const CBoolVector &v); unsigned BoolVector_CountSum(const CBoolVector &v) { unsigned sum = 0; @@ -59,9 +62,13 @@ static void BoolVector_Fill_False(CBoolVector &v, unsigned size) class CInArchiveException {}; class CUnsupportedFeatureException: public CInArchiveException {}; +MY_ATTR_NORETURN static void ThrowException() { throw CInArchiveException(); } +MY_ATTR_NORETURN static inline void ThrowEndOfData() { ThrowException(); } +MY_ATTR_NORETURN static inline void ThrowUnsupported() { throw CUnsupportedFeatureException(); } +MY_ATTR_NORETURN static inline void ThrowIncorrect() { ThrowException(); } class CStreamSwitch @@ -328,7 +335,7 @@ HRESULT CInArchive::FindAndReadSignature(IInStream *stream, const UInt64 *search { memcpy(_header, p, kHeaderSize); _arhiveBeginStreamPosition += offset + pos; - return stream->Seek(_arhiveBeginStreamPosition + kHeaderSize, STREAM_SEEK_SET, NULL); + return stream->Seek((Int64)(_arhiveBeginStreamPosition + kHeaderSize), STREAM_SEEK_SET, NULL); } } @@ -344,7 +351,7 @@ HRESULT CInArchive::Open(IInStream *stream, const UInt64 *searchHeaderSizeLimit) Close(); RINOK(stream->Seek(0, STREAM_SEEK_CUR, &_arhiveBeginStreamPosition)) RINOK(stream->Seek(0, STREAM_SEEK_END, &_fileEndPosition)) - RINOK(stream->Seek(_arhiveBeginStreamPosition, STREAM_SEEK_SET, NULL)) + RINOK(stream->Seek((Int64)_arhiveBeginStreamPosition, STREAM_SEEK_SET, NULL)) RINOK(FindAndReadSignature(stream, searchHeaderSizeLimit)); _stream = stream; return S_OK; @@ -478,7 +485,7 @@ void CDatabase::GetPath(unsigned index, UString &path) const #if defined(_WIN32) && defined(MY_CPU_LE) - wmemcpy(s, (const wchar_t *)p, size); + wmemcpy(s, (const wchar_t *)(const void *)p, size); #else @@ -506,10 +513,27 @@ HRESULT CDatabase::GetPath_Prop(unsigned index, PROPVARIANT *path) const throw() if (size >= (1 << 14)) return S_OK; - RINOK(PropVarEm_Alloc_Bstr(path, (unsigned)size - 1)); + // (size) includes null terminator + + /* + #if WCHAR_MAX > 0xffff + + const Byte *p = ((const Byte *)NamesBuf + offset * 2); + size = Utf16LE__Get_Num_WCHARs(p, size - 1); + // (size) doesn't include null terminator + RINOK(PropVarEm_Alloc_Bstr(path, (unsigned)size)); wchar_t *s = path->bstrVal; + wchar_t *sEnd = Utf16LE__To_WCHARs_Sep(p, size, s); + *sEnd = 0; + if (s + size != sEnd) return E_FAIL; + #else + */ + + RINOK(PropVarEm_Alloc_Bstr(path, (unsigned)size - 1)); + wchar_t *s = path->bstrVal; const Byte *p = ((const Byte *)NamesBuf + offset * 2); + // Utf16LE__To_WCHARs_Sep(p, size, s); for (size_t i = 0; i < size; i++) { @@ -518,10 +542,14 @@ HRESULT CDatabase::GetPath_Prop(unsigned index, PROPVARIANT *path) const throw() #if WCHAR_PATH_SEPARATOR != L'/' if (c == L'/') c = WCHAR_PATH_SEPARATOR; + else if (c == L'\\') + c = WCHAR_IN_FILE_NAME_BACKSLASH_REPLACEMENT; // WSL scheme #endif *s++ = c; } + // #endif + return S_OK; /* @@ -673,7 +701,7 @@ void CInArchive::ReadUnpackInfo( { UInt32 indexOfMainStream = 0; UInt32 numPackStreams = 0; - folders.FoCodersDataOffset[fo] = _inByteBack->GetPtr() - startBufPtr; + folders.FoCodersDataOffset[fo] = (size_t)(_inByteBack->GetPtr() - startBufPtr); CNum numInStreams = 0; CNum numCoders = inByte->ReadNum(); @@ -794,10 +822,10 @@ void CInArchive::ReadUnpackInfo( folders.FoToMainUnpackSizeIndex[fo] = (Byte)indexOfMainStream; } - size_t dataSize = _inByteBack->GetPtr() - startBufPtr; + const size_t dataSize = (size_t)(_inByteBack->GetPtr() - startBufPtr); folders.FoToCoderUnpackSizes[fo] = numCodersOutStreams; folders.FoStartPackStreamIndex[fo] = packStreamIndex; - folders.FoCodersDataOffset[fo] = _inByteBack->GetPtr() - startBufPtr; + folders.FoCodersDataOffset[fo] = (size_t)(_inByteBack->GetPtr() - startBufPtr); folders.CodersData.CopyFrom(startBufPtr, dataSize); // if (folders.NumPackStreams != packStreamIndex) ThrowUnsupported(); @@ -962,6 +990,8 @@ void CInArchive::ReadSubStreamsInfo( } } + + void CInArchive::ReadStreamsInfo( const CObjectVector<CByteBuffer> *dataVector, UInt64 &dataOffset, @@ -974,7 +1004,11 @@ void CInArchive::ReadStreamsInfo( if (type == NID::kPackInfo) { dataOffset = ReadNumber(); + if (dataOffset > _rangeLimit) + ThrowIncorrect(); ReadPackInfo(folders); + if (folders.PackPositions[folders.NumPackStreams] > _rangeLimit - dataOffset) + ThrowIncorrect(); type = ReadID(); } @@ -1029,7 +1063,7 @@ void CInArchive::ReadBoolVector(unsigned numItems, CBoolVector &v) mask = 0x80; } p[i] = ((b & mask) != 0); - mask >>= 1; + mask = (Byte)(mask >> 1); } } @@ -1090,8 +1124,8 @@ HRESULT CInArchive::ReadAndDecodePackedStreams( for (CNum i = 0; i < folders.NumFolders; i++) { CByteBuffer &data = dataVector.AddNew(); - UInt64 unpackSize64 = folders.GetFolderUnpackSize(i); - size_t unpackSize = (size_t)unpackSize64; + const UInt64 unpackSize64 = folders.GetFolderUnpackSize(i); + const size_t unpackSize = (size_t)unpackSize64; if (unpackSize != unpackSize64) ThrowUnsupported(); data.Alloc(unpackSize); @@ -1106,7 +1140,7 @@ HRESULT CInArchive::ReadAndDecodePackedStreams( EXTERNAL_CODECS_LOC_VARS _stream, baseOffset + dataOffset, folders, i, - NULL, // *unpackSize + NULL, // &unpackSize64 outStream, NULL, // *compressProgress @@ -1127,6 +1161,9 @@ HRESULT CInArchive::ReadAndDecodePackedStreams( if (dataAfterEnd_Error) ThereIsHeaderError = true; + if (unpackSize != outStreamSpec->GetPos()) + ThrowIncorrect(); + if (folders.FolderCRCs.ValidAndDefined(i)) if (CrcCalc(data, unpackSize) != folders.FolderCRCs.Vals[i]) ThrowIncorrect(); @@ -1226,8 +1263,8 @@ HRESULT CInArchive::ReadHeader( unsigned i; for (i = 0; i < numFiles; i++) { - size_t curRem = (rem - pos) / 2; - const UInt16 *buf = (const UInt16 *)(db.NamesBuf + pos); + const size_t curRem = (rem - pos) / 2; + const UInt16 *buf = (const UInt16 *)(const void *)(db.NamesBuf + pos); size_t j; for (j = 0; j < curRem && buf[j] != 0; j++); if (j == curRem) @@ -1519,13 +1556,13 @@ HRESULT CInArchive::ReadDatabase2( const unsigned kCheckSize = 512; Byte buf[kCheckSize]; RINOK(_stream->Seek(0, STREAM_SEEK_END, &fileSize)); - UInt64 rem = fileSize - cur; + const UInt64 rem = fileSize - cur; unsigned checkSize = kCheckSize; if (rem < kCheckSize) checkSize = (unsigned)(rem); if (checkSize < 3) return S_FALSE; - RINOK(_stream->Seek(fileSize - checkSize, STREAM_SEEK_SET, NULL)); + RINOK(_stream->Seek((Int64)(fileSize - checkSize), STREAM_SEEK_SET, NULL)); RINOK(ReadStream_FALSE(_stream, buf, (size_t)checkSize)); if (buf[checkSize - 1] != 0) @@ -1534,8 +1571,8 @@ HRESULT CInArchive::ReadDatabase2( unsigned i; for (i = checkSize - 2;; i--) { - if (buf[i] == NID::kEncodedHeader && buf[i + 1] == NID::kPackInfo || - buf[i] == NID::kHeader && buf[i + 1] == NID::kMainStreamsInfo) + if ((buf[i] == NID::kEncodedHeader && buf[i + 1] == NID::kPackInfo) || + (buf[i] == NID::kHeader && buf[i + 1] == NID::kMainStreamsInfo)) break; if (i == 0) return S_FALSE; @@ -1543,7 +1580,7 @@ HRESULT CInArchive::ReadDatabase2( nextHeaderSize = checkSize - i; nextHeaderOffset = rem - nextHeaderSize; nextHeaderCRC = CrcCalc(buf + i, (size_t)nextHeaderSize); - RINOK(_stream->Seek(cur, STREAM_SEEK_SET, NULL)); + RINOK(_stream->Seek((Int64)cur, STREAM_SEEK_SET, NULL)); db.StartHeaderWasRecovered = true; } else @@ -1560,25 +1597,32 @@ HRESULT CInArchive::ReadDatabase2( if ((Int64)nextHeaderOffset < 0 || nextHeaderSize > ((UInt64)1 << 62)) return S_FALSE; + + HeadersSize = kHeaderSize; + if (nextHeaderSize == 0) { if (nextHeaderOffset != 0) return S_FALSE; db.IsArc = true; + db.HeadersSize = HeadersSize; return S_OK; } if (!db.StartHeaderWasRecovered) db.IsArc = true; - HeadersSize += kHeaderSize + nextHeaderSize; + HeadersSize += nextHeaderSize; + // db.EndHeaderOffset = nextHeaderOffset; + _rangeLimit = nextHeaderOffset; + db.PhySize = kHeaderSize + nextHeaderOffset + nextHeaderSize; if (_fileEndPosition - db.ArcInfo.StartPositionAfterHeader < nextHeaderOffset + nextHeaderSize) { db.UnexpectedEnd = true; return S_FALSE; } - RINOK(_stream->Seek(nextHeaderOffset, STREAM_SEEK_CUR, NULL)); + RINOK(_stream->Seek((Int64)nextHeaderOffset, STREAM_SEEK_CUR, NULL)); size_t nextHeaderSize_t = (size_t)nextHeaderSize; if (nextHeaderSize_t != nextHeaderSize) diff --git a/CPP/7zip/Archive/7z/7zIn.h b/CPP/7zip/Archive/7z/7zIn.h index 6a61d314..ffa1e4bc 100644 --- a/CPP/7zip/Archive/7z/7zIn.h +++ b/CPP/7zip/Archive/7z/7zIn.h @@ -174,13 +174,14 @@ struct CDatabase: public CFolders HRESULT GetPath_Prop(unsigned index, PROPVARIANT *path) const throw(); }; + struct CInArchiveInfo { CArchiveVersion Version; - UInt64 StartPosition; - UInt64 StartPositionAfterHeader; - UInt64 DataStartPosition; - UInt64 DataStartPosition2; + UInt64 StartPosition; // in stream + UInt64 StartPositionAfterHeader; // in stream + UInt64 DataStartPosition; // in stream + UInt64 DataStartPosition2; // in stream. it's for headers CRecordVector<UInt64> FileInfoPopIDs; void Clear() @@ -193,6 +194,7 @@ struct CInArchiveInfo } }; + struct CDbEx: public CDatabase { CInArchiveInfo ArcInfo; @@ -202,6 +204,7 @@ struct CDbEx: public CDatabase UInt64 HeadersSize; UInt64 PhySize; + // UInt64 EndHeaderOffset; // relative to position after StartHeader (32 bytes) /* CRecordVector<size_t> SecureOffsets; @@ -255,6 +258,7 @@ struct CDbEx: public CDatabase HeadersSize = 0; PhySize = 0; + // EndHeaderOffset = 0; } bool CanUpdate() const @@ -349,6 +353,8 @@ class CInArchive UInt64 _arhiveBeginStreamPosition; UInt64 _fileEndPosition; + UInt64 _rangeLimit; // relative to position after StartHeader (32 bytes) + Byte _header[kHeaderSize]; UInt64 HeadersSize; diff --git a/CPP/7zip/Archive/7z/7zItem.h b/CPP/7zip/Archive/7z/7zItem.h index ee4aed3f..0f9fdada 100644 --- a/CPP/7zip/Archive/7z/7zItem.h +++ b/CPP/7zip/Archive/7z/7zItem.h @@ -50,7 +50,7 @@ public: { FOR_VECTOR(i, PackStreams) if (PackStreams[i] == packStream) - return i; + return (int)i; return -1; } @@ -58,7 +58,7 @@ public: { FOR_VECTOR(i, Bonds) if (Bonds[i].PackIndex == packStream) - return i; + return (int)i; return -1; } diff --git a/CPP/7zip/Archive/7z/7zOut.cpp b/CPP/7zip/Archive/7z/7zOut.cpp index aa977292..2786bf28 100644 --- a/CPP/7zip/Archive/7z/7zOut.cpp +++ b/CPP/7zip/Archive/7z/7zOut.cpp @@ -5,6 +5,7 @@ #include "../../../../C/7zCrc.h" #include "../../../Common/AutoPtr.h" +// #include "../../../Common/UTFConvert.h" #include "../../Common/StreamObjects.h" @@ -196,7 +197,7 @@ void COutArchive::WriteNumber(UInt64 value) break; } firstByte |= mask; - mask >>= 1; + mask = (Byte)(mask >> 1); } WriteByte(firstByte); for (; i > 0; i--) @@ -206,9 +207,9 @@ void COutArchive::WriteNumber(UInt64 value) } } -static UInt32 GetBigNumberSize(UInt64 value) +static unsigned GetBigNumberSize(UInt64 value) { - int i; + unsigned i; for (i = 1; i < 9; i++) if (value < (((UInt64)1 << (i * 7)))) break; @@ -264,18 +265,18 @@ void COutArchive::WriteFolder(const CFolder &folder) for (idSize = 1; idSize < sizeof(id); idSize++) if ((id >> (8 * idSize)) == 0) break; - idSize &= 0xF; + // idSize &= 0xF; // idSize is smaller than 16 already Byte temp[16]; for (unsigned t = idSize; t != 0; t--, id >>= 8) temp[t] = (Byte)(id & 0xFF); - Byte b = (Byte)(idSize); - bool isComplex = !coder.IsSimpleCoder(); + unsigned b = idSize; + const bool isComplex = !coder.IsSimpleCoder(); b |= (isComplex ? 0x10 : 0); - size_t propsSize = coder.Props.Size(); + const size_t propsSize = coder.Props.Size(); b |= ((propsSize != 0) ? 0x20 : 0); - temp[0] = b; + temp[0] = (Byte)b; WriteBytes(temp, idSize + 1); if (isComplex) { @@ -309,7 +310,7 @@ void COutArchive::WriteBoolVector(const CBoolVector &boolVector) { if (boolVector[i]) b |= mask; - mask >>= 1; + mask = (Byte)(mask >> 1); if (mask == 0) { WriteByte(b); @@ -476,7 +477,7 @@ void COutArchive::WriteAlignedBools(const CBoolVector &v, unsigned numDefined, B { const unsigned bvSize = (numDefined == v.Size()) ? 0 : Bv_GetSizeInBytes(v); const UInt64 dataSize = ((UInt64)numDefined << itemSizeShifts) + bvSize + 2; - SkipToAligned(3 + (unsigned)bvSize + (unsigned)GetBigNumberSize(dataSize), itemSizeShifts); + SkipToAligned(3 + bvSize + GetBigNumberSize(dataSize), itemSizeShifts); WriteByte(type); WriteNumber(dataSize); @@ -545,7 +546,39 @@ void COutArchive::WriteHeader( WriteByte(NID::kHeader); - // Archive Properties + /* + { + // It's example for per archive properies writing + + WriteByte(NID::kArchiveProperties); + + // you must use random 40-bit number that will identify you + // then you can use same kDeveloperID for any properties and methods + const UInt64 kDeveloperID = 0x123456789A; // change that value to real random 40-bit number + + #define GENERATE_7Z_ID(developerID, subID) (((UInt64)0x3F << 56) | ((UInt64)developerID << 16) | subID) + + { + const UInt64 kSubID = 0x1; // you can use small number for subID + const UInt64 kID = GENERATE_7Z_ID(kDeveloperID, kSubID); + WriteNumber(kID); + const unsigned kPropsSize = 3; // it's example size + WriteNumber(kPropsSize); + for (unsigned i = 0; i < kPropsSize; i++) + WriteByte((Byte)(i & 0xFF)); + } + { + const UInt64 kSubID = 0x2; // you can use small number for subID + const UInt64 kID = GENERATE_7Z_ID(kDeveloperID, kSubID); + WriteNumber(kID); + const unsigned kPropsSize = 5; // it's example size + WriteNumber(kPropsSize); + for (unsigned i = 0; i < kPropsSize; i++) + WriteByte((Byte)(i + 16)); + } + WriteByte(NID::kEnd); + } + */ if (db.Folders.Size() > 0) { @@ -637,7 +670,15 @@ void COutArchive::WriteHeader( const UString &name = db.Names[i]; if (!name.IsEmpty()) numDefined++; - namesDataSize += (name.Len() + 1) * 2; + const size_t numUtfChars = + /* + #if WCHAR_MAX > 0xffff + Get_Num_Utf16_chars_from_wchar_string(name.Ptr()); + #else + */ + name.Len(); + // #endif + namesDataSize += (numUtfChars + 1) * 2; } if (numDefined > 0) @@ -654,6 +695,25 @@ void COutArchive::WriteHeader( for (unsigned t = 0; t <= name.Len(); t++) { wchar_t c = name[t]; + + /* + #if WCHAR_MAX > 0xffff + if (c >= 0x10000) + { + c -= 0x10000; + if (c < (1 << 20)) + { + unsigned c0 = 0xd800 + ((c >> 10) & 0x3FF); + WriteByte((Byte)c0); + WriteByte((Byte)(c0 >> 8)); + c = 0xdc00 + (c & 0x3FF); + } + else + c = '_'; // we change character unsupported by UTF16 + } + #endif + */ + WriteByte((Byte)c); WriteByte((Byte)(c >> 8)); } @@ -855,7 +915,7 @@ HRESULT COutArchive::WriteDatabase( h.NextHeaderSize = headerSize; h.NextHeaderCRC = headerCRC; h.NextHeaderOffset = headerOffset; - RINOK(Stream->Seek(_prefixHeaderPos, STREAM_SEEK_SET, NULL)); + RINOK(Stream->Seek((Int64)_prefixHeaderPos, STREAM_SEEK_SET, NULL)); return WriteStartHeader(h); } } diff --git a/CPP/7zip/Archive/7z/7zUpdate.cpp b/CPP/7zip/Archive/7z/7zUpdate.cpp index 6705fc00..b641d93f 100644 --- a/CPP/7zip/Archive/7z/7zUpdate.cpp +++ b/CPP/7zip/Archive/7z/7zUpdate.cpp @@ -55,8 +55,8 @@ struct CFilterMode #define PE_SIG 0x00004550 #define PE_OptHeader_Magic_32 0x10B #define PE_OptHeader_Magic_64 0x20B -#define PE_SectHeaderSize 40 -#define PE_SECT_EXECUTE 0x20000000 +// #define PE_SectHeaderSize 40 +// #define PE_SECT_EXECUTE 0x20000000 static int Parse_EXE(const Byte *buf, size_t size, CFilterMode *filterMode) { @@ -254,10 +254,12 @@ static BoolInt Parse_WAV(const Byte *buf, size_t size, CFilterMode *filterMode) if (subChunkSize < 0x10 || subChunkSize > 0x12 || GetUi16(buf + 0x14) != 1) return False; - unsigned numChannels = GetUi16(buf + 0x16); - unsigned bitsPerSample = GetUi16(buf + 0x22); - - if ((bitsPerSample & 0x7) != 0 || bitsPerSample >= 256 || numChannels >= 256) + const unsigned numChannels = GetUi16(buf + 0x16); + const unsigned bitsPerSample = GetUi16(buf + 0x22); + if ((bitsPerSample & 0x7) != 0) + return False; + const UInt32 delta = (UInt32)numChannels * (bitsPerSample >> 3); + if (delta == 0 || delta > 256) return False; pos = 0x14 + subChunkSize; @@ -271,9 +273,6 @@ static BoolInt Parse_WAV(const Byte *buf, size_t size, CFilterMode *filterMode) subChunkSize = GetUi32(buf + pos + 4); if (GetUi32(buf + pos) == WAV_SUBCHUNK_data) { - unsigned delta = numChannels * (bitsPerSample >> 3); - if (delta >= 256) - return False; filterMode->Id = k_Delta; filterMode->Delta = delta; return True; @@ -418,7 +417,7 @@ static unsigned Get_FilterGroup_for_Folder( static HRESULT WriteRange(IInStream *inStream, ISequentialOutStream *outStream, UInt64 position, UInt64 size, ICompressProgressInfo *progress) { - RINOK(inStream->Seek(position, STREAM_SEEK_SET, 0)); + RINOK(inStream->Seek((Int64)position, STREAM_SEEK_SET, 0)); CLimitedSequentialInStream *streamSpec = new CLimitedSequentialInStream; CMyComPtr<CLimitedSequentialInStream> inStreamLimited(streamSpec); streamSpec->SetStream(inStream); @@ -642,13 +641,13 @@ struct CRefItem if (sortByType) { int slashPos = ui.Name.ReverseFind_PathSepar(); - NamePos = slashPos + 1; + NamePos = (unsigned)(slashPos + 1); int dotPos = ui.Name.ReverseFind_Dot(); if (dotPos <= slashPos) ExtensionPos = ui.Name.Len(); else { - ExtensionPos = dotPos + 1; + ExtensionPos = (unsigned)(dotPos + 1); if (ExtensionPos != ui.Name.Len()) { AString s; @@ -836,7 +835,7 @@ HRESULT CAnalysis::GetFilterGroup(UInt32 index, const CUpdateItem &ui, CFilterMo { const wchar_t *ext; if (dotPos > slashPos) - ext = ui.Name.Ptr(dotPos + 1); + ext = ui.Name.Ptr((unsigned)(dotPos + 1)); else ext = ui.Name.RightPtr(0); @@ -1071,12 +1070,12 @@ static HRESULT MakeExeMethod(CCompressionMethodMode &mode, if (alignBits != 0) { if (alignBits > 2 || filterMode.Id == k_Delta) - nextMethod.AddProp32(NCoderPropID::kPosStateBits, alignBits); + nextMethod.AddProp32(NCoderPropID::kPosStateBits, (unsigned)alignBits); unsigned lc = 0; if (alignBits < 3) - lc = 3 - alignBits; + lc = (unsigned)(3 - alignBits); nextMethod.AddProp32(NCoderPropID::kLitContextBits, lc); - nextMethod.AddProp32(NCoderPropID::kLitPosBits, alignBits); + nextMethod.AddProp32(NCoderPropID::kLitPosBits, (unsigned)alignBits); } } } @@ -1453,7 +1452,7 @@ public: UInt64 StartPos; const CFolders *Folders; - int FolderIndex; + unsigned FolderIndex; // bool send_UnpackSize; // UInt64 UnpackSize; @@ -1609,7 +1608,10 @@ HRESULT Update( CRecordVector<CFilterMode2> filters; CObjectVector<CSolidGroup> groups; + + #ifndef _7ZIP_ST bool thereAreRepacks = false; + #endif bool useFilters = options.UseFilters; if (useFilters) @@ -1636,7 +1638,7 @@ HRESULT Update( { int index = updateItems[i].IndexInArchive; if (index != -1) - fileIndexToUpdateIndexMap[(unsigned)index] = i; + fileIndexToUpdateIndexMap[(unsigned)index] = (int)i; } for (i = 0; i < db->NumFolders; i++) @@ -1656,7 +1658,7 @@ HRESULT Update( { indexInFolder++; int updateIndex = fileIndexToUpdateIndexMap[fi]; - if (updateIndex >= 0 && !updateItems[updateIndex].NewData) + if (updateIndex >= 0 && !updateItems[(unsigned)updateIndex].NewData) { numCopyItems++; repackSize += file.Size; @@ -1688,7 +1690,9 @@ HRESULT Update( complexity += db->GetFolderFullPackSize(i); else { + #ifndef _7ZIP_ST thereAreRepacks = true; + #endif complexity += repackSize; if (inSizeForReduce2 < repackSize) inSizeForReduce2 = repackSize; @@ -1727,10 +1731,12 @@ HRESULT Update( #ifndef _7ZIP_ST CStreamBinder sb; + /* if (options.MultiThreadMixer) { RINOK(sb.CreateEvents()); } + */ #endif @@ -1742,7 +1748,9 @@ HRESULT Update( #ifdef EXTERNAL_CODECS threadDecoder.__externalCodecs = __externalCodecs; #endif - RINOK(threadDecoder.Create()); + WRes wres = threadDecoder.Create(); + if (wres != 0) + return HRESULT_FROM_WIN32(wres); } #endif @@ -1887,7 +1895,7 @@ HRESULT Update( if (ui.HasStream()) continue; } - else if (ui.IndexInArchive != -1 && db->Files[ui.IndexInArchive].HasStream) + else if (ui.IndexInArchive != -1 && db->Files[(unsigned)ui.IndexInArchive].HasStream) continue; /* if (ui.TreeFolderIndex >= 0) @@ -1912,8 +1920,8 @@ HRESULT Update( } else { - GetFile(*db, ui.IndexInArchive, file, file2); - db->GetPath(ui.IndexInArchive, name); + GetFile(*db, (unsigned)ui.IndexInArchive, file, file2); + db->GetPath((unsigned)ui.IndexInArchive, name); } /* @@ -2065,7 +2073,7 @@ HRESULT Update( { indexInFolder++; int updateIndex = fileIndexToUpdateIndexMap[fi]; - if (updateIndex >= 0 && !updateItems[updateIndex].NewData) + if (updateIndex >= 0 && !updateItems[(unsigned)updateIndex].NewData) needExtract = true; // decodeSize += file.Size; } @@ -2099,8 +2107,8 @@ HRESULT Update( { repackBase = threadDecoder.FosSpec; CMyComPtr<ISequentialOutStream> sbOutStream; - sb.CreateStreams(&sbInStream, &sbOutStream); - sb.ReInit(); + sb.CreateStreams2(sbInStream, sbOutStream); + RINOK(sb.Create_ReInit()); threadDecoder.FosSpec->_stream = sbOutStream; @@ -2171,7 +2179,9 @@ HRESULT Update( #ifndef _7ZIP_ST if (options.MultiThreadMixer) { - threadDecoder.Start(); + WRes wres = threadDecoder.Start(); + if (wres != 0) + return HRESULT_FROM_WIN32(wres); } #endif } @@ -2197,7 +2207,11 @@ HRESULT Update( inStreamSizeCount.Release(); sbInStream.Release(); - threadDecoder.WaitExecuteFinish(); + { + WRes wres = threadDecoder.WaitExecuteFinish(); + if (wres != 0) + return HRESULT_FROM_WIN32(wres); + } HRESULT decodeRes = threadDecoder.Result; // if (res == k_My_HRESULT_CRC_ERROR) @@ -2259,7 +2273,7 @@ HRESULT Update( int updateIndex = fileIndexToUpdateIndexMap[fi]; if (updateIndex >= 0) { - const CUpdateItem &ui = updateItems[updateIndex]; + const CUpdateItem &ui = updateItems[(unsigned)updateIndex]; if (ui.NewData) continue; @@ -2347,7 +2361,7 @@ HRESULT Update( { int slashPos = ui.Name.ReverseFind_PathSepar(); int dotPos = ui.Name.ReverseFind_Dot(); - const wchar_t *ext = ui.Name.Ptr(dotPos <= slashPos ? ui.Name.Len() : dotPos + 1); + const wchar_t *ext = ui.Name.Ptr(dotPos <= slashPos ? ui.Name.Len() : (unsigned)(dotPos + 1)); if (numSubFiles == 0) prevExtension = ext; else if (!StringsAreEqualNoCase(ext, prevExtension)) @@ -2403,8 +2417,8 @@ HRESULT Update( } else { - GetFile(*db, ui.IndexInArchive, file, file2); - db->GetPath(ui.IndexInArchive, name); + GetFile(*db, (unsigned)ui.IndexInArchive, file, file2); + db->GetPath((unsigned)ui.IndexInArchive, name); } if (file2.IsAnti || file.IsDir) return E_FAIL; diff --git a/CPP/7zip/Archive/7z/7zUpdate.h b/CPP/7zip/Archive/7z/7zUpdate.h index a7abf779..7c0f78a8 100644 --- a/CPP/7zip/Archive/7z/7zUpdate.h +++ b/CPP/7zip/Archive/7z/7zUpdate.h @@ -31,7 +31,7 @@ struct CTreeFolder struct CUpdateItem { int IndexInArchive; - int IndexInClient; + unsigned IndexInClient; UInt64 CTime; UInt64 ATime; diff --git a/CPP/7zip/Archive/ApmHandler.cpp b/CPP/7zip/Archive/ApmHandler.cpp index 4d3f2728..73e5fcb6 100644 --- a/CPP/7zip/Archive/ApmHandler.cpp +++ b/CPP/7zip/Archive/ApmHandler.cpp @@ -240,7 +240,7 @@ STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value) mainIndex = -1; break; } - mainIndex = i; + mainIndex = (int)i; } } if (mainIndex >= 0) diff --git a/CPP/7zip/Archive/ArHandler.cpp b/CPP/7zip/Archive/ArHandler.cpp index 09a62201..0bea8b4e 100644 --- a/CPP/7zip/Archive/ArHandler.cpp +++ b/CPP/7zip/Archive/ArHandler.cpp @@ -618,13 +618,15 @@ STDMETHODIMP CHandler::Open(IInStream *stream, _items.DeleteFrontal(1); for (unsigned i = 0; i < _items.Size(); i++) if (_items[i].Name.IsPrefixedBy("data.tar.")) + { if (_mainSubfile < 0) - _mainSubfile = i; + _mainSubfile = (int)i; else { _mainSubfile = -1; break; } + } } else { @@ -845,7 +847,7 @@ STDMETHODIMP CHandler::GetStream(UInt32 index, ISequentialInStream **stream) } REGISTER_ARC_I( - "Ar", "ar a deb lib", 0, 0xEC, + "Ar", "ar a deb udeb lib", 0, 0xEC, kSignature, 0, 0, diff --git a/CPP/7zip/Archive/ArchiveExports.cpp b/CPP/7zip/Archive/ArchiveExports.cpp index 28e9946d..6549b3d2 100644 --- a/CPP/7zip/Archive/ArchiveExports.cpp +++ b/CPP/7zip/Archive/ArchiveExports.cpp @@ -46,7 +46,7 @@ static inline HRESULT SetPropGUID(const GUID &guid, PROPVARIANT *value) return SetPropStrFromBin((const char *)&guid, sizeof(guid), value); } -int FindFormatCalssId(const GUID *clsid) +static int FindFormatCalssId(const GUID *clsid) { GUID cls = *clsid; CLS_ARC_ID_ITEM(cls) = 0; @@ -59,6 +59,7 @@ int FindFormatCalssId(const GUID *clsid) return -1; } +STDAPI CreateArchiver(const GUID *clsid, const GUID *iid, void **outObject); STDAPI CreateArchiver(const GUID *clsid, const GUID *iid, void **outObject) { COM_TRY_BEGIN @@ -89,6 +90,7 @@ STDAPI CreateArchiver(const GUID *clsid, const GUID *iid, void **outObject) return S_OK; } +STDAPI GetHandlerProperty2(UInt32 formatIndex, PROPID propID, PROPVARIANT *value); STDAPI GetHandlerProperty2(UInt32 formatIndex, PROPID propID, PROPVARIANT *value) { COM_TRY_BEGIN @@ -130,17 +132,20 @@ STDAPI GetHandlerProperty2(UInt32 formatIndex, PROPID propID, PROPVARIANT *value COM_TRY_END } +STDAPI GetHandlerProperty(PROPID propID, PROPVARIANT *value); STDAPI GetHandlerProperty(PROPID propID, PROPVARIANT *value) { return GetHandlerProperty2(g_DefaultArcIndex, propID, value); } +STDAPI GetNumberOfFormats(UINT32 *numFormats); STDAPI GetNumberOfFormats(UINT32 *numFormats) { *numFormats = g_NumArcs; return S_OK; } +STDAPI GetIsArc(UInt32 formatIndex, Func_IsArc *isArc); STDAPI GetIsArc(UInt32 formatIndex, Func_IsArc *isArc) { *isArc = NULL; diff --git a/CPP/7zip/Archive/ArjHandler.cpp b/CPP/7zip/Archive/ArjHandler.cpp index fb9e3e7a..0e353dca 100644 --- a/CPP/7zip/Archive/ArjHandler.cpp +++ b/CPP/7zip/Archive/ArjHandler.cpp @@ -235,13 +235,13 @@ namespace NFileType namespace NFlags { const Byte kGarbled = 1 << 0; - const Byte kAnsiPage = 1 << 1; // or (OLD_SECURED_FLAG) obsolete + // const Byte kAnsiPage = 1 << 1; // or (OLD_SECURED_FLAG) obsolete const Byte kVolume = 1 << 2; const Byte kExtFile = 1 << 3; - const Byte kPathSym = 1 << 4; - const Byte kBackup = 1 << 5; // obsolete - const Byte kSecured = 1 << 6; - const Byte kDualName = 1 << 7; + // const Byte kPathSym = 1 << 4; + // const Byte kBackup = 1 << 5; // obsolete + // const Byte kSecured = 1 << 6; + // const Byte kDualName = 1 << 7; } namespace NHostOS @@ -375,6 +375,32 @@ HRESULT CArcHeader::Parse(const Byte *p, unsigned size) return S_OK; } + +struct CExtendedInfo +{ + UInt64 Size; + bool CrcError; + + void Clear() + { + Size = 0; + CrcError = false; + } + void ParseToPropVar(NCOM::CPropVariant &prop) const + { + if (Size != 0) + { + AString s; + s += "Extended:"; + s.Add_UInt32((UInt32)Size); + if (CrcError) + s += ":CRC_ERROR"; + prop = s; + } + } +}; + + struct CItem { AString Name; @@ -399,6 +425,8 @@ struct CItem // Byte LastChapter; UInt64 DataPosition; + + CExtendedInfo ExtendedInfo; bool IsEncrypted() const { return (Flags & NFlags::kGarbled) != 0; } bool IsDir() const { return (FileType == NFileType::kDirectory); } @@ -462,7 +490,7 @@ enum EErrorType { k_ErrorType_OK, k_ErrorType_Corrupted, - k_ErrorType_UnexpectedEnd, + k_ErrorType_UnexpectedEnd }; class CArc @@ -476,19 +504,22 @@ public: UInt64 NumFiles; CArcHeader Header; + CExtendedInfo ExtendedInfo; + HRESULT Open(); HRESULT GetNextItem(CItem &item, bool &filled); void Close() { IsArc = false; Error = k_ErrorType_OK; + ExtendedInfo.Clear(); } private: - UInt32 _blockSize; - Byte _block[kBlockSizeMax + 4]; + unsigned _blockSize; + CByteBuffer _block; - HRESULT ReadBlock(bool &filled, bool readSignature); - HRESULT SkipExtendedHeaders(); + HRESULT ReadBlock(bool &filled, CExtendedInfo *extendedInfo); + HRESULT SkipExtendedHeaders(CExtendedInfo &extendedInfo); HRESULT Read(void *data, size_t *size); }; @@ -503,14 +534,14 @@ HRESULT CArc::Read(void *data, size_t *size) { size_t _processed_ = (_size_); RINOK(Read(_dest_, &_processed_)); \ if (_processed_ != (_size_)) { Error = k_ErrorType_UnexpectedEnd; return S_OK; } } -HRESULT CArc::ReadBlock(bool &filled, bool readSignature) +HRESULT CArc::ReadBlock(bool &filled, CExtendedInfo *extendedInfo) { Error = k_ErrorType_OK; filled = false; Byte buf[4]; - unsigned signSize = readSignature ? 2 : 0; + const unsigned signSize = extendedInfo ? 0 : 2; READ_STREAM(buf, signSize + 2) - if (readSignature) + if (!extendedInfo) if (buf[0] != kSig0 || buf[1] != kSig1) { Error = k_ErrorType_Corrupted; @@ -519,28 +550,48 @@ HRESULT CArc::ReadBlock(bool &filled, bool readSignature) _blockSize = Get16(buf + signSize); if (_blockSize == 0) // end of archive return S_OK; - if (_blockSize < kBlockSizeMin || - _blockSize > kBlockSizeMax) + + if (!extendedInfo) + if (_blockSize < kBlockSizeMin || _blockSize > kBlockSizeMax) + { + Error = k_ErrorType_Corrupted; + return S_OK; + } + + const size_t readSize = _blockSize + 4; + if (readSize > _block.Size()) { - Error = k_ErrorType_Corrupted; - return S_OK; + // extended data size is limited by (64 KB) + // _blockSize is less than 64 KB + const size_t upSize = (_blockSize > kBlockSizeMax ? (1 << 16) : kBlockSizeMax); + _block.Alloc(upSize + 4); } - READ_STREAM(_block, _blockSize + 4); + + if (extendedInfo) + extendedInfo->Size += _blockSize; + + READ_STREAM(_block, readSize); if (Get32(_block + _blockSize) != CrcCalc(_block, _blockSize)) { - Error = k_ErrorType_Corrupted; - return S_OK; + if (extendedInfo) + extendedInfo->CrcError = true; + else + { + Error = k_ErrorType_Corrupted; + return S_OK; + } } filled = true; return S_OK; } -HRESULT CArc::SkipExtendedHeaders() +HRESULT CArc::SkipExtendedHeaders(CExtendedInfo &extendedInfo) { + extendedInfo.Clear(); for (UInt32 i = 0;; i++) { bool filled; - RINOK(ReadBlock(filled, false)); + RINOK(ReadBlock(filled, &extendedInfo)); if (!filled) return S_OK; if (Callback && (i & 0xFF) == 0) @@ -551,17 +602,17 @@ HRESULT CArc::SkipExtendedHeaders() HRESULT CArc::Open() { bool filled; - RINOK(ReadBlock(filled, true)); + RINOK(ReadBlock(filled, NULL)); // (extendedInfo = NULL) if (!filled) return S_FALSE; RINOK(Header.Parse(_block, _blockSize)); IsArc = true; - return SkipExtendedHeaders(); + return SkipExtendedHeaders(ExtendedInfo); } HRESULT CArc::GetNextItem(CItem &item, bool &filled) { - RINOK(ReadBlock(filled, true)); + RINOK(ReadBlock(filled, NULL)); // (extendedInfo = NULL) if (!filled) return S_OK; filled = false; @@ -576,7 +627,7 @@ HRESULT CArc::GetNextItem(CItem &item, bool &filled) extraData = GetUi32(_block + pos); */ - RINOK(SkipExtendedHeaders()); + RINOK(SkipExtendedHeaders(item.ExtendedInfo)); filled = true; return S_OK; } @@ -603,7 +654,8 @@ static const Byte kArcProps[] = kpidCTime, kpidMTime, kpidHostOS, - kpidComment + kpidComment, + kpidCharacts }; static const Byte kProps[] = @@ -619,7 +671,8 @@ static const Byte kProps[] = kpidCRC, kpidMethod, kpidHostOS, - kpidComment + kpidComment, + kpidCharacts }; IMP_IInArchive_Props @@ -671,10 +724,14 @@ STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value) { case k_ErrorType_UnexpectedEnd: v |= kpv_ErrorFlags_UnexpectedEnd; break; case k_ErrorType_Corrupted: v |= kpv_ErrorFlags_HeadersError; break; + case k_ErrorType_OK: + default: + break; } prop = v; break; } + case kpidCharacts: _arc.ExtendedInfo.ParseToPropVar(prop); break; } prop.Detach(value); return S_OK; @@ -706,6 +763,7 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val case kpidHostOS: SetHostOS(item.HostOS, prop); break; case kpidMTime: SetTime(item.MTime, prop); break; case kpidComment: SetUnicodeString(item.Comment, prop); break; + case kpidCharacts: item.ExtendedInfo.ParseToPropVar(prop); break; } prop.Detach(value); return S_OK; diff --git a/CPP/7zip/Archive/Base64Handler.cpp b/CPP/7zip/Archive/Base64Handler.cpp new file mode 100644 index 00000000..63b4552e --- /dev/null +++ b/CPP/7zip/Archive/Base64Handler.cpp @@ -0,0 +1,511 @@ +// Base64Handler.cpp + +#include "StdAfx.h" + +#include "../../../C/CpuArch.h" + +#include "../../Common/ComTry.h" +#include "../../Common/MyBuffer.h" +#include "../../Common/IntToString.h" +#include "../../Common/MyVector.h" + +#include "../../Windows/PropVariant.h" + +#include "../Common/ProgressUtils.h" +#include "../Common/RegisterArc.h" +#include "../Common/StreamUtils.h" +#include "../Common/InBuffer.h" + +/* +spaces: + 9(TAB),10(LF),13(CR),32(SPACE) + Non-breaking space: + 0xa0 : Unicode, Windows code pages 1250-1258 + 0xff (unused): DOS code pages + +end of stream markers: '=' (0x3d): + "=" , if numBytes (% 3 == 2) + "==" , if numBytes (% 3 == 1) +*/ + + +static const Byte k_Base64Table[256] = +{ + 66,77,77,77,77,77,77,77,77,65,65,77,77,65,77,77, + 77,77,77,77,77,77,77,77,77,77,77,77,77,77,77,77, + 65,77,77,77,77,77,77,77,77,77,77,62,77,77,77,63, + 52,53,54,55,56,57,58,59,60,61,77,77,77,64,77,77, + 77, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10,11,12,13,14, + 15,16,17,18,19,20,21,22,23,24,25,77,77,77,77,77, + 77,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40, + 41,42,43,44,45,46,47,48,49,50,51,77,77,77,77,77, + 77,77,77,77,77,77,77,77,77,77,77,77,77,77,77,77, + 77,77,77,77,77,77,77,77,77,77,77,77,77,77,77,77, + 65,77,77,77,77,77,77,77,77,77,77,77,77,77,77,77, + 77,77,77,77,77,77,77,77,77,77,77,77,77,77,77,77, + 77,77,77,77,77,77,77,77,77,77,77,77,77,77,77,77, + 77,77,77,77,77,77,77,77,77,77,77,77,77,77,77,77, + 77,77,77,77,77,77,77,77,77,77,77,77,77,77,77,77, + 77,77,77,77,77,77,77,77,77,77,77,77,77,77,77,77 +}; + +static const unsigned k_Code_Equals = 64; +static const unsigned k_Code_Space = 65; +static const unsigned k_Code_Zero = 66; + +API_FUNC_static_IsArc IsArc_Base64(const Byte *p, size_t size) +{ + size_t num = 0; + size_t firstSpace = 0; + + for (;;) + { + if (size == 0) + return k_IsArc_Res_NEED_MORE; + UInt32 c = k_Base64Table[(Byte)(*p++)]; + size--; + if (c < 64) + { + num++; + continue; + } + + if (c == k_Code_Space) + { + if (p[-1] == ' ' && firstSpace == 0) + firstSpace = num; + continue; + } + + if (c != k_Code_Equals) + return k_IsArc_Res_NO; + break; + } + + { + // we try to redece false positive detection here. + // we don't expect space character in starting base64 line + const unsigned kNumExpectedNonSpaceSyms = 20; + if (firstSpace != 0 && firstSpace < num && firstSpace < kNumExpectedNonSpaceSyms) + return k_IsArc_Res_NO; + } + + num &= 3; + + if (num <= 1) + return k_IsArc_Res_NO; + if (num != 3) + { + if (size == 0) + return k_IsArc_Res_NEED_MORE; + UInt32 c = k_Base64Table[(Byte)(*p++)]; + size--; + if (c != k_Code_Equals) + return k_IsArc_Res_NO; + } + + for (;;) + { + if (size == 0) + return k_IsArc_Res_YES; + UInt32 c = k_Base64Table[(Byte)(*p++)]; + size--; + if (c == k_Code_Space) + continue; + return k_IsArc_Res_NO; + } +} +} + + +enum EBase64Res +{ + k_Base64_RES_MaybeFinished, + k_Base64_RES_Finished, + k_Base64_RES_NeedMoreInput, + k_Base64_RES_UnexpectedChar +}; + + +static EBase64Res Base64ToBin(Byte *p, size_t size, const Byte **srcEnd, Byte **destEnd) +{ + Byte *dest = p; + UInt32 val = 1; + EBase64Res res = k_Base64_RES_NeedMoreInput; + + for (;;) + { + if (size == 0) + { + if (val == 1) + res = k_Base64_RES_MaybeFinished; + break; + } + UInt32 c = k_Base64Table[(Byte)(*p++)]; + size--; + if (c < 64) + { + val = (val << 6) | c; + if ((val & ((UInt32)1 << 24)) == 0) + continue; + dest[0] = (Byte)(val >> 16); + dest[1] = (Byte)(val >> 8); + dest[2] = (Byte)(val); + dest += 3; + val = 1; + continue; + } + + if (c == k_Code_Space) + continue; + + if (c == k_Code_Equals) + { + if (val >= (1 << 12)) + { + if (val & (1 << 18)) + { + res = k_Base64_RES_Finished; + break; + } + if (size == 0) + break; + c = k_Base64Table[(Byte)(*p++)]; + size--; + if (c == k_Code_Equals) + { + res = k_Base64_RES_Finished; + break; + } + } + } + + p--; + res = k_Base64_RES_UnexpectedChar; + break; + } + + if (val >= ((UInt32)1 << 12)) + { + if (val & (1 << 18)) + { + *dest++ = (Byte)(val >> 10); + val <<= 2; + } + *dest++ = (Byte)(val >> 4); + } + + *srcEnd = p; + *destEnd = dest; + return res; +} + + +static const Byte *Base64_SkipSpaces(const Byte *p, size_t size) +{ + for (;;) + { + if (size == 0) + return p; + UInt32 c = k_Base64Table[(Byte)(*p++)]; + size--; + if (c == k_Code_Space) + continue; + return p - 1; + } +} + + +// the following function is used by DmgHandler.cpp + +Byte *Base64ToBin(Byte *dest, const char *src); +Byte *Base64ToBin(Byte *dest, const char *src) +{ + UInt32 val = 1; + + for (;;) + { + UInt32 c = k_Base64Table[(Byte)(*src++)]; + + if (c < 64) + { + val = (val << 6) | c; + if ((val & ((UInt32)1 << 24)) == 0) + continue; + dest[0] = (Byte)(val >> 16); + dest[1] = (Byte)(val >> 8); + dest[2] = (Byte)(val); + dest += 3; + val = 1; + continue; + } + + if (c == k_Code_Space) + continue; + + if (c == k_Code_Equals) + break; + + if (c == k_Code_Zero && val == 1) // end of string + return dest; + + return NULL; + } + + if (val < (1 << 12)) + return NULL; + + if (val & (1 << 18)) + { + *dest++ = (Byte)(val >> 10); + val <<= 2; + } + else if (k_Base64Table[(Byte)(*src++)] != k_Code_Equals) + return NULL; + *dest++ = (Byte)(val >> 4); + + for (;;) + { + Byte c = k_Base64Table[(Byte)(*src++)]; + if (c == k_Code_Space) + continue; + if (c == k_Code_Zero) + return dest; + return NULL; + } +} + + +namespace NArchive { +namespace NBase64 { + +class CHandler: + public IInArchive, + public CMyUnknownImp +{ + bool _isArc; + UInt64 _phySize; + size_t _size; + EBase64Res _sres; + CByteBuffer _data; +public: + MY_UNKNOWN_IMP1(IInArchive) + INTERFACE_IInArchive(;) +}; + +static const Byte kProps[] = +{ + kpidSize, + kpidPackSize, +}; + +IMP_IInArchive_Props +IMP_IInArchive_ArcProps_NO_Table + +STDMETHODIMP CHandler::GetNumberOfItems(UInt32 *numItems) +{ + *numItems = 1; + return S_OK; +} + +STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value) +{ + NWindows::NCOM::CPropVariant prop; + switch (propID) + { + case kpidPhySize: if (_phySize != 0) prop = _phySize; break; + case kpidErrorFlags: + { + UInt32 v = 0; + if (!_isArc) v |= kpv_ErrorFlags_IsNotArc; + if (_sres == k_Base64_RES_NeedMoreInput) v |= kpv_ErrorFlags_UnexpectedEnd; + if (v != 0) + prop = v; + break; + } + } + prop.Detach(value); + return S_OK; +} + +STDMETHODIMP CHandler::GetProperty(UInt32 /* index */, PROPID propID, PROPVARIANT *value) +{ + // COM_TRY_BEGIN + NWindows::NCOM::CPropVariant prop; + switch (propID) + { + case kpidSize: prop = (UInt64)_size; break; + case kpidPackSize: prop = _phySize; break; + } + prop.Detach(value); + return S_OK; + // COM_TRY_END +} + + +static HRESULT ReadStream_OpenProgress(ISequentialInStream *stream, void *data, size_t size, IArchiveOpenCallback *openCallback) throw() +{ + UInt64 bytes = 0; + while (size != 0) + { + const UInt32 kBlockSize = ((UInt32)1 << 24); + UInt32 curSize = (size < kBlockSize) ? (UInt32)size : kBlockSize; + UInt32 processedSizeLoc; + RINOK(stream->Read(data, curSize, &processedSizeLoc)); + if (processedSizeLoc == 0) + return E_FAIL; + data = (void *)((Byte *)data + processedSizeLoc); + size -= processedSizeLoc; + bytes += processedSizeLoc; + const UInt64 files = 1; + RINOK(openCallback->SetCompleted(&files, &bytes)); + } + return S_OK; +} + + +STDMETHODIMP CHandler::Open(IInStream *stream, const UInt64 *, IArchiveOpenCallback *openCallback) +{ + COM_TRY_BEGIN + { + Close(); + { + const unsigned kStartSize = 1 << 12; + _data.Alloc(kStartSize); + size_t size = kStartSize; + RINOK(ReadStream(stream, _data, &size)); + UInt32 isArcRes = IsArc_Base64(_data, size); + if (isArcRes == k_IsArc_Res_NO) + return S_FALSE; + } + _isArc = true; + + UInt64 packSize64; + RINOK(stream->Seek(0, STREAM_SEEK_END, &packSize64)); + + if (packSize64 == 0) + return S_FALSE; + + size_t curSize = 1 << 16; + if (curSize > packSize64) + curSize = (size_t)packSize64; + const unsigned kLogStep = 4; + + for (;;) + { + RINOK(stream->Seek(0, STREAM_SEEK_SET, NULL)); + + _data.Alloc(curSize); + RINOK(ReadStream_OpenProgress(stream, _data, curSize, openCallback)); + + const Byte *srcEnd; + Byte *dest; + _sres = Base64ToBin(_data, curSize, &srcEnd, &dest); + _size = dest - _data; + size_t mainSize = srcEnd - _data; + _phySize = mainSize; + if (_sres == k_Base64_RES_UnexpectedChar) + break; + if (curSize != mainSize) + { + const Byte *end2 = Base64_SkipSpaces(srcEnd, curSize - mainSize); + if ((size_t)(end2 - _data) != curSize) + break; + _phySize = curSize; + } + + if (curSize == packSize64) + break; + + UInt64 curSize64 = packSize64; + if (curSize < (packSize64 >> kLogStep)) + curSize64 = (UInt64)curSize << kLogStep; + curSize = (size_t)curSize64; + if (curSize != curSize64) + return E_OUTOFMEMORY; + } + if (_size == 0) + return S_FALSE; + return S_OK; + } + COM_TRY_END +} + +STDMETHODIMP CHandler::Close() +{ + _phySize = 0; + _size = 0; + _isArc = false; + _sres = k_Base64_RES_MaybeFinished; + _data.Free(); + return S_OK; +} + + +STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems, + Int32 testMode, IArchiveExtractCallback *extractCallback) +{ + COM_TRY_BEGIN + bool allFilesMode = (numItems == (UInt32)(Int32)-1); + if (allFilesMode) + numItems = 1; + if (numItems == 0) + return S_OK; + if (numItems != 1 || *indices != 0) + return E_INVALIDARG; + + RINOK(extractCallback->SetTotal(_size)); + + CLocalProgress *lps = new CLocalProgress; + CMyComPtr<ICompressProgressInfo> progress = lps; + lps->Init(extractCallback, false); + + { + lps->InSize = lps->OutSize = 0; + RINOK(lps->SetCur()); + + CMyComPtr<ISequentialOutStream> realOutStream; + Int32 askMode = testMode ? + NExtract::NAskMode::kTest : + NExtract::NAskMode::kExtract; + + RINOK(extractCallback->GetStream(0, &realOutStream, askMode)); + + if (!testMode && !realOutStream) + return S_OK; + + extractCallback->PrepareOperation(askMode); + + if (realOutStream) + { + RINOK(WriteStream(realOutStream, (const Byte *)_data, _size)); + realOutStream.Release(); + } + + Int32 opRes = NExtract::NOperationResult::kOK; + + if (_sres != k_Base64_RES_Finished) + { + if (_sres == k_Base64_RES_NeedMoreInput) + opRes = NExtract::NOperationResult::kUnexpectedEnd; + else if (_sres == k_Base64_RES_UnexpectedChar) + opRes = NExtract::NOperationResult::kDataError; + } + + RINOK(extractCallback->SetOperationResult(opRes)); + } + + lps->InSize = _phySize; + lps->OutSize = _size; + return lps->SetCur(); + + COM_TRY_END +} + +REGISTER_ARC_I_NO_SIG( + "Base64", "b64", 0, 0xC5, + 0, + NArcInfoFlags::kKeepName | NArcInfoFlags::kStartOpen | NArcInfoFlags::kByExtOnlyOpen, + IsArc_Base64) + +}} diff --git a/CPP/7zip/Archive/Cab/CabHandler.cpp b/CPP/7zip/Archive/Cab/CabHandler.cpp index 4395ae1a..9f50d3aa 100644 --- a/CPP/7zip/Archive/Cab/CabHandler.cpp +++ b/CPP/7zip/Archive/Cab/CabHandler.cpp @@ -309,11 +309,14 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val case kpidMethod: { - UInt32 realFolderIndex = item.GetFolderIndex(db.Folders.Size()); - const CFolder &folder = db.Folders[realFolderIndex]; - char s[kMethodNameBufSize];; - SetMethodName(s, folder.GetMethod(), folder.MethodMinor); - prop = s; + const int realFolderIndex = item.GetFolderIndex(db.Folders.Size()); + if (realFolderIndex >= 0) + { + const CFolder &folder = db.Folders[(unsigned)realFolderIndex]; + char s[kMethodNameBufSize];; + SetMethodName(s, folder.GetMethod(), folder.MethodMinor); + prop = s; + } break; } @@ -341,7 +344,8 @@ STDMETHODIMP CHandler::Open(IInStream *inStream, CInArchive archive; CMyComPtr<IArchiveOpenVolumeCallback> openVolumeCallback; - callback->QueryInterface(IID_IArchiveOpenVolumeCallback, (void **)&openVolumeCallback); + if (callback) + callback->QueryInterface(IID_IArchiveOpenVolumeCallback, (void **)&openVolumeCallback); CMyComPtr<IInStream> nextStream = inStream; bool prevChecked = false; @@ -420,7 +424,10 @@ STDMETHODIMP CHandler::Open(IInStream *inStream, } } - RINOK(callback->SetCompleted(&numItems, NULL)); + if (callback) + { + RINOK(callback->SetCompleted(&numItems, NULL)); + } nextStream = NULL; @@ -1007,7 +1014,7 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems, continue; } - unsigned startIndex2 = m_Database.FolderStartFileIndex[folderIndex]; + const unsigned startIndex2 = m_Database.FolderStartFileIndex[(unsigned)folderIndex]; unsigned startIndex = startIndex2; extractStatuses.Clear(); for (; startIndex < index; startIndex++) @@ -1037,8 +1044,10 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems, CFolderOutStream *cabFolderOutStream = new CFolderOutStream; CMyComPtr<ISequentialOutStream> outStream(cabFolderOutStream); - unsigned folderIndex2 = item.GetFolderIndex(db.Folders.Size()); - const CFolder &folder = db.Folders[folderIndex2]; + const int folderIndex2 = item.GetFolderIndex(db.Folders.Size()); + if (folderIndex2 < 0) + return E_FAIL; + const CFolder &folder = db.Folders[(unsigned)folderIndex2]; cabFolderOutStream->Init(&m_Database, &extractStatuses, startIndex2, curUnpack, extractCallback, testMode); @@ -1107,12 +1116,14 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems, } const CDatabaseEx &db2 = m_Database.Volumes[volIndex]; - const CFolder &folder2 = db2.Folders[locFolderIndex]; + if (locFolderIndex < 0) + return E_FAIL; + const CFolder &folder2 = db2.Folders[(unsigned)locFolderIndex]; if (bl == 0) { cabBlockInStreamSpec->ReservedSize = db2.ArcInfo.GetDataBlockReserveSize(); - RINOK(db2.Stream->Seek(db2.StartPosition + folder2.DataStart, STREAM_SEEK_SET, NULL)); + RINOK(db2.Stream->Seek((Int64)(db2.StartPosition + folder2.DataStart), STREAM_SEEK_SET, NULL)); } if (bl == folder2.NumDataBlocks) @@ -1242,7 +1253,7 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems, if (res != S_OK || cabFolderOutStream->NeedMoreWrite()) { - RINOK(cabFolderOutStream->FlushCorrupted(folderIndex2)); + RINOK(cabFolderOutStream->FlushCorrupted((unsigned)folderIndex2)); } totalUnPacked += curUnpack; diff --git a/CPP/7zip/Archive/Cab/CabIn.cpp b/CPP/7zip/Archive/Cab/CabIn.cpp index ca0052bf..e11ce9d0 100644 --- a/CPP/7zip/Archive/Cab/CabIn.cpp +++ b/CPP/7zip/Archive/Cab/CabIn.cpp @@ -114,8 +114,8 @@ HRESULT CSignatureFinder::Find() Byte b = Signature[0]; for (;;) { - if (*p == b) break; p++; - if (*p == b) break; p++; + if (*p == b) { break; } p++; + if (*p == b) { break; } p++; } Pos = (UInt32)(p - Buf); if (End - Pos < _HeaderSize) @@ -311,7 +311,7 @@ HRESULT CInArchive::Open2(CDatabaseEx &db, const UInt64 *searchHeaderSizeLimit) { // printf("\n!!! Seek Error !!!!\n"); // fflush(stdout); - RINOK(db.Stream->Seek(db.StartPosition + ai.FileHeadersOffset, STREAM_SEEK_SET, NULL)); + RINOK(db.Stream->Seek((Int64)(db.StartPosition + ai.FileHeadersOffset), STREAM_SEEK_SET, NULL)); limitedStreamSpec->Init(ai.Size - ai.FileHeadersOffset); _inBuffer.Init(); } diff --git a/CPP/7zip/Archive/Cab/CabIn.h b/CPP/7zip/Archive/Cab/CabIn.h index a1fc6bdc..39586d12 100644 --- a/CPP/7zip/Archive/Cab/CabIn.h +++ b/CPP/7zip/Archive/Cab/CabIn.h @@ -100,7 +100,7 @@ struct CDatabase int GetNumberOfNewFolders() const { - int res = Folders.Size(); + int res = (int)Folders.Size(); if (IsTherePrevFolder()) res--; return res; diff --git a/CPP/7zip/Archive/Cab/CabItem.h b/CPP/7zip/Archive/Cab/CabItem.h index 9b513202..9a912d5e 100644 --- a/CPP/7zip/Archive/Cab/CabItem.h +++ b/CPP/7zip/Archive/Cab/CabItem.h @@ -56,8 +56,8 @@ struct CItem if (ContinuedFromPrev()) return 0; if (ContinuedToNext()) - return numFolders - 1; - return FolderIndex; + return (int)numFolders - 1; + return (int)FolderIndex; } }; diff --git a/CPP/7zip/Archive/Chm/ChmHandler.cpp b/CPP/7zip/Archive/Chm/ChmHandler.cpp index 7ffdafe0..03e7ddd2 100644 --- a/CPP/7zip/Archive/Chm/ChmHandler.cpp +++ b/CPP/7zip/Archive/Chm/ChmHandler.cpp @@ -145,10 +145,12 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val case kpidMethod: { if (!item.IsDir()) + { if (item.Section == 0) prop = "Copy"; else if (item.Section < m_Database.Sections.Size()) prop = m_Database.Sections[(unsigned)item.Section].GetMethodName(); + } break; } case kpidBlock: diff --git a/CPP/7zip/Archive/Chm/ChmIn.cpp b/CPP/7zip/Archive/Chm/ChmIn.cpp index 7e3f155b..f4916b68 100644 --- a/CPP/7zip/Archive/Chm/ChmIn.cpp +++ b/CPP/7zip/Archive/Chm/ChmIn.cpp @@ -13,7 +13,6 @@ #include "ChmIn.h" -#define Get16(p) GetUi16(p) #define Get32(p) GetUi32(p) #define Get64(p) GetUi64(p) @@ -117,7 +116,7 @@ UString CSectionInfo::GetMethodName() const if (!IsLzx()) { UString temp; - if (ConvertUTF8ToUnicode(Name, temp)) + ConvertUTF8ToUnicode(Name, temp); s += temp; s += ": "; } diff --git a/CPP/7zip/Archive/ComHandler.cpp b/CPP/7zip/Archive/ComHandler.cpp index d2dc6c5f..a1f643b7 100644 --- a/CPP/7zip/Archive/ComHandler.cpp +++ b/CPP/7zip/Archive/ComHandler.cpp @@ -36,7 +36,7 @@ enum EType k_Type_Msp, k_Type_Doc, k_Type_Ppt, - k_Type_Xls, + k_Type_Xls }; static const char * const kExtensions[] = @@ -51,10 +51,10 @@ static const char * const kExtensions[] = namespace NFatID { - static const UInt32 kFree = 0xFFFFFFFF; + // static const UInt32 kFree = 0xFFFFFFFF; static const UInt32 kEndOfChain = 0xFFFFFFFE; - static const UInt32 kFatSector = 0xFFFFFFFD; - static const UInt32 kMatSector = 0xFFFFFFFC; + // static const UInt32 kFatSector = 0xFFFFFFFD; + // static const UInt32 kMatSector = 0xFFFFFFFC; static const UInt32 kMaxValue = 0xFFFFFFFA; } @@ -62,9 +62,9 @@ namespace NItemType { static const Byte kEmpty = 0; static const Byte kStorage = 1; - static const Byte kStream = 2; - static const Byte kLockBytes = 3; - static const Byte kProperty = 4; + // static const Byte kStream = 2; + // static const Byte kLockBytes = 3; + // static const Byte kProperty = 4; static const Byte kRootStorage = 5; } @@ -298,7 +298,7 @@ static bool CompoundMsiNameToFileName(const UString &name, UString &res) for (unsigned i = 0; i < name.Len(); i++) { wchar_t c = name[i]; - if (c < k_Msi_StartUnicodeChar || c > k_Msi_StartUnicodeChar + k_Msi_UnicodeRange) + if (c < (wchar_t)k_Msi_StartUnicodeChar || c > (wchar_t)(k_Msi_StartUnicodeChar + k_Msi_UnicodeRange)) return false; /* if (i == 0) @@ -578,11 +578,10 @@ HRESULT CDatabase::Open(IInStream *inStream) { // bool isThereExt = (msiName.Find(L'.') >= 0); bool isMsiSpec = (msiName[0] == k_Msi_SpecChar); - if (msiName.Len() >= 4 && StringsAreEqualNoCase_Ascii(msiName.RightPtr(4), ".cab") - || !isMsiSpec && msiName.Len() >= 3 && StringsAreEqualNoCase_Ascii(msiName.RightPtr(3), "exe") - // || !isMsiSpec && !isThereExt + if ((msiName.Len() >= 4 && StringsAreEqualNoCase_Ascii(msiName.RightPtr(4), ".cab")) + || (!isMsiSpec && msiName.Len() >= 3 && StringsAreEqualNoCase_Ascii(msiName.RightPtr(3), "exe")) + // || (!isMsiSpec && !isThereExt) ) - { numCabs++; MainSubfile = i; diff --git a/CPP/7zip/Archive/Common/CoderMixer2.cpp b/CPP/7zip/Archive/Common/CoderMixer2.cpp index c7002121..c8b67bd4 100644 --- a/CPP/7zip/Archive/Common/CoderMixer2.cpp +++ b/CPP/7zip/Archive/Common/CoderMixer2.cpp @@ -137,7 +137,7 @@ bool CBondsChecks::CheckCoder(unsigned coderIndex) return false; _coderUsed[coderIndex] = true; - UInt32 start = BindInfo->Coder_to_Stream[coderIndex]; + const UInt32 start = BindInfo->Coder_to_Stream[coderIndex]; for (unsigned i = 0; i < coder.NumStreams; i++) { @@ -146,10 +146,10 @@ bool CBondsChecks::CheckCoder(unsigned coderIndex) if (BindInfo->IsStream_in_PackStreams(ind)) continue; - int bond = BindInfo->FindBond_for_PackStream(ind); + const int bond = BindInfo->FindBond_for_PackStream(ind); if (bond < 0) return false; - if (!CheckCoder(BindInfo->Bonds[bond].UnpackIndex)) + if (!CheckCoder(BindInfo->Bonds[(unsigned)bond].UnpackIndex)) return false; } @@ -246,15 +246,15 @@ bool CMixer::Is_UnpackSize_Correct_for_Coder(UInt32 coderIndex) if (coderIndex == _bi.UnpackCoder) return true; - int bond = _bi.FindBond_for_UnpackStream(coderIndex); + const int bond = _bi.FindBond_for_UnpackStream(coderIndex); if (bond < 0) throw 20150213; /* UInt32 coderIndex, coderStreamIndex; - _bi.GetCoder_for_Stream(_bi.Bonds[bond].PackIndex, coderIndex, coderStreamIndex); + _bi.GetCoder_for_Stream(_bi.Bonds[(unsigned)bond].PackIndex, coderIndex, coderStreamIndex); */ - UInt32 nextCoder = _bi.Stream_to_Coder[_bi.Bonds[bond].PackIndex]; + const UInt32 nextCoder = _bi.Stream_to_Coder[_bi.Bonds[(unsigned)bond].PackIndex]; if (!IsFilter_Vector[nextCoder]) return false; @@ -267,11 +267,11 @@ bool CMixer::Is_PackSize_Correct_for_Stream(UInt32 streamIndex) if (_bi.IsStream_in_PackStreams(streamIndex)) return true; - int bond = _bi.FindBond_for_PackStream(streamIndex); + const int bond = _bi.FindBond_for_PackStream(streamIndex); if (bond < 0) throw 20150213; - UInt32 nextCoder = _bi.Bonds[bond].UnpackIndex; + const UInt32 nextCoder = _bi.Bonds[(unsigned)bond].UnpackIndex; if (!IsFilter_Vector[nextCoder]) return false; @@ -281,8 +281,8 @@ bool CMixer::Is_PackSize_Correct_for_Stream(UInt32 streamIndex) bool CMixer::Is_PackSize_Correct_for_Coder(UInt32 coderIndex) { - UInt32 startIndex = _bi.Coder_to_Stream[coderIndex]; - UInt32 numStreams = _bi.Coders[coderIndex].NumStreams; + const UInt32 startIndex = _bi.Coder_to_Stream[coderIndex]; + const UInt32 numStreams = _bi.Coders[coderIndex].NumStreams; for (UInt32 i = 0; i < numStreams; i++) if (!Is_PackSize_Correct_for_Stream(startIndex + i)) return false; @@ -293,19 +293,19 @@ bool CMixer::IsThere_ExternalCoder_in_PackTree(UInt32 coderIndex) { if (IsExternal_Vector[coderIndex]) return true; - UInt32 startIndex = _bi.Coder_to_Stream[coderIndex]; - UInt32 numStreams = _bi.Coders[coderIndex].NumStreams; + const UInt32 startIndex = _bi.Coder_to_Stream[coderIndex]; + const UInt32 numStreams = _bi.Coders[coderIndex].NumStreams; for (UInt32 i = 0; i < numStreams; i++) { - UInt32 si = startIndex + i; + const UInt32 si = startIndex + i; if (_bi.IsStream_in_PackStreams(si)) continue; - int bond = _bi.FindBond_for_PackStream(si); + const int bond = _bi.FindBond_for_PackStream(si); if (bond < 0) throw 20150213; - if (IsThere_ExternalCoder_in_PackTree(_bi.Bonds[bond].UnpackIndex)) + if (IsThere_ExternalCoder_in_PackTree(_bi.Bonds[(unsigned)bond].UnpackIndex)) return true; } return false; @@ -360,7 +360,7 @@ CCoder &CMixerST::GetCoder(unsigned index) return _coders[index]; } -void CMixerST::ReInit() {} +HRESULT CMixerST::ReInit2() { return S_OK; } HRESULT CMixerST::GetInStream2( ISequentialInStream * const *inStreams, /* const UInt64 * const *inSizes, */ @@ -444,18 +444,18 @@ HRESULT CMixerST::GetInStream( } } - int bond = FindBond_for_Stream( + const int bond = FindBond_for_Stream( true, // forInputStream inStreamIndex); if (bond < 0) return E_INVALIDARG; RINOK(GetInStream2(inStreams, /* inSizes, */ - _bi.Bonds[bond].Get_OutIndex(EncodeMode), &seqInStream)); + _bi.Bonds[(unsigned)bond].Get_OutIndex(EncodeMode), &seqInStream)); while (_binderStreams.Size() <= (unsigned)bond) _binderStreams.AddNew(); - CStBinderStream &bs = _binderStreams[bond]; + CStBinderStream &bs = _binderStreams[(unsigned)bond]; if (bs.StreamRef || bs.InStreamSpec) return E_NOTIMPL; @@ -498,13 +498,13 @@ HRESULT CMixerST::GetOutStream( } } - int bond = FindBond_for_Stream( + const int bond = FindBond_for_Stream( false, // forInputStream outStreamIndex); if (bond < 0) return E_INVALIDARG; - UInt32 inStreamIndex = _bi.Bonds[bond].Get_InIndex(EncodeMode); + UInt32 inStreamIndex = _bi.Bonds[(unsigned)bond].Get_InIndex(EncodeMode); UInt32 coderIndex = inStreamIndex; UInt32 coderStreamIndex = 0; @@ -560,7 +560,7 @@ HRESULT CMixerST::GetOutStream( while (_binderStreams.Size() <= (unsigned)bond) _binderStreams.AddNew(); - CStBinderStream &bs = _binderStreams[bond]; + CStBinderStream &bs = _binderStreams[(unsigned)bond]; if (bs.StreamRef || bs.OutStreamSpec) return E_NOTIMPL; @@ -610,13 +610,13 @@ HRESULT CMixerST::FinishStream(UInt32 streamIndex) return S_OK; } - int bond = FindBond_for_Stream( + const int bond = FindBond_for_Stream( false, // forInputStream streamIndex); if (bond < 0) return E_INVALIDARG; - UInt32 inStreamIndex = _bi.Bonds[bond].Get_InIndex(EncodeMode); + UInt32 inStreamIndex = _bi.Bonds[(unsigned)bond].Get_InIndex(EncodeMode); UInt32 coderIndex = inStreamIndex; UInt32 coderStreamIndex = 0; @@ -654,7 +654,7 @@ void CMixerST::SelectMainCoder(bool useFirst) unsigned ci = _bi.UnpackCoder; int firstNonFilter = -1; - int firstAllowed = ci; + unsigned firstAllowed = ci; for (;;) { @@ -674,7 +674,7 @@ void CMixerST::SelectMainCoder(bool useFirst) UInt32 st = _bi.Coder_to_Stream[ci]; if (_bi.IsStream_in_PackStreams(st)) break; - int bond = _bi.FindBond_for_PackStream(st); + const int bond = _bi.FindBond_for_PackStream(st); if (bond < 0) throw 20150213; @@ -682,15 +682,15 @@ void CMixerST::SelectMainCoder(bool useFirst) break; if (firstNonFilter == -1 && !IsFilter_Vector[ci]) - firstNonFilter = ci; + firstNonFilter = (int)ci; - ci = _bi.Bonds[bond].UnpackIndex; + ci = _bi.Bonds[(unsigned)bond].UnpackIndex; } if (useFirst) ci = firstAllowed; else if (firstNonFilter >= 0) - ci = firstNonFilter; + ci = (unsigned)firstNonFilter; MainCoderIndex = ci; } @@ -919,7 +919,8 @@ HRESULT CMixerMT::SetBindInfo(const CBindInfo &bindInfo) _streamBinders.Clear(); FOR_VECTOR (i, _bi.Bonds) { - RINOK(_streamBinders.AddNew().CreateEvents()); + // RINOK(_streamBinders.AddNew().CreateEvents()); + _streamBinders.AddNew(); } return S_OK; } @@ -941,10 +942,13 @@ CCoder &CMixerMT::GetCoder(unsigned index) return _coders[index]; } -void CMixerMT::ReInit() +HRESULT CMixerMT::ReInit2() { FOR_VECTOR (i, _streamBinders) - _streamBinders[i].ReInit(); + { + RINOK(_streamBinders[i].Create_ReInit()); + } + return S_OK; } void CMixerMT::SelectMainCoder(bool useFirst) @@ -962,10 +966,10 @@ void CMixerMT::SelectMainCoder(bool useFirst) UInt32 st = _bi.Coder_to_Stream[ci]; if (_bi.IsStream_in_PackStreams(st)) break; - int bond = _bi.FindBond_for_PackStream(st); + const int bond = _bi.FindBond_for_PackStream(st); if (bond < 0) throw 20150213; - ci = _bi.Bonds[bond].UnpackIndex; + ci = _bi.Bonds[(unsigned)bond].UnpackIndex; } MainCoderIndex = ci; @@ -1012,9 +1016,9 @@ HRESULT CMixerMT::Init(ISequentialInStream * const *inStreams, ISequentialOutStr outCoderStreamIndex = EncodeMode ? coderStreamIndex : 0; } - _streamBinders[i].CreateStreams( - &_coders[inCoderIndex].InStreams[inCoderStreamIndex], - &_coders[outCoderIndex].OutStreams[outCoderStreamIndex]); + _streamBinders[i].CreateStreams2( + _coders[inCoderIndex].InStreams[inCoderStreamIndex], + _coders[outCoderIndex].OutStreams[outCoderStreamIndex]); CMyComPtr<ICompressSetBufSize> inSetSize, outSetSize; _coders[inCoderIndex].QueryInterface(IID_ICompressSetBufSize, (void **)&inSetSize); @@ -1072,18 +1076,31 @@ HRESULT CMixerMT::Code( for (i = 0; i < _coders.Size(); i++) if (i != MainCoderIndex) { - RINOK(_coders[i].Create()); + const WRes wres = _coders[i].Create(); + if (wres != 0) + return HRESULT_FROM_WIN32(wres); } for (i = 0; i < _coders.Size(); i++) if (i != MainCoderIndex) - _coders[i].Start(); + { + const WRes wres = _coders[i].Start(); + if (wres != 0) + return HRESULT_FROM_WIN32(wres); + } _coders[MainCoderIndex].Code(progress); + WRes wres = 0; for (i = 0; i < _coders.Size(); i++) if (i != MainCoderIndex) - _coders[i].WaitExecuteFinish(); + { + WRes wres2 = _coders[i].WaitExecuteFinish(); + if (wres == 0) + wres = wres2; + } + if (wres != 0) + return HRESULT_FROM_WIN32(wres); RINOK(ReturnIfError(E_ABORT)); RINOK(ReturnIfError(E_OUTOFMEMORY)); diff --git a/CPP/7zip/Archive/Common/CoderMixer2.h b/CPP/7zip/Archive/Common/CoderMixer2.h index 798411ab..f099ac3e 100644 --- a/CPP/7zip/Archive/Common/CoderMixer2.h +++ b/CPP/7zip/Archive/Common/CoderMixer2.h @@ -107,7 +107,7 @@ struct CBindInfo { FOR_VECTOR (i, Bonds) if (Bonds[i].PackIndex == packStream) - return i; + return (int)i; return -1; } @@ -115,7 +115,7 @@ struct CBindInfo { FOR_VECTOR (i, Bonds) if (Bonds[i].UnpackIndex == unpackStream) - return i; + return (int)i; return -1; } @@ -144,7 +144,7 @@ struct CBindInfo { FOR_VECTOR(i, PackStreams) if (PackStreams[i] == streamIndex) - return i; + return (int)i; return -1; } @@ -251,6 +251,7 @@ public: // , InternalPackSizeError(false) {} + virtual ~CMixer() {}; /* Sequence of calling: @@ -279,7 +280,7 @@ public: virtual void AddCoder(const CCreatedCoder &cod) = 0; virtual CCoder &GetCoder(unsigned index) = 0; virtual void SelectMainCoder(bool useFirst) = 0; - virtual void ReInit() = 0; + virtual HRESULT ReInit2() = 0; virtual void SetCoderInfo(unsigned coderIndex, const UInt64 *unpackSize, const UInt64 * const *packSizes, bool finish) = 0; virtual HRESULT Code( ISequentialInStream * const *inStreams, @@ -322,6 +323,8 @@ class CMixerST: public CMixer, public CMyUnknownImp { + CLASS_NO_COPY(CMixerST) + HRESULT GetInStream2(ISequentialInStream * const *inStreams, /* const UInt64 * const *inSizes, */ UInt32 outStreamIndex, ISequentialInStream **inStreamRes); HRESULT GetInStream(ISequentialInStream * const *inStreams, /* const UInt64 * const *inSizes, */ @@ -345,7 +348,7 @@ public: virtual void AddCoder(const CCreatedCoder &cod); virtual CCoder &GetCoder(unsigned index); virtual void SelectMainCoder(bool useFirst); - virtual void ReInit(); + virtual HRESULT ReInit2(); virtual void SetCoderInfo(unsigned coderIndex, const UInt64 *unpackSize, const UInt64 * const *packSizes, bool finish) { _coders[coderIndex].SetCoderInfo(unpackSize, packSizes, finish); } virtual HRESULT Code( @@ -402,7 +405,7 @@ public: }; CCoderMT(): EncodeMode(false) {} - ~CCoderMT() { CVirtThread::WaitThreadFinish(); } + virtual ~CCoderMT() { CVirtThread::WaitThreadFinish(); } void Code(ICompressProgressInfo *progress); }; @@ -413,11 +416,14 @@ class CMixerMT: public CMixer, public CMyUnknownImp { + CLASS_NO_COPY(CMixerMT) + CObjectVector<CStreamBinder> _streamBinders; HRESULT Init(ISequentialInStream * const *inStreams, ISequentialOutStream * const *outStreams); HRESULT ReturnIfError(HRESULT code); + // virtual ~CMixerMT() {}; public: CObjectVector<CCoderMT> _coders; @@ -427,7 +433,7 @@ public: virtual void AddCoder(const CCreatedCoder &cod); virtual CCoder &GetCoder(unsigned index); virtual void SelectMainCoder(bool useFirst); - virtual void ReInit(); + virtual HRESULT ReInit2(); virtual void SetCoderInfo(unsigned coderIndex, const UInt64 *unpackSize, const UInt64 * const *packSizes, bool finish) { _coders[coderIndex].SetCoderInfo(unpackSize, packSizes, finish); } virtual HRESULT Code( diff --git a/CPP/7zip/Archive/Common/HandlerOut.cpp b/CPP/7zip/Archive/Common/HandlerOut.cpp index 77a35c74..972a766a 100644 --- a/CPP/7zip/Archive/Common/HandlerOut.cpp +++ b/CPP/7zip/Archive/Common/HandlerOut.cpp @@ -179,8 +179,8 @@ HRESULT CMultiMethodProps::SetProperty(const wchar_t *nameSpec, const PROPVARIAN } if (number > 64) return E_FAIL; - for (int j = _methods.Size(); j <= (int)number; j++) - _methods.Add(COneMethodInfo()); + for (unsigned j = _methods.Size(); j <= number; j++) + _methods.AddNew(); return _methods[number].ParseMethodFromPROPVARIANT(realName, value); } diff --git a/CPP/7zip/Archive/Common/ItemNameUtils.cpp b/CPP/7zip/Archive/Common/ItemNameUtils.cpp index d5093a24..905a863d 100644 --- a/CPP/7zip/Archive/Common/ItemNameUtils.cpp +++ b/CPP/7zip/Archive/Common/ItemNameUtils.cpp @@ -8,7 +8,10 @@ namespace NArchive { namespace NItemName { static const wchar_t kOsPathSepar = WCHAR_PATH_SEPARATOR; + +#if WCHAR_PATH_SEPARATOR != L'/' static const wchar_t kUnixPathSepar = L'/'; +#endif void ReplaceSlashes_OsToUnix #if WCHAR_PATH_SEPARATOR != L'/' @@ -44,17 +47,35 @@ UString GetOsPath_Remove_TailSlash(const UString &name) } -void ReplaceToOsSlashes_Remove_TailSlash(UString &name) -{ - if (!name.IsEmpty()) - { +void ReplaceToOsSlashes_Remove_TailSlash(UString &name, bool #if WCHAR_PATH_SEPARATOR != L'/' - name.Replace(kUnixPathSepar, kOsPathSepar); + useBackslashReplacement #endif - - if (name.Back() == kOsPathSepar) - name.DeleteBack(); + ) +{ + if (name.IsEmpty()) + return; + + #if WCHAR_PATH_SEPARATOR != L'/' + { + // name.Replace(kUnixPathSepar, kOsPathSepar); + const unsigned len = name.Len(); + for (unsigned i = 0; i < len; i++) + { + wchar_t c = name[i]; + if (c == L'/') + c = WCHAR_PATH_SEPARATOR; + else if (useBackslashReplacement && c == L'\\') + c = WCHAR_IN_FILE_NAME_BACKSLASH_REPLACEMENT; // WSL scheme + else + continue; + name.ReplaceOneCharAtPos(i, c); + } } + #endif + + if (name.Back() == kOsPathSepar) + name.DeleteBack(); } @@ -66,12 +87,15 @@ bool HasTailSlash(const AString &name, UINT { if (name.IsEmpty()) return false; - char c = + char c; #if defined(_WIN32) && !defined(UNDER_CE) - *CharPrevExA((WORD)codePage, name, name.Ptr(name.Len()), 0); - #else - name.Back(); + if (codePage != CP_UTF8) + c = *CharPrevExA((WORD)codePage, name, name.Ptr(name.Len()), 0); + else #endif + { + c = name.Back(); + } return (c == '/'); } diff --git a/CPP/7zip/Archive/Common/ItemNameUtils.h b/CPP/7zip/Archive/Common/ItemNameUtils.h index 31150864..6a4d6c71 100644 --- a/CPP/7zip/Archive/Common/ItemNameUtils.h +++ b/CPP/7zip/Archive/Common/ItemNameUtils.h @@ -13,7 +13,7 @@ void ReplaceSlashes_OsToUnix(UString &name); UString GetOsPath(const UString &name); UString GetOsPath_Remove_TailSlash(const UString &name); -void ReplaceToOsSlashes_Remove_TailSlash(UString &name); +void ReplaceToOsSlashes_Remove_TailSlash(UString &name, bool useBackslashReplacement = false); bool HasTailSlash(const AString &name, UINT codePage); diff --git a/CPP/7zip/Archive/Common/MultiStream.cpp b/CPP/7zip/Archive/Common/MultiStream.cpp index 1de74afe..162fc928 100644 --- a/CPP/7zip/Archive/Common/MultiStream.cpp +++ b/CPP/7zip/Archive/Common/MultiStream.cpp @@ -36,7 +36,7 @@ STDMETHODIMP CMultiStream::Read(void *data, UInt32 size, UInt32 *processedSize) UInt64 localPos = _pos - s.GlobalOffset; if (localPos != s.LocalPos) { - RINOK(s.Stream->Seek(localPos, STREAM_SEEK_SET, &s.LocalPos)); + RINOK(s.Stream->Seek((Int64)localPos, STREAM_SEEK_SET, &s.LocalPos)); } UInt64 rem = s.Size - localPos; if (size > rem) @@ -60,9 +60,9 @@ STDMETHODIMP CMultiStream::Seek(Int64 offset, UInt32 seekOrigin, UInt64 *newPosi } if (offset < 0) return HRESULT_WIN32_ERROR_NEGATIVE_SEEK; - _pos = offset; + _pos = (UInt64)offset; if (newPosition) - *newPosition = offset; + *newPosition = (UInt64)offset; return S_OK; } diff --git a/CPP/7zip/Archive/Common/OutStreamWithSha1.cpp b/CPP/7zip/Archive/Common/OutStreamWithSha1.cpp index 77252938..ac26edf7 100644 --- a/CPP/7zip/Archive/Common/OutStreamWithSha1.cpp +++ b/CPP/7zip/Archive/Common/OutStreamWithSha1.cpp @@ -10,7 +10,7 @@ STDMETHODIMP COutStreamWithSha1::Write(const void *data, UInt32 size, UInt32 *pr if (_stream) result = _stream->Write(data, size, &size); if (_calculate) - Sha1_Update(&_sha, (const Byte *)data, size); + Sha1_Update(Sha(), (const Byte *)data, size); _size += size; if (processedSize) *processedSize = size; diff --git a/CPP/7zip/Archive/Common/OutStreamWithSha1.h b/CPP/7zip/Archive/Common/OutStreamWithSha1.h index 41a84cd6..5a7bfef3 100644 --- a/CPP/7zip/Archive/Common/OutStreamWithSha1.h +++ b/CPP/7zip/Archive/Common/OutStreamWithSha1.h @@ -5,6 +5,7 @@ #include "../../../../C/Sha1.h" +#include "../../../Common/MyBuffer2.h" #include "../../../Common/MyCom.h" #include "../../IStream.h" @@ -15,10 +16,16 @@ class COutStreamWithSha1: { CMyComPtr<ISequentialOutStream> _stream; UInt64 _size; - CSha1 _sha; + // CSha1 _sha; bool _calculate; + CAlignedBuffer _sha; + + CSha1 *Sha() { return (CSha1 *)(void *)(Byte *)_sha; } public: MY_UNKNOWN_IMP + + COutStreamWithSha1(): _sha(sizeof(CSha1)) {} + STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize); void SetStream(ISequentialOutStream *stream) { _stream = stream; } void ReleaseStream() { _stream.Release(); } @@ -26,11 +33,11 @@ public: { _size = 0; _calculate = calculate; - Sha1_Init(&_sha); + Sha1_Init(Sha()); } - void InitSha1() { Sha1_Init(&_sha); } + void InitSha1() { Sha1_Init(Sha()); } UInt64 GetSize() const { return _size; } - void Final(Byte *digest) { Sha1_Final(&_sha, digest); } + void Final(Byte *digest) { Sha1_Final(Sha(), digest); } }; #endif diff --git a/CPP/7zip/Archive/CpioHandler.cpp b/CPP/7zip/Archive/CpioHandler.cpp index b8fb530f..ffdab16c 100644 --- a/CPP/7zip/Archive/CpioHandler.cpp +++ b/CPP/7zip/Archive/CpioHandler.cpp @@ -131,7 +131,7 @@ enum EErrorType { k_ErrorType_OK, k_ErrorType_Corrupted, - k_ErrorType_UnexpectedEnd, + k_ErrorType_UnexpectedEnd }; struct CInArchive @@ -218,7 +218,7 @@ API_FUNC_static_IsArc IsArc_Cpio(const Byte *p, size_t size) { if (size < k_OctRecord_Size) return k_IsArc_Res_NEED_MORE; - for (int i = 6; i < k_OctRecord_Size; i++) + for (unsigned i = 6; i < k_OctRecord_Size; i++) { char c = p[i]; if (c < '0' || c > '7') @@ -231,7 +231,7 @@ API_FUNC_static_IsArc IsArc_Cpio(const Byte *p, size_t size) { if (size < k_HexRecord_Size) return k_IsArc_Res_NEED_MORE; - for (int i = 6; i < k_HexRecord_Size; i++) + for (unsigned i = 6; i < k_HexRecord_Size; i++) { char c = p[i]; if ((c < '0' || c > '9') && @@ -268,7 +268,9 @@ API_FUNC_static_IsArc IsArc_Cpio(const Byte *p, size_t size) if (nameSize > (1 << 8)) return k_IsArc_Res_NO; } - if (numLinks == 0 || numLinks >= (1 << 10)) + // 20.03: some cpio files have (numLinks == 0). + // if (numLinks == 0) return k_IsArc_Res_NO; + if (numLinks >= (1 << 10)) return k_IsArc_Res_NO; if (nameSize == 0 || nameSize > kNameSizeMax) return k_IsArc_Res_NO; @@ -462,6 +464,9 @@ STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value) { case k_ErrorType_UnexpectedEnd: v |= kpv_ErrorFlags_UnexpectedEnd; break; case k_ErrorType_Corrupted: v |= kpv_ErrorFlags_HeadersError; break; + case k_ErrorType_OK: + default: + break; } prop = v; break; @@ -565,23 +570,30 @@ STDMETHODIMP CHandler::Open(IInStream *stream, const UInt64 *, IArchiveOpenCallb { // Read tailing zeros. // Most of cpio files use 512-bytes aligned zeros - UInt64 pos = arc.Processed; - const UInt32 kTailSize_MAX = 1 << 9; + // rare case: 4K/8K aligment is possible also + const unsigned kTailSize_MAX = 1 << 9; Byte buf[kTailSize_MAX]; - UInt32 rem = (kTailSize_MAX - (UInt32)pos) & (kTailSize_MAX - 1); - if (rem != 0) + unsigned pos = (unsigned)arc.Processed & (kTailSize_MAX - 1); + if (pos != 0) // use this check to support 512 bytes alignment only + for (;;) { - rem++; // we need to see that it's end of file + unsigned rem = kTailSize_MAX - pos; size_t processed = rem; - RINOK(ReadStream(stream, buf, &processed)); - if (processed < rem) - { - unsigned i; - for (i = 0; i < processed && buf[i] == 0; i++); - if (i == processed) - _phySize += processed; - } + RINOK(ReadStream(stream, buf + pos, &processed)); + if (processed != rem) + break; + + for (; pos < kTailSize_MAX && buf[pos] == 0; pos++) + {} + if (pos != kTailSize_MAX) + break; + _phySize += processed; + pos = 0; + + // use break to support 512 bytes alignment zero tail + // don't use break to support 512*n bytes alignment zero tail + break; } } @@ -622,7 +634,9 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val UString res; bool needConvert = true; #ifdef _WIN32 - if (ConvertUTF8ToUnicode(item.Name, res)) + // if ( + ConvertUTF8ToUnicode(item.Name, res); + // ) needConvert = false; #endif if (needConvert) diff --git a/CPP/7zip/Archive/DllExports2.cpp b/CPP/7zip/Archive/DllExports2.cpp index 10889e75..967a7cbf 100644 --- a/CPP/7zip/Archive/DllExports2.cpp +++ b/CPP/7zip/Archive/DllExports2.cpp @@ -22,11 +22,24 @@ #include "IArchive.h" -HINSTANCE g_hInstance; +#ifdef _WIN32 + +#if defined(_UNICODE) && !defined(_WIN64) && !defined(UNDER_CE) #define NT_CHECK_FAIL_ACTION return FALSE; +#endif + +HINSTANCE g_hInstance; + +extern "C" +BOOL WINAPI DllMain( + #ifdef UNDER_CE + HANDLE + #else + HINSTANCE + #endif + hInstance, DWORD dwReason, LPVOID /*lpReserved*/); -#ifdef _WIN32 extern "C" BOOL WINAPI DllMain( #ifdef UNDER_CE @@ -50,7 +63,22 @@ BOOL WINAPI DllMain( */ return TRUE; } -#endif + +#else // _WIN32 + +#include "../../Common/StringConvert.h" +// #include <stdio.h> + +// STDAPI LibStartup(); +static __attribute__((constructor)) void Init_ForceToUTF8(); +static __attribute__((constructor)) void Init_ForceToUTF8() +{ + g_ForceToUTF8 = IsNativeUTF8(); + // printf("\nDLLExports2.cpp::Init_ForceToUTF8 =%d\n", g_ForceToUTF8 ? 1 : 0); +} + +#endif // _WIN32 + DEFINE_GUID(CLSID_CArchiveHandler, k_7zip_GUID_Data1, @@ -62,6 +90,7 @@ STDAPI CreateCoder(const GUID *clsid, const GUID *iid, void **outObject); STDAPI CreateHasher(const GUID *clsid, IHasher **hasher); STDAPI CreateArchiver(const GUID *clsid, const GUID *iid, void **outObject); +STDAPI CreateObject(const GUID *clsid, const GUID *iid, void **outObject); STDAPI CreateObject(const GUID *clsid, const GUID *iid, void **outObject) { // COM_TRY_BEGIN @@ -76,16 +105,20 @@ STDAPI CreateObject(const GUID *clsid, const GUID *iid, void **outObject) // COM_TRY_END } +STDAPI SetLargePageMode(); STDAPI SetLargePageMode() { #if defined(_7ZIP_LARGE_PAGES) + #ifdef _WIN32 SetLargePageSize(); #endif + #endif return S_OK; } extern bool g_CaseSensitive; +STDAPI SetCaseSensitive(Int32 caseSensitive); STDAPI SetCaseSensitive(Int32 caseSensitive) { g_CaseSensitive = (caseSensitive != 0); @@ -96,6 +129,7 @@ STDAPI SetCaseSensitive(Int32 caseSensitive) CExternalCodecs g_ExternalCodecs; +STDAPI SetCodecs(ICompressCodecsInfo *compressCodecsInfo); STDAPI SetCodecs(ICompressCodecsInfo *compressCodecsInfo) { COM_TRY_BEGIN @@ -114,6 +148,7 @@ STDAPI SetCodecs(ICompressCodecsInfo *compressCodecsInfo) #else +STDAPI SetCodecs(ICompressCodecsInfo *); STDAPI SetCodecs(ICompressCodecsInfo *) { return S_OK; diff --git a/CPP/7zip/Archive/DmgHandler.cpp b/CPP/7zip/Archive/DmgHandler.cpp index d9fe6016..a08dcac1 100644 --- a/CPP/7zip/Archive/DmgHandler.cpp +++ b/CPP/7zip/Archive/DmgHandler.cpp @@ -33,99 +33,22 @@ #define Get32(p) GetBe32(p) #define Get64(p) GetBe64(p) -static const Byte k_Base64Table[256] = -{ - 66,77,77,77,77,77,77,77,77,65,65,77,77,65,77,77, - 77,77,77,77,77,77,77,77,77,77,77,77,77,77,77,77, - 65,77,77,77,77,77,77,77,77,77,77,62,77,77,77,63, - 52,53,54,55,56,57,58,59,60,61,77,77,77,64,77,77, - 77, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10,11,12,13,14, - 15,16,17,18,19,20,21,22,23,24,25,77,77,77,77,77, - 77,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40, - 41,42,43,44,45,46,47,48,49,50,51,77,77,77,77,77, - 77,77,77,77,77,77,77,77,77,77,77,77,77,77,77,77, - 77,77,77,77,77,77,77,77,77,77,77,77,77,77,77,77, - 77,77,77,77,77,77,77,77,77,77,77,77,77,77,77,77, - 77,77,77,77,77,77,77,77,77,77,77,77,77,77,77,77, - 77,77,77,77,77,77,77,77,77,77,77,77,77,77,77,77, - 77,77,77,77,77,77,77,77,77,77,77,77,77,77,77,77, - 77,77,77,77,77,77,77,77,77,77,77,77,77,77,77,77, - 77,77,77,77,77,77,77,77,77,77,77,77,77,77,77,77 -}; - -static Byte *Base64ToBin(Byte *dest, const char *src) -{ - UInt32 val = 1; - - for (;;) - { - UInt32 c = k_Base64Table[(Byte)(*src++)]; - - if (c < 64) - { - val = (val << 6) | c; - if ((val & ((UInt32)1 << 24)) == 0) - continue; - dest[0] = (Byte)(val >> 16); - dest[1] = (Byte)(val >> 8); - dest[2] = (Byte)(val); - dest += 3; - val = 1; - continue; - } - - if (c == 65) // space - continue; - - if (c == 64) // '=' - break; - - if (c == 66 && val == 1) // end of string - return dest; - - return NULL; - } - - if (val < (1 << 12)) - return NULL; - - if (val & (1 << 18)) - { - *dest++ = (Byte)(val >> 10); - *dest++ = (Byte)(val >> 2); - } - else if (k_Base64Table[(Byte)(*src++)] != 64) // '=' - return NULL; - else - *dest++ = (Byte)(val >> 4); - - for (;;) - { - Byte c = k_Base64Table[(Byte)(*src++)]; - if (c == 65) // space - continue; - if (c == 66) // end of string - return dest; - return NULL; - } -} - +Byte *Base64ToBin(Byte *dest, const char *src); namespace NArchive { namespace NDmg { -enum -{ - METHOD_ZERO_0 = 0, - METHOD_COPY = 1, - METHOD_ZERO_2 = 2, // without file CRC calculation - METHOD_ADC = 0x80000004, - METHOD_ZLIB = 0x80000005, - METHOD_BZIP2 = 0x80000006, - METHOD_LZFSE = 0x80000007, - METHOD_COMMENT = 0x7FFFFFFE, // is used to comment "+beg" and "+end" in extra field. - METHOD_END = 0xFFFFFFFF -}; + +static const UInt32 METHOD_ZERO_0 = 0; +static const UInt32 METHOD_COPY = 1; +static const UInt32 METHOD_ZERO_2 = 2; // without file CRC calculation +static const UInt32 METHOD_ADC = 0x80000004; +static const UInt32 METHOD_ZLIB = 0x80000005; +static const UInt32 METHOD_BZIP2 = 0x80000006; +static const UInt32 METHOD_LZFSE = 0x80000007; +static const UInt32 METHOD_COMMENT = 0x7FFFFFFE; // is used to comment "+beg" and "+end" in extra field. +static const UInt32 METHOD_END = 0xFFFFFFFF; + struct CBlock { @@ -266,7 +189,7 @@ void CMethods::GetString(AString &res) const for (i = 0; i < Types.Size(); i++) { - UInt32 type = Types[i]; + const UInt32 type = Types[i]; if (type == METHOD_COMMENT || type == METHOD_END) continue; char buf[16]; @@ -407,6 +330,7 @@ STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value) case kpidWarning: if (_masterCrcError) prop = "Master CRC error"; + break; case kpidWarningFlags: { @@ -727,7 +651,8 @@ HRESULT CHandler::Open2(IInStream *stream) if (xmlPair2.Len > len) xmlPair2.Len = len; CByteBuffer buf2; - if (ReadData(stream, xmlPair2, buf2) != S_OK + if (xmlPair2.Len < len + || ReadData(stream, xmlPair2, buf2) != S_OK || memcmp(buf2, sz, len) != 0) { // if absolute offset is not OK, probably it's archive with offset @@ -1054,7 +979,9 @@ STDMETHODIMP CHandler::GetNumberOfItems(UInt32 *numItems) return S_OK; } +#ifdef DMG_SHOW_RAW #define RAW_PREFIX "raw" STRING_PATH_SEPARATOR +#endif STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *value) { @@ -1608,7 +1535,7 @@ public: }; -unsigned FindBlock(const CRecordVector<CBlock> &blocks, UInt64 pos) +static unsigned FindBlock(const CRecordVector<CBlock> &blocks, UInt64 pos) { unsigned left = 0, right = blocks.Size(); for (;;) @@ -1762,8 +1689,8 @@ STDMETHODIMP CInStream::Read(void *data, UInt32 size, UInt32 *processedSize) } const CBlock &block = File->Blocks[_latestBlock]; - UInt64 offset = _virtPos - block.UnpPos; - UInt64 rem = block.UnpSize - offset; + const UInt64 offset = _virtPos - block.UnpPos; + const UInt64 rem = block.UnpSize - offset; if (size > rem) size = (UInt32)rem; @@ -1777,7 +1704,7 @@ STDMETHODIMP CInStream::Read(void *data, UInt32 size, UInt32 *processedSize) else if (block.IsZeroMethod()) memset(data, 0, size); else if (size != 0) - memcpy(data, _chunks[_latestChunk].Buf + offset, size); + memcpy(data, _chunks[_latestChunk].Buf + (size_t)offset, size); _virtPos += size; if (processedSize) diff --git a/CPP/7zip/Archive/ElfHandler.cpp b/CPP/7zip/Archive/ElfHandler.cpp index c5ce279e..efcde95d 100644 --- a/CPP/7zip/Archive/ElfHandler.cpp +++ b/CPP/7zip/Archive/ElfHandler.cpp @@ -226,6 +226,7 @@ void CSegment::Parse(const Byte *p, bool mode64, bool be) // Section types +/* #define SHT_NULL 0 #define SHT_PROGBITS 1 #define SHT_SYMTAB 2 @@ -234,7 +235,9 @@ void CSegment::Parse(const Byte *p, bool mode64, bool be) #define SHT_HASH 5 #define SHT_DYNAMIC 6 #define SHT_NOTE 7 +*/ #define SHT_NOBITS 8 +/* #define SHT_REL 9 #define SHT_SHLIB 10 #define SHT_DYNSYM 11 @@ -245,7 +248,7 @@ void CSegment::Parse(const Byte *p, bool mode64, bool be) #define SHT_PREINIT_ARRAY 16 #define SHT_GROUP 17 #define SHT_SYMTAB_SHNDX 18 - +*/ static const CUInt32PCharPair g_SectTypes[] = { @@ -633,11 +636,11 @@ static const CUInt32PCharPair g_MIPS_Flags[] = }; -#define ET_NONE 0 +// #define ET_NONE 0 #define ET_REL 1 -#define ET_EXEC 2 +// #define ET_EXEC 2 #define ET_DYN 3 -#define ET_CORE 4 +// #define ET_CORE 4 static const char * const g_Types[] = { diff --git a/CPP/7zip/Archive/ExtHandler.cpp b/CPP/7zip/Archive/ExtHandler.cpp index db65fbea..e9808aac 100644 --- a/CPP/7zip/Archive/ExtHandler.cpp +++ b/CPP/7zip/Archive/ExtHandler.cpp @@ -99,6 +99,8 @@ static UInt32 Crc16Calc(Byte const *data, size_t size) #define EXT4_GOOD_OLD_INODE_SIZE 128 +#define EXT_NODE_SIZE_MIN 128 + // inodes numbers @@ -436,9 +438,9 @@ bool CHeader::Parse(const Byte *p) LE_16 (0x58, InodeSize); if (FirstInode < k_INODE_GOOD_OLD_FIRST) return false; - if (InodeSize > (UInt32)1 << BlockBits) - return false; - if (GetLog(InodeSize) < 0) + if (InodeSize > ((UInt32)1 << BlockBits) + || InodeSize < EXT_NODE_SIZE_MIN + || GetLog(InodeSize) < 0) return false; } @@ -603,7 +605,7 @@ struct CExtent if (Len > (UInt32)0x8000) { IsInited = false; - Len -= (UInt32)0x8000; + Len = (UInt16)(Len - (UInt32)0x8000); } LE_32 (0x08, PhyStart); UInt16 hi; @@ -628,8 +630,8 @@ struct CNode int DirIndex; // in _dirs[] UInt16 Mode; - UInt16 Uid; - UInt16 Gid; + UInt32 Uid; // fixed 21.02 + UInt32 Gid; // fixed 21.02 // UInt16 Checksum; UInt64 FileSize; @@ -730,6 +732,8 @@ bool CNode::Parse(const Byte *p, const CHeader &_h) if (_h.InodeSize > 128) { + // InodeSize is power of 2, so the following check is not required: + // if (_h.InodeSize < 128 + 2) return false; UInt16 extra_isize; LE_16 (0x80, extra_isize); if (128 + extra_isize > _h.InodeSize) @@ -842,7 +846,7 @@ class CHandler: } - const int GetParentAux(const CItem &item) const + int GetParentAux(const CItem &item) const { if (item.Node < _h.FirstInode && _auxSysIndex >= 0) return _auxSysIndex; @@ -931,7 +935,7 @@ HRESULT CHandler::ParseDir(const Byte *p, size_t size, unsigned iNodeDir) return S_FALSE; if (_isUTF) - _isUTF = CheckUTF8(item.Name); + _isUTF = CheckUTF8_AString(item.Name); if (iNode == 0) { @@ -1201,7 +1205,7 @@ HRESULT CHandler::Open2(IInStream *inStream) UInt32 numNodes = _h.InodesPerGroup; if (numNodes > _h.NumInodes) numNodes = _h.NumInodes; - size_t nodesDataSize = (size_t)numNodes * _h.InodeSize; + const size_t nodesDataSize = (size_t)numNodes * _h.InodeSize; if (nodesDataSize / _h.InodeSize != numNodes) return S_FALSE; @@ -1213,7 +1217,7 @@ HRESULT CHandler::Open2(IInStream *inStream) return S_FALSE; } - UInt32 numReserveInodes = _h.NumInodes - _h.NumFreeInodes + 1; + const UInt32 numReserveInodes = _h.NumInodes - _h.NumFreeInodes + 1; // numReserveInodes = _h.NumInodes + 1; if (numReserveInodes != 0) { @@ -1348,7 +1352,8 @@ HRESULT CHandler::Open2(IInStream *inStream) RINOK(CheckProgress()); } - if (_nodes[_refs[k_INODE_ROOT]].ParentNode != k_INODE_ROOT) + int ref = _refs[k_INODE_ROOT]; + if (ref < 0 || _nodes[ref].ParentNode != k_INODE_ROOT) return S_FALSE; } diff --git a/CPP/7zip/Archive/FatHandler.cpp b/CPP/7zip/Archive/FatHandler.cpp index bf6053e0..1cbc8508 100644 --- a/CPP/7zip/Archive/FatHandler.cpp +++ b/CPP/7zip/Archive/FatHandler.cpp @@ -682,7 +682,7 @@ HRESULT CDatabase::Open() RINOK(ReadStream_FALSE(InStream, byteBuf, readSize)); NumCurUsedBytes += readSize; - const UInt32 *src = (const UInt32 *)(const Byte *)byteBuf; + const UInt32 *src = (const UInt32 *)(const void *)(const Byte *)byteBuf; UInt32 *dest = Fat + i; if (numFreeClustersDefined) for (UInt32 j = 0; j < size; j++) diff --git a/CPP/7zip/Archive/FlvHandler.cpp b/CPP/7zip/Archive/FlvHandler.cpp index 1f52f60b..97a7c268 100644 --- a/CPP/7zip/Archive/FlvHandler.cpp +++ b/CPP/7zip/Archive/FlvHandler.cpp @@ -23,14 +23,14 @@ ((UInt32)((const Byte *)(p))[1] << 8) | \ ((const Byte *)(p))[2] ) -#define Get16(p) GetBe16(p) +// #define Get16(p) GetBe16(p) #define Get24(p) GetBe24(p) #define Get32(p) GetBe32(p) namespace NArchive { namespace NFlv { -static const UInt32 kFileSizeMax = (UInt32)1 << 30; +// static const UInt32 kFileSizeMax = (UInt32)1 << 30; static const UInt32 kNumChunksMax = (UInt32)1 << 23; static const UInt32 kTagHeaderSize = 11; diff --git a/CPP/7zip/Archive/GptHandler.cpp b/CPP/7zip/Archive/GptHandler.cpp index a86ad37c..7b3d23bb 100644 --- a/CPP/7zip/Archive/GptHandler.cpp +++ b/CPP/7zip/Archive/GptHandler.cpp @@ -333,16 +333,25 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val { case kpidPath: { + // Windows BDP partitions can have identical names. + // So we add the partition number at front UString s; - for (unsigned i = 0; i < kNameLen; i++) + s.Add_UInt32(index); { - wchar_t c = (wchar_t)Get16(item.Name + i * 2); - if (c == 0) - break; - s += c; + UString s2; + for (unsigned i = 0; i < kNameLen; i++) + { + wchar_t c = (wchar_t)Get16(item.Name + i * 2); + if (c == 0) + break; + s2 += c; + } + if (!s2.IsEmpty()) + { + s += '.'; + s += s2; + } } - if (s.IsEmpty()) - s.Add_UInt32(index); { s += '.'; const char *ext = NULL; diff --git a/CPP/7zip/Archive/GzHandler.cpp b/CPP/7zip/Archive/GzHandler.cpp index 130f8b35..0054840d 100644 --- a/CPP/7zip/Archive/GzHandler.cpp +++ b/CPP/7zip/Archive/GzHandler.cpp @@ -45,7 +45,7 @@ namespace NGz { namespace NFlags { - const Byte kIsText = 1 << 0; + // const Byte kIsText = 1 << 0; const Byte kCrc = 1 << 1; const Byte kExtra = 1 << 2; const Byte kName = 1 << 3; @@ -234,7 +234,8 @@ static UInt32 Is_Deflate(const Byte *p, size_t size) return k_IsArc_Res_NO; if (size < 4) return k_IsArc_Res_NEED_MORE; - if (GetUi16(p) != (UInt16)~GetUi16(p + 2)) + UInt16 r = (UInt16)~GetUi16(p + 2); + if (GetUi16(p) != r) return k_IsArc_Res_NO; } else if (type == 2) @@ -248,8 +249,8 @@ static UInt32 Is_Deflate(const Byte *p, size_t size) return k_IsArc_Res_YES; } -static unsigned kNameMaxLen = 1 << 12; -static unsigned kCommentMaxLen = 1 << 16; +static const unsigned kNameMaxLen = 1 << 12; +static const unsigned kCommentMaxLen = 1 << 16; API_FUNC_static_IsArc IsArc_Gz(const Byte *p, size_t size) { @@ -962,7 +963,7 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numIt UString name = prop.bstrVal; int slashPos = name.ReverseFind_PathSepar(); if (slashPos >= 0) - name.DeleteFrontal(slashPos + 1); + name.DeleteFrontal((unsigned)(slashPos + 1)); newItem.Name = UnicodeStringToMultiByte(name, CP_ACP); if (!newItem.Name.IsEmpty()) newItem.Flags |= NFlags::kName; @@ -1019,7 +1020,7 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numIt newItem.WriteHeader(outStream); offset += _headerSize; } - RINOK(_stream->Seek(offset, STREAM_SEEK_SET, NULL)); + RINOK(_stream->Seek((Int64)offset, STREAM_SEEK_SET, NULL)); return NCompress::CopyStream(_stream, outStream, progress); diff --git a/CPP/7zip/Archive/HandlerCont.cpp b/CPP/7zip/Archive/HandlerCont.cpp index c2d5c70c..22a8c4a9 100644 --- a/CPP/7zip/Archive/HandlerCont.cpp +++ b/CPP/7zip/Archive/HandlerCont.cpp @@ -269,7 +269,7 @@ HRESULT ReadZeroTail(ISequentialInStream *stream, bool &areThereNonZeros, UInt64 for (;;) { UInt32 size = 0; - HRESULT(stream->Read(buf, kBufSize, &size)); + RINOK(stream->Read(buf, kBufSize, &size)); if (size == 0) return S_OK; for (UInt32 i = 0; i < size; i++) diff --git a/CPP/7zip/Archive/HfsHandler.cpp b/CPP/7zip/Archive/HfsHandler.cpp index ca1d7bda..57313280 100644 --- a/CPP/7zip/Archive/HfsHandler.cpp +++ b/CPP/7zip/Archive/HfsHandler.cpp @@ -275,7 +275,7 @@ struct CItem CItem(): UseAttr(false), UseInlineData(false) {} bool IsDir() const { return Type == RECORD_TYPE_FOLDER; } - const CFork &GetFork(bool isResource) const { return (CFork & )*(isResource ? &ResourceFork: &DataFork ); } + const CFork &GetFork(bool isResource) const { return (const CFork & )*(isResource ? &ResourceFork: &DataFork ); } }; struct CAttr @@ -320,12 +320,14 @@ public: UInt64 SpecOffset; UInt64 PhySize; UInt64 PhySize2; + UInt64 ArcFileSize; void Clear() { SpecOffset = 0; PhySize = 0; PhySize2 = 0; + ArcFileSize = 0; HeadersError = false; ThereAreAltStreams = false; // CaseSensetive = false; @@ -440,7 +442,10 @@ HRESULT CDatabase::ReadFile(const CFork &fork, CByteBuffer &buf, IInStream *inSt { if (fork.NumBlocks >= Header.NumBlocks) return S_FALSE; - size_t totalSize = (size_t)fork.NumBlocks << Header.BlockSizeLog; + if ((ArcFileSize >> Header.BlockSizeLog) + 1 < fork.NumBlocks) + return S_FALSE; + + const size_t totalSize = (size_t)fork.NumBlocks << Header.BlockSizeLog; if ((totalSize >> Header.BlockSizeLog) != fork.NumBlocks) return S_FALSE; buf.Alloc(totalSize); @@ -473,20 +478,36 @@ struct CNodeDescriptor // Byte Height; unsigned NumRecords; - bool CheckNumRecords(unsigned nodeSizeLog) - { - return (kNodeDescriptor_Size + ((UInt32)NumRecords + 1) * 2 <= ((UInt32)1 << nodeSizeLog)); - } - void Parse(const Byte *p); + bool Parse(const Byte *p, unsigned nodeSizeLog); }; -void CNodeDescriptor::Parse(const Byte *p) + +bool CNodeDescriptor::Parse(const Byte *p, unsigned nodeSizeLog) { fLink = Get32(p); // bLink = Get32(p + 4); Kind = p[8]; // Height = p[9]; NumRecords = Get16(p + 10); + + const size_t nodeSize = (size_t)1 << nodeSizeLog; + if (kNodeDescriptor_Size + ((UInt32)NumRecords + 1) * 2 > nodeSize) + return false; + const size_t limit = nodeSize - ((UInt32)NumRecords + 1) * 2; + + p += nodeSize - 2; + + for (unsigned i = 0; i < NumRecords; i++) + { + const UInt32 offs = Get16(p); + p -= 2; + const UInt32 offsNext = Get16(p); + if (offs < kNodeDescriptor_Size + || offs >= offsNext + || offsNext > limit) + return false; + } + return true; } struct CHeaderRec @@ -576,7 +597,7 @@ HRESULT CDatabase::LoadExtentFile(const CFork &fork, IInStream *inStream, CObjec if (node == 0) return S_OK; - CByteBuffer usedBuf(hr.TotalNodes); + CByteArr usedBuf(hr.TotalNodes); memset(usedBuf, 0, hr.TotalNodes); while (node != 0) @@ -585,10 +606,9 @@ HRESULT CDatabase::LoadExtentFile(const CFork &fork, IInStream *inStream, CObjec return S_FALSE; usedBuf[node] = 1; - size_t nodeOffset = (size_t)node << hr.NodeSizeLog; + const size_t nodeOffset = (size_t)node << hr.NodeSizeLog; CNodeDescriptor desc; - desc.Parse(p + nodeOffset); - if (!desc.CheckNumRecords(hr.NodeSizeLog)) + if (!desc.Parse(p + nodeOffset, hr.NodeSizeLog)) return S_FALSE; if (desc.Kind != kNodeType_Leaf) return S_FALSE; @@ -597,18 +617,16 @@ HRESULT CDatabase::LoadExtentFile(const CFork &fork, IInStream *inStream, CObjec for (unsigned i = 0; i < desc.NumRecords; i++) { - const UInt32 nodeSize = (UInt32)1 << hr.NodeSizeLog; - const UInt32 offs = Get16(p + nodeOffset + nodeSize - (i + 1) * 2); - const UInt32 offsNext = Get16(p + nodeOffset + nodeSize - (i + 2) * 2); - if (offs > nodeSize || offsNext > nodeSize) - return S_FALSE; - UInt32 recSize = offsNext - offs; + const UInt32 nodeSize = (1 << hr.NodeSizeLog); + const Byte *r = p + nodeOffset + nodeSize - i * 2; + const UInt32 offs = Get16(r - 2); + UInt32 recSize = Get16(r - 4) - offs; const unsigned kKeyLen = 10; if (recSize != 2 + kKeyLen + kNumFixedExtents * 8) return S_FALSE; - const Byte *r = p + nodeOffset + offs; + r = p + nodeOffset + offs; if (Get16(r) != kKeyLen) return S_FALSE; @@ -717,7 +735,7 @@ HRESULT CDatabase::LoadAttrs(const CFork &fork, IInStream *inStream, IArchiveOpe if (node == 0) return S_OK; - CByteBuffer usedBuf(hr.TotalNodes); + CByteArr usedBuf(hr.TotalNodes); memset(usedBuf, 0, hr.TotalNodes); CFork resFork; @@ -728,10 +746,9 @@ HRESULT CDatabase::LoadAttrs(const CFork &fork, IInStream *inStream, IArchiveOpe return S_FALSE; usedBuf[node] = 1; - size_t nodeOffset = (size_t)node << hr.NodeSizeLog; + const size_t nodeOffset = (size_t)node << hr.NodeSizeLog; CNodeDescriptor desc; - desc.Parse(p + nodeOffset); - if (!desc.CheckNumRecords(hr.NodeSizeLog)) + if (!desc.Parse(p + nodeOffset, hr.NodeSizeLog)) return S_FALSE; if (desc.Kind != kNodeType_Leaf) return S_FALSE; @@ -739,19 +756,14 @@ HRESULT CDatabase::LoadAttrs(const CFork &fork, IInStream *inStream, IArchiveOpe for (unsigned i = 0; i < desc.NumRecords; i++) { const UInt32 nodeSize = (1 << hr.NodeSizeLog); - const UInt32 offs = Get16(p + nodeOffset + nodeSize - (i + 1) * 2); - const UInt32 offsNext = Get16(p + nodeOffset + nodeSize - (i + 2) * 2); - UInt32 recSize = offsNext - offs; - if (offs >= nodeSize - || offsNext > nodeSize - || offsNext < offs) - return S_FALSE; - + const Byte *r = p + nodeOffset + nodeSize - i * 2; + const UInt32 offs = Get16(r - 2); + UInt32 recSize = Get16(r - 4) - offs; const unsigned kHeadSize = 14; if (recSize < kHeadSize) return S_FALSE; - const Byte *r = p + nodeOffset + offs; + r = p + nodeOffset + offs; UInt32 keyLen = Get16(r); // UInt16 pad = Get16(r + 2); @@ -805,7 +817,7 @@ HRESULT CDatabase::LoadAttrs(const CFork &fork, IInStream *inStream, IArchiveOpe if (progress && (i & 0xFFF) == 0) { - UInt64 numFiles = 0; + const UInt64 numFiles = 0; RINOK(progress->SetCompleted(&numFiles, NULL)); } } @@ -873,13 +885,6 @@ bool CDatabase::Parse_decmpgfs(const CAttr &attr, CItem &item, bool &skip) HRESULT CDatabase::LoadCatalog(const CFork &fork, const CObjectVector<CIdExtents> *overflowExtentsArray, IInStream *inStream, IArchiveOpenCallback *progress) { - unsigned reserveSize = (unsigned)(Header.NumFolders + 1 + Header.NumFiles); - Items.ClearAndReserve(reserveSize); - Refs.ClearAndReserve(reserveSize); - - CRecordVector<CIdIndexPair> IdToIndexMap; - IdToIndexMap.ClearAndReserve(reserveSize); - CByteBuffer buf; RINOK(ReadFile(fork, buf, inStream)); const Byte *p = (const Byte *)buf; @@ -888,10 +893,24 @@ HRESULT CDatabase::LoadCatalog(const CFork &fork, const CObjectVector<CIdExtents // nodeDesc.Parse(p); CHeaderRec hr; RINOK(hr.Parse2(buf)); - + + CRecordVector<CIdIndexPair> IdToIndexMap; + + const unsigned reserveSize = (unsigned)(Header.NumFolders + 1 + Header.NumFiles); + + const unsigned kBasicRecSize = 0x58; + const unsigned kMinRecSize = kBasicRecSize + 10; + + if ((UInt64)reserveSize * kMinRecSize < buf.Size()) + { + Items.ClearAndReserve(reserveSize); + Refs.ClearAndReserve(reserveSize); + IdToIndexMap.ClearAndReserve(reserveSize); + } + // CaseSensetive = (Header.IsHfsX() && hr.KeyCompareType == 0xBC); - CByteBuffer usedBuf(hr.TotalNodes); + CByteArr usedBuf(hr.TotalNodes); memset(usedBuf, 0, hr.TotalNodes); CFork resFork; @@ -908,8 +927,7 @@ HRESULT CDatabase::LoadCatalog(const CFork &fork, const CObjectVector<CIdExtents const size_t nodeOffset = (size_t)node << hr.NodeSizeLog; CNodeDescriptor desc; - desc.Parse(p + nodeOffset); - if (!desc.CheckNumRecords(hr.NodeSizeLog)) + if (!desc.Parse(p + nodeOffset, hr.NodeSizeLog)) return S_FALSE; if (desc.Kind != kNodeType_Leaf) return S_FALSE; @@ -917,16 +935,13 @@ HRESULT CDatabase::LoadCatalog(const CFork &fork, const CObjectVector<CIdExtents for (unsigned i = 0; i < desc.NumRecords; i++) { const UInt32 nodeSize = (1 << hr.NodeSizeLog); - const UInt32 offs = Get16(p + nodeOffset + nodeSize - (i + 1) * 2); - const UInt32 offsNext = Get16(p + nodeOffset + nodeSize - (i + 2) * 2); - UInt32 recSize = offsNext - offs; - if (offs >= nodeSize - || offsNext > nodeSize - || offsNext < offs - || recSize < 6) + const Byte *r = p + nodeOffset + nodeSize - i * 2; + const UInt32 offs = Get16(r - 2); + UInt32 recSize = Get16(r - 4) - offs; + if (recSize < 6) return S_FALSE; - const Byte *r = p + nodeOffset + offs; + r = p + nodeOffset + offs; UInt32 keyLen = Get16(r); UInt32 parentID = Get32(r + 2); if (keyLen < 6 || (keyLen & 1) != 0 || keyLen + 2 > recSize) @@ -952,7 +967,6 @@ HRESULT CDatabase::LoadCatalog(const CFork &fork, const CObjectVector<CIdExtents type != RECORD_TYPE_FILE) continue; - const unsigned kBasicRecSize = 0x58; if (recSize < kBasicRecSize) return S_FALSE; @@ -1042,7 +1056,7 @@ HRESULT CDatabase::LoadCatalog(const CFork &fork, const CObjectVector<CIdExtents } if (progress && (Items.Size() & 0xFFF) == 0) { - UInt64 numItems = Items.Size(); + const UInt64 numItems = Items.Size(); RINOK(progress->SetCompleted(&numItems, NULL)); } } @@ -1286,9 +1300,12 @@ HRESULT CDatabase::Open2(IInStream *inStream, IArchiveOpenCallback *progress) if (h.NumFolders > ((UInt32)1 << 29) || h.NumFiles > ((UInt32)1 << 30)) return S_FALSE; + + RINOK(inStream->Seek(0, STREAM_SEEK_END, &ArcFileSize)); + if (progress) { - UInt64 numFiles = (UInt64)h.NumFiles + h.NumFolders + 1; + const UInt64 numFiles = (UInt64)h.NumFiles + h.NumFolders + 1; RINOK(progress->SetTotal(&numFiles, NULL)); } @@ -1313,13 +1330,6 @@ HRESULT CDatabase::Open2(IInStream *inStream, IArchiveOpenCallback *progress) h.VolID = Get64(p + 0x68); */ - /* - UInt64 endPos; - RINOK(inStream->Seek(0, STREAM_SEEK_END, &endPos)); - if ((endPos >> h.BlockSizeLog) < h.NumBlocks) - return S_FALSE; - */ - ResFileName = kResFileName; CFork extentsFork, catalogFork, attrFork; @@ -1499,7 +1509,7 @@ STDMETHODIMP CHandler::GetRawProp(UInt32 index, PROPID propID, const void **data else s = &Items[ref.ItemIndex].Name; *data = (const wchar_t *)(*s); - *dataSize = (s->Len() + 1) * sizeof(wchar_t); + *dataSize = (s->Len() + 1) * (UInt32)sizeof(wchar_t); *propType = PROP_DATA_TYPE_wchar_t_PTR_Z_LE; return S_OK; } @@ -1700,7 +1710,7 @@ HRESULT CHandler::ExtractZlibFile( } outPos += blockSize; - UInt64 progressPos = progressStart + outPos; + const UInt64 progressPos = progressStart + outPos; RINOK(extractCallback->SetCompleted(&progressPos)); } @@ -1884,7 +1894,7 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems, } pos += cur; extentRem -= cur; - UInt64 processed = currentTotalSize + pos; + const UInt64 processed = currentTotalSize + pos; RINOK(extractCallback->SetCompleted(&processed)); } } diff --git a/CPP/7zip/Archive/IArchive.h b/CPP/7zip/Archive/IArchive.h index 7d7256c9..8290c735 100644 --- a/CPP/7zip/Archive/IArchive.h +++ b/CPP/7zip/Archive/IArchive.h @@ -10,6 +10,30 @@ #define ARCHIVE_INTERFACE_SUB(i, base, x) DECL_INTERFACE_SUB(i, base, 6, x) #define ARCHIVE_INTERFACE(i, x) ARCHIVE_INTERFACE_SUB(i, IUnknown, x) +/* +How the function in 7-Zip returns object for output parameter via pointer + +1) The caller sets the value of variable before function call: + PROPVARIANT : vt = VT_EMPTY + BSTR : NULL + IUnknown* and derived interfaces : NULL + another scalar types : any non-initialized value is allowed + +2) The callee in current 7-Zip code now can free input object for output parameter: + PROPVARIANT : the callee calls VariantClear(propvaiant_ptr) for input + value stored in variable + another types : the callee ignores stored value. + +3) The callee writes new value to variable for output parameter and + returns execution to caller. + +4) The caller must free or release object returned by the callee: + PROPVARIANT : VariantClear(&propvaiant) + BSTR : SysFreeString(bstr) + IUnknown* and derived interfaces : if (ptr) ptr->Relase() +*/ + + namespace NFileTimeType { enum EEnum @@ -34,6 +58,7 @@ namespace NArcInfoFlags const UInt32 kPreArc = 1 << 9; // such archive can be stored before real archive (like SFX stub) const UInt32 kSymLinks = 1 << 10; // the handler supports symbolic links const UInt32 kHardLinks = 1 << 11; // the handler supports hard links + const UInt32 kByExtOnlyOpen = 1 << 12; // call handler only if file extension matches } namespace NArchive @@ -106,7 +131,7 @@ namespace NArchive enum { kOK = 0 - , // kError + // , kError }; } } @@ -137,13 +162,13 @@ IArchiveExtractCallback::GetStream() Int32 askExtractMode (Extract::NAskMode) if (askMode != NExtract::NAskMode::kExtract) { - then the callee can not real stream: (*inStream == NULL) + then the callee doesn't write data to stream: (*outStream == NULL) } Out: - (*inStream == NULL) - for directories - (*inStream == NULL) - if link (hard link or symbolic link) was created - if (*inStream == NULL && askMode == NExtract::NAskMode::kExtract) + (*outStream == NULL) - for directories + (*outStream == NULL) - if link (hard link or symbolic link) was created + if (*outStream == NULL && askMode == NExtract::NAskMode::kExtract) { then the caller must skip extracting of that file. } diff --git a/CPP/7zip/Archive/IhexHandler.cpp b/CPP/7zip/Archive/IhexHandler.cpp index 00ff80a7..05453ee6 100644 --- a/CPP/7zip/Archive/IhexHandler.cpp +++ b/CPP/7zip/Archive/IhexHandler.cpp @@ -121,9 +121,9 @@ static int Parse(const Byte *p) #define kType_Data 0 #define kType_Eof 1 #define kType_Seg 2 -#define kType_CsIp 3 +// #define kType_CsIp 3 #define kType_High 4 -#define kType_Ip32 5 +// #define kType_Ip32 5 #define kType_MAX 5 diff --git a/CPP/7zip/Archive/Iso/IsoHandler.cpp b/CPP/7zip/Archive/Iso/IsoHandler.cpp index 2230cd23..87f4aa3b 100644 --- a/CPP/7zip/Archive/Iso/IsoHandler.cpp +++ b/CPP/7zip/Archive/Iso/IsoHandler.cpp @@ -3,6 +3,7 @@ #include "StdAfx.h" #include "../../../Common/ComTry.h" +#include "../../../Common/MyLinux.h" #include "../../../Common/StringConvert.h" #include "../../../Windows/PropVariant.h" @@ -221,16 +222,15 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val case kpidSymLink: if (_archive.IsSusp) { - UString s; UInt32 mode; if (item.GetPx(_archive.SuspSkipSize, k_Px_Mode, mode)) { - if (((mode >> 12) & 0xF) == 10) + if (MY_LIN_S_ISLNK(mode)) { AString s8; if (item.GetSymLink(_archive.SuspSkipSize, s8)) { - s = MultiByteToUnicodeString(s8, CP_OEMCP); + UString s = MultiByteToUnicodeString(s8, CP_OEMCP); prop = s; } } diff --git a/CPP/7zip/Archive/Iso/IsoIn.cpp b/CPP/7zip/Archive/Iso/IsoIn.cpp index b0bfb164..211b3eea 100644 --- a/CPP/7zip/Archive/Iso/IsoIn.cpp +++ b/CPP/7zip/Archive/Iso/IsoIn.cpp @@ -299,10 +299,12 @@ void CInArchive::ReadVolumeDescriptor(CVolumeDescriptor &d) static const Byte kSig_CD001[5] = { 'C', 'D', '0', '0', '1' }; +/* static const Byte kSig_NSR02[5] = { 'N', 'S', 'R', '0', '2' }; static const Byte kSig_NSR03[5] = { 'N', 'S', 'R', '0', '3' }; static const Byte kSig_BEA01[5] = { 'B', 'E', 'A', '0', '1' }; static const Byte kSig_TEA01[5] = { 'T', 'E', 'A', '0', '1' }; +*/ static inline bool CheckSignature(const Byte *sig, const Byte *data) { diff --git a/CPP/7zip/Archive/Iso/IsoItem.h b/CPP/7zip/Archive/Iso/IsoItem.h index 5ae13a60..a42ae039 100644 --- a/CPP/7zip/Archive/Iso/IsoItem.h +++ b/CPP/7zip/Archive/Iso/IsoItem.h @@ -149,7 +149,7 @@ struct CDirRecord } - const bool GetSymLink(int skipSize, AString &link) const + bool GetSymLink(int skipSize, AString &link) const { link.Empty(); const Byte *p = NULL; @@ -208,7 +208,7 @@ struct CDirRecord return true; } - static const bool GetLe32Be32(const Byte *p, UInt32 &dest) + static bool GetLe32Be32(const Byte *p, UInt32 &dest) { UInt32 v1 = GetUi32(p); UInt32 v2 = GetBe32(p + 4); @@ -221,7 +221,7 @@ struct CDirRecord } - const bool GetPx(int skipSize, unsigned pxType, UInt32 &val) const + bool GetPx(int skipSize, unsigned pxType, UInt32 &val) const { val = 0; const Byte *p = NULL; @@ -237,7 +237,7 @@ struct CDirRecord } /* - const bool GetTf(int skipSize, unsigned pxType, CRecordingDateTime &t) const + bool GetTf(int skipSize, unsigned pxType, CRecordingDateTime &t) const { const Byte *p = NULL; unsigned len = 0; diff --git a/CPP/7zip/Archive/LzhHandler.cpp b/CPP/7zip/Archive/LzhHandler.cpp index 53d69db7..e1984d28 100644 --- a/CPP/7zip/Archive/LzhHandler.cpp +++ b/CPP/7zip/Archive/LzhHandler.cpp @@ -41,6 +41,7 @@ static UInt16 g_LzhCrc16Table[256]; #define CRC16_UPDATE_BYTE(crc, b) (g_LzhCrc16Table[((crc) ^ (b)) & 0xFF] ^ ((crc) >> 8)) +UInt32 LzhCrc16Update(UInt32 crc, const void *data, size_t size); UInt32 LzhCrc16Update(UInt32 crc, const void *data, size_t size) { const Byte *p = (const Byte *)data; @@ -83,13 +84,7 @@ struct CExtension AString GetString() const { AString s; - for (size_t i = 0; i < Data.Size(); i++) - { - char c = (char)Data[i]; - if (c == 0) - break; - s += c; - } + s.SetFrom_CalcLen((const char *)(const Byte *)Data, (unsigned)Data.Size()); return s; } }; @@ -184,11 +179,13 @@ struct CItem return i; return -1; } + bool GetUnixTime(UInt32 &value) const { value = 0; int index = FindExt(kExtIdUnixTime); - if (index < 0) + if (index < 0 + || Extensions[index].Data.Size() < 4) { if (Level == 2) { @@ -220,13 +217,14 @@ struct CItem AString GetName() const { - AString dirName (GetDirName()); + AString s (GetDirName()); const char kDirSeparator = '\\'; // check kDirSeparator in Linux - dirName.Replace((char)(unsigned char)0xFF, kDirSeparator); - if (!dirName.IsEmpty() && dirName.Back() != kDirSeparator) - dirName += kDirSeparator; - return dirName + GetFileName(); + s.Replace((char)(unsigned char)0xFF, kDirSeparator); + if (!s.IsEmpty() && s.Back() != kDirSeparator) + s += kDirSeparator; + s += GetFileName(); + return s; } }; @@ -332,7 +330,7 @@ static HRESULT GetNextItem(ISequentialInStream *stream, bool &filled, CItem &ite return S_FALSE; CExtension ext; RINOK(ReadStream_FALSE(stream, &ext.Type, 1)) - nextSize -= 3; + nextSize = (UInt16)(nextSize - 3); ext.Data.Alloc(nextSize); RINOK(ReadStream_FALSE(stream, (Byte *)ext.Data, nextSize)) item.Extensions.Add(ext); diff --git a/CPP/7zip/Archive/LzmaHandler.cpp b/CPP/7zip/Archive/LzmaHandler.cpp index 9eac3ca1..ba547c83 100644 --- a/CPP/7zip/Archive/LzmaHandler.cpp +++ b/CPP/7zip/Archive/LzmaHandler.cpp @@ -242,29 +242,25 @@ STDMETHODIMP CHandler::GetNumberOfItems(UInt32 *numItems) } -static void DictSizeToString(UInt32 val, char *s) +static char * DictSizeToString(UInt32 val, char *s) { for (unsigned i = 0; i <= 31; i++) if (((UInt32)1 << i) == val) - { - ::ConvertUInt32ToString(i, s); - return; - } + return ::ConvertUInt32ToString(i, s); char c = 'b'; if ((val & ((1 << 20) - 1)) == 0) { val >>= 20; c = 'm'; } else if ((val & ((1 << 10) - 1)) == 0) { val >>= 10; c = 'k'; } - ::ConvertUInt32ToString(val, s); - s += MyStringLen(s); + s = ::ConvertUInt32ToString(val, s); *s++ = c; *s = 0; + return s; } static char *AddProp32(char *s, const char *name, UInt32 v) { *s++ = ':'; s = MyStpCpy(s, name); - ::ConvertUInt32ToString(v, s); - return s + MyStringLen(s); + return ::ConvertUInt32ToString(v, s); } void CHandler::GetMethod(NCOM::CPropVariant &prop) @@ -277,8 +273,7 @@ void CHandler::GetMethod(NCOM::CPropVariant &prop) if (_header.FilterID != 0) s = MyStpCpy(s, "BCJ "); s = MyStpCpy(s, "LZMA:"); - DictSizeToString(_header.GetDicSize(), s); - s += strlen(s); + s = DictSizeToString(_header.GetDicSize(), s); UInt32 d = _header.GetProp(); // if (d != 0x5D) @@ -315,10 +310,10 @@ API_FUNC_static_IsArc IsArc_Lzma(const Byte *p, size_t size) return k_IsArc_Res_NEED_MORE; if (p[0] >= 5 * 5 * 9) return k_IsArc_Res_NO; - UInt64 unpackSize = GetUi64(p + 1 + 4); + const UInt64 unpackSize = GetUi64(p + 1 + 4); if (unpackSize != (UInt64)(Int64)-1) { - if (size >= ((UInt64)1 << 56)) + if (unpackSize >= ((UInt64)1 << 56)) return k_IsArc_Res_NO; } if (unpackSize != 0) diff --git a/CPP/7zip/Archive/MachoHandler.cpp b/CPP/7zip/Archive/MachoHandler.cpp index 1f65574d..bc8ba223 100644 --- a/CPP/7zip/Archive/MachoHandler.cpp +++ b/CPP/7zip/Archive/MachoHandler.cpp @@ -35,11 +35,11 @@ namespace NMacho { #define CPU_SUBTYPE_I386_ALL 3 -#define CPU_TYPE_PPC64 (CPU_ARCH_ABI64 | CPU_TYPE_PPC) +// #define CPU_TYPE_PPC64 (CPU_ARCH_ABI64 | CPU_TYPE_PPC) #define CPU_TYPE_AMD64 (CPU_ARCH_ABI64 | CPU_TYPE_386) #define CPU_TYPE_ARM64 (CPU_ARCH_ABI64 | CPU_TYPE_ARM) -#define CPU_SUBTYPE_LIB64 (1 << 31) +#define CPU_SUBTYPE_LIB64 ((UInt32)1 << 31) #define CPU_SUBTYPE_POWERPC_970 100 diff --git a/CPP/7zip/Archive/MbrHandler.cpp b/CPP/7zip/Archive/MbrHandler.cpp index 14a1224c..026696f3 100644 --- a/CPP/7zip/Archive/MbrHandler.cpp +++ b/CPP/7zip/Archive/MbrHandler.cpp @@ -51,10 +51,10 @@ struct CChs bool Check() const { return GetSector() > 0; } }; -#define RINOZ(x) { int __tt = (x); if (__tt != 0) return __tt; } // Chs in some MBRs contains only low bits of "Cyl number". So we disable check. /* +#define RINOZ(x) { int __tt = (x); if (__tt != 0) return __tt; } static int CompareChs(const CChs &c1, const CChs &c2) { RINOZ(MyCompare(c1.GetCyl(), c2.GetCyl())); diff --git a/CPP/7zip/Archive/MubHandler.cpp b/CPP/7zip/Archive/MubHandler.cpp index 6d054356..c790265d 100644 --- a/CPP/7zip/Archive/MubHandler.cpp +++ b/CPP/7zip/Archive/MubHandler.cpp @@ -33,7 +33,7 @@ namespace NMub { #define MACH_CPU_TYPE_AMD64 (MACH_CPU_ARCH_ABI64 | MACH_CPU_TYPE_386) #define MACH_CPU_TYPE_ARM64 (MACH_CPU_ARCH_ABI64 | MACH_CPU_TYPE_ARM) -#define MACH_CPU_SUBTYPE_LIB64 (1 << 31) +#define MACH_CPU_SUBTYPE_LIB64 ((UInt32)1 << 31) #define MACH_CPU_SUBTYPE_I386_ALL 3 @@ -124,14 +124,15 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val } if (ext) strcpy(temp, ext); - if (item.SubType != 0 && ( - item.Type != MACH_CPU_TYPE_386 && - item.Type != MACH_CPU_TYPE_AMD64 || - (item.SubType & ~(UInt32)MACH_CPU_SUBTYPE_LIB64) != MACH_CPU_SUBTYPE_I386_ALL)) + if (item.SubType != 0) + if ((item.Type != MACH_CPU_TYPE_386 && + item.Type != MACH_CPU_TYPE_AMD64) + || (item.SubType & ~(UInt32)MACH_CPU_SUBTYPE_LIB64) != MACH_CPU_SUBTYPE_I386_ALL + ) { unsigned pos = MyStringLen(temp); temp[pos++] = '-'; - ConvertUInt32ToString(item.SubType, temp + pos); + ConvertUInt32ToString(item.SubType, temp + pos); } return PropVarEm_Set_Str(value, temp); } diff --git a/CPP/7zip/Archive/Nsis/NsisHandler.cpp b/CPP/7zip/Archive/Nsis/NsisHandler.cpp index 095105fe..aa0a9175 100644 --- a/CPP/7zip/Archive/Nsis/NsisHandler.cpp +++ b/CPP/7zip/Archive/Nsis/NsisHandler.cpp @@ -50,6 +50,7 @@ static const Byte kArcProps[] = { kpidMethod, kpidSolid, + kpidBit64, kpidHeadersSize, kpidEmbeddedStubSize, kpidSubType @@ -134,6 +135,7 @@ STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value) break; } + case kpidBit64: if (_archive.Is64Bit) prop = true; break; case kpidMethod: prop = _methodString; break; case kpidSolid: prop = _archive.IsSolid; break; case kpidOffset: prop = _archive.StartOffset; break; diff --git a/CPP/7zip/Archive/Nsis/NsisIn.cpp b/CPP/7zip/Archive/Nsis/NsisIn.cpp index f4f9ab04..3c1a0f17 100644 --- a/CPP/7zip/Archive/Nsis/NsisIn.cpp +++ b/CPP/7zip/Archive/Nsis/NsisIn.cpp @@ -155,7 +155,7 @@ enum kNumCmds }; -static const unsigned kNumAdditionalParkCmds = 3; + struct CCommandInfo { @@ -506,18 +506,20 @@ void CInArchive::AddLicense(UInt32 param, Int32 langID) #endif -#define kVar_CMDLINE 20 +// #define kVar_CMDLINE 20 #define kVar_INSTDIR 21 #define kVar_OUTDIR 22 #define kVar_EXEDIR 23 -#define kVar_LANGUAGE 24 +// #define kVar_LANGUAGE 24 #define kVar_TEMP 25 #define kVar_PLUGINSDIR 26 #define kVar_EXEPATH 27 // NSIS 2.26+ -#define kVar_EXEFILE 28 // NSIS 2.26+ +// #define kVar_EXEFILE 28 // NSIS 2.26+ #define kVar_HWNDPARENT_225 27 +#ifdef NSIS_SCRIPT #define kVar_HWNDPARENT 29 +#endif // #define kVar__CLICK 30 #define kVar_Spec_OUTDIR_225 29 // NSIS 2.04 - 2.25 @@ -606,9 +608,9 @@ void CInArchive::AddParam_UInt(UInt32 value) #define NS_CODE_SKIP 252 #define NS_CODE_VAR 253 #define NS_CODE_SHELL 254 -#define NS_CODE_LANG 255 +// #define NS_CODE_LANG 255 -#define NS_3_CODE_LANG 1 +// #define NS_3_CODE_LANG 1 #define NS_3_CODE_SHELL 2 #define NS_3_CODE_VAR 3 #define NS_3_CODE_SKIP 4 @@ -1364,7 +1366,7 @@ void CInArchive::ReadString2(AString &s, UInt32 pos) #ifdef NSIS_SCRIPT -#define DEL_DIR 1 +// #define DEL_DIR 1 #define DEL_RECURSE 2 #define DEL_REBOOT 4 // #define DEL_SIMPLE 8 @@ -1445,9 +1447,11 @@ static void FlagsToString2(CDynLimBuf &s, const char * const *table, unsigned nu static bool DoesNeedQuotes(const char *s) { - char c = s[0]; - if (c == 0 || c == '#' || c == ';' || (c == '/' && s[1] == '*')) - return true; + { + char c = s[0]; + if (c == 0 || c == '#' || c == ';' || (c == '/' && s[1] == '*')) + return true; + } for (;;) { char c = *s++; @@ -1737,12 +1741,12 @@ void CNsis_CtlColors::Parse(const Byte *p) // Win32 constants #define MY__TRANSPARENT 1 -#define MY__OPAQUE 2 +// #define MY__OPAQUE 2 -#define MY__GENERIC_READ (1 << 31) -#define MY__GENERIC_WRITE (1 << 30) -#define MY__GENERIC_EXECUTE (1 << 29) -#define MY__GENERIC_ALL (1 << 28) +#define MY__GENERIC_READ ((UInt32)1 << 31) +#define MY__GENERIC_WRITE ((UInt32)1 << 30) +#define MY__GENERIC_EXECUTE ((UInt32)1 << 29) +#define MY__GENERIC_ALL ((UInt32)1 << 28) #define MY__CREATE_NEW 1 #define MY__CREATE_ALWAYS 2 @@ -2068,9 +2072,11 @@ void CSection::Parse(const Byte *p) #define SF_BOLD (1 << 3) #define SF_RO (1 << 4) #define SF_EXPAND (1 << 5) +/* #define SF_PSELECTED (1 << 6) #define SF_TOGGLED (1 << 7) #define SF_NAMECHG (1 << 8) +*/ bool CInArchive::PrintSectionBegin(const CSection §, unsigned index) { @@ -2115,7 +2121,7 @@ bool CInArchive::PrintSectionBegin(const CSection §, unsigned index) Script += ' '; else */ - SmallSpaceComment(); + SmallSpaceComment(); Script += "Section_"; Add_UInt(index); @@ -2290,14 +2296,15 @@ bool CInArchive::CompareCommands(const Byte *rawCmds, const Byte *sequence, size return true; } -#endif static const UInt32 kSectionSize_base = 6 * 4; -static const UInt32 kSectionSize_8bit = kSectionSize_base + 1024; -static const UInt32 kSectionSize_16bit = kSectionSize_base + 1024 * 2; -static const UInt32 kSectionSize_16bit_Big = kSectionSize_base + 8196 * 2; +// static const UInt32 kSectionSize_8bit = kSectionSize_base + 1024; +// static const UInt32 kSectionSize_16bit = kSectionSize_base + 1024 * 2; +// static const UInt32 kSectionSize_16bit_Big = kSectionSize_base + 8196 * 2; // 8196 is default string length in NSIS-Unicode since 2.37.3 +#endif + static void AddString(AString &dest, const char *src) { @@ -2330,8 +2337,13 @@ AString CInArchive::GetFormatDescription() const if (IsUnicode) AddString(s, "Unicode"); + + if (Is64Bit) + AddString(s, "64-bit"); + if (LogCmdIsEnabled) AddString(s, "log"); + if (BadCmd >= 0) { AddString(s, "BadCmd="); @@ -2342,9 +2354,11 @@ AString CInArchive::GetFormatDescription() const #ifdef NSIS_SCRIPT +static const unsigned kNumAdditionalParkCmds = 3; + unsigned CInArchive::GetNumSupportedCommands() const { - unsigned numCmds = IsPark() ? kNumCmds : kNumCmds - kNumAdditionalParkCmds; + unsigned numCmds = IsPark() ? (unsigned)kNumCmds : (unsigned)(kNumCmds) - kNumAdditionalParkCmds; if (!LogCmdIsEnabled) numCmds--; if (!IsUnicode) @@ -2792,26 +2806,20 @@ bool CInArchive::IsAbsolutePathVar(UInt32 strPos) const return false; } -#define IS_LETTER_CHAR(c) ((c) >= 'a' && (c) <= 'z' || (c) >= 'A' && (c) <= 'Z') +#define IS_LETTER_CHAR(c) (((c) >= 'a' && (c) <= 'z') || ((c) >= 'A' && (c) <= 'Z')) // We use same check as in NSIS decoder -bool IsDrivePath(const wchar_t *s) { return IS_LETTER_CHAR(s[0]) && s[1] == ':' /* && s[2] == '\\' */ ; } -bool IsDrivePath(const char *s) { return IS_LETTER_CHAR(s[0]) && s[1] == ':' /* && s[2] == '\\' */ ; } +static bool IsDrivePath(const wchar_t *s) { return IS_LETTER_CHAR(s[0]) && s[1] == ':' /* && s[2] == '\\' */ ; } +static bool IsDrivePath(const char *s) { return IS_LETTER_CHAR(s[0]) && s[1] == ':' /* && s[2] == '\\' */ ; } static bool IsAbsolutePath(const wchar_t *s) { - return - s[0] == WCHAR_PATH_SEPARATOR && - s[1] == WCHAR_PATH_SEPARATOR || - IsDrivePath(s); + return (s[0] == WCHAR_PATH_SEPARATOR && s[1] == WCHAR_PATH_SEPARATOR) || IsDrivePath(s); } static bool IsAbsolutePath(const char *s) { - return - s[0] == CHAR_PATH_SEPARATOR && - s[1] == CHAR_PATH_SEPARATOR || - IsDrivePath(s); + return (s[0] == CHAR_PATH_SEPARATOR && s[1] == CHAR_PATH_SEPARATOR) || IsDrivePath(s); } void CInArchive::SetItemName(CItem &item, UInt32 strPos) @@ -3748,8 +3756,8 @@ HRESULT CInArchive::ReadEntries(const CBlockHeader &bh) for (UInt32 j = i - 1; j >= kkk + 3; j--) { - const Byte *pCmd = p + kCmdSize * (j - kkk); - AddParam(GET_CMD_PARAM(pCmd, 0)); + const Byte *pCmd2 = p + kCmdSize * (j - kkk); + AddParam(GET_CMD_PARAM(pCmd2, 0)); } NewLine(); Tab(true); @@ -3850,13 +3858,13 @@ HRESULT CInArchive::ReadEntries(const CBlockHeader &bh) { case k_ExecFlags_AutoClose: case k_ExecFlags_RebootFlag: - if (v < 2) s2 = (v == 0) ? "false" : "true"; break; + if (v < 2) { s2 = (v == 0) ? "false" : "true"; } break; case k_ExecFlags_ShellVarContext: - if (v < 2) s2 = (v == 0) ? "current" : "all"; break; + if (v < 2) { s2 = (v == 0) ? "current" : "all"; } break; case k_ExecFlags_Silent: - if (v < 2) s2 = (v == 0) ? "normal" : "silent"; break; + if (v < 2) { s2 = (v == 0) ? "normal" : "silent"; } break; case k_ExecFlags_RegView: - if (v == 0) s2 = "32"; + if (v == 0) s2 = "32"; else if (v == 256) s2 = "64"; break; case k_ExecFlags_DetailsPrint: @@ -3864,6 +3872,7 @@ HRESULT CInArchive::ReadEntries(const CBlockHeader &bh) else if (v == 2) s2 = "textonly"; else if (v == 4) s2 = "listonly"; else if (v == 6) s2 = "none"; + break; } if (s2) { @@ -4400,7 +4409,7 @@ HRESULT CInArchive::ReadEntries(const CBlockHeader &bh) s += 'F'; Add_UInt(key - kMy_VK_F1 + 1); } - else if (key >= 'A' && key <= 'Z' || key >= '0' && key <= '9') + else if ((key >= 'A' && key <= 'Z') || (key >= '0' && key <= '9')) s += (char)key; else { @@ -4687,6 +4696,7 @@ HRESULT CInArchive::ReadEntries(const CBlockHeader &bh) s += "Text"; AddParam(params[1]); } + break; } case EW_SECTIONSET: @@ -4829,9 +4839,6 @@ HRESULT CInArchive::ReadEntries(const CBlockHeader &bh) } else { - if (curSectionIndex == 49) - curSectionIndex = curSectionIndex; - if (PrintSectionBegin(sect, curSectionIndex)) curSectionIndex++; else @@ -4846,8 +4853,8 @@ HRESULT CInArchive::ReadEntries(const CBlockHeader &bh) static int CompareItems(void *const *p1, void *const *p2, void *param) { - const CItem &i1 = **(CItem **)p1; - const CItem &i2 = **(CItem **)p2; + const CItem &i1 = **(const CItem *const *)p1; + const CItem &i2 = **(const CItem *const *)p2; RINOZ(MyCompare(i1.Pos, i2.Pos)); const CInArchive *inArchive = (const CInArchive *)param; if (inArchive->IsUnicode) @@ -4970,14 +4977,15 @@ HRESULT CInArchive::SortItems() return S_OK; } +#ifdef NSIS_SCRIPT // Flags for common_header.flags -#define CH_FLAGS_DETAILS_SHOWDETAILS 1 -#define CH_FLAGS_DETAILS_NEVERSHOW 2 +// #define CH_FLAGS_DETAILS_SHOWDETAILS 1 +// #define CH_FLAGS_DETAILS_NEVERSHOW 2 #define CH_FLAGS_PROGRESS_COLORED 4 #define CH_FLAGS_SILENT 8 #define CH_FLAGS_SILENT_LOG 16 #define CH_FLAGS_AUTO_CLOSE 32 -#define CH_FLAGS_DIR_NO_SHOW 64 // unused now +// #define CH_FLAGS_DIR_NO_SHOW 64 // unused now #define CH_FLAGS_NO_ROOT_DIR 128 #define CH_FLAGS_COMP_ONLY_ON_CUSTOM 256 #define CH_FLAGS_NO_CUSTOM 512 @@ -4989,29 +4997,59 @@ static const char * const k_PostStrings[] = , "uninstcmd" // NSIS 2.25+, used by uninstaller: , "wininit" // NSIS 2.25+, used by move file on reboot }; +#endif + + +void CBlockHeader::Parse(const Byte *p, unsigned bhoSize) +{ + if (bhoSize == 12) + { + // UInt64 a = GetUi64(p); + if (GetUi32(p + 4) != 0) + throw 1; + } + Offset = GetUi32(p); + Num = GetUi32(p + bhoSize - 4); +} + +#define PARSE_BH(k, bh) bh.Parse (p1 + 4 + bhoSize * k, bhoSize) + HRESULT CInArchive::Parse() { // UInt32 offset = ReadUInt32(); // ???? offset == FirstHeader.HeaderSize - const Byte *p = _data; + const Byte * const p1 = _data; + + if (_size < 4 + 12 * 8) + Is64Bit = false; + else + { + Is64Bit = true; + // here we test high 32-bit of possible UInt64 CBlockHeader::Offset field + for (int k = 0; k < 8; k++) + if (GetUi32(p1 + 4 + 12 * k + 4) != 0) + Is64Bit = false; + } - if (_size < 4 + 8 * 8) + const unsigned bhoSize = Is64Bit ? 12 : 8; + if (_size < 4 + bhoSize * 8) return S_FALSE; CBlockHeader bhEntries, bhStrings, bhLangTables; - bhEntries.Parse(p + 4 + 8 * 2); - bhStrings.Parse(p + 4 + 8 * 3); - bhLangTables.Parse(p + 4 + 8 * 4); + + PARSE_BH (2, bhEntries); + PARSE_BH (3, bhStrings); + PARSE_BH (4, bhLangTables); #ifdef NSIS_SCRIPT CBlockHeader bhFont; - bhPages.Parse(p + 4 + 8 * 0); - bhSections.Parse(p + 4 + 8 * 1); - bhCtlColors.Parse(p + 4 + 8 * 5); - bhFont.Parse(p + 4 + 8 * 6); - bhData.Parse(p + 4 + 8 * 7); + PARSE_BH (0, bhPages); + PARSE_BH (1, bhSections); + PARSE_BH (5, bhCtlColors); + PARSE_BH (6, bhFont); + PARSE_BH (7, bhData); #endif @@ -5084,6 +5122,7 @@ HRESULT CInArchive::Parse() case NMethodType::kDeflate: m = "zlib"; break; case NMethodType::kBZip2: m = "bzip2"; break; case NMethodType::kLZMA: m = "lzma"; break; + default: break; } Script += "SetCompressor"; if (IsSolid) @@ -5167,7 +5206,7 @@ HRESULT CInArchive::Parse() memset(strUsed, 0, NumStringChars); { - UInt32 ehFlags = Get32(p); + UInt32 ehFlags = Get32(p1); UInt32 showDetails = ehFlags & 3;// CH_FLAGS_DETAILS_SHOWDETAILS & CH_FLAGS_DETAILS_NEVERSHOW; if (showDetails >= 1 && showDetails <= 2) { @@ -5208,11 +5247,16 @@ HRESULT CInArchive::Parse() } } - unsigned paramsOffset = 4 + 8 * 8; - if (bhPages.Offset == 276) - paramsOffset -= 8; + unsigned paramsOffset; + { + unsigned numBhs = 8; + // probably its for old NSIS? + if (bhoSize == 8 && bhPages.Offset == 276) + numBhs = 7; + paramsOffset = 4 + bhoSize * numBhs; + } - const Byte *p2 = p + paramsOffset; + const Byte *p2 = p1 + paramsOffset; { UInt32 rootKey = Get32(p2); // (rootKey = -1) in uninstaller by default (the bug in NSIS) @@ -5261,7 +5305,8 @@ HRESULT CInArchive::Parse() } UInt32 license_bg = Get32(p2 + 36); - if (license_bg != (UInt32)(Int32)-1 && license_bg != -15) // COLOR_BTNFACE + if (license_bg != (UInt32)(Int32)-1 && + license_bg != (UInt32)(Int32)-15) // COLOR_BTNFACE { Script += "LicenseBkColor"; if ((Int32)license_bg == -5) // COLOR_WINDOW @@ -5275,13 +5320,19 @@ HRESULT CInArchive::Parse() AddLF(); } - UInt32 langtable_size = Get32(p2 + 32); if (bhLangTables.Num > 0) { + const UInt32 langtable_size = Get32(p2 + 32); + if (langtable_size == (UInt32)(Int32)-1) return E_NOTIMPL; // maybe it's old NSIS archive() - UInt32 numStrings = (langtable_size - 10) / 4; + if (langtable_size < 10) + return S_FALSE; + if (bhLangTables.Num > (_size - bhLangTables.Offset) / langtable_size) + return S_FALSE; + + const UInt32 numStrings = (langtable_size - 10) / 4; _numLangStrings = numStrings; AddLF(); Separator(); @@ -5289,12 +5340,12 @@ HRESULT CInArchive::Parse() PrintNumComment("LANG STRINGS", numStrings); AddLF(); - if (licenseLangIndex >= 0) + if (licenseLangIndex >= 0 && (unsigned)licenseLangIndex < numStrings) { for (UInt32 i = 0; i < bhLangTables.Num; i++) { - const Byte *p = _data + bhLangTables.Offset + langtable_size * i; - LANGID langID = Get16(p); + const Byte * const p = _data + bhLangTables.Offset + langtable_size * i; + const UInt16 langID = Get16(p); UInt32 val = Get32(p + 10 + (UInt32)licenseLangIndex * 4); if (val != 0) { @@ -5309,33 +5360,24 @@ HRESULT CInArchive::Parse() AddLF(); } - UInt32 brandingText = 0; - UInt32 caption = 0; - UInt32 name = 0; + UInt32 names[3] = { 0 }; + UInt32 i; for (i = 0; i < bhLangTables.Num; i++) { - const Byte *p = _data + bhLangTables.Offset + langtable_size * i; - LANGID langID = Get16(p); + const Byte * const p = _data + bhLangTables.Offset + langtable_size * i; + const UInt16 langID = Get16(p); if (i == 0 || langID == 1033) _mainLang = p + 10; + for (unsigned k = 0; k < ARRAY_SIZE(names) && k < numStrings; k++) { - UInt32 v = Get32(p + 10 + 0 * 4); - if (v != 0 && (langID == 1033 || brandingText == 0)) - brandingText = v; - } - { - UInt32 v = Get32(p + 10 + 1 * 4); - if (v != 0 && (langID == 1033 || caption == 0)) - caption = v; - } - { - UInt32 v = Get32(p + 10 + 2 * 4); - if (v != 0 && (langID == 1033 || name == 0)) - name = v; + UInt32 v = Get32(p + 10 + k * 4); + if (v != 0 && (langID == 1033 || names[k] == 0)) + names[k] = v; } } - + + const UInt32 name = names[2]; if (name != 0) { Script += "Name"; @@ -5346,6 +5388,7 @@ HRESULT CInArchive::Parse() } /* + const UInt32 caption = names[1]; if (caption != 0) { Script += "Caption"; @@ -5354,6 +5397,7 @@ HRESULT CInArchive::Parse() } */ + const UInt32 brandingText = names[0]; if (brandingText != 0) { Script += "BrandingText"; @@ -5365,8 +5409,8 @@ HRESULT CInArchive::Parse() for (i = 0; i < bhLangTables.Num; i++) { - const Byte *p = _data + bhLangTables.Offset + langtable_size * i; - LANGID langID = Get16(p); + const Byte * const p = _data + bhLangTables.Offset + langtable_size * i; + const UInt16 langID = Get16(p); AddLF(); AddCommentAndString("LANG:"); @@ -5641,10 +5685,12 @@ HRESULT CInArchive::Open2(const Byte *sig, size_t size) if (Get32((const Byte *)buf) != FirstHeader.HeaderSize) return S_FALSE; } - size_t processedSize = FirstHeader.HeaderSize; - RINOK(Decoder.Read(_data, &processedSize)); - if (processedSize != FirstHeader.HeaderSize) - return S_FALSE; + { + size_t processedSize = FirstHeader.HeaderSize; + RINOK(Decoder.Read(_data, &processedSize)); + if (processedSize != FirstHeader.HeaderSize) + return S_FALSE; + } #ifdef NSIS_SCRIPT if (IsSolid) @@ -5824,14 +5870,25 @@ HRESULT CInArchive::Open(IInStream *inStream, const UInt64 *maxCheckStartPositio DataStreamOffset = pos + kStartHeaderSize; FirstHeader.Flags = Get32(buf); if ((FirstHeader.Flags & (~kFlagsMask)) != 0) + { + // return E_NOTIMPL; return S_FALSE; + } IsInstaller = (FirstHeader.Flags & NFlags::kUninstall) == 0; FirstHeader.HeaderSize = Get32(buf + kSignatureSize + 4); FirstHeader.ArcSize = Get32(buf + kSignatureSize + 8); if (FirstHeader.ArcSize <= kStartHeaderSize) return S_FALSE; - + + /* + if ((FirstHeader.Flags & NFlags::k_BI_ExternalFileSupport) != 0) + { + UInt32 datablock_low = Get32(buf + kSignatureSize + 12); + UInt32 datablock_high = Get32(buf + kSignatureSize + 16); + } + */ + RINOK(inStream->Seek(0, STREAM_SEEK_END, &_fileSize)); IsArc = true; @@ -5872,7 +5929,8 @@ UString CInArchive::ConvertToUnicode(const AString &s) const if (IsUnicode) { UString res; - if (ConvertUTF8ToUnicode(s, res)) + // if ( + ConvertUTF8ToUnicode(s, res); return res; } return MultiByteToUnicodeString(s); @@ -5886,6 +5944,7 @@ void CInArchive::Clear2() IsNsis200 = false; LogCmdIsEnabled = false; BadCmd = -1; + Is64Bit = false; #ifdef NSIS_SCRIPT Name.Empty(); diff --git a/CPP/7zip/Archive/Nsis/NsisIn.h b/CPP/7zip/Archive/Nsis/NsisIn.h index 028e4a5d..5c88188d 100644 --- a/CPP/7zip/Archive/Nsis/NsisIn.h +++ b/CPP/7zip/Archive/Nsis/NsisIn.h @@ -34,6 +34,11 @@ namespace NFlags const UInt32 kSilent = 2; const UInt32 kNoCrc = 4; const UInt32 kForceCrc = 8; + // NSISBI fork flags: + const UInt32 k_BI_LongOffset = 16; + const UInt32 k_BI_ExternalFileSupport = 32; + const UInt32 k_BI_ExternalFile = 64; + const UInt32 k_BI_IsStubInstaller = 128; } struct CFirstHeader @@ -58,11 +63,7 @@ struct CBlockHeader UInt32 Offset; UInt32 Num; - void Parse(const Byte *p) - { - Offset = GetUi32(p); - Num = GetUi32(p + 4); - } + void Parse(const Byte *p, unsigned bhoSize); }; struct CItem @@ -159,6 +160,7 @@ public: CByteBuffer _data; CObjectVector<CItem> Items; bool IsUnicode; + bool Is64Bit; private: UInt32 _stringsPos; // relative to _data UInt32 NumStringChars; @@ -170,7 +172,6 @@ private: ENsisType NsisType; bool IsNsis200; // NSIS 2.03 and before bool IsNsis225; // NSIS 2.25 and before - bool LogCmdIsEnabled; int BadCmd; // -1: no bad command; in another cases lowest bad command id diff --git a/CPP/7zip/Archive/NtfsHandler.cpp b/CPP/7zip/Archive/NtfsHandler.cpp index 21372033..daa01fef 100644 --- a/CPP/7zip/Archive/NtfsHandler.cpp +++ b/CPP/7zip/Archive/NtfsHandler.cpp @@ -208,7 +208,7 @@ enum Posix name can be after or before Win32 name */ -static const Byte kFileNameType_Posix = 0; // for hard links +// static const Byte kFileNameType_Posix = 0; // for hard links static const Byte kFileNameType_Win32 = 1; // after Dos name static const Byte kFileNameType_Dos = 2; // short name static const Byte kFileNameType_Win32Dos = 3; // short and full name are same @@ -386,8 +386,8 @@ struct CAttr static int CompareAttr(void *const *elem1, void *const *elem2, void *) { - const CAttr &a1 = *(*((const CAttr **)elem1)); - const CAttr &a2 = *(*((const CAttr **)elem2)); + const CAttr &a1 = *(*((const CAttr *const *)elem1)); + const CAttr &a2 = *(*((const CAttr *const *)elem2)); RINOZ(MyCompare(a1.Type, a2.Type)); if (a1.Name.IsEmpty()) { @@ -717,12 +717,16 @@ static size_t Lznt1Dec(Byte *dest, size_t outBufLim, size_t destLen, const Byte UInt32 dist = (v >> (16 - numDistBits)); if (dist >= sbOffset) return 0; - Int32 offs = -1 - dist; - Byte *p = dest + destSize; - for (UInt32 t = 0; t < len; t++) - p[t] = p[t + offs]; + const size_t offs = 1 + dist; + Byte *p = dest + destSize - offs; destSize += len; sbOffset += len; + const Byte *lim = p + len; + p[offs] = *p; ++p; + p[offs] = *p; ++p; + do + p[offs] = *p; + while (++p != lim); } } } @@ -1094,7 +1098,7 @@ struct CMftRec void CMftRec::ParseDataNames() { DataRefs.Clear(); - DataAttrs.Sort(CompareAttr, 0); + DataAttrs.Sort(CompareAttr, NULL); for (unsigned i = 0; i < DataAttrs.Size();) { @@ -2188,7 +2192,7 @@ STDMETHODIMP CHandler::GetRawProp(UInt32 index, PROPID propID, const void **data *data = (const wchar_t *)EmptyString; else *data = s->GetRawPtr(); - *dataSize = (s->Len() + 1) * sizeof(wchar_t); + *dataSize = (s->Len() + 1) * (UInt32)sizeof(wchar_t); *propType = PROP_DATA_TYPE_wchar_t_PTR_Z_LE; #endif return S_OK; diff --git a/CPP/7zip/Archive/PeHandler.cpp b/CPP/7zip/Archive/PeHandler.cpp index 675293ba..ee265571 100644 --- a/CPP/7zip/Archive/PeHandler.cpp +++ b/CPP/7zip/Archive/PeHandler.cpp @@ -363,8 +363,8 @@ struct CSection CSection(): IsRealSect(false), IsDebug(false), IsAdditionalSection(false) {} - const UInt32 GetSizeExtract() const { return PSize; } - const UInt32 GetSizeMin() const { return MyMin(PSize, VSize); } + UInt32 GetSizeExtract() const { return PSize; } + UInt32 GetSizeMin() const { return MyMin(PSize, VSize); } void UpdateTotalSize(UInt32 &totalSize) const { @@ -768,15 +768,15 @@ class CHandler: bool _oneLang; UString _resourcesPrefix; CUsedBitmap _usedRes; - bool _parseResources; + // bool _parseResources; bool _checksumError; bool IsOpt() const { return _header.OptHeaderSize != 0; } COptHeader _optHeader; - bool _allowTail; bool _coffMode; + bool _allowTail; HRESULT LoadDebugSections(IInStream *stream, bool &thereIsSection); HRESULT Open2(IInStream *stream, IArchiveOpenCallback *callback); @@ -2005,10 +2005,12 @@ HRESULT CHandler::OpenResources(unsigned sectionIndex, IInStream *stream, IArchi const UInt32 mask = ((UInt32)1 << numBits) - 1; const size_t end = (size_t)((sect.VSize + mask) & (UInt32)~mask); if (end > sect.VSize) + { if (end <= sect.PSize) fileSize = end; else fileSize = sect.PSize; + } } } @@ -2459,7 +2461,7 @@ HRESULT CHandler::Open2(IInStream *stream, IArchiveOpenCallback *callback) return S_FALSE; } - _parseResources = true; + bool _parseResources = true; // _parseResources = false; UInt64 mainSize = 0, mainSize2 = 0; @@ -2467,11 +2469,11 @@ HRESULT CHandler::Open2(IInStream *stream, IArchiveOpenCallback *callback) for (i = 0; i < _sections.Size(); i++) { const CSection § = _sections[i]; - CMixItem mixItem; - mixItem.SectionIndex = i; if (IsOpt()) - if (_parseResources && sect.Name == ".rsrc" && _items.IsEmpty()) + if (_parseResources && sect.Name == ".rsrc") { + // 20.01: we try to parse only first copy of .rsrc section. + _parseResources = false; const unsigned numMixItems = _mixItems.Size(); HRESULT res = OpenResources(i, stream, callback); if (res == S_OK) @@ -2483,6 +2485,8 @@ HRESULT CHandler::Open2(IInStream *stream, IArchiveOpenCallback *callback) const CResItem &item = _items[j]; if (item.Enabled) { + CMixItem mixItem; + mixItem.SectionIndex = i; mixItem.ResourceIndex = j; if (item.IsRcDataOrUnknown()) { @@ -2531,6 +2535,7 @@ HRESULT CHandler::Open2(IInStream *stream, IArchiveOpenCallback *callback) _mixItems.DeleteFrom(numMixItems); CloseResources(); } + if (sect.IsAdditionalSection) { if (sect.PSize >= mainSize) @@ -2542,6 +2547,9 @@ HRESULT CHandler::Open2(IInStream *stream, IArchiveOpenCallback *callback) else if (sect.PSize >= mainSize2) mainSize2 = sect.PSize; } + + CMixItem mixItem; + mixItem.SectionIndex = i; _mixItems.Add(mixItem); } @@ -3017,7 +3025,7 @@ static const Byte kProps[] = enum { - kpidSubSystem = kpidUserDefined, + kpidSubSystem = kpidUserDefined // , kpidImageBase }; diff --git a/CPP/7zip/Archive/PpmdHandler.cpp b/CPP/7zip/Archive/PpmdHandler.cpp index c80400bc..05a07e53 100644 --- a/CPP/7zip/Archive/PpmdHandler.cpp +++ b/CPP/7zip/Archive/PpmdHandler.cpp @@ -1,5 +1,5 @@ /* PpmdHandler.cpp -- PPMd format handler -2015-11-30 : Igor Pavlov : Public domain +2020 : Igor Pavlov : Public domain This code is based on: PPMd var.H (2001) / var.I (2002): Dmitry Shkarin : Public domain Carryless rangecoder (1999): Dmitry Subbotin : Public domain */ @@ -59,7 +59,7 @@ struct CItem unsigned Restor; HRESULT ReadHeader(ISequentialInStream *s, UInt32 &headerSize); - bool IsSupported() const { return Ver == 7 || (Ver == 8 && Restor <= 1); } + bool IsSupported() const { return Ver == 7 || (Ver == 8 && Restor < PPMD8_RESTORE_METHOD_UNSUPPPORTED); } }; HRESULT CItem::ReadHeader(ISequentialInStream *s, UInt32 &headerSize) @@ -218,91 +218,11 @@ STDMETHODIMP CHandler::Close() return S_OK; } -static const UInt32 kTopValue = (1 << 24); -static const UInt32 kBot = (1 << 15); -struct CRangeDecoder -{ - IPpmd7_RangeDec vt; - UInt32 Range; - UInt32 Code; - UInt32 Low; - CByteInBufWrap *Stream; - -public: - bool Init() - { - Code = 0; - Low = 0; - Range = 0xFFFFFFFF; - for (int i = 0; i < 4; i++) - Code = (Code << 8) | Stream->ReadByte(); - return Code < 0xFFFFFFFF; - } - - void Normalize() - { - while ((Low ^ (Low + Range)) < kTopValue || - Range < kBot && ((Range = (0 - Low) & (kBot - 1)), 1)) - { - Code = (Code << 8) | Stream->ReadByte(); - Range <<= 8; - Low <<= 8; - } - } - - CRangeDecoder(); -}; - - -extern "C" { - -#define GET_RangeDecoder CRangeDecoder *p = CONTAINER_FROM_VTBL(pp, CRangeDecoder, vt); - -static UInt32 Range_GetThreshold(const IPpmd7_RangeDec *pp, UInt32 total) -{ - GET_RangeDecoder - return p->Code / (p->Range /= total); -} - -static void Range_Decode(const IPpmd7_RangeDec *pp, UInt32 start, UInt32 size) -{ - GET_RangeDecoder - start *= p->Range; - p->Low += start; - p->Code -= start; - p->Range *= size; - p->Normalize(); -} - -static UInt32 Range_DecodeBit(const IPpmd7_RangeDec *pp, UInt32 size0) -{ - GET_RangeDecoder - if (p->Code / (p->Range >>= 14) < size0) - { - Range_Decode(&p->vt, 0, size0); - return 0; - } - else - { - Range_Decode(&p->vt, size0, (1 << 14) - size0); - return 1; - } -} - -} - -CRangeDecoder::CRangeDecoder() -{ - vt.GetThreshold = Range_GetThreshold; - vt.Decode = Range_Decode; - vt.DecodeBit = Range_DecodeBit; -} struct CPpmdCpp { unsigned Ver; - CRangeDecoder _rc; CPpmd7 _ppmd7; CPpmd8 _ppmd8; @@ -339,20 +259,20 @@ struct CPpmdCpp { if (Ver == 7) { - _rc.Stream = inStream; - return _rc.Init(); + _ppmd7.rc.dec.Stream = &inStream->vt; + return (Ppmd7a_RangeDec_Init(&_ppmd7.rc.dec) != 0); } else { _ppmd8.Stream.In = &inStream->vt; - return Ppmd8_RangeDec_Init(&_ppmd8) != 0; + return Ppmd8_Init_RangeDec(&_ppmd8) != 0; } } bool IsFinishedOK() { if (Ver == 7) - return Ppmd7z_RangeDec_IsFinishedOK(&_rc); + return Ppmd7z_RangeDec_IsFinishedOK(&_ppmd7.rc.dec); return Ppmd8_RangeDec_IsFinishedOK(&_ppmd8); } }; @@ -416,14 +336,15 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems, size_t i; int sym = 0; + Byte *buf = outBuf.Buf; if (ppmd.Ver == 7) { for (i = 0; i < kBufSize; i++) { - sym = Ppmd7_DecodeSymbol(&ppmd._ppmd7, &ppmd._rc.vt); + sym = Ppmd7a_DecodeSymbol(&ppmd._ppmd7); if (inBuf.Extra || sym < 0) break; - outBuf.Buf[i] = (Byte)sym; + buf[i] = (Byte)sym; } } else @@ -433,7 +354,7 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems, sym = Ppmd8_DecodeSymbol(&ppmd._ppmd8); if (inBuf.Extra || sym < 0) break; - outBuf.Buf[i] = (Byte)sym; + buf[i] = (Byte)sym; } } diff --git a/CPP/7zip/Archive/QcowHandler.cpp b/CPP/7zip/Archive/QcowHandler.cpp index 065f59b3..200ec62d 100644 --- a/CPP/7zip/Archive/QcowHandler.cpp +++ b/CPP/7zip/Archive/QcowHandler.cpp @@ -8,6 +8,7 @@ #include "../../Common/ComTry.h" #include "../../Common/IntToString.h" +#include "../../Common/MyBuffer2.h" #include "../../Windows/PropVariant.h" @@ -31,13 +32,21 @@ namespace NQcow { static const Byte k_Signature[] = SIGNATURE; +/* +VA to PA maps: + high bits (L1) : : in L1 Table : the reference to L1 Table + mid bits (L2) : _numMidBits : in L2 Table : the reference to cluster + low bits : _clusterBits +*/ + class CHandler: public CHandlerImg { unsigned _clusterBits; unsigned _numMidBits; UInt64 _compressedFlag; - CObjectVector<CByteBuffer> _tables; + CObjArray2<UInt32> _dir; + CAlignedBuffer _table; UInt64 _cacheCluster; CByteBuffer _cache; CByteBuffer _cacheCompressed; @@ -63,7 +72,7 @@ class CHandler: public CHandlerImg UInt32 _version; UInt32 _cryptMethod; - HRESULT Seek(UInt64 offset) + HRESULT Seek2(UInt64 offset) { _posInArc = offset; return Stream->Seek(offset, STREAM_SEEK_SET, NULL); @@ -72,7 +81,7 @@ class CHandler: public CHandlerImg HRESULT InitAndSeek() { _virtPos = 0; - return Seek(0); + return Seek2(0); } HRESULT Open2(IInStream *stream, IArchiveOpenCallback *openCallback); @@ -85,10 +94,15 @@ public: }; +static const UInt32 kEmptyDirItem = (UInt32)0 - 1; + STDMETHODIMP CHandler::Read(void *data, UInt32 size, UInt32 *processedSize) { if (processedSize) *processedSize = 0; + + // printf("\nRead _virtPos = %6d size = %6d\n", (UInt32)_virtPos, size); + if (_virtPos >= _size) return S_OK; { @@ -101,9 +115,9 @@ STDMETHODIMP CHandler::Read(void *data, UInt32 size, UInt32 *processedSize) for (;;) { - UInt64 cluster = _virtPos >> _clusterBits; - size_t clusterSize = (size_t)1 << _clusterBits; - size_t lowBits = (size_t)_virtPos & (clusterSize - 1); + const UInt64 cluster = _virtPos >> _clusterBits; + const size_t clusterSize = (size_t)1 << _clusterBits; + const size_t lowBits = (size_t)_virtPos & (clusterSize - 1); { size_t rem = clusterSize - lowBits; if (size > rem) @@ -113,21 +127,19 @@ STDMETHODIMP CHandler::Read(void *data, UInt32 size, UInt32 *processedSize) if (cluster == _cacheCluster) { memcpy(data, _cache + lowBits, size); - _virtPos += size; - if (processedSize) - *processedSize = size; - return S_OK; + break; } - UInt64 high = cluster >> _numMidBits; + const UInt64 high = cluster >> _numMidBits; - if (high < _tables.Size()) + if (high < _dir.Size()) { - const CByteBuffer &buffer = _tables[(unsigned)high]; + const UInt32 tabl = _dir[(unsigned)high]; - if (buffer.Size() != 0) + if (tabl != kEmptyDirItem) { - size_t midBits = (size_t)cluster & (((size_t)1 << _numMidBits) - 1); + const Byte *buffer = _table + ((size_t)tabl << (_numMidBits + 3)); + const size_t midBits = (size_t)cluster & (((size_t)1 << _numMidBits) - 1); const Byte *p = (const Byte *)buffer + (midBits << 3); UInt64 v = Get64(p); @@ -137,19 +149,32 @@ STDMETHODIMP CHandler::Read(void *data, UInt32 size, UInt32 *processedSize) { if (_version <= 1) return E_FAIL; - unsigned numOffsetBits = (62 - (_clusterBits - 8)); - UInt64 offset = v & (((UInt64)1 << 62) - 1); + + /* + the example of table record for 12-bit clusters (4KB uncompressed). + 2 bits : isCompressed status + 4 bits : num_sectors_minus1; packSize = (num_sectors_minus1 + 1) * 512; + it uses one additional bit over unpacked cluster_bits + 49 bits : offset of 512-sector + 9 bits : offset in 512-sector + */ + + const unsigned numOffsetBits = (62 - (_clusterBits - 9 + 1)); + const UInt64 offset = v & (((UInt64)1 << 62) - 1); const size_t dataSize = ((size_t)(offset >> numOffsetBits) + 1) << 9; - offset &= ((UInt64)1 << numOffsetBits) - 1; - UInt64 sectorOffset = offset >> 9 << 9; - UInt64 offset2inCache = sectorOffset - _comprPos; + UInt64 sectorOffset = offset & (((UInt64)1 << numOffsetBits) - (1 << 9)); + const UInt64 offset2inCache = sectorOffset - _comprPos; + // _comprPos is aligned for 512-bytes + // we try to use previous _cacheCompressed that contains compressed data + // that was read for previous unpacking + if (sectorOffset >= _comprPos && offset2inCache < _comprSize) { if (offset2inCache != 0) { _comprSize -= (size_t)offset2inCache; - memmove(_cacheCompressed, _cacheCompressed + offset2inCache, _comprSize); + memmove(_cacheCompressed, _cacheCompressed + (size_t)offset2inCache, _comprSize); _comprPos = sectorOffset; } sectorOffset += _comprSize; @@ -160,25 +185,27 @@ STDMETHODIMP CHandler::Read(void *data, UInt32 size, UInt32 *processedSize) _comprSize = 0; } - // printf("\nDeflate"); - if (sectorOffset != _posInArc) + if (dataSize > _comprSize) { - // printf("\nDeflate %12I64x %12I64x\n", sectorOffset, sectorOffset - _posInArc); - RINOK(Seek(sectorOffset)); + if (sectorOffset != _posInArc) + { + // printf("\nDeflate-Seek %12I64x %12I64x\n", sectorOffset, sectorOffset - _posInArc); + RINOK(Seek2(sectorOffset)); + } + if (_cacheCompressed.Size() < dataSize) + return E_FAIL; + const size_t dataSize3 = dataSize - _comprSize; + size_t dataSize2 = dataSize3; + // printf("\n\n=======\nReadStream = %6d _comprPos = %6d \n", (UInt32)dataSize2, (UInt32)_comprPos); + RINOK(ReadStream(Stream, _cacheCompressed + _comprSize, &dataSize2)); + _posInArc += dataSize2; + if (dataSize2 != dataSize3) + return E_FAIL; + _comprSize += dataSize2; } - if (_cacheCompressed.Size() < dataSize) - return E_FAIL; - size_t dataSize3 = dataSize - _comprSize; - size_t dataSize2 = dataSize3; - RINOK(ReadStream(Stream, _cacheCompressed + _comprSize, &dataSize2)); - _posInArc += dataSize2; - if (dataSize2 != dataSize3) - return E_FAIL; - _comprSize += dataSize2; - const size_t kSectorMask = (1 << 9) - 1; - size_t offsetInSector = ((size_t)offset & kSectorMask); + const size_t offsetInSector = ((size_t)offset & kSectorMask); _bufInStreamSpec->Init(_cacheCompressed + offsetInSector, dataSize - offsetInSector); _cacheCluster = (UInt64)(Int64)-1; @@ -187,7 +214,7 @@ STDMETHODIMP CHandler::Read(void *data, UInt32 size, UInt32 *processedSize) _bufOutStreamSpec->Init(_cache, clusterSize); // Do we need to use smaller block than clusterSize for last cluster? - UInt64 blockSize64 = clusterSize; + const UInt64 blockSize64 = clusterSize; HRESULT res = _deflateDecoderSpec->Code(_bufInStream, _bufOutStream, NULL, &blockSize64, NULL); /* @@ -206,10 +233,7 @@ STDMETHODIMP CHandler::Read(void *data, UInt32 size, UInt32 *processedSize) continue; /* memcpy(data, _cache + lowBits, size); - _virtPos += size; - if (processedSize) - *processedSize = size; - return S_OK; + break; */ } @@ -221,7 +245,7 @@ STDMETHODIMP CHandler::Read(void *data, UInt32 size, UInt32 *processedSize) if (v != _posInArc) { // printf("\n%12I64x\n", v - _posInArc); - RINOK(Seek(v)); + RINOK(Seek2(v)); } HRESULT res = Stream->Read(data, size, &size); _posInArc += size; @@ -235,11 +259,13 @@ STDMETHODIMP CHandler::Read(void *data, UInt32 size, UInt32 *processedSize) } memset(data, 0, size); - _virtPos += size; - if (processedSize) - *processedSize = size; - return S_OK; + break; } + + _virtPos += size; + if (processedSize) + *processedSize = size; + return S_OK; } @@ -347,8 +373,8 @@ HRESULT CHandler::Open2(IInStream *stream, IArchiveOpenCallback *openCallback) const UInt64 backOffset = Get64(buf + 8); // UInt32 backSize = Get32(buf + 0x10); - UInt64 l1Offset = 0; - UInt32 l1Size = 0; + UInt64 l1Offset; + UInt32 l1Size; if (_version == 1) { @@ -364,8 +390,8 @@ HRESULT CHandler::Open2(IInStream *stream, IArchiveOpenCallback *openCallback) l1Offset = Get64(buf + 0x28); if (l1Offset < 0x30) return S_FALSE; - unsigned numBits2 = (_clusterBits + _numMidBits); - UInt64 l1Size64 = (_size + (((UInt64)1 << numBits2) - 1)) >> numBits2; + const unsigned numBits2 = (_clusterBits + _numMidBits); + const UInt64 l1Size64 = (_size + (((UInt64)1 << numBits2) - 1)) >> numBits2; if (l1Size64 > ((UInt32)1 << 31)) return S_FALSE; l1Size = (UInt32)l1Size64; @@ -381,8 +407,8 @@ HRESULT CHandler::Open2(IInStream *stream, IArchiveOpenCallback *openCallback) l1Size = Get32(buf + 0x24); l1Offset = Get64(buf + 0x28); // must be aligned for cluster - UInt64 refOffset = Get64(buf + 0x30); // must be aligned for cluster - UInt32 refClusters = Get32(buf + 0x38); + const UInt64 refOffset = Get64(buf + 0x30); // must be aligned for cluster + const UInt32 refClusters = Get32(buf + 0x38); // UInt32 numSnapshots = Get32(buf + 0x3C); // UInt64 snapshotsOffset = Get64(buf + 0x40); // must be aligned for cluster @@ -393,14 +419,14 @@ HRESULT CHandler::Open2(IInStream *stream, IArchiveOpenCallback *openCallback) if (refClusters != 0) { - size_t numBytes = refClusters << _clusterBits; + const size_t numBytes = refClusters << _clusterBits; /* CByteBuffer refs; refs.Alloc(numBytes); RINOK(stream->Seek(refOffset, STREAM_SEEK_SET, NULL)); RINOK(ReadStream_FALSE(stream, refs, numBytes)); */ - UInt64 end = refOffset + numBytes; + const UInt64 end = refOffset + numBytes; if (_phySize < end) _phySize = end; /* @@ -426,7 +452,7 @@ HRESULT CHandler::Open2(IInStream *stream, IArchiveOpenCallback *openCallback) CByteBuffer table; { - size_t t1SizeBytes = (size_t)l1Size << 3; + const size_t t1SizeBytes = (size_t)l1Size << 3; if ((t1SizeBytes >> 3) != l1Size) return S_FALSE; table.Alloc(t1SizeBytes); @@ -442,41 +468,72 @@ HRESULT CHandler::Open2(IInStream *stream, IArchiveOpenCallback *openCallback) } } - if (openCallback) + _compressedFlag = (_version <= 1) ? ((UInt64)1 << 63) : ((UInt64)1 << 62); + const UInt64 offsetMask = _compressedFlag - 1; + + UInt32 numTables = 0; + UInt32 i; + + for (i = 0; i < l1Size; i++) { - UInt64 totalBytes = (UInt64)l1Size << (_numMidBits + 3); - RINOK(openCallback->SetTotal(NULL, &totalBytes)); + const UInt64 v = Get64((const Byte *)table + (size_t)i * 8) & offsetMask; + if (v != 0) + numTables++; } - _compressedFlag = (_version <= 1) ? ((UInt64)1 << 63) : ((UInt64)1 << 62); - const UInt64 offsetMask = _compressedFlag - 1; + if (numTables != 0) + { + const size_t size = (size_t)numTables << (_numMidBits + 3); + if (size >> (_numMidBits + 3) != numTables) + return E_OUTOFMEMORY; + _table.Alloc(size); + if (!_table.IsAllocated()) + return E_OUTOFMEMORY; + } + + _dir.SetSize(l1Size); - for (UInt32 i = 0; i < l1Size; i++) + UInt32 curTable = 0; + + if (openCallback) { - if (openCallback) - { - UInt64 numBytes = (UInt64)i << (_numMidBits + 3); - RINOK(openCallback->SetCompleted(NULL, &numBytes)); - } + const UInt64 totalBytes = (UInt64)numTables << (_numMidBits + 3); + RINOK(openCallback->SetTotal(NULL, &totalBytes)); + } - CByteBuffer &buf2 = _tables.AddNew(); - + for (i = 0; i < l1Size; i++) + { + Byte *buf2; + const size_t midSize = (size_t)1 << (_numMidBits + 3); + { - UInt64 v = Get64((const Byte *)table + (size_t)i * 8); - v &= offsetMask; + const UInt64 v = Get64((const Byte *)table + (size_t)i * 8) & offsetMask; if (v == 0) + { + _dir[i] = kEmptyDirItem; continue; + } + + _dir[i] = curTable; + const size_t tableOffset = ((size_t)curTable << (_numMidBits + 3)); + buf2 = (Byte *)_table + tableOffset; + curTable++; + + if (openCallback && (tableOffset & 0xFFFFF) == 0) + { + const UInt64 numBytes = tableOffset; + RINOK(openCallback->SetCompleted(NULL, &numBytes)); + } - buf2.Alloc((size_t)1 << (_numMidBits + 3)); RINOK(stream->Seek(v, STREAM_SEEK_SET, NULL)); - RINOK(ReadStream_FALSE(stream, buf2, clusterSize)); + RINOK(ReadStream_FALSE(stream, buf2, midSize)); - const UInt64 end = v + clusterSize; + const UInt64 end = v + midSize; if (_phySize < end) _phySize = end; } - for (size_t k = 0; k < clusterSize; k += 8) + for (size_t k = 0; k < midSize; k += 8) { const UInt64 v = Get64((const Byte *)buf2 + (size_t)k); if (v == 0) @@ -519,12 +576,15 @@ HRESULT CHandler::Open2(IInStream *stream, IArchiveOpenCallback *openCallback) } } - UInt64 end = offset + dataSize; + const UInt64 end = offset + dataSize; if (_phySize < end) _phySize = end; } } + if (curTable != numTables) + return E_FAIL; + if (_cryptMethod != 0) _unsupported = true; @@ -538,7 +598,8 @@ HRESULT CHandler::Open2(IInStream *stream, IArchiveOpenCallback *openCallback) STDMETHODIMP CHandler::Close() { - _tables.Clear(); + _table.Free(); + _dir.Free(); _phySize = 0; _size = 0; @@ -588,7 +649,7 @@ STDMETHODIMP CHandler::GetStream(UInt32 /* index */, ISequentialInStream **strea _deflateDecoderSpec->Set_NeedFinishInput(true); } - size_t clusterSize = (size_t)1 << _clusterBits; + const size_t clusterSize = (size_t)1 << _clusterBits; _cache.AllocAtLeast(clusterSize); _cacheCompressed.AllocAtLeast(clusterSize * 2); } diff --git a/CPP/7zip/Archive/Rar/Rar5Handler.cpp b/CPP/7zip/Archive/Rar/Rar5Handler.cpp index 320771d5..bb8a2edb 100644 --- a/CPP/7zip/Archive/Rar/Rar5Handler.cpp +++ b/CPP/7zip/Archive/Rar/Rar5Handler.cpp @@ -124,19 +124,13 @@ static unsigned ReadVarInt(const Byte *p, size_t maxSize, UInt64 *val) bool CLinkInfo::Parse(const Byte *p, unsigned size) { const Byte *pStart = p; - unsigned num = ReadVarInt(p, size, &Type); - if (num == 0) return false; p += num; size -= num; - - num = ReadVarInt(p, size, &Flags); - if (num == 0) return false; p += num; size -= num; - + unsigned num; UInt64 len; - num = ReadVarInt(p, size, &len); - if (num == 0) return false; p += num; size -= num; - + num = ReadVarInt(p, size, &Type); if (num == 0) { return false; } p += num; size -= num; + num = ReadVarInt(p, size, &Flags); if (num == 0) { return false; } p += num; size -= num; + num = ReadVarInt(p, size, &len); if (num == 0) { return false; } p += num; size -= num; if (size != len) return false; - NameLen = (unsigned)len; NameOffset = (unsigned)(p - pStart); return true; @@ -319,10 +313,10 @@ bool CCryptoInfo::Parse(const Byte *p, size_t size) Cnt = 0; unsigned num = ReadVarInt(p, size, &Algo); - if (num == 0) return false; p += num; size -= num; + if (num == 0) { return false; } p += num; size -= num; num = ReadVarInt(p, size, &Flags); - if (num == 0) return false; p += num; size -= num; + if (num == 0) { return false; } p += num; size -= num; if (size > 0) Cnt = p[0]; @@ -344,10 +338,10 @@ bool CItem::FindExtra_Version(UInt64 &version) const UInt64 flags; unsigned num = ReadVarInt(p, size, &flags); - if (num == 0) return false; p += num; size -= num; + if (num == 0) { return false; } p += num; size -= num; num = ReadVarInt(p, size, &version); - if (num == 0) return false; p += num; size -= num; + if (num == 0) { return false; } p += num; size -= num; return size == 0; } @@ -406,8 +400,8 @@ void CItem::Link_to_Prop(unsigned linkType, NWindows::NCOM::CPropVariant &prop) s.SetFrom_CalcLen((const char *)(Extra + link.NameOffset), link.NameLen); UString unicode; - if (ConvertUTF8ToUnicode(s, unicode)) - prop = NItemName::GetOsPath(unicode); + ConvertUTF8ToUnicode(s, unicode); + prop = NItemName::GetOsPath(unicode); } bool CItem::GetAltStreamName(AString &name) const @@ -596,11 +590,12 @@ public: static HRESULT MySetPassword(ICryptoGetTextPassword *getTextPassword, NCrypto::NRar5::CDecoder *cryptoDecoderSpec) { - CMyComBSTR password; + CMyComBSTR_Wipe password; RINOK(getTextPassword->CryptoGetTextPassword(&password)); - AString utf8; + AString_Wipe utf8; const unsigned kPasswordLen_MAX = 127; - UString unicode = (LPCOLESTR)password; + UString_Wipe unicode; + unicode.SetFromBstr(password); if (unicode.Len() > kPasswordLen_MAX) unicode.DeleteFrom(kPasswordLen_MAX); ConvertUnicodeToUTF8(unicode, utf8); @@ -1153,7 +1148,7 @@ HRESULT CUnpacker::Code(const CItem &item, const CItem &lastItem, UInt64 packSiz } else { - res = res; + // res = res; } if (isCryptoMode) @@ -1434,8 +1429,8 @@ STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value) AString s; s.SetFrom_CalcLen((const char *)(const Byte *)cmt, (unsigned)cmt.Size()); UString unicode; - if (ConvertUTF8ToUnicode(s, unicode)) - prop = unicode; + ConvertUTF8ToUnicode(s, unicode); + prop = unicode; } } break; @@ -1686,13 +1681,12 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val if (name[0] != ':') s += ':'; s += name; - if (!ConvertUTF8ToUnicode(s, unicodeName)) - break; + ConvertUTF8ToUnicode(s, unicodeName); } else { - if (!ConvertUTF8ToUnicode(item.Name, unicodeName)) - break; + ConvertUTF8ToUnicode(item.Name, unicodeName); + if (item.Version_Defined) { char temp[32]; @@ -1752,8 +1746,8 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val { name.DeleteFrontal(1); UString unicodeName; - if (ConvertUTF8ToUnicode(name, unicodeName)) - prop = unicodeName; + ConvertUTF8ToUnicode(name, unicodeName); + prop = unicodeName; } } break; diff --git a/CPP/7zip/Archive/Rar/RarHandler.cpp b/CPP/7zip/Archive/Rar/RarHandler.cpp index dd78e312..7491c50b 100644 --- a/CPP/7zip/Archive/Rar/RarHandler.cpp +++ b/CPP/7zip/Archive/Rar/RarHandler.cpp @@ -466,7 +466,7 @@ bool CInArchive::ReadHeaderReal(const Byte *p, unsigned size, CItem &item) for (unsigned i = 0; i < sizeof(item.Salt); i++) item.Salt[i] = p[i]; p += sizeof(item.Salt); - size -= sizeof(item.Salt); + size -= (unsigned)sizeof(item.Salt); } // some rar archives have HasExtTime flag without field. @@ -526,31 +526,36 @@ HRESULT CInArchive::GetNextItem(CItem &item, ICryptoGetTextPassword *getTextPass } // m_RarAESSpec->SetRar350Mode(ArcInfo.IsEncryptOld()); - // Salt - const UInt32 kSaltSize = 8; - Byte salt[kSaltSize]; - if (!ReadBytesAndTestSize(salt, kSaltSize)) - return S_FALSE; - m_Position += kSaltSize; - RINOK(m_RarAESSpec->SetDecoderProperties2(salt, kSaltSize)) - // Password - CMyComBSTR password; - RINOK(getTextPassword->CryptoGetTextPassword(&password)) - unsigned len = 0; - if (password) - len = MyStringLen(password); - if (len > kPasswordLen_MAX) - len = kPasswordLen_MAX; - - CByteArr buffer(len * 2); - for (unsigned i = 0; i < len; i++) { - wchar_t c = password[i]; - ((Byte *)buffer)[i * 2] = (Byte)c; - ((Byte *)buffer)[i * 2 + 1] = (Byte)(c >> 8); + // Salt + const UInt32 kSaltSize = 8; + Byte salt[kSaltSize]; + if (!ReadBytesAndTestSize(salt, kSaltSize)) + return S_FALSE; + m_Position += kSaltSize; + RINOK(m_RarAESSpec->SetDecoderProperties2(salt, kSaltSize)) } - m_RarAESSpec->SetPassword((const Byte *)buffer, len * 2); + { + // Password + CMyComBSTR_Wipe password; + RINOK(getTextPassword->CryptoGetTextPassword(&password)) + unsigned len = 0; + if (password) + len = MyStringLen(password); + if (len > kPasswordLen_MAX) + len = kPasswordLen_MAX; + + CByteBuffer_Wipe buffer(len * 2); + for (unsigned i = 0; i < len; i++) + { + wchar_t c = password[i]; + ((Byte *)buffer)[i * 2] = (Byte)c; + ((Byte *)buffer)[i * 2 + 1] = (Byte)(c >> 8); + } + + m_RarAESSpec->SetPassword((const Byte *)buffer, len * 2); + } const UInt32 kDecryptedBufferSize = (1 << 12); if (m_DecryptedDataAligned.Size() == 0) @@ -1621,7 +1626,7 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems, // if (getTextPassword) { - CMyComBSTR password; + CMyComBSTR_Wipe password; RINOK(getTextPassword->CryptoGetTextPassword(&password)); if (item.UnPackVersion >= 29) @@ -1631,7 +1636,7 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems, len = MyStringLen(password); if (len > kPasswordLen_MAX) len = kPasswordLen_MAX; - CByteArr buffer(len * 2); + CByteBuffer_Wipe buffer(len * 2); for (unsigned k = 0; k < len; k++) { wchar_t c = password[k]; @@ -1642,13 +1647,14 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems, } else { - AString oemPassword; + AString_Wipe oemPassword; if (password) { - UString unicode = (LPCOLESTR)password; + UString_Wipe unicode; + unicode.SetFromBstr(password); if (unicode.Len() > kPasswordLen_MAX) unicode.DeleteFrom(kPasswordLen_MAX); - oemPassword = UnicodeStringToMultiByte(unicode, CP_OEMCP); + UnicodeStringToMultiByte2(oemPassword, unicode, CP_OEMCP); } rar20CryptoDecoderSpec->SetPassword((const Byte *)(const char *)oemPassword, oemPassword.Len()); } diff --git a/CPP/7zip/Archive/Rar/RarHandler.h b/CPP/7zip/Archive/Rar/RarHandler.h index e444bd77..a62b60cd 100644 --- a/CPP/7zip/Archive/Rar/RarHandler.h +++ b/CPP/7zip/Archive/Rar/RarHandler.h @@ -26,7 +26,7 @@ struct CInArcInfo UInt32 DataCRC; bool EndOfArchive_was_Read; - CInArcInfo(): EndFlags(0), EndOfArchive_was_Read(false), VolNumber(0) {} + CInArcInfo(): EndFlags(0), VolNumber(0), EndOfArchive_was_Read(false) {} UInt64 GetPhySize() const { return EndPos - StartPos; } diff --git a/CPP/7zip/Archive/SplitHandler.cpp b/CPP/7zip/Archive/SplitHandler.cpp index f4a10b1d..6705aee0 100644 --- a/CPP/7zip/Archive/SplitHandler.cpp +++ b/CPP/7zip/Archive/SplitHandler.cpp @@ -142,8 +142,8 @@ HRESULT CHandler::Open2(IInStream *stream, IArchiveOpenCallback *callback) } int dotPos = name.ReverseFind_Dot(); - const UString prefix = name.Left(dotPos + 1); - const UString ext = name.Ptr(dotPos + 1); + const UString prefix = name.Left((unsigned)(dotPos + 1)); + const UString ext = name.Ptr((unsigned)(dotPos + 1)); UString ext2 = ext; ext2.MakeLower_Ascii(); diff --git a/CPP/7zip/Archive/SquashfsHandler.cpp b/CPP/7zip/Archive/SquashfsHandler.cpp index 89de660f..74bc8fb8 100644 --- a/CPP/7zip/Archive/SquashfsHandler.cpp +++ b/CPP/7zip/Archive/SquashfsHandler.cpp @@ -41,9 +41,9 @@ static const unsigned kNumDirLevelsMax = (1 << 10); #define Get64(p) (be ? GetBe64(p) : GetUi64(p)) */ -UInt16 Get16b(const Byte *p, bool be) { return be ? GetBe16(p) : GetUi16(p); } -UInt32 Get32b(const Byte *p, bool be) { return be ? GetBe32(p) : GetUi32(p); } -UInt64 Get64b(const Byte *p, bool be) { return be ? GetBe64(p) : GetUi64(p); } +static UInt16 Get16b(const Byte *p, bool be) { return be ? GetBe16(p) : GetUi16(p); } +static UInt32 Get32b(const Byte *p, bool be) { return be ? GetBe32(p) : GetUi32(p); } +static UInt64 Get64b(const Byte *p, bool be) { return be ? GetBe64(p) : GetUi64(p); } #define Get16(p) Get16b(p, be) #define Get32(p) Get32b(p, be) @@ -121,6 +121,10 @@ static const char * const k_Flags[] = , "ALWAYS_FRAGMENTS" , "DUPLICATES_REMOVED" , "EXPORTABLE" + , "UNCOMPRESSED_XATTRS" + , "NO_XATTRS" + , "COMPRESSOR_OPTIONS" + , "UNCOMPRESSED_IDS" }; static const UInt32 kNotCompressedBit16 = (1 << 15); @@ -129,10 +133,10 @@ static const UInt32 kNotCompressedBit32 = (1 << 24); #define GET_COMPRESSED_BLOCK_SIZE(size) ((size) & ~kNotCompressedBit32) #define IS_COMPRESSED_BLOCK(size) (((size) & kNotCompressedBit32) == 0) -static const UInt32 kHeaderSize1 = 0x33; -static const UInt32 kHeaderSize2 = 0x3F; +// static const UInt32 kHeaderSize1 = 0x33; +// static const UInt32 kHeaderSize2 = 0x3F; static const UInt32 kHeaderSize3 = 0x77; -static const UInt32 kHeaderSize4 = 0x60; +// static const UInt32 kHeaderSize4 = 0x60; struct CHeader { @@ -1243,7 +1247,8 @@ HRESULT CHandler::Decompress(ISequentialOutStream *outStream, Byte *outBuf, bool &status, &g_Alloc); if (res != 0) return SResToHRESULT(res); - if (status != LZMA_STATUS_FINISHED_WITH_MARK) + if (status != LZMA_STATUS_FINISHED_WITH_MARK + && status != LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK) return S_FALSE; } else @@ -1310,7 +1315,7 @@ HRESULT CHandler::ReadData(CData &data, UInt64 start, UInt64 end) { if (end < start || end - start >= ((UInt64)1 << 32)) return S_FALSE; - UInt32 size = (UInt32)(end - start); + const UInt32 size = (UInt32)(end - start); RINOK(_stream->Seek(start, STREAM_SEEK_SET, NULL)); _dynOutStreamSpec->Init(); UInt32 packPos = 0; @@ -1322,8 +1327,11 @@ HRESULT CHandler::ReadData(CData &data, UInt64 start, UInt64 end) return S_FALSE; UInt32 packSize = size - packPos; RINOK(ReadMetadataBlock(packSize)); - if (_dynOutStreamSpec->GetSize() >= ((UInt64)1 << 32)) - return S_FALSE; + { + const size_t tSize = _dynOutStreamSpec->GetSize(); + if (tSize != (UInt32)tSize) + return S_FALSE; + } packPos += packSize; } data.UnpackPos.Add((UInt32)_dynOutStreamSpec->GetSize()); @@ -1487,7 +1495,7 @@ HRESULT CHandler::OpenDir(int parent, UInt32 startBlock, UInt32 offset, unsigned if (_openCodePage == CP_UTF8) { tempString.SetFrom_CalcLen((const char *)p, size); - if (!CheckUTF8(tempString)) + if (!CheckUTF8_AString(tempString)) _openCodePage = CP_OEMCP; } @@ -1608,11 +1616,14 @@ HRESULT CHandler::Open2(IInStream *inStream) { UInt32 pos = 0; UInt32 totalSize = (UInt32)_inodesData.Data.Size(); + const unsigned kMinNodeParseSize = 4; + if (_h.NumInodes > totalSize / kMinNodeParseSize) + return S_FALSE; _nodesPos.ClearAndReserve(_h.NumInodes); _nodes.ClearAndReserve(_h.NumInodes); // we use _blockToNode for binary search seed optimizations _blockToNode.ClearAndReserve(_inodesData.GetNumBlocks() + 1); - int curBlock = 0; + unsigned curBlock = 0; for (UInt32 i = 0; i < _h.NumInodes; i++) { CNode n; @@ -2090,9 +2101,9 @@ HRESULT CHandler::ReadBlock(UInt64 blockIndex, Byte *dest, size_t blockSize) bool compressed; if (blockIndex < _blockCompressed.Size()) { - compressed = _blockCompressed[(int)blockIndex]; - blockOffset = _blockOffsets[(int)blockIndex]; - packBlockSize = (UInt32)(_blockOffsets[(int)blockIndex + 1] - blockOffset); + compressed = _blockCompressed[(unsigned)blockIndex]; + blockOffset = _blockOffsets[(unsigned)blockIndex]; + packBlockSize = (UInt32)(_blockOffsets[(unsigned)blockIndex + 1] - blockOffset); blockOffset += node.StartBlock; } else @@ -2126,14 +2137,16 @@ HRESULT CHandler::ReadBlock(UInt64 blockIndex, Byte *dest, size_t blockSize) bool outBufWasWritten; UInt32 outBufWasWrittenSize; HRESULT res = Decompress(_outStream, _cachedBlock, &outBufWasWritten, &outBufWasWrittenSize, packBlockSize, _h.BlockSize); + RINOK(res); if (outBufWasWritten) _cachedUnpackBlockSize = outBufWasWrittenSize; else _cachedUnpackBlockSize = (UInt32)_outStreamSpec->GetPos(); - RINOK(res); } else { + if (packBlockSize > _h.BlockSize) + return S_FALSE; RINOK(ReadStream_FALSE(_limitedInStream, _cachedBlock, packBlockSize)); _cachedUnpackBlockSize = packBlockSize; } diff --git a/CPP/7zip/Archive/SwfHandler.cpp b/CPP/7zip/Archive/SwfHandler.cpp index ebb6acfd..9666c69d 100644 --- a/CPP/7zip/Archive/SwfHandler.cpp +++ b/CPP/7zip/Archive/SwfHandler.cpp @@ -776,21 +776,21 @@ STDMETHODIMP CHandler::Open(IInStream *stream, const UInt64 *, IArchiveOpenCallb static UInt16 Read16(CInBuffer &stream) { - UInt16 res = 0; - for (int i = 0; i < 2; i++) + UInt32 res = 0; + for (unsigned i = 0; i < 2; i++) { Byte b; if (!stream.ReadByte(b)) throw 1; - res |= (UInt16)b << (i * 8); + res |= (UInt32)b << (i * 8); } - return res; + return (UInt16)res; } static UInt32 Read32(CInBuffer &stream) { UInt32 res = 0; - for (int i = 0; i < 4; i++) + for (unsigned i = 0; i < 4; i++) { Byte b; if (!stream.ReadByte(b)) @@ -826,7 +826,7 @@ UInt32 CBitReader::ReadBits(unsigned numBits) res <<= numBits; NumBits -= numBits; res |= (Val >> NumBits); - Val &= (1 << NumBits) - 1; + Val = (Byte)(Val & (((unsigned)1 << NumBits) - 1)); break; } else diff --git a/CPP/7zip/Archive/Tar/TarHandler.cpp b/CPP/7zip/Archive/Tar/TarHandler.cpp index 72fbf74e..bc00e3fc 100644 --- a/CPP/7zip/Archive/Tar/TarHandler.cpp +++ b/CPP/7zip/Archive/Tar/TarHandler.cpp @@ -24,7 +24,9 @@ using namespace NWindows; namespace NArchive { namespace NTar { -static const UINT k_DefaultCodePage = CP_OEMCP; // it uses it if UTF8 check in names shows error +// 21.02: we use UTF8 code page by default, even if some files show error +// before 21.02 : CP_OEMCP; +// static const UINT k_DefaultCodePage = CP_UTF8; static const Byte kProps[] = @@ -39,13 +41,15 @@ static const Byte kProps[] = kpidGroup, kpidSymLink, kpidHardLink, + kpidCharacts // kpidLinkType }; static const Byte kArcProps[] = { kpidHeadersSize, - kpidCodePage + kpidCodePage, + kpidCharacts }; IMP_IInArchive_Props @@ -67,8 +71,12 @@ STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value) { case k_ErrorType_UnexpectedEnd: flags = kpv_ErrorFlags_UnexpectedEnd; break; case k_ErrorType_Corrupted: flags = kpv_ErrorFlags_HeadersError; break; + // case k_ErrorType_OK: break; + // case k_ErrorType_Warning: break; + default: break; } - prop = flags; + if (flags != 0) + prop = flags; break; } @@ -96,6 +104,13 @@ STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value) prop = name; break; } + + case kpidCharacts: + { + AString s = _encodingCharacts.GetCharactsString(); + prop = s; + break; + } } prop.Detach(value); return S_OK; @@ -119,12 +134,64 @@ HRESULT CHandler::ReadItem2(ISequentialInStream *stream, bool &filled, CItemEx & */ if (item.IsPaxExtendedHeader()) _thereIsPaxExtendedHeader = true; + if (item.IsThereWarning()) + _warning = true; } _phySize += item.HeaderSize; _headersSize += item.HeaderSize; return S_OK; } + +void CEncodingCharacts::Check(const AString &s) +{ + IsAscii = s.IsAscii(); + if (!IsAscii) + { + /* + { + Oem_Checked = true; + UString u; + MultiByteToUnicodeString2(u, s, CP_OEMCP); + Oem_Ok = (u.Find((wchar_t)0xfffd) <= 0); + } + Utf_Checked = true; + */ + UtfCheck.Check_AString(s); + } +} + + +AString CEncodingCharacts::GetCharactsString() const +{ + AString s; + if (IsAscii) + { + s += "ASCII"; + } + /* + if (Oem_Checked) + { + s.Add_Space_if_NotEmpty(); + s += (Oem_Ok ? "oem-ok" : "oem-error"); + } + if (Utf_Checked) + */ + else + { + s.Add_Space_if_NotEmpty(); + s += (UtfCheck.IsOK() ? "UTF8" : "UTF8-ERROR"); // "UTF8-error" + { + AString s2; + UtfCheck.PrintStatus(s2); + s.Add_Space_if_NotEmpty(); + s += s2; + } + } + return s; +} + + HRESULT CHandler::Open2(IInStream *stream, IArchiveOpenCallback *callback) { UInt64 endPos = 0; @@ -135,12 +202,7 @@ HRESULT CHandler::Open2(IInStream *stream, IArchiveOpenCallback *callback) _phySizeDefined = true; - bool utf8_OK = true; - if (!_forceCodePage) - { - if (!utf8_OK) - _curCodePage = k_DefaultCodePage; - } + // bool utf8_OK = true; for (;;) { @@ -151,8 +213,8 @@ HRESULT CHandler::Open2(IInStream *stream, IArchiveOpenCallback *callback) break; _isArc = true; - _items.Add(item); + /* if (!_forceCodePage) { if (utf8_OK) utf8_OK = CheckUTF8(item.Name, item.NameCouldBeReduced); @@ -160,8 +222,14 @@ HRESULT CHandler::Open2(IInStream *stream, IArchiveOpenCallback *callback) if (utf8_OK) utf8_OK = CheckUTF8(item.User); if (utf8_OK) utf8_OK = CheckUTF8(item.Group); } - - RINOK(stream->Seek(item.GetPackSizeAligned(), STREAM_SEEK_CUR, &_phySize)); + */ + + item.EncodingCharacts.Check(item.Name); + _encodingCharacts.Update(item.EncodingCharacts); + + _items.Add(item); + + RINOK(stream->Seek((Int64)item.GetPackSizeAligned(), STREAM_SEEK_CUR, &_phySize)); if (_phySize > endPos) { _error = k_ErrorType_UnexpectedEnd; @@ -188,11 +256,13 @@ HRESULT CHandler::Open2(IInStream *stream, IArchiveOpenCallback *callback) } } + /* if (!_forceCodePage) { if (!utf8_OK) _curCodePage = k_DefaultCodePage; } + */ _openCodePage = _curCodePage; if (_items.Size() == 0) @@ -255,6 +325,7 @@ STDMETHODIMP CHandler::Close() _latestIsRead = false; // _isSparse = false; _thereIsPaxExtendedHeader = false; + _encodingCharacts.Clear(); _items.Clear(); _seqStream.Release(); _stream.Release(); @@ -315,7 +386,8 @@ void CHandler::TarStringToUnicode(const AString &s, NWindows::NCOM::CPropVariant else MultiByteToUnicodeString2(dest, s, _curCodePage); if (toOs) - NItemName::ReplaceToOsSlashes_Remove_TailSlash(dest); + NItemName::ReplaceToOsSlashes_Remove_TailSlash(dest, + true); // useBackslashReplacement prop = dest; } @@ -358,6 +430,17 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val case kpidSymLink: if (item->LinkFlag == NFileHeader::NLinkFlag::kSymLink && !item->LinkName.IsEmpty()) TarStringToUnicode(item->LinkName, prop); break; case kpidHardLink: if (item->LinkFlag == NFileHeader::NLinkFlag::kHardLink && !item->LinkName.IsEmpty()) TarStringToUnicode(item->LinkName, prop); break; // case kpidLinkType: prop = (int)item->LinkFlag; break; + case kpidCharacts: + { + AString s = item->EncodingCharacts.GetCharactsString(); + if (item->IsThereWarning()) + { + s.Add_Space_if_NotEmpty(); + s += "HEADER_ERROR"; + } + prop = s; + break; + } } prop.Detach(value); return S_OK; @@ -407,7 +490,7 @@ HRESULT CHandler::Extract(const UInt32 *indices, UInt32 numItems, Int32 askMode = testMode ? NExtract::NAskMode::kTest : NExtract::NAskMode::kExtract; - Int32 index = allFilesMode ? i : indices[i]; + const UInt32 index = allFilesMode ? i : indices[i]; const CItemEx *item; if (seqMode) { @@ -475,7 +558,7 @@ HRESULT CHandler::Extract(const UInt32 *indices, UInt32 numItems, { if (!seqMode) { - RINOK(_stream->Seek(item->GetDataPosition(), STREAM_SEEK_SET, NULL)); + RINOK(_stream->Seek((Int64)item->GetDataPosition(), STREAM_SEEK_SET, NULL)); } streamSpec->Init(item->GetPackSizeAligned()); RINOK(copyCoder->Code(inStream2, outStream, NULL, NULL, progress)); @@ -566,7 +649,7 @@ STDMETHODIMP CSparseStream::Read(void *data, UInt32 size, UInt32 *processedSize) UInt64 phyPos = PhyOffsets[left] + relat; if (_needStartSeek || _phyPos != phyPos) { - RINOK(Handler->_stream->Seek(item.GetDataPosition() + phyPos, STREAM_SEEK_SET, NULL)); + RINOK(Handler->_stream->Seek((Int64)(item.GetDataPosition() + phyPos), STREAM_SEEK_SET, NULL)); _needStartSeek = false; _phyPos = phyPos; } @@ -604,7 +687,7 @@ STDMETHODIMP CSparseStream::Seek(Int64 offset, UInt32 seekOrigin, UInt64 *newPos } if (offset < 0) return HRESULT_WIN32_ERROR_NEGATIVE_SEEK; - _virtPos = offset; + _virtPos = (UInt64)offset; if (newPosition) *newPosition = _virtPos; return S_OK; @@ -650,7 +733,6 @@ STDMETHODIMP CHandler::GetStream(UInt32 index, ISequentialInStream **stream) void CHandler::Init() { _forceCodePage = false; - // _codePage = CP_OEMCP; _curCodePage = _specifiedCodePage = CP_UTF8; // CP_OEMCP; _thereIsPaxExtendedHeader = false; } diff --git a/CPP/7zip/Archive/Tar/TarHandler.h b/CPP/7zip/Archive/Tar/TarHandler.h index eb9c049e..4834c2a7 100644 --- a/CPP/7zip/Archive/Tar/TarHandler.h +++ b/CPP/7zip/Archive/Tar/TarHandler.h @@ -48,6 +48,8 @@ private: UInt32 _curCodePage; UInt32 _openCodePage; + CEncodingCharacts _encodingCharacts; + NCompress::CCopyCoder *copyCoderSpec; CMyComPtr<ICompressCoder> copyCoder; diff --git a/CPP/7zip/Archive/Tar/TarHandlerOut.cpp b/CPP/7zip/Archive/Tar/TarHandlerOut.cpp index 41934339..7a7a2cba 100644 --- a/CPP/7zip/Archive/Tar/TarHandlerOut.cpp +++ b/CPP/7zip/Archive/Tar/TarHandlerOut.cpp @@ -25,8 +25,8 @@ STDMETHODIMP CHandler::GetFileTimeType(UInt32 *type) return S_OK; } -HRESULT GetPropString(IArchiveUpdateCallback *callback, UInt32 index, PROPID propId, - AString &res, UINT codePage, bool convertSlash = false) +HRESULT GetPropString(IArchiveUpdateCallback *callback, UInt32 index, PROPID propId, AString &res, + UINT codePage, unsigned utfFlags, bool convertSlash) { NCOM::CPropVariant prop; RINOK(callback->GetProperty(index, propId, &prop)); @@ -39,7 +39,7 @@ HRESULT GetPropString(IArchiveUpdateCallback *callback, UInt32 index, PROPID pro if (codePage == CP_UTF8) { - ConvertUnicodeToUTF8(s, res); + ConvertUnicodeToUTF8_Flags(s, res, utfFlags); // if (!ConvertUnicodeToUTF8(s, res)) // return E_INVALIDARG; } else @@ -56,8 +56,8 @@ HRESULT GetPropString(IArchiveUpdateCallback *callback, UInt32 index, PROPID pro static int CompareUpdateItems(void *const *p1, void *const *p2, void *) { - const CUpdateItem &u1 = *(*((const CUpdateItem **)p1)); - const CUpdateItem &u2 = *(*((const CUpdateItem **)p2)); + const CUpdateItem &u1 = *(*((const CUpdateItem *const *)p1)); + const CUpdateItem &u2 = *(*((const CUpdateItem *const *)p2)); if (!u1.NewProps) { if (u2.NewProps) @@ -78,8 +78,15 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numIt if ((_stream && (_error != k_ErrorType_OK || _warning /* || _isSparse */)) || _seqStream) return E_NOTIMPL; CObjectVector<CUpdateItem> updateItems; - UINT codePage = (_forceCodePage ? _specifiedCodePage : _openCodePage); - + const UINT codePage = (_forceCodePage ? _specifiedCodePage : _openCodePage); + const unsigned utfFlags = g_Unicode_To_UTF8_Flags; + /* + // for debug only: + unsigned utfFlags = 0; + utfFlags |= UTF_FLAG__TO_UTF8__EXTRACT_BMP_ESCAPE; + utfFlags |= UTF_FLAG__TO_UTF8__SURROGATE_ERROR; + */ + for (UInt32 i = 0; i < numItems; i++) { CUpdateItem ui; @@ -94,7 +101,7 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numIt ui.NewProps = IntToBool(newProps); ui.NewData = IntToBool(newData); - ui.IndexInArc = indexInArc; + ui.IndexInArc = (int)indexInArc; ui.IndexInClient = i; if (IntToBool(newProps)) @@ -138,11 +145,11 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numIt ui.MTime = NTime::FileTimeToUnixTime64(prop.filetime); } - RINOK(GetPropString(callback, i, kpidPath, ui.Name, codePage, true)); + RINOK(GetPropString(callback, i, kpidPath, ui.Name, codePage, utfFlags, true)); if (ui.IsDir && !ui.Name.IsEmpty() && ui.Name.Back() != '/') ui.Name += '/'; - RINOK(GetPropString(callback, i, kpidUser, ui.User, codePage)); - RINOK(GetPropString(callback, i, kpidGroup, ui.Group, codePage)); + RINOK(GetPropString(callback, i, kpidUser, ui.User, codePage, utfFlags, false)); + RINOK(GetPropString(callback, i, kpidGroup, ui.Group, codePage, utfFlags, false)); } if (IntToBool(newData)) @@ -168,7 +175,7 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numIt updateItems.Sort(CompareUpdateItems, NULL); } - return UpdateArchive(_stream, outStream, _items, updateItems, codePage, callback); + return UpdateArchive(_stream, outStream, _items, updateItems, codePage, utfFlags, callback); COM_TRY_END } diff --git a/CPP/7zip/Archive/Tar/TarHeader.h b/CPP/7zip/Archive/Tar/TarHeader.h index 47971b58..249368f6 100644 --- a/CPP/7zip/Archive/Tar/TarHeader.h +++ b/CPP/7zip/Archive/Tar/TarHeader.h @@ -58,6 +58,7 @@ namespace NFileHeader const char kGnu_LongLink = 'K'; const char kGnu_LongName = 'L'; const char kSparse = 'S'; + const char kLabel = 'V'; const char kDumpDir = 'D'; /* GNUTYPE_DUMPDIR. data: list of files created by the --incremental (-G) option Each file name is preceded by either diff --git a/CPP/7zip/Archive/Tar/TarIn.cpp b/CPP/7zip/Archive/Tar/TarIn.cpp index 32761658..0099e6f7 100644 --- a/CPP/7zip/Archive/Tar/TarIn.cpp +++ b/CPP/7zip/Archive/Tar/TarIn.cpp @@ -81,14 +81,14 @@ static void ReadString(const char *s, unsigned size, AString &result) static bool ParseInt64(const char *p, Int64 &val) { UInt32 h = GetBe32(p); - val = GetBe64(p + 4); + val = (Int64)GetBe64(p + 4); if (h == (UInt32)1 << 31) return ((val >> 63) & 1) == 0; if (h == (UInt32)(Int32)-1) return ((val >> 63) & 1) != 0; UInt64 uv; bool res = OctalToNumber(p, 12, uv); - val = uv; + val = (Int64)uv; return res; } @@ -112,7 +112,9 @@ static bool ParseSize(const char *p, UInt64 &val) val = GetBe64(p + 4); return ((val >> 63) & 1) == 0; } - return OctalToNumber(p, 12, val); + return OctalToNumber(p, 12, val, + true // 20.03: allow empty size for 'V' Label entry + ); } #define CHECK(x) { if (!(x)) return k_IsArc_Res_NO; } @@ -201,8 +203,8 @@ static HRESULT GetNextItemReal(ISequentialInStream *stream, bool &filled, CItemE // we allow empty Mode value for LongName prefix items RIF(OctalToNumber32(p, 8, item.Mode, true)); p += 8; - if (!OctalToNumber32(p, 8, item.UID)) item.UID = 0; p += 8; - if (!OctalToNumber32(p, 8, item.GID)) item.GID = 0; p += 8; + if (!OctalToNumber32(p, 8, item.UID)) { item.UID = 0; } p += 8; + if (!OctalToNumber32(p, 8, item.GID)) { item.GID = 0; } p += 8; RIF(ParseSize(p, item.PackSize)); item.Size = item.PackSize; @@ -245,6 +247,15 @@ static HRESULT GetNextItemReal(ISequentialInStream *stream, bool &filled, CItemE item.PackSize = 0; item.Size = 0; } + + if (item.LinkFlag == NFileHeader::NLinkFlag::kDirectory) + { + // GNU tar ignores Size field, if LinkFlag is kDirectory + // 21.02 : we set PackSize = 0 to be more compatible with GNU tar + item.PackSize = 0; + // item.Size = 0; + } + /* TAR standard requires sum of unsigned byte values. But some TAR programs use sum of signed byte values. @@ -269,7 +280,7 @@ static HRESULT GetNextItemReal(ISequentialInStream *stream, bool &filled, CItemE if (item.LinkFlag == NFileHeader::NLinkFlag::kSparse) { - Byte isExtended = buf[482]; + Byte isExtended = (Byte)buf[482]; if (isExtended != 0 && isExtended != 1) return S_OK; RIF(ParseSize(buf + 483, item.Size)); @@ -309,7 +320,7 @@ static HRESULT GetNextItemReal(ISequentialInStream *stream, bool &filled, CItemE } item.HeaderSize += NFileHeader::kRecordSize; - isExtended = buf[21 * 24]; + isExtended = (Byte)buf[21 * 24]; if (isExtended != 0 && isExtended != 1) return S_OK; for (unsigned i = 0; i < 21; i++) @@ -442,9 +453,16 @@ HRESULT ReadItem(ISequentialInStream *stream, bool &filled, CItemEx &item, EErro case 'x': case 'X': { - // pax Extended Header - if (item.Name.IsPrefixedBy("PaxHeader/") - || item.Name.Find("PaxHeaders.4467/") >= 0) + const char *s = item.Name.Ptr(); + if (IsString1PrefixedByString2(s, "./")) + s += 2; + if (IsString1PrefixedByString2(s, "./")) + s += 2; + if ( IsString1PrefixedByString2(s, "PaxHeader/") + || IsString1PrefixedByString2(s, "PaxHeaders.X/") + || IsString1PrefixedByString2(s, "PaxHeaders.4467/") + || StringsAreEqual_Ascii(s, "@PaxHeader") + ) { RINOK(ReadDataToString(stream, item, pax, error)); if (error != k_ErrorType_OK) diff --git a/CPP/7zip/Archive/Tar/TarItem.h b/CPP/7zip/Archive/Tar/TarItem.h index bc3b4084..8c34b841 100644 --- a/CPP/7zip/Archive/Tar/TarItem.h +++ b/CPP/7zip/Archive/Tar/TarItem.h @@ -4,6 +4,7 @@ #define __ARCHIVE_TAR_ITEM_H #include "../../../Common/MyLinux.h" +#include "../../../Common/UTFConvert.h" #include "../Common/ItemNameUtils.h" @@ -108,8 +109,52 @@ struct CItem } UInt64 GetPackSizeAligned() const { return (PackSize + 0x1FF) & (~((UInt64)0x1FF)); } + + bool IsThereWarning() const + { + // that Header Warning is possible if (Size != 0) for dir item + return (PackSize < Size) && (LinkFlag == NFileHeader::NLinkFlag::kDirectory); + } }; + + +struct CEncodingCharacts +{ + bool IsAscii; + // bool Oem_Checked; + // bool Oem_Ok; + // bool Utf_Checked; + CUtf8Check UtfCheck; + + void Clear() + { + IsAscii = true; + // Oem_Checked = false; + // Oem_Ok = false; + // Utf_Checked = false; + UtfCheck.Clear(); + } + + void Update(const CEncodingCharacts &ec) + { + if (!ec.IsAscii) + IsAscii = false; + + // if (ec.Utf_Checked) + { + UtfCheck.Update(ec.UtfCheck); + // Utf_Checked = true; + } + } + + CEncodingCharacts() { Clear(); } + void Check(const AString &s); + AString GetCharactsString() const; +}; + + + struct CItemEx: public CItem { UInt64 HeaderPos; @@ -117,6 +162,8 @@ struct CItemEx: public CItem bool NameCouldBeReduced; bool LinkNameCouldBeReduced; + CEncodingCharacts EncodingCharacts; + UInt64 GetDataPosition() const { return HeaderPos + HeaderSize; } UInt64 GetFullSize() const { return HeaderSize + PackSize; } }; diff --git a/CPP/7zip/Archive/Tar/TarOut.cpp b/CPP/7zip/Archive/Tar/TarOut.cpp index 51081e8b..e2da3238 100644 --- a/CPP/7zip/Archive/Tar/TarOut.cpp +++ b/CPP/7zip/Archive/Tar/TarOut.cpp @@ -62,7 +62,7 @@ static void WriteOctal_12_Signed(char *s, Int64 val) { if (val >= 0) { - WriteOctal_12(s, val); + WriteOctal_12(s, (UInt64)val); return; } s[0] = s[1] = s[2] = s[3] = (char)(Byte)0xFF; diff --git a/CPP/7zip/Archive/Tar/TarUpdate.cpp b/CPP/7zip/Archive/Tar/TarUpdate.cpp index 0cdb30d1..c7598f8d 100644 --- a/CPP/7zip/Archive/Tar/TarUpdate.cpp +++ b/CPP/7zip/Archive/Tar/TarUpdate.cpp @@ -15,13 +15,10 @@ namespace NArchive { namespace NTar { -HRESULT GetPropString(IArchiveUpdateCallback *callback, UInt32 index, PROPID propId, - AString &res, UINT codePage, bool convertSlash = false); - HRESULT UpdateArchive(IInStream *inStream, ISequentialOutStream *outStream, const CObjectVector<NArchive::NTar::CItemEx> &inputItems, const CObjectVector<CUpdateItem> &updateItems, - UINT codePage, + UINT codePage, unsigned utfFlags, IArchiveUpdateCallback *updateCallback) { COutArchive outArchive; @@ -43,7 +40,7 @@ HRESULT UpdateArchive(IInStream *inStream, ISequentialOutStream *outStream, if (ui.NewData) complexity += ui.Size; else - complexity += inputItems[ui.IndexInArc].GetFullSize(); + complexity += inputItems[(unsigned)ui.IndexInArc].GetFullSize(); } RINOK(updateCallback->SetTotal(complexity)); @@ -95,12 +92,12 @@ HRESULT UpdateArchive(IInStream *inStream, ISequentialOutStream *outStream, memcpy(item.Magic, NFileHeader::NMagic::kUsTar_00, 8); } else - item = inputItems[ui.IndexInArc]; + item = inputItems[(unsigned)ui.IndexInArc]; AString symLink; if (ui.NewData || ui.NewProps) { - RINOK(GetPropString(updateCallback, ui.IndexInClient, kpidSymLink, symLink, codePage, true)); + RINOK(GetPropString(updateCallback, ui.IndexInClient, kpidSymLink, symLink, codePage, utfFlags, true)); if (!symLink.IsEmpty()) { item.LinkFlag = NFileHeader::NLinkFlag::kSymLink; @@ -159,7 +156,7 @@ HRESULT UpdateArchive(IInStream *inStream, ISequentialOutStream *outStream, { AString hardLink; - RINOK(GetPropString(updateCallback, ui.IndexInClient, kpidHardLink, hardLink, codePage, true)); + RINOK(GetPropString(updateCallback, ui.IndexInClient, kpidHardLink, hardLink, codePage, utfFlags, true)); if (!hardLink.IsEmpty()) { item.LinkFlag = NFileHeader::NLinkFlag::kHardLink; @@ -189,7 +186,7 @@ HRESULT UpdateArchive(IInStream *inStream, ISequentialOutStream *outStream, outArchive.Pos = fileHeaderStartPos; item.PackSize = copyCoderSpec->TotalSize; RINOK(outArchive.WriteHeader(item)); - RINOK(outSeekStream->Seek(item.PackSize, STREAM_SEEK_CUR, NULL)); + RINOK(outSeekStream->Seek((Int64)item.PackSize, STREAM_SEEK_CUR, NULL)); outArchive.Pos += item.PackSize; } RINOK(outArchive.FillDataResidual(item.PackSize)); @@ -201,7 +198,7 @@ HRESULT UpdateArchive(IInStream *inStream, ISequentialOutStream *outStream, } else { - const CItemEx &existItem = inputItems[ui.IndexInArc]; + const CItemEx &existItem = inputItems[(unsigned)ui.IndexInArc]; UInt64 size; if (ui.NewProps) @@ -231,12 +228,12 @@ HRESULT UpdateArchive(IInStream *inStream, ISequentialOutStream *outStream, item.GID = existItem.GID; RINOK(outArchive.WriteHeader(item)); - RINOK(inStream->Seek(existItem.GetDataPosition(), STREAM_SEEK_SET, NULL)); + RINOK(inStream->Seek((Int64)existItem.GetDataPosition(), STREAM_SEEK_SET, NULL)); size = existItem.PackSize; } else { - RINOK(inStream->Seek(existItem.HeaderPos, STREAM_SEEK_SET, NULL)); + RINOK(inStream->Seek((Int64)existItem.HeaderPos, STREAM_SEEK_SET, NULL)); size = existItem.GetFullSize(); } diff --git a/CPP/7zip/Archive/Tar/TarUpdate.h b/CPP/7zip/Archive/Tar/TarUpdate.h index b758635f..1e3d0217 100644 --- a/CPP/7zip/Archive/Tar/TarUpdate.h +++ b/CPP/7zip/Archive/Tar/TarUpdate.h @@ -13,7 +13,7 @@ namespace NTar { struct CUpdateItem { int IndexInArc; - int IndexInClient; + unsigned IndexInClient; UInt64 Size; Int64 MTime; UInt32 Mode; @@ -30,9 +30,12 @@ struct CUpdateItem HRESULT UpdateArchive(IInStream *inStream, ISequentialOutStream *outStream, const CObjectVector<CItemEx> &inputItems, const CObjectVector<CUpdateItem> &updateItems, - UINT codePage, + UINT codePage, unsigned utfFlags, IArchiveUpdateCallback *updateCallback); +HRESULT GetPropString(IArchiveUpdateCallback *callback, UInt32 index, PROPID propId, AString &res, + UINT codePage, unsigned utfFlags, bool convertSlash); + }} #endif diff --git a/CPP/7zip/Archive/Udf/UdfIn.cpp b/CPP/7zip/Archive/Udf/UdfIn.cpp index cfe6c5ad..520ceeea 100644 --- a/CPP/7zip/Archive/Udf/UdfIn.cpp +++ b/CPP/7zip/Archive/Udf/UdfIn.cpp @@ -39,13 +39,13 @@ static const UInt64 kFileNameLengthTotalMax = (UInt64)1 << 33; static const UInt64 kInlineExtentsSizeMax = (UInt64)1 << 33; #define CRC16_INIT_VAL 0 -#define CRC16_GET_DIGEST(crc) (crc) +// #define CRC16_GET_DIGEST(crc) (crc) #define CRC16_UPDATE_BYTE(crc, b) ((UInt16)(g_Crc16Table[(((crc) >> 8) ^ (b)) & 0xFF] ^ ((crc) << 8))) #define kCrc16Poly 0x1021 static UInt16 g_Crc16Table[256]; -void MY_FAST_CALL Crc16GenerateTable(void) +static void MY_FAST_CALL Crc16GenerateTable(void) { UInt32 i; for (i = 0; i < 256; i++) @@ -57,7 +57,7 @@ void MY_FAST_CALL Crc16GenerateTable(void) } } -UInt32 MY_FAST_CALL Crc16_Update(UInt32 v, const void *data, size_t size) +static UInt32 MY_FAST_CALL Crc16_Update(UInt32 v, const void *data, size_t size) { const Byte *p = (const Byte *)data; for (; size > 0 ; size--, p++) @@ -65,7 +65,7 @@ UInt32 MY_FAST_CALL Crc16_Update(UInt32 v, const void *data, size_t size) return v; } -UInt32 MY_FAST_CALL Crc16Calc(const void *data, size_t size) +static UInt32 MY_FAST_CALL Crc16Calc(const void *data, size_t size) { return Crc16_Update(CRC16_INIT_VAL, data, size); } diff --git a/CPP/7zip/Archive/Udf/UdfIn.h b/CPP/7zip/Archive/Udf/UdfIn.h index f7379401..c26f6099 100644 --- a/CPP/7zip/Archive/Udf/UdfIn.h +++ b/CPP/7zip/Archive/Udf/UdfIn.h @@ -351,7 +351,7 @@ class CInArchive UInt64 _processedProgressBytes; UInt64 _fileNameLengthTotal; - int _numRefs; + unsigned _numRefs; UInt32 _numExtents; UInt64 _inlineExtentsSize; bool CheckExtent(int volIndex, int partitionRef, UInt32 blockPos, UInt32 len) const; diff --git a/CPP/7zip/Archive/UefiHandler.cpp b/CPP/7zip/Archive/UefiHandler.cpp index 5892d568..67fe795a 100644 --- a/CPP/7zip/Archive/UefiHandler.cpp +++ b/CPP/7zip/Archive/UefiHandler.cpp @@ -52,7 +52,7 @@ static const Byte k_IntelMeSignature[] = 0x5A, 0xA5, 0xF0, 0x0F }; -bool IsIntelMe(const Byte *p) +static bool IsIntelMe(const Byte *p) { return memcmp(p, k_IntelMeSignature, sizeof(k_IntelMeSignature)) == 0; } @@ -318,19 +318,19 @@ static const CUInt32PCharPair g_FFS_FILE_ATTRIBUTES[] = // SECTION_TYPE -#define SECTION_ALL 0x00 +// #define SECTION_ALL 0x00 #define SECTION_COMPRESSION 0x01 #define SECTION_GUID_DEFINED 0x02 // Leaf section Type values -#define SECTION_PE32 0x10 -#define SECTION_PIC 0x11 -#define SECTION_TE 0x12 +// #define SECTION_PE32 0x10 +// #define SECTION_PIC 0x11 +// #define SECTION_TE 0x12 #define SECTION_DXE_DEPEX 0x13 #define SECTION_VERSION 0x14 #define SECTION_USER_INTERFACE 0x15 -#define SECTION_COMPATIBILITY16 0x16 +// #define SECTION_COMPATIBILITY16 0x16 #define SECTION_FIRMWARE_VOLUME_IMAGE 0x17 #define SECTION_FREEFORM_SUBTYPE_GUID 0x18 #define SECTION_RAW 0x19 @@ -471,7 +471,7 @@ public: bool Parse(const Byte *p) { - int i; + unsigned i; for (i = 0; i < kFileHeaderSize; i++) if (p[i] != 0xFF) break; @@ -719,11 +719,11 @@ class CHandler: HRESULT ParseIntelMe(int bufIndex, UInt32 posBase, UInt32 exactSize, UInt32 limitSize, - int parent, int method, int level); + int parent, int method, unsigned level); HRESULT ParseVolume(int bufIndex, UInt32 posBase, UInt32 exactSize, UInt32 limitSize, - int parent, int method, int level); + int parent, int method, unsigned level); HRESULT OpenCapsule(IInStream *stream); HRESULT OpenFv(IInStream *stream, const UInt64 *maxCheckStartPosition, IArchiveOpenCallback *callback); @@ -857,13 +857,13 @@ STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value) } #ifdef SHOW_DEBUG_INFO -static void PrintLevel(int level) +static void PrintLevel(unsigned level) { PRF(printf("\n")); - for (int i = 0; i < level; i++) + for (unsigned i = 0; i < level; i++) PRF(printf(" ")); } -static void MyPrint(UInt32 posBase, UInt32 size, int level, const char *name) +static void MyPrint(UInt32 posBase, UInt32 size, unsigned level, const char *name) { PrintLevel(level); PRF(printf("%s, pos = %6x, size = %6x", name, posBase, size)); @@ -1312,7 +1312,7 @@ bool CVolFfsHeader::Parse(const Byte *p) HRESULT CHandler::ParseVolume( int bufIndex, UInt32 posBase, UInt32 exactSize, UInt32 limitSize, - int parent, int method, int level) + int parent, int method, unsigned level) { if (level > kLevelMax) return S_FALSE; @@ -1333,7 +1333,7 @@ HRESULT CHandler::ParseVolume( if (!Is_FF_Stream(p + kFfsGuidOffset, 16)) item.SetGuid(p + kFfsGuidOffset); // if (item.Name.IsEmpty()) - item.Name += "[VOL]"; + item.Name += "[VOL]"; AddItem(item); return S_OK; } @@ -1512,7 +1512,7 @@ static const char * const kRegionName[] = HRESULT CHandler::ParseIntelMe( int bufIndex, UInt32 posBase, UInt32 exactSize, UInt32 limitSize, - int parent, int method, int level) + int parent, int method, unsigned level) { UNUSED_VAR(limitSize) level++; diff --git a/CPP/7zip/Archive/VdiHandler.cpp b/CPP/7zip/Archive/VdiHandler.cpp index b8ef35bb..66cf39cd 100644 --- a/CPP/7zip/Archive/VdiHandler.cpp +++ b/CPP/7zip/Archive/VdiHandler.cpp @@ -18,7 +18,6 @@ #include "HandlerCont.h" -#define Get16(p) GetUi16(p) #define Get32(p) GetUi32(p) #define Get64(p) GetUi64(p) @@ -87,7 +86,7 @@ class CHandler: public CHandlerImg Byte Guids[kNumGuids][16]; - HRESULT Seek(UInt64 offset) + HRESULT Seek2(UInt64 offset) { _posInArc = offset; return Stream->Seek(offset, STREAM_SEEK_SET, NULL); @@ -96,7 +95,7 @@ class CHandler: public CHandlerImg HRESULT InitAndSeek() { _virtPos = 0; - return Seek(0); + return Seek2(0); } HRESULT Open2(IInStream *stream, IArchiveOpenCallback *openCallback); @@ -143,7 +142,7 @@ STDMETHODIMP CHandler::Read(void *data, UInt32 size, UInt32 *processedSize) offset += lowBits; if (offset != _posInArc) { - RINOK(Seek(offset)); + RINOK(Seek2(offset)); } HRESULT res = Stream->Read(data, size, &size); _posInArc += size; diff --git a/CPP/7zip/Archive/VhdHandler.cpp b/CPP/7zip/Archive/VhdHandler.cpp index d79ae907..c70d667e 100644 --- a/CPP/7zip/Archive/VhdHandler.cpp +++ b/CPP/7zip/Archive/VhdHandler.cpp @@ -248,7 +248,7 @@ class CHandler: public CHandlerImg } void Reset_PosInArc() { _posInArc = (UInt64)0 - 1; } - HRESULT Seek(UInt64 offset); + HRESULT Seek2(UInt64 offset); HRESULT InitAndSeek(); HRESULT ReadPhy(UInt64 offset, void *data, UInt32 size); @@ -316,7 +316,7 @@ public: STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize); }; -HRESULT CHandler::Seek(UInt64 offset) { return Stream->Seek(_startOffset + offset, STREAM_SEEK_SET, NULL); } +HRESULT CHandler::Seek2(UInt64 offset) { return Stream->Seek(_startOffset + offset, STREAM_SEEK_SET, NULL); } HRESULT CHandler::InitAndSeek() { @@ -327,7 +327,7 @@ HRESULT CHandler::InitAndSeek() _virtPos = _posInArc = 0; BitMapTag = kUnusedBlock; BitMap.Alloc(Dyn.NumBitMapSectors() << kSectorSize_Log); - return Seek(0); + return Seek2(0); } HRESULT CHandler::ReadPhy(UInt64 offset, void *data, UInt32 size) @@ -337,7 +337,7 @@ HRESULT CHandler::ReadPhy(UInt64 offset, void *data, UInt32 size) if (offset != _posInArc) { _posInArc = offset; - RINOK(Seek(offset)); + RINOK(Seek2(offset)); } HRESULT res = ReadStream_FALSE(Stream, data, size); if (res == S_OK) diff --git a/CPP/7zip/Archive/VmdkHandler.cpp b/CPP/7zip/Archive/VmdkHandler.cpp index 942bd792..096bd103 100644 --- a/CPP/7zip/Archive/VmdkHandler.cpp +++ b/CPP/7zip/Archive/VmdkHandler.cpp @@ -41,7 +41,7 @@ namespace NVmdk { static const Byte k_Signature[] = SIGNATURE; static const UInt32 k_Flags_NL = (UInt32)1 << 0; -static const UInt32 k_Flags_RGD = (UInt32)1 << 1; +// static const UInt32 k_Flags_RGD = (UInt32)1 << 1; static const UInt32 k_Flags_ZeroGrain = (UInt32)1 << 2; static const UInt32 k_Flags_Compressed = (UInt32)1 << 16; static const UInt32 k_Flags_Marker = (UInt32)1 << 17; @@ -855,11 +855,13 @@ STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value) } case kpidId: + { if (desc && !desc->CID.IsEmpty()) { prop = desc->CID; - break; } + break; + } case kpidName: { diff --git a/CPP/7zip/Archive/Wim/WimHandler.cpp b/CPP/7zip/Archive/Wim/WimHandler.cpp index 927a0b38..2553c175 100644 --- a/CPP/7zip/Archive/Wim/WimHandler.cpp +++ b/CPP/7zip/Archive/Wim/WimHandler.cpp @@ -350,7 +350,7 @@ STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value) COM_TRY_END } -void GetFileTime(const Byte *p, NCOM::CPropVariant &prop) +static void GetFileTime(const Byte *p, NCOM::CPropVariant &prop) { prop.vt = VT_FILETIME; prop.filetime.dwLowDateTime = Get32(p); diff --git a/CPP/7zip/Archive/Wim/WimHandlerOut.cpp b/CPP/7zip/Archive/Wim/WimHandlerOut.cpp index 18740c70..6b4497fe 100644 --- a/CPP/7zip/Archive/Wim/WimHandlerOut.cpp +++ b/CPP/7zip/Archive/Wim/WimHandlerOut.cpp @@ -4,6 +4,7 @@ #include "../../../Common/ComTry.h" #include "../../../Common/IntToString.h" +#include "../../../Common/MyBuffer2.h" #include "../../../Common/StringToInt.h" #include "../../../Common/UTFConvert.h" #include "../../../Common/Wildcard.h" @@ -93,9 +94,15 @@ struct CMetaItem CByteBuffer Reparse; unsigned GetNumAltStreams() const { return AltStreams.Size() - NumSkipAltStreams; } - CMetaItem(): UpdateIndex(-1), HashIndex(-1), SecurityId(-1), - FileID(0), VolID(0), - Skip(false), NumSkipAltStreams(0) {} + CMetaItem(): + UpdateIndex(-1) + , HashIndex(-1) + , FileID(0) + , VolID(0) + , SecurityId(-1) + , Skip(false) + , NumSkipAltStreams(0) + {} }; @@ -320,20 +327,23 @@ class CInStreamWithSha1: { CMyComPtr<ISequentialInStream> _stream; UInt64 _size; - NCrypto::NSha1::CContext _sha; + // NCrypto::NSha1::CContext _sha; + CAlignedBuffer _sha; + CSha1 *Sha() { return (CSha1 *)(void *)(Byte *)_sha; } public: MY_UNKNOWN_IMP1(IInStream) STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize); + CInStreamWithSha1(): _sha(sizeof(CSha1)) {} void SetStream(ISequentialInStream *stream) { _stream = stream; } void Init() { _size = 0; - _sha.Init(); + Sha1_Init(Sha()); } void ReleaseStream() { _stream.Release(); } UInt64 GetSize() const { return _size; } - void Final(Byte *digest) { _sha.Final(digest); } + void Final(Byte *digest) { Sha1_Final(Sha(), digest); } }; STDMETHODIMP CInStreamWithSha1::Read(void *data, UInt32 size, UInt32 *processedSize) @@ -341,7 +351,7 @@ STDMETHODIMP CInStreamWithSha1::Read(void *data, UInt32 size, UInt32 *processedS UInt32 realProcessedSize; HRESULT result = _stream->Read(data, size, &realProcessedSize); _size += realProcessedSize; - _sha.Update((const Byte *)data, realProcessedSize); + Sha1_Update(Sha(), (const Byte *)data, realProcessedSize); if (processedSize) *processedSize = realProcessedSize; return result; @@ -427,9 +437,9 @@ static size_t WriteItem(const CStreamInfo *streams, const CMetaItem &item, Byte Set16(p + 0x64, (UInt16)fileNameLen); unsigned i; for (i = 0; i * 2 < fileNameLen; i++) - Set16(p + kDirRecordSize + i * 2, item.Name[i]); + Set16(p + kDirRecordSize + i * 2, (UInt16)item.Name[i]); for (i = 0; i * 2 < shortNameLen; i++) - Set16(p + kDirRecordSize + fileNameLen2 + i * 2, item.ShortName[i]); + Set16(p + kDirRecordSize + fileNameLen2 + i * 2, (UInt16)item.ShortName[i]); if (item.GetNumAltStreams() == 0) { @@ -468,7 +478,7 @@ static size_t WriteItem(const CStreamInfo *streams, const CMetaItem &item, Byte memcpy(p + 0x10, streams[ss.HashIndex].Hash, kHashSize); Set16(p + 0x24, (UInt16)fileNameLen); for (i = 0; i * 2 < fileNameLen; i++) - Set16(p + 0x26 + i * 2, ss.Name[i]); + Set16(p + 0x26 + i * 2, (UInt16)ss.Name[i]); totalLen += curLen; p += curLen; } @@ -690,7 +700,7 @@ static void AddTrees(CObjectVector<CDir> &trees, CObjectVector<CMetaItem> &metaI } -#define IS_LETTER_CHAR(c) ((c) >= 'a' && (c) <= 'z' || (c) >= 'A' && (c) <= 'Z') +#define IS_LETTER_CHAR(c) (((c) >= 'a' && (c) <= 'z') || ((c) >= 'A' && (c) <= 'Z')) @@ -1024,7 +1034,7 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outSeqStream, UInt32 nu imageIndex = (int)val - 1; if (imageIndex < (int)isChangedImage.Size()) - if (!isChangedImage[imageIndex]) + if (!isChangedImage[imageIndex]) return E_FAIL; AddTrees(trees, db.MetaItems, ri, imageIndex); @@ -1079,7 +1089,27 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outSeqStream, UInt32 nu fileName.Empty(); } else + { + /* + #if WCHAR_MAX > 0xffff + if (c >= 0x10000) + { + c -= 0x10000; + + if (c < (1 << 20)) + { + wchar_t c0 = 0xd800 + ((c >> 10) & 0x3FF); + fileName += c0; + c = 0xdc00 + (c & 0x3FF); + } + else + c = '_'; // we change character unsupported by UTF16 + } + #endif + */ + fileName += c; + } } if (isAltStream) @@ -1838,7 +1868,7 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outSeqStream, UInt32 nu if (_xmls.Size() == 1) { const CWimXml &_oldXml = _xmls[0]; - if ((int)i < _oldXml.Images.Size()) + if (i < _oldXml.Images.Size()) { // int ttt = _oldXml.Images[i].ItemIndexInXml; item = _oldXml.Xml.Root.SubItems[_oldXml.Images[i].ItemIndexInXml]; @@ -1880,7 +1910,7 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outSeqStream, UInt32 nu CByteArr xmlBuf(xmlSize); Set16((Byte *)xmlBuf, 0xFEFF); for (i = 0; i < (unsigned)utf16.Len(); i++) - Set16((Byte *)xmlBuf + 2 + i * 2, utf16[i]); + Set16((Byte *)xmlBuf + 2 + i * 2, (UInt16)utf16[i]); RINOK(WriteStream(outStream, (const Byte *)xmlBuf, xmlSize)); } diff --git a/CPP/7zip/Archive/Wim/WimIn.cpp b/CPP/7zip/Archive/Wim/WimIn.cpp index 3c712084..fef6b34f 100644 --- a/CPP/7zip/Archive/Wim/WimIn.cpp +++ b/CPP/7zip/Archive/Wim/WimIn.cpp @@ -302,12 +302,12 @@ HRESULT CUnpacker::Unpack2( UInt64 packDataSize; size_t numChunks; { - UInt64 numChunks64 = (unpackSize + (((UInt32)1 << chunkSizeBits) - 1)) >> chunkSizeBits; - UInt64 sizesBufSize64 = (numChunks64 - 1) << entrySizeShifts; + const UInt64 numChunks64 = (unpackSize + (((UInt32)1 << chunkSizeBits) - 1)) >> chunkSizeBits; + const UInt64 sizesBufSize64 = (numChunks64 - 1) << entrySizeShifts; if (sizesBufSize64 > resource.PackSize) return S_FALSE; packDataSize = resource.PackSize - sizesBufSize64; - size_t sizesBufSize = (size_t)sizesBufSize64; + const size_t sizesBufSize = (size_t)sizesBufSize64; if (sizesBufSize != sizesBufSize64) return E_OUTOFMEMORY; sizesBuf.AllocAtLeast(sizesBufSize); @@ -639,10 +639,10 @@ HRESULT CDatabase::ParseDirItem(size_t pos, int parent) p += dirRecordSize; { - if (*(const UInt16 *)(p + fileNameLen) != 0) + if (*(const UInt16 *)(const void *)(p + fileNameLen) != 0) return S_FALSE; for (UInt32 j = 0; j < fileNameLen; j += 2) - if (*(const UInt16 *)(p + j) == 0) + if (*(const UInt16 *)(const void *)(p + j) == 0) return S_FALSE; } @@ -652,10 +652,10 @@ HRESULT CDatabase::ParseDirItem(size_t pos, int parent) { // empty shortName has no ZERO at the end ? const Byte *p2 = p + fileNameLen2; - if (*(const UInt16 *)(p2 + shortNameLen) != 0) + if (*(const UInt16 *)(const void *)(p2 + shortNameLen) != 0) return S_FALSE; for (UInt32 j = 0; j < shortNameLen; j += 2) - if (*(const UInt16 *)(p2 + j) == 0) + if (*(const UInt16 *)(const void *)(p2 + j) == 0) return S_FALSE; } @@ -703,10 +703,10 @@ HRESULT CDatabase::ParseDirItem(size_t pos, int parent) { const Byte *p3 = p2 + extraOffset + 2; - if (*(const UInt16 *)(p3 + fileNameLen111) != 0) + if (*(const UInt16 *)(const void *)(p3 + fileNameLen111) != 0) return S_FALSE; for (UInt32 j = 0; j < fileNameLen111; j += 2) - if (*(const UInt16 *)(p3 + j) == 0) + if (*(const UInt16 *)(const void *)(p3 + j) == 0) return S_FALSE; // PRF(printf("\n %S", p3)); @@ -1790,7 +1790,8 @@ void CImageInfo::Parse(const CXmlItem &item) { CTimeDefined = ParseTime(item, CTime, "CREATIONTIME"); MTimeDefined = ParseTime(item, MTime, "LASTMODIFICATIONTIME"); - NameDefined = ConvertUTF8ToUnicode(item.GetSubStringForTag("NAME"), Name); + NameDefined = true; + ConvertUTF8ToUnicode(item.GetSubStringForTag("NAME"), Name); ParseNumber64(item.GetSubStringForTag("DIRCOUNT"), DirCount); ParseNumber64(item.GetSubStringForTag("FILECOUNT"), FileCount); diff --git a/CPP/7zip/Archive/XarHandler.cpp b/CPP/7zip/Archive/XarHandler.cpp index f20b1eb9..35dd607a 100644 --- a/CPP/7zip/Archive/XarHandler.cpp +++ b/CPP/7zip/Archive/XarHandler.cpp @@ -82,11 +82,13 @@ struct CFile int Parent; - CFile(): IsDir(false), HasData(false), ModeDefined(false), Sha1IsDefined(false), - /* packSha1IsDefined(false), */ - Parent(-1), + CFile(): Size(0), PackSize(0), Offset(0), - CTime(0), MTime(0), ATime(0), Mode(0) {} + CTime(0), MTime(0), ATime(0), Mode(0), + IsDir(false), HasData(false), ModeDefined(false), Sha1IsDefined(false), + /* packSha1IsDefined(false), */ + Parent(-1) + {} bool IsCopyMethod() const { @@ -435,8 +437,8 @@ static void Utf8StringToProp(const AString &s, NCOM::CPropVariant &prop) if (!s.IsEmpty()) { UString us; - if (ConvertUTF8ToUnicode(s, us)) - prop = us; + ConvertUTF8ToUnicode(s, us); + prop = us; } } diff --git a/CPP/7zip/Archive/XzHandler.cpp b/CPP/7zip/Archive/XzHandler.cpp index 801619fb..2803f6a8 100644 --- a/CPP/7zip/Archive/XzHandler.cpp +++ b/CPP/7zip/Archive/XzHandler.cpp @@ -61,20 +61,29 @@ class CHandler: public CCommonMethodProps #endif { - CXzStatInfo _stat; - SRes MainDecodeSRes; + CXzStatInfo _stat; // it's stat from backward parsing + CXzStatInfo _stat2; // it's data from forward parsing, if the decoder was called + SRes _stat2_decode_SRes; + bool _stat_defined; + bool _stat2_defined; + + const CXzStatInfo *GetStat() const + { + if (_stat_defined) return &_stat; + if (_stat2_defined) return &_stat2; + return NULL; + } bool _isArc; bool _needSeekToStart; - bool _phySize_Defined; bool _firstBlockWasRead; AString _methodsString; + #ifndef EXTRACT_ONLY UInt32 _filterId; - UInt64 _numSolidBytes; void InitXz() @@ -85,6 +94,7 @@ class CHandler: #endif + void Init() { #ifndef EXTRACT_ONLY @@ -109,18 +119,24 @@ class CHandler: #endif decoder._memUsage = _memUsage; - MainDecodeSRes = SZ_OK; - - RINOK(decoder.Decode(seqInStream, outStream, + HRESULT hres = decoder.Decode(seqInStream, outStream, NULL, // *outSizeLimit true, // finishStream - progress)); + progress); - _stat = decoder.Stat; - MainDecodeSRes = decoder.MainDecodeSRes; + if (decoder.MainDecodeSRes_wasUsed + && decoder.MainDecodeSRes != SZ_ERROR_MEM + && decoder.MainDecodeSRes != SZ_ERROR_UNSUPPORTED) + { + // if (!_stat2_defined) + { + _stat2_decode_SRes = decoder.MainDecodeSRes; + _stat2 = decoder.Stat; + _stat2_defined = true; + } + } - _phySize_Defined = true; - return S_OK; + return hres; } public: @@ -143,8 +159,8 @@ public: INTERFACE_IOutArchive(;) #endif - size_t _blocksArraySize; CBlockInfo *_blocks; + size_t _blocksArraySize; UInt64 _maxBlocksSize; CMyComPtr<IInStream> _stream; CMyComPtr<ISequentialInStream> _seqStream; @@ -156,7 +172,7 @@ public: HRESULT SeekToPackPos(UInt64 pos) { - return _stream->Seek(pos, STREAM_SEEK_SET, NULL); + return _stream->Seek((Int64)pos, STREAM_SEEK_SET, NULL); } }; @@ -325,13 +341,16 @@ STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value) { COM_TRY_BEGIN NCOM::CPropVariant prop; + + const CXzStatInfo *stat = GetStat(); + switch (propID) { - case kpidPhySize: if (_phySize_Defined) prop = _stat.InSize; break; - case kpidNumStreams: if (_stat.NumStreams_Defined) prop = _stat.NumStreams; break; - case kpidNumBlocks: if (_stat.NumBlocks_Defined) prop = _stat.NumBlocks; break; - case kpidUnpackSize: if (_stat.UnpackSize_Defined) prop = _stat.OutSize; break; - case kpidClusterSize: if (_stat.NumBlocks_Defined && _stat.NumBlocks > 1) prop = _maxBlocksSize; break; + case kpidPhySize: if (stat) prop = stat->InSize; break; + case kpidNumStreams: if (stat && stat->NumStreams_Defined) prop = stat->NumStreams; break; + case kpidNumBlocks: if (stat && stat->NumBlocks_Defined) prop = stat->NumBlocks; break; + case kpidUnpackSize: if (stat && stat->UnpackSize_Defined) prop = stat->OutSize; break; + case kpidClusterSize: if (_stat_defined && _stat.NumBlocks_Defined && stat->NumBlocks > 1) prop = _maxBlocksSize; break; case kpidCharacts: if (_firstBlockWasRead) { @@ -350,14 +369,14 @@ STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value) case kpidErrorFlags: { UInt32 v = 0; - SRes sres = MainDecodeSRes; // _stat.DecodeRes2; // - if (!_isArc) v |= kpv_ErrorFlags_IsNotArc; - if (/*_stat.UnexpectedEnd */ sres == SZ_ERROR_INPUT_EOF) v |= kpv_ErrorFlags_UnexpectedEnd; - if (_stat.DataAfterEnd) v |= kpv_ErrorFlags_DataAfterEnd; - if (/* _stat.HeadersError */ sres == SZ_ERROR_ARCHIVE) v |= kpv_ErrorFlags_HeadersError; - if (/* _stat.Unsupported */ sres == SZ_ERROR_UNSUPPORTED) v |= kpv_ErrorFlags_UnsupportedMethod; - if (/* _stat.DataError */ sres == SZ_ERROR_DATA) v |= kpv_ErrorFlags_DataError; - if (/* _stat.CrcError */ sres == SZ_ERROR_CRC) v |= kpv_ErrorFlags_CrcError; + SRes sres = _stat2_decode_SRes; + if (!_isArc) v |= kpv_ErrorFlags_IsNotArc; + if (sres == SZ_ERROR_INPUT_EOF) v |= kpv_ErrorFlags_UnexpectedEnd; + if (_stat2_defined && _stat2.DataAfterEnd) v |= kpv_ErrorFlags_DataAfterEnd; + if (sres == SZ_ERROR_ARCHIVE) v |= kpv_ErrorFlags_HeadersError; + if (sres == SZ_ERROR_UNSUPPORTED) v |= kpv_ErrorFlags_UnsupportedMethod; + if (sres == SZ_ERROR_DATA) v |= kpv_ErrorFlags_DataError; + if (sres == SZ_ERROR_CRC) v |= kpv_ErrorFlags_CrcError; if (v != 0) prop = v; break; @@ -384,11 +403,12 @@ STDMETHODIMP CHandler::GetNumberOfItems(UInt32 *numItems) STDMETHODIMP CHandler::GetProperty(UInt32, PROPID propID, PROPVARIANT *value) { COM_TRY_BEGIN + const CXzStatInfo *stat = GetStat(); NCOM::CPropVariant prop; switch (propID) { - case kpidSize: if (_stat.UnpackSize_Defined) prop = _stat.OutSize; break; - case kpidPackSize: if (_phySize_Defined) prop = _stat.InSize; break; + case kpidSize: if (stat && stat->UnpackSize_Defined) prop = stat->OutSize; break; + case kpidPackSize: if (stat) prop = stat->InSize; break; case kpidMethod: if (!_methodsString.IsEmpty()) prop = _methodsString; break; } prop.Detach(value); @@ -402,7 +422,9 @@ struct COpenCallbackWrap ICompressProgress vt; IArchiveOpenCallback *OpenCallback; HRESULT Res; - COpenCallbackWrap(IArchiveOpenCallback *progress); + + // new clang shows "non-POD" warning for offsetof(), if we use constructor instead of Init() + void Init(IArchiveOpenCallback *progress); }; static SRes OpenCallbackProgress(const ICompressProgress *pp, UInt64 inSize, UInt64 /* outSize */) @@ -413,7 +435,7 @@ static SRes OpenCallbackProgress(const ICompressProgress *pp, UInt64 inSize, UIn return HRESULT_To_SRes(p->Res, SZ_ERROR_PROGRESS); } -COpenCallbackWrap::COpenCallbackWrap(IArchiveOpenCallback *callback) +void COpenCallbackWrap::Init(IArchiveOpenCallback *callback) { vt.Progress = OpenCallbackProgress; OpenCallback = callback; @@ -482,7 +504,11 @@ HRESULT CHandler::Open2(IInStream *inStream, /* UInt32 flags, */ IArchiveOpenCal CSeqInStreamWrap inStreamWrap; inStreamWrap.Init(inStream); + SRes res = Xz_ReadHeader(&st, &inStreamWrap.vt); + + if (inStreamWrap.Res != S_OK) + return inStreamWrap.Res; if (res != SZ_OK) return SRes_to_Open_HRESULT(res); @@ -490,8 +516,27 @@ HRESULT CHandler::Open2(IInStream *inStream, /* UInt32 flags, */ IArchiveOpenCal CXzBlock block; BoolInt isIndex; UInt32 headerSizeRes; + SRes res2 = XzBlock_ReadHeader(&block, &inStreamWrap.vt, &isIndex, &headerSizeRes); - if (res2 == SZ_OK && !isIndex) + + if (inStreamWrap.Res != S_OK) + return inStreamWrap.Res; + + if (res2 != SZ_OK) + { + if (res2 == SZ_ERROR_INPUT_EOF) + { + _stat2_decode_SRes = res2; + _stream = inStream; + _seqStream = inStream; + _isArc = true; + return S_OK; + } + + if (res2 == SZ_ERROR_ARCHIVE) + return S_FALSE; + } + else if (!isIndex) { _firstBlockWasRead = true; _firstBlock = block; @@ -526,7 +571,8 @@ HRESULT CHandler::Open2(IInStream *inStream, /* UInt32 flags, */ IArchiveOpenCal lookStream.realStream = &inStreamImp.vt; LookToRead2_Init(&lookStream); - COpenCallbackWrap openWrap(callback); + COpenCallbackWrap openWrap; + openWrap.Init(callback); CXzsCPP xzs; Int64 startPosition; @@ -539,7 +585,7 @@ HRESULT CHandler::Open2(IInStream *inStream, /* UInt32 flags, */ IArchiveOpenCal */ if (res == SZ_OK && startPosition == 0) { - _phySize_Defined = true; + _stat_defined = true; _stat.OutSize = Xzs_GetUnpackSize(&xzs.p); _stat.UnpackSize_Defined = true; @@ -615,6 +661,7 @@ HRESULT CHandler::Open2(IInStream *inStream, /* UInt32 flags, */ IArchiveOpenCal } RINOK(SRes_to_Open_HRESULT(res)); + _stream = inStream; _seqStream = inStream; _isArc = true; @@ -645,12 +692,15 @@ STDMETHODIMP CHandler::OpenSeq(ISequentialInStream *stream) STDMETHODIMP CHandler::Close() { XzStatInfo_Clear(&_stat); + XzStatInfo_Clear(&_stat2); + _stat_defined = false; + _stat2_defined = false; + _stat2_decode_SRes = SZ_OK; _isArc = false; _needSeekToStart = false; - _phySize_Defined = false; _firstBlockWasRead = false; - + _methodsString.Empty(); _stream.Release(); _seqStream.Release(); @@ -660,8 +710,6 @@ STDMETHODIMP CHandler::Close() _blocksArraySize = 0; _maxBlocksSize = 0; - MainDecodeSRes = SZ_OK; - return S_OK; } @@ -729,7 +777,7 @@ CInStream::~CInStream() } -size_t FindBlock(const CBlockInfo *blocks, size_t numBlocks, UInt64 pos) +static size_t FindBlock(const CBlockInfo *blocks, size_t numBlocks, UInt64 pos) { size_t left = 0, right = numBlocks; for (;;) @@ -900,9 +948,9 @@ STDMETHODIMP CInStream::Seek(Int64 offset, UInt32 seekOrigin, UInt64 *newPositio } if (offset < 0) return HRESULT_WIN32_ERROR_NEGATIVE_SEEK; - _virtPos = offset; + _virtPos = (UInt64)offset; if (newPosition) - *newPosition = offset; + *newPosition = (UInt64)offset; return S_OK; } @@ -951,7 +999,7 @@ STDMETHODIMP CHandler::GetStream(UInt32 index, ISequentialInStream **stream) static Int32 Get_Extract_OperationResult(const NCompress::NXz::CDecoder &decoder) { Int32 opRes; - SRes sres = decoder.MainDecodeSRes; // decoder.Stat.DecodeRes2; + SRes sres = decoder.MainDecodeSRes; if (sres == SZ_ERROR_NO_ARCHIVE) // (!IsArc) opRes = NExtract::NOperationResult::kIsNotArc; else if (sres == SZ_ERROR_INPUT_EOF) // (UnexpectedEnd) @@ -985,8 +1033,10 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems, if (numItems != (UInt32)(Int32)-1 && (numItems != 1 || indices[0] != 0)) return E_INVALIDARG; - if (_phySize_Defined) - extractCallback->SetTotal(_stat.InSize); + const CXzStatInfo *stat = GetStat(); + + if (stat) + extractCallback->SetTotal(stat->InSize); UInt64 currentTotalPacked = 0; RINOK(extractCallback->SetCompleted(¤tTotalPacked)); @@ -1106,7 +1156,7 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numIt */ #ifndef _7ZIP_ST - xzProps.numTotalThreads = _numThreads; + xzProps.numTotalThreads = (int)_numThreads; #endif xzProps.blockSize = _numSolidBytes; @@ -1161,7 +1211,9 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numIt CMyComPtr<ICompressProgressInfo> progress = lps; lps->Init(updateCallback, true); - return encoderSpec->Code(fileInStream, outStream, NULL, NULL, progress); + RINOK(encoderSpec->Code(fileInStream, outStream, NULL, NULL, progress)); + + return updateCallback->SetOperationResult(NArchive::NUpdate::NOperationResult::kOK); } if (indexInArchive != 0) @@ -1176,8 +1228,9 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numIt if (_stream) { - if (_phySize_Defined) - RINOK(updateCallback->SetTotal(_stat.InSize)); + const CXzStatInfo *stat = GetStat(); + if (stat) + RINOK(updateCallback->SetTotal(stat->InSize)); RINOK(_stream->Seek(0, STREAM_SEEK_SET, NULL)); } diff --git a/CPP/7zip/Archive/Zip/ZipAddCommon.cpp b/CPP/7zip/Archive/Zip/ZipAddCommon.cpp index 1ee7e22f..2bb57d5c 100644 --- a/CPP/7zip/Archive/Zip/ZipAddCommon.cpp +++ b/CPP/7zip/Archive/Zip/ZipAddCommon.cpp @@ -88,14 +88,18 @@ STDMETHODIMP CLzmaEncoder::Code(ISequentialInStream *inStream, ISequentialOutStr } -CAddCommon::CAddCommon(const CCompressionMethodMode &options): - _options(options), +CAddCommon::CAddCommon(): _copyCoderSpec(NULL), + _isLzmaEos(false), _cryptoStreamSpec(NULL), - _buf(NULL), - _isLzmaEos(false) + _buf(NULL) {} +void CAddCommon::SetOptions(const CCompressionMethodMode &options) +{ + _options = options; +} + CAddCommon::~CAddCommon() { MidFree(_buf); @@ -230,6 +234,11 @@ HRESULT CAddCommon::Compress( unsigned numTestMethods = _options.MethodSequence.Size(); bool descriptorMode = outSeqMode; + + // ZipCrypto without descriptor requires additional reading pass for + // inStream to calculate CRC for password check field. + // The descriptor allows to use ZipCrypto check field without CRC (InfoZip's modification). + if (!outSeqMode) if (inSeqMode && _options.PasswordIsDefined && !_options.IsAesMode) descriptorMode = true; @@ -262,6 +271,15 @@ HRESULT CAddCommon::Compress( RINOK(outStream->SetSize(0)); RINOK(outStream->Seek(0, STREAM_SEEK_SET, NULL)); } + + method = _options.MethodSequence[i]; + if (method == NCompressionMethod::kStore && descriptorMode) + { + // we still can create descriptor_mode archives with "Store" method, but they are not good for 100% + return E_NOTIMPL; + } + + bool needCode = true; if (_options.PasswordIsDefined) { @@ -314,23 +332,25 @@ HRESULT CAddCommon::Compress( RINOK(_filterSpec->WriteHeader_Check16(outStream, (UInt16)check)); } - RINOK(_cryptoStreamSpec->SetOutStream(outStream)); - RINOK(_cryptoStreamSpec->InitEncoder()); - outStreamReleaser.FilterCoder = _cryptoStreamSpec; + if (method == NCompressionMethod::kStore) + { + needCode = false; + RINOK(_cryptoStreamSpec->Code(inCrcStream, outStream, NULL, NULL, progress)); + } + else + { + RINOK(_cryptoStreamSpec->SetOutStream(outStream)); + RINOK(_cryptoStreamSpec->InitEncoder()); + outStreamReleaser.FilterCoder = _cryptoStreamSpec; + } } - method = _options.MethodSequence[i]; - - switch (method) + if (needCode) { + switch (method) + { case NCompressionMethod::kStore: { - if (descriptorMode) - { - // we still can create descriptor_mode archives with "Store" method, but they are not good for 100% - return E_NOTIMPL; - } - if (!_copyCoderSpec) { _copyCoderSpec = new NCompress::CCopyCoder; @@ -438,15 +458,21 @@ HRESULT CAddCommon::Compress( } } + try { RINOK(_compressEncoder->Code(inCrcStream, outStreamNew, NULL, NULL, progress)); + } catch (...) { return E_FAIL; } break; } + } // switch end + + if (_options.PasswordIsDefined) + { + RINOK(_cryptoStreamSpec->OutStreamFinish()); + } } if (_options.PasswordIsDefined) { - RINOK(_cryptoStreamSpec->OutStreamFinish()); - if (_options.IsAesMode) { RINOK(_filterAesSpec->WriteFooter(outStream)); diff --git a/CPP/7zip/Archive/Zip/ZipAddCommon.h b/CPP/7zip/Archive/Zip/ZipAddCommon.h index ff3251db..0aa44adf 100644 --- a/CPP/7zip/Archive/Zip/ZipAddCommon.h +++ b/CPP/7zip/Archive/Zip/ZipAddCommon.h @@ -28,9 +28,15 @@ struct CCompressingResult Byte ExtractVersion; bool DescriptorMode; bool LzmaEos; + + CCompressingResult() + { + // for GCC: + UnpackSize = 0; + } }; -class CAddCommon +class CAddCommon MY_UNCOPYABLE { CCompressionMethodMode _options; NCompress::CCopyCoder *_copyCoderSpec; @@ -50,7 +56,9 @@ class CAddCommon HRESULT CalcStreamCRC(ISequentialInStream *inStream, UInt32 &resultCRC); public: - CAddCommon(const CCompressionMethodMode &options); + // CAddCommon(const CCompressionMethodMode &options); + CAddCommon(); + void SetOptions(const CCompressionMethodMode &options); ~CAddCommon(); HRESULT Set_Pre_CompressionResult(bool inSeqMode, bool outSeqMode, UInt64 unpackSize, diff --git a/CPP/7zip/Archive/Zip/ZipCompressionMode.h b/CPP/7zip/Archive/Zip/ZipCompressionMode.h index 1125f6ed..842991c4 100644 --- a/CPP/7zip/Archive/Zip/ZipCompressionMode.h +++ b/CPP/7zip/Archive/Zip/ZipCompressionMode.h @@ -35,7 +35,7 @@ struct CCompressionMethodMode: public CBaseProps { CRecordVector<Byte> MethodSequence; bool PasswordIsDefined; - AString Password; + AString Password; // _Wipe UInt64 _dataSizeReduce; bool _dataSizeReduceDefined; @@ -47,6 +47,8 @@ struct CCompressionMethodMode: public CBaseProps _dataSizeReduceDefined = false; _dataSizeReduce = 0; } + + ~CCompressionMethodMode() { Password.Wipe_and_Empty(); } }; }} diff --git a/CPP/7zip/Archive/Zip/ZipHandler.cpp b/CPP/7zip/Archive/Zip/ZipHandler.cpp index a4794f51..72a77cb7 100644 --- a/CPP/7zip/Archive/Zip/ZipHandler.cpp +++ b/CPP/7zip/Archive/Zip/ZipHandler.cpp @@ -18,6 +18,17 @@ #include "../../Common/StreamUtils.h" #include "../../Compress/CopyCoder.h" + +#ifdef EXTERNAL_CODECS +#ifndef SUPPORT_LZFSE +#define SUPPORT_LZFSE +#endif +#endif + +#ifdef SUPPORT_LZFSE +#include "../../Compress/LzfseDecoder.h" +#endif + #include "../../Compress/LzmaDecoder.h" #include "../../Compress/ImplodeDecoder.h" #include "../../Compress/PpmdZip.h" @@ -81,16 +92,24 @@ const char * const kMethodNames1[kNumMethodNames1] = , "BZip2" , NULL , "LZMA" + , NULL + , NULL + , NULL + , NULL + , NULL + , "zstd-pk" }; const char * const kMethodNames2[kNumMethodNames2] = { - "xz" + "zstd-wz" + , "MP3" + , "xz" , "Jpeg" , "WavPack" , "PPMd" - , "WzAES" + , "LZFSE" // , "WzAES" }; #define kMethod_AES "AES" @@ -240,6 +259,12 @@ STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value) if (m_Archive.IsZip64) s.Add_OptSpaced("Zip64"); + if (m_Archive.IsCdUnsorted) + s.Add_OptSpaced("Unsorted_CD"); + + if (m_Archive.IsApk) + s.Add_OptSpaced("apk"); + if (m_Archive.ExtraMinorError) s.Add_OptSpaced("Minor_Extra_ERROR"); @@ -312,9 +337,8 @@ STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value) // case kpidIsAltStream: prop = true; break; } - prop.Detach(value); + return prop.Detach(value); COM_TRY_END - return S_OK; } STDMETHODIMP CHandler::GetNumberOfItems(UInt32 *numItems) @@ -336,7 +360,9 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val { UString res; item.GetUnicodeString(res, item.Name, false, _forceCodePage, _specifiedCodePage); - NItemName::ReplaceToOsSlashes_Remove_TailSlash(res); + NItemName::ReplaceToOsSlashes_Remove_TailSlash(res, + item.Is_MadeBy_Unix() // useBackslashReplacement + ); /* if (item.ParentOfAltStream >= 0) { @@ -359,7 +385,7 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val case kpidIsDir: prop = item.IsDir(); break; case kpidSize: { - if (item.FromCentral || !item.FromLocal || !item.HasDescriptor() || item.DescriptorWasRead) + if (!item.IsBadDescriptor()) prop = item.Size; break; } @@ -467,23 +493,27 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val case kpidMethod: { - unsigned id = item.Method; AString m; - - if (item.IsEncrypted()) + bool isWzAes = false; + unsigned id = item.Method; + + if (id == NFileHeader::NCompressionMethod::kWzAES) { - if (id == NFileHeader::NCompressionMethod::kWzAES) + CWzAesExtra aesField; + if (extra.GetWzAes(aesField)) { m += kMethod_AES; - CWzAesExtra aesField; - if (extra.GetWzAes(aesField)) - { - m += '-'; - m.Add_UInt32(((unsigned)aesField.Strength + 1) * 64); - id = aesField.Method; - } + m += '-'; + m.Add_UInt32(((unsigned)aesField.Strength + 1) * 64); + id = aesField.Method; + isWzAes = true; } - else if (item.IsStrongEncrypted()) + } + + if (item.IsEncrypted()) + if (!isWzAes) + { + if (item.IsStrongEncrypted()) { CStrongCryptoExtra f; f.AlgId = 0; @@ -506,8 +536,9 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val } else m += kMethod_ZipCrypto; - m += ' '; } + + m.Add_Space_if_NotEmpty(); { const char *s = NULL; @@ -516,7 +547,7 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val else { int id2 = (int)id - (int)kMethodNames2Start; - if (id2 >= 0 && id2 < kNumMethodNames2) + if (id2 >= 0 && (unsigned)id2 < kNumMethodNames2) s = kMethodNames2[id2]; } if (s) @@ -532,7 +563,7 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val { if (level & 1) m += ":eos"; - level &= ~1; + level &= ~(unsigned)1; } else if (id == NFileHeader::NCompressionMethod::kDeflate) { @@ -576,7 +607,7 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val } UInt32 flags = item.Flags; - flags &= ~(6); // we don't need compression related bits here. + flags &= ~(unsigned)6; // we don't need compression related bits here. if (flags != 0) { @@ -589,7 +620,7 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val } } - if (!item.FromCentral && item.FromLocal && item.HasDescriptor() && !item.DescriptorWasRead) + if (item.IsBadDescriptor()) s.Add_OptSpaced("Descriptor_ERROR"); if (!s.IsEmpty()) @@ -634,8 +665,7 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val */ } - prop.Detach(value); - return S_OK; + return prop.Detach(value); COM_TRY_END } @@ -860,11 +890,14 @@ public: }; -static HRESULT SkipStreamData(ISequentialInStream *stream, bool &thereAreData) +static HRESULT SkipStreamData(ISequentialInStream *stream, + ICompressProgressInfo *progress, UInt64 packSize, UInt64 unpackSize, + bool &thereAreData) { thereAreData = false; const size_t kBufSize = 1 << 12; Byte buf[kBufSize]; + UInt64 prev = packSize; for (;;) { size_t size = kBufSize; @@ -872,10 +905,80 @@ static HRESULT SkipStreamData(ISequentialInStream *stream, bool &thereAreData) if (size == 0) return S_OK; thereAreData = true; + packSize += size; + if ((packSize - prev) >= (1 << 22)) + { + prev = packSize; + RINOK(progress->SetRatioInfo(&packSize, &unpackSize)); + } } } + +class COutStreamWithPadPKCS7: + public ISequentialOutStream, + public CMyUnknownImp +{ + CMyComPtr<ISequentialOutStream> _stream; + UInt64 _size; + UInt64 _padPos; + UInt32 _padSize; + bool _padFailure; +public: + MY_UNKNOWN_IMP + STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize); + void SetStream(ISequentialOutStream *stream) { _stream = stream; } + void ReleaseStream() { _stream.Release(); } + + // padSize == 0 means (no_pad Mode) + void Init(UInt64 padPos, UInt32 padSize) + { + _padPos = padPos; + _padSize = padSize; + _size = 0; + _padFailure = false; + } + UInt64 GetSize() const { return _size; } + bool WasPadFailure() const { return _padFailure; } +}; + + +STDMETHODIMP COutStreamWithPadPKCS7::Write(const void *data, UInt32 size, UInt32 *processedSize) +{ + UInt32 written = 0; + HRESULT result = S_OK; + if (_size < _padPos) + { + const UInt64 rem = _padPos - _size; + UInt32 num = size; + if (num > rem) + num = (UInt32)rem; + result = _stream->Write(data, num, &written); + _size += written; + if (processedSize) + *processedSize = written; + if (_size != _padPos || result != S_OK) + return result; + size -= written; + data = ((const Byte *)data) + written; + } + _size += size; + written += size; + if (processedSize) + *processedSize = written; + if (_padSize != 0) + for (; size != 0; size--) + { + if (*(const Byte *)data != _padSize) + _padFailure = true; + data = ((const Byte *)data) + 1; + } + return result; +} + + + HRESULT CZipDecoder::Decode( DECL_EXTERNAL_CODECS_LOC_VARS CInArchive &archive, const CItemEx &item, @@ -895,9 +998,32 @@ HRESULT CZipDecoder::Decode( bool needCRC = true; bool wzAesMode = false; bool pkAesMode = false; + + bool badDescriptor = item.IsBadDescriptor(); + if (badDescriptor) + needCRC = false; + unsigned id = item.Method; + CWzAesExtra aesField; + // LZFSE and WinZip's AES use same id - kWzAES. + + if (id == NFileHeader::NCompressionMethod::kWzAES) + { + if (item.GetMainExtra().GetWzAes(aesField)) + { + if (!item.IsEncrypted()) + { + res = NExtract::NOperationResult::kUnsupportedMethod; + return S_OK; + } + wzAesMode = true; + needCRC = aesField.NeedCrc(); + } + } + + if (!wzAesMode) if (item.IsEncrypted()) { if (item.IsStrongEncrypted()) @@ -910,14 +1036,6 @@ HRESULT CZipDecoder::Decode( } pkAesMode = true; } - else if (id == NFileHeader::NCompressionMethod::kWzAES) - { - CWzAesExtra aesField; - if (!item.GetMainExtra().GetWzAes(aesField)) - return S_OK; - wzAesMode = true; - needCRC = aesField.NeedCrc(); - } } COutStreamWithCRC *outStreamSpec = new COutStreamWithCRC; @@ -957,9 +1075,6 @@ HRESULT CZipDecoder::Decode( { if (wzAesMode) { - CWzAesExtra aesField; - if (!item.GetMainExtra().GetWzAes(aesField)) - return S_OK; id = aesField.Method; if (!_wzAesDecoder) { @@ -1002,12 +1117,12 @@ HRESULT CZipDecoder::Decode( if (getTextPassword) { - CMyComBSTR password; + CMyComBSTR_Wipe password; RINOK(getTextPassword->CryptoGetTextPassword(&password)); - AString charPassword; + AString_Wipe charPassword; if (password) { - UnicodeStringToMultiByte2(charPassword, (const wchar_t *)password, CP_ACP); + UnicodeStringToMultiByte2(charPassword, (LPCOLESTR)password, CP_ACP); /* if (wzAesMode || pkAesMode) { @@ -1063,6 +1178,10 @@ HRESULT CZipDecoder::Decode( mi.Coder = new NCompress::NXz::CComDecoder; else if (id == NFileHeader::NCompressionMethod::kPPMd) mi.Coder = new NCompress::NPpmdZip::CDecoder(true); + #ifdef SUPPORT_LZFSE + else if (id == NFileHeader::NCompressionMethod::kWzAES) + mi.Coder = new NCompress::NLzfse::CDecoder; + #endif else { CMethodId szMethodID; @@ -1089,7 +1208,8 @@ HRESULT CZipDecoder::Decode( m = methodItems.Add(mi); } - ICompressCoder *coder = methodItems[m].Coder; + const CMethodItem &mi = methodItems[m]; + ICompressCoder *coder = mi.Coder; #ifndef _7ZIP_ST @@ -1123,14 +1243,22 @@ HRESULT CZipDecoder::Decode( } - CMyComPtr<ISequentialInStream> inStreamNew; - bool isFullStreamExpected = (!item.HasDescriptor() || item.PackSize != 0); bool needReminderCheck = false; bool dataAfterEnd = false; bool truncatedError = false; bool lzmaEosError = false; + bool headersError = false; + bool padError = false; + bool readFromFilter = false; + + const bool useUnpackLimit = (id == NFileHeader::NCompressionMethod::kStore + || !item.HasDescriptor() + || item.Size >= ((UInt64)1 << 32) + || item.LocalExtra.IsZip64 + || item.CentralExtra.IsZip64 + ); { HRESULT result = S_OK; @@ -1198,23 +1326,7 @@ HRESULT CZipDecoder::Decode( } } } - - if (result == S_OK) - { - inStreamReleaser.FilterCoder = filterStreamSpec; - RINOK(filterStreamSpec->SetInStream(inStream)); - - /* IFilter::Init() does nothing in all zip crypto filters. - So we can call any Initialize function in CFilterCoder. */ - - RINOK(filterStreamSpec->Init_NoSubFilterInit()); - // RINOK(filterStreamSpec->SetOutStreamSize(NULL)); - - inStreamNew = filterStream; - } } - else - inStreamNew = inStream; if (result == S_OK) { @@ -1222,26 +1334,84 @@ HRESULT CZipDecoder::Decode( coder->QueryInterface(IID_ICompressSetFinishMode, (void **)&setFinishMode); if (setFinishMode) { - RINOK(setFinishMode->SetFinishMode(BoolToInt(true))); + RINOK(setFinishMode->SetFinishMode(BoolToUInt(true))); } const UInt64 coderPackSize = limitedStreamSpec->GetRem(); - bool useUnpackLimit = (id == 0 - || !item.HasDescriptor() - || item.Size >= ((UInt64)1 << 32) - || item.LocalExtra.IsZip64 - || item.CentralExtra.IsZip64 - ); + if (id == NFileHeader::NCompressionMethod::kStore && item.IsEncrypted()) + { + readFromFilter = false; + + COutStreamWithPadPKCS7 *padStreamSpec = NULL; + CMyComPtr<ISequentialOutStream> padStream; + UInt32 padSize = 0; + + if (pkAesMode) + { + padStreamSpec = new COutStreamWithPadPKCS7; + padStream = padStreamSpec; + padSize = _pkAesDecoderSpec->GetPadSize((UInt32)item.Size); + padStreamSpec->SetStream(outStream); + padStreamSpec->Init(item.Size, padSize); + } + + // Here we decode minimal required size, including padding + const UInt64 expectedSize = item.Size + padSize; + UInt64 size = coderPackSize; + if (item.Size > coderPackSize) + headersError = true; + else if (expectedSize != coderPackSize) + { + headersError = true; + if (coderPackSize > expectedSize) + size = expectedSize; + } - result = coder->Code(inStreamNew, outStream, - isFullStreamExpected ? &coderPackSize : NULL, - // NULL, - useUnpackLimit ? &item.Size : NULL, - compressProgress); + result = filterStreamSpec->Code(inStream, padStream ? + (ISequentialOutStream *)padStream : + (ISequentialOutStream *)outStream, + NULL, &size, compressProgress); - if (result == S_OK) + if (outStreamSpec->GetSize() != item.Size) + truncatedError = true; + + if (pkAesMode) + { + if (padStreamSpec->GetSize() != size) + truncatedError = true; + if (padStreamSpec->WasPadFailure()) + padError = true; + } + } + else { + if (item.IsEncrypted()) + { + readFromFilter = true; + inStreamReleaser.FilterCoder = filterStreamSpec; + RINOK(filterStreamSpec->SetInStream(inStream)); + + /* IFilter::Init() does nothing in all zip crypto filters. + So we can call any Initialize function in CFilterCoder. */ + + RINOK(filterStreamSpec->Init_NoSubFilterInit()); + // RINOK(filterStreamSpec->SetOutStreamSize(NULL)); + } + + try { + result = coder->Code(readFromFilter ? + (ISequentialInStream *)filterStream : + (ISequentialInStream *)inStream, + outStream, + isFullStreamExpected ? &coderPackSize : NULL, + // NULL, + useUnpackLimit ? &item.Size : NULL, + compressProgress); + } catch (...) { return E_FAIL; } + + if (result == S_OK) + { CMyComPtr<ICompressGetInStreamProcessedSize> getInStreamProcessedSize; coder->QueryInterface(IID_ICompressGetInStreamProcessedSize, (void **)&getInStreamProcessedSize); if (getInStreamProcessedSize && setFinishMode) @@ -1259,7 +1429,32 @@ HRESULT CZipDecoder::Decode( { if (processed + padSize < coderPackSize) dataAfterEnd = true; - // also here we can check PKCS7 padding data from reminder (it can be inside stream buffer in coder). + else + { + // here we can PKCS7 padding data from reminder (it can be inside stream buffer in coder). + CMyComPtr<ICompressReadUnusedFromInBuf> readInStream; + coder->QueryInterface(IID_ICompressReadUnusedFromInBuf, (void **)&readInStream); + if (readInStream) + { + // change pad size, it we support another block size in ZipStron + // here we request more to detect error with data after end. + const UInt32 kBufSize = NCrypto::NZipStrong::kAesPadAllign + 16; + Byte buf[kBufSize]; + UInt32 processedSize; + RINOK(readInStream->ReadUnusedFromInBuf(buf, kBufSize, &processedSize)); + if (processedSize > padSize) + dataAfterEnd = true; + else + { + if (ReadStream_FALSE(filterStream, buf + processedSize, padSize - processedSize) != S_OK) + padError = true; + else + for (unsigned i = 0; i < padSize; i++) + if (buf[i] != padSize) + padError = true; + } + } + } } } else @@ -1270,11 +1465,15 @@ HRESULT CZipDecoder::Decode( dataAfterEnd = true; } else if (processed > coderPackSize) + { + // that case is additional check, that can show the bugs in code (coder) truncatedError = true; + } needReminderCheck = isFullStreamExpected; } } } + } } if (result == S_OK && id == NFileHeader::NCompressionMethod::kLZMA) @@ -1298,19 +1497,33 @@ HRESULT CZipDecoder::Decode( bool authOk = true; if (needCRC) crcOK = (outStreamSpec->GetCRC() == item.Crc); + + if (useUnpackLimit) + if (outStreamSpec->GetSize() != item.Size) + truncatedError = true; if (wzAesMode) { + const UInt64 unpackSize = outStreamSpec->GetSize(); + const UInt64 packSize = limitedStreamSpec->GetSize(); bool thereAreData = false; - if (SkipStreamData(inStreamNew, thereAreData) != S_OK) + // read to the end from filter or from packed stream + if (SkipStreamData(readFromFilter ? + (ISequentialInStream *)filterStream : + (ISequentialInStream *)inStream, + compressProgress, packSize, unpackSize, thereAreData) != S_OK) authOk = false; - if (needReminderCheck && thereAreData) dataAfterEnd = true; - - limitedStreamSpec->Init(NCrypto::NWzAes::kMacSize); - if (_wzAesDecoderSpec->CheckMac(inStream, authOk) != S_OK) - authOk = false; + + if (limitedStreamSpec->GetRem() != 0) + truncatedError = true; + else + { + limitedStreamSpec->Init(NCrypto::NWzAes::kMacSize); + if (_wzAesDecoderSpec->CheckMac(inStream, authOk) != S_OK) + authOk = false; + } } res = NExtract::NOperationResult::kCRCError; @@ -1321,10 +1534,16 @@ HRESULT CZipDecoder::Decode( if (dataAfterEnd) res = NExtract::NOperationResult::kDataAfterEnd; + else if (padError) + res = NExtract::NOperationResult::kCRCError; else if (truncatedError) res = NExtract::NOperationResult::kUnexpectedEnd; + else if (headersError) + res = NExtract::NOperationResult::kHeadersError; else if (lzmaEosError) res = NExtract::NOperationResult::kHeadersError; + else if (badDescriptor) + res = NExtract::NOperationResult::kUnexpectedEnd; // CheckDescriptor() supports only data descriptor with signature and // it doesn't support "old" pkzip's data descriptor without signature. diff --git a/CPP/7zip/Archive/Zip/ZipHandler.h b/CPP/7zip/Archive/Zip/ZipHandler.h index bee57c00..3043e41c 100644 --- a/CPP/7zip/Archive/Zip/ZipHandler.h +++ b/CPP/7zip/Archive/Zip/ZipHandler.h @@ -15,8 +15,8 @@ namespace NArchive { namespace NZip { -const unsigned kNumMethodNames1 = NFileHeader::NCompressionMethod::kLZMA + 1; -const unsigned kMethodNames2Start = NFileHeader::NCompressionMethod::kXz; +const unsigned kNumMethodNames1 = NFileHeader::NCompressionMethod::kZstdPk + 1; +const unsigned kMethodNames2Start = NFileHeader::NCompressionMethod::kZstdWz; const unsigned kNumMethodNames2 = NFileHeader::NCompressionMethod::kWzAES + 1 - kMethodNames2Start; extern const char * const kMethodNames1[kNumMethodNames1]; diff --git a/CPP/7zip/Archive/Zip/ZipHandlerOut.cpp b/CPP/7zip/Archive/Zip/ZipHandlerOut.cpp index c21b5605..a9b3eae5 100644 --- a/CPP/7zip/Archive/Zip/ZipHandlerOut.cpp +++ b/CPP/7zip/Archive/Zip/ZipHandlerOut.cpp @@ -53,7 +53,7 @@ static int FindZipMethod(const char *s, const char * const *names, unsigned num) { const char *name = names[i]; if (name && StringsAreEqualNoCase_Ascii(s, name)) - return i; + return (int)i; } return -1; } @@ -65,7 +65,7 @@ static int FindZipMethod(const char *s) return k; k = FindZipMethod(s, kMethodNames2, kNumMethodNames2); if (k >= 0) - return kMethodNames2Start + k; + return (int)kMethodNames2Start + k; return -1; } @@ -75,7 +75,7 @@ static int FindZipMethod(const char *s) catch(const CSystemException &e) { return e.ErrorCode; } \ catch(...) { return E_OUTOFMEMORY; } -static HRESULT GetTime(IArchiveUpdateCallback *callback, int index, PROPID propID, FILETIME &filetime) +static HRESULT GetTime(IArchiveUpdateCallback *callback, unsigned index, PROPID propID, FILETIME &filetime) { filetime.dwHighDateTime = filetime.dwLowDateTime = 0; NCOM::CPropVariant prop; @@ -106,6 +106,10 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numIt UInt64 largestSize = 0; bool largestSizeDefined = false; + #ifdef _WIN32 + const UINT oemCP = GetOEMCP(); + #endif + UString name; CUpdateItem ui; @@ -125,7 +129,7 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numIt ui.NewProps = IntToBool(newProps); ui.NewData = IntToBool(newData); - ui.IndexInArc = indexInArc; + ui.IndexInArc = (int)indexInArc; ui.IndexInClient = i; bool existInArchive = (indexInArc != (UInt32)(Int32)-1); @@ -240,10 +244,25 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numIt if (needSlash) name += kSlash; - UINT codePage = _forceCodePage ? _specifiedCodePage : CP_OEMCP; - + const UINT codePage = _forceCodePage ? _specifiedCodePage : CP_OEMCP; bool tryUtf8 = true; - if ((m_ForceLocal || !m_ForceUtf8) && codePage != CP_UTF8) + + /* + Windows 10 allows users to set UTF-8 in Region Settings via option: + "Beta: Use Unicode UTF-8 for worldwide language support" + In that case Windows uses CP_UTF8 when we use CP_OEMCP. + 21.02 fixed: + we set UTF-8 mark for non-latin files for such UTF-8 mode in Windows. + we write additional Info-Zip Utf-8 FileName Extra for non-latin names/ + */ + + if ((codePage != CP_UTF8) && + #ifdef _WIN32 + (m_ForceLocal || !m_ForceUtf8) && (oemCP != CP_UTF8) + #else + (m_ForceLocal && !m_ForceUtf8) + #endif + ) { bool defaultCharWasUsed; ui.Name = UnicodeStringToMultiByte(name, codePage, '_', defaultCharWasUsed); @@ -251,13 +270,26 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numIt MultiByteToUnicodeString(ui.Name, codePage) != name)); } + const bool isNonLatin = !name.IsAscii(); + if (tryUtf8) { - ui.IsUtf8 = !name.IsAscii(); + ui.IsUtf8 = isNonLatin; ConvertUnicodeToUTF8(name, ui.Name); + + #ifndef _WIN32 + if (ui.IsUtf8 && !CheckUTF8_AString(ui.Name)) + { + // if it's non-Windows and there are non-UTF8 characters we clear UTF8-flag + ui.IsUtf8 = false; + } + #endif } + else if (isNonLatin) + Convert_Unicode_To_UTF8_Buf(name, ui.Name_Utf); - if (ui.Name.Len() >= (1 << 16)) + if (ui.Name.Len() >= (1 << 16) + || ui.Name_Utf.Size() >= (1 << 16) - 128) return E_INVALIDARG; { @@ -337,10 +369,10 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numIt options._dataSizeReduceDefined = largestSizeDefined; options.PasswordIsDefined = false; - options.Password.Empty(); + options.Password.Wipe_and_Empty(); if (getTextPassword) { - CMyComBSTR password; + CMyComBSTR_Wipe password; Int32 passwordIsDefined; RINOK(getTextPassword->CryptoGetTextPassword2(&passwordIsDefined, &password)); options.PasswordIsDefined = IntToBool(passwordIsDefined); @@ -352,7 +384,7 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numIt if (!IsSimpleAsciiString(password)) return E_INVALIDARG; if (password) - options.Password = UnicodeStringToMultiByte((LPCOLESTR)password, CP_OEMCP); + UnicodeStringToMultiByte2(options.Password, (LPCOLESTR)password, CP_OEMCP); if (options.IsAesMode) { if (options.Password.Len() > NCrypto::NWzAes::kPasswordSizeMax) @@ -496,7 +528,7 @@ STDMETHODIMP CHandler::SetProperties(const wchar_t * const *names, const PROPVAR UInt32 id = prop.ulVal; if (id > 0xFF) return E_INVALIDARG; - m_MainMethod = id; + m_MainMethod = (int)id; } else { @@ -518,7 +550,7 @@ STDMETHODIMP CHandler::SetProperties(const wchar_t * const *names, const PROPVAR const char *end; UInt32 id = ConvertStringToUInt32(methodName, &end); if (*end == 0 && id <= 0xFF) - m_MainMethod = id; + m_MainMethod = (int)id; else if (methodName.IsEqualTo_Ascii_NoCase("Copy")) // it's alias for "Store" m_MainMethod = 0; } diff --git a/CPP/7zip/Archive/Zip/ZipHeader.h b/CPP/7zip/Archive/Zip/ZipHeader.h index 5e6f00e4..c5c7166e 100644 --- a/CPP/7zip/Archive/Zip/ZipHeader.h +++ b/CPP/7zip/Archive/Zip/ZipHeader.h @@ -56,7 +56,10 @@ namespace NFileHeader kTerse = 18, kLz77 = 19, + kZstdPk = 20, + kZstdWz = 93, + kMP3 = 94, kXz = 95, kJpeg = 96, kWavPack = 97, @@ -90,7 +93,10 @@ namespace NFileHeader kUnixExtra = 0x5855, kIzUnicodeComment = 0x6375, kIzUnicodeName = 0x7075, - kWzAES = 0x9901 + kUnix2Extra = 0x7855, + kUnix3Extra = 0x7875, + kWzAES = 0x9901, + kApkAlign = 0xD935 }; } diff --git a/CPP/7zip/Archive/Zip/ZipIn.cpp b/CPP/7zip/Archive/Zip/ZipIn.cpp index 509753c2..880ff218 100644 --- a/CPP/7zip/Archive/Zip/ZipIn.cpp +++ b/CPP/7zip/Archive/Zip/ZipIn.cpp @@ -152,6 +152,9 @@ void CInArchive::Close() IsArc = false; IsZip64 = false; + IsApk = false; + IsCdUnsorted = false; + HeadersError = false; HeadersWarning = false; ExtraMinorError = false; @@ -169,7 +172,7 @@ void CInArchive::Close() IsMultiVol = false; UseDisk_in_SingleVol = false; EcdVolIndex = 0; - + ArcInfo.Clear(); ClearRefs(); @@ -181,7 +184,7 @@ HRESULT CInArchive::Seek_SavePos(UInt64 offset) { // InitBuf(); // if (!Stream) return S_FALSE; - return Stream->Seek(offset, STREAM_SEEK_SET, &_streamPos); + return Stream->Seek((Int64)offset, STREAM_SEEK_SET, &_streamPos); } HRESULT CInArchive::SeekToVol(int volIndex, UInt64 offset) @@ -193,9 +196,9 @@ HRESULT CInArchive::SeekToVol(int volIndex, UInt64 offset) { if ((unsigned)volIndex >= Vols.Streams.Size()) return S_FALSE; - if (!Vols.Streams[volIndex].Stream) + if (!Vols.Streams[(unsigned)volIndex].Stream) return S_FALSE; - Stream = Vols.Streams[volIndex].Stream; + Stream = Vols.Streams[(unsigned)volIndex].Stream; } else if (volIndex == -2) { @@ -277,11 +280,11 @@ HRESULT CInArchive::ReadFromCache(Byte *data, unsigned size, unsigned &processed } else { - UInt32 cur = 0; - result = Stream->Read(data, size, &cur); + size_t cur = size; + result = ReadStream(Stream, data, &cur); data += cur; - size -= cur; - processed += cur; + size -= (unsigned)cur; + processed += (unsigned)cur; _streamPos += cur; _cnt += cur; if (cur != 0) @@ -299,7 +302,7 @@ HRESULT CInArchive::ReadFromCache(Byte *data, unsigned size, unsigned &processed || (unsigned)Vols.StreamIndex + 1 >= Vols.Streams.Size()) break; - const CVols::CSubStreamInfo &s = Vols.Streams[Vols.StreamIndex + 1]; + const CVols::CSubStreamInfo &s = Vols.Streams[(unsigned)Vols.StreamIndex + 1]; if (!s.Stream) break; result = s.SeekToStart(); @@ -316,6 +319,16 @@ HRESULT CInArchive::ReadFromCache(Byte *data, unsigned size, unsigned &processed } +HRESULT CInArchive::ReadFromCache_FALSE(Byte *data, unsigned size) +{ + unsigned processed; + HRESULT res = ReadFromCache(data, size, processed); + if (res == S_OK && size != processed) + return S_FALSE; + return res; +} + + static bool CheckDosTime(UInt32 dosTime) { if (dosTime == 0) @@ -412,8 +425,12 @@ API_FUNC_IsArc IsArc_Zip(const Byte *p, size_t size) const unsigned nameSize = Get16(p + 22); unsigned extraSize = Get16(p + 24); const UInt32 extraOffset = kLocalHeaderSize + (UInt32)nameSize; + + /* + // 21.02: fixed. we don't use the following check if (extraOffset + extraSize > (1 << 16)) return k_IsArc_Res_NO; + */ p -= 4; @@ -498,12 +515,9 @@ static const Byte *FindPK(const Byte *p, const Byte *limit) { for (;;) { - Byte b0 = p[0]; - if (p >= limit) - return p; - p++; - if (b0 == 0x50) - break; + Byte b0; + b0 = p[0]; if (p >= limit) return p; p++; if (b0 == 0x50) break; + b0 = p[0]; if (p >= limit) return p; p++; if (b0 == 0x50) break; } if (p[0] == 0x4B) return p - 1; @@ -540,10 +554,7 @@ HRESULT CInArchive::FindMarker(const UInt64 *searchLimit) if (searchLimit && *searchLimit == 0) { Byte startBuf[kMarkerSize]; - unsigned processed; - RINOK(ReadFromCache(startBuf, kMarkerSize, processed)); - if (processed != kMarkerSize) - return S_FALSE; + RINOK(ReadFromCache_FALSE(startBuf, kMarkerSize)); UInt32 marker = Get32(startBuf); _signature = marker; @@ -551,9 +562,7 @@ HRESULT CInArchive::FindMarker(const UInt64 *searchLimit) if ( marker == NSignature::kNoSpan || marker == NSignature::kSpan) { - RINOK(ReadFromCache(startBuf, kMarkerSize, processed)); - if (processed != kMarkerSize) - return S_FALSE; + RINOK(ReadFromCache_FALSE(startBuf, kMarkerSize)); _signature = Get32(startBuf); } @@ -605,7 +614,7 @@ HRESULT CInArchive::FindMarker(const UInt64 *searchLimit) SkipLookahed(avail); - const CVols::CSubStreamInfo &s = Vols.Streams[Vols.StreamIndex + 1]; + const CVols::CSubStreamInfo &s = Vols.Streams[(unsigned)Vols.StreamIndex + 1]; if (!s.Stream) break; @@ -645,14 +654,14 @@ HRESULT CInArchive::FindMarker(const UInt64 *searchLimit) p = FindPK(p, limit); if (p >= limit) break; - const size_t rem = pStart + avail - p; + const size_t rem = (size_t)(pStart + avail - p); UInt32 res = IsArc_Zip_2(p, rem, isFinished); if (res != k_IsArc_Res_NO) { if (rem < kMarkerSize) return S_FALSE; _signature = Get32(p); - SkipLookahed(p - pStart); + SkipLookahed((size_t)(p - pStart)); ArcInfo.MarkerVolIndex = Vols.StreamIndex; ArcInfo.MarkerPos = GetVirtStreamPos(); ArcInfo.MarkerPos2 = ArcInfo.MarkerPos; @@ -674,7 +683,7 @@ HRESULT CInArchive::FindMarker(const UInt64 *searchLimit) if (!IsMultiVol && isFinished) break; - SkipLookahed(p - pStart); + SkipLookahed((size_t)(p - pStart)); if (Callback && (_cnt - progressPrev) >= ((UInt32)1 << 23)) { @@ -728,7 +737,7 @@ HRESULT CInArchive::IncreaseRealPosition(UInt64 offset, bool &isFinished) if (!IsMultiVol) { _cnt += offset; - return Stream->Seek(offset, STREAM_SEEK_CUR, &_streamPos); + return Stream->Seek((Int64)offset, STREAM_SEEK_CUR, &_streamPos); } for (;;) @@ -744,7 +753,7 @@ HRESULT CInArchive::IncreaseRealPosition(UInt64 offset, bool &isFinished) return S_OK; } { - const CVols::CSubStreamInfo &s = Vols.Streams[Vols.StreamIndex]; + const CVols::CSubStreamInfo &s = Vols.Streams[(unsigned)Vols.StreamIndex]; if (!s.Stream) { isFinished = true; @@ -756,7 +765,7 @@ HRESULT CInArchive::IncreaseRealPosition(UInt64 offset, bool &isFinished) if ((UInt64)offset <= rem) { _cnt += offset; - return Stream->Seek(offset, STREAM_SEEK_CUR, &_streamPos); + return Stream->Seek((Int64)offset, STREAM_SEEK_CUR, &_streamPos); } RINOK(Seek_SavePos(s.Size)); offset -= rem; @@ -771,7 +780,7 @@ HRESULT CInArchive::IncreaseRealPosition(UInt64 offset, bool &isFinished) isFinished = true; return S_OK; } - const CVols::CSubStreamInfo &s2 = Vols.Streams[Vols.StreamIndex]; + const CVols::CSubStreamInfo &s2 = Vols.Streams[(unsigned)Vols.StreamIndex]; if (!s2.Stream) { isFinished = true; @@ -834,7 +843,7 @@ HRESULT CInArchive::LookAhead(size_t minRequired) || (unsigned)Vols.StreamIndex + 1 >= Vols.Streams.Size()) return S_OK; - const CVols::CSubStreamInfo &s = Vols.Streams[Vols.StreamIndex + 1]; + const CVols::CSubStreamInfo &s = Vols.Streams[(unsigned)Vols.StreamIndex + 1]; if (!s.Stream) return S_OK; @@ -979,7 +988,7 @@ bool CInArchive::ReadFileName(unsigned size, AString &s) #define ZIP64_IS_16_MAX(n) ((n) == 0xFFFF) -bool CInArchive::ReadExtra(unsigned extraSize, CExtraBlock &extra, +bool CInArchive::ReadExtra(const CLocalItem &item, unsigned extraSize, CExtraBlock &extra, UInt64 &unpackSize, UInt64 &packSize, UInt64 &localOffset, UInt32 &disk) { extra.Clear(); @@ -1010,16 +1019,16 @@ bool CInArchive::ReadExtra(unsigned extraSize, CExtraBlock &extra, bool isOK = true; if (ZIP64_IS_32_MAX(unpackSize)) - if (size < 8) isOK = false; else { size -= 8; unpackSize = ReadUInt64(); } + { 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 (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 (size < 8) isOK = false; else { size -= 8; localOffset = ReadUInt64(); }} if (isOK && ZIP64_IS_16_MAX(disk)) - if (size < 4) isOK = false; else { size -= 4; disk = ReadUInt32(); } + { if (size < 4) isOK = false; else { size -= 4; disk = ReadUInt32(); }} if (!isOK || size != 0) { @@ -1033,6 +1042,11 @@ bool CInArchive::ReadExtra(unsigned extraSize, CExtraBlock &extra, { ReadBuffer(subBlock.Data, size); extra.SubBlocks.Add(subBlock); + if (subBlock.ID == NFileHeader::NExtraID::kIzUnicodeName) + { + if (!subBlock.CheckIzUnicode(item.Name)) + extra.Error = true; + } } } @@ -1054,7 +1068,7 @@ bool CInArchive::ReadLocalItem(CItemEx &item) { item.Disk = 0; if (IsMultiVol && Vols.StreamIndex >= 0) - item.Disk = Vols.StreamIndex; + item.Disk = (UInt32)Vols.StreamIndex; const unsigned kPureHeaderSize = kLocalHeaderSize - 4; Byte p[kPureHeaderSize]; SafeRead(p, kPureHeaderSize); @@ -1088,7 +1102,7 @@ bool CInArchive::ReadLocalItem(CItemEx &item) { UInt64 localOffset = 0; UInt32 disk = 0; - if (!ReadExtra(extraSize, item.LocalExtra, item.Size, item.PackSize, localOffset, disk)) + if (!ReadExtra(item, extraSize, item.LocalExtra, item.Size, item.PackSize, localOffset, disk)) { /* 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. @@ -1111,33 +1125,39 @@ bool CInArchive::ReadLocalItem(CItemEx &item) HeadersWarning = true; } - return item.LocalFullHeaderSize <= ((UInt32)1 << 16); + // return item.LocalFullHeaderSize <= ((UInt32)1 << 16); + return true; } -static bool FlagsAreSame(const CItem &i1, const CItem &i2) +static bool FlagsAreSame(const CItem &i1, const CItem &i2_cd) { - if (i1.Method != i2.Method) + if (i1.Method != i2_cd.Method) return false; - if (i1.Flags == i2.Flags) + + UInt32 mask = i1.Flags ^ i2_cd.Flags; + if (mask == 0) return true; - UInt32 mask = 0xFFFF; switch (i1.Method) { case NFileHeader::NCompressionMethod::kDeflate: - mask = 0x7FF9; + mask &= 0x7FF9; break; default: if (i1.Method <= NFileHeader::NCompressionMethod::kImplode) - mask = 0x7FFF; + mask &= 0x7FFF; } // we can ignore utf8 flag, if name is ascii - if ((i1.Flags ^ i2.Flags) & NFileHeader::NFlags::kUtf8) - if (i1.Name.IsAscii() && i2.Name.IsAscii()) + if (mask & NFileHeader::NFlags::kUtf8) + if (i1.Name.IsAscii() && i2_cd.Name.IsAscii()) mask &= ~NFileHeader::NFlags::kUtf8; + + // some bad archive in rare case can use descriptor without descriptor flag in Central Dir + // if (i1.HasDescriptor()) + mask &= ~NFileHeader::NFlags::kDescriptorUsedMask; - return ((i1.Flags & mask) == (i2.Flags & mask)); + return (mask == 0); } @@ -1167,13 +1187,13 @@ static bool AreEqualPaths_IgnoreSlashes(const char *s1, const char *s2) static bool AreItemsEqual(const CItemEx &localItem, const CItemEx &cdItem) { - if (!FlagsAreSame(cdItem, localItem)) + if (!FlagsAreSame(localItem, cdItem)) return false; if (!localItem.HasDescriptor()) { if (cdItem.PackSize != localItem.PackSize || cdItem.Size != localItem.Size - || cdItem.Crc != localItem.Crc && cdItem.Crc != 0) // some program writes 0 to crc field in central directory + || (cdItem.Crc != localItem.Crc && cdItem.Crc != 0)) // some program writes 0 to crc field in central directory return false; } /* pkzip 2.50 creates incorrect archives. It uses @@ -1235,7 +1255,7 @@ HRESULT CInArchive::ReadLocalItemAfterCdItem(CItemEx &item, bool &isAvail, bool return S_FALSE; } Stream = Vols.Streams[item.Disk].Stream; - Vols.StreamIndex = item.Disk; + Vols.StreamIndex = (int)item.Disk; if (!Stream) { isAvail = false; @@ -1251,7 +1271,7 @@ HRESULT CInArchive::ReadLocalItemAfterCdItem(CItemEx &item, bool &isAvail, bool } Stream = StreamRef; - offset += ArcInfo.Base; + offset = (UInt64)((Int64)offset + ArcInfo.Base); if (ArcInfo.Base < 0 && (Int64)offset < 0) { isAvail = false; @@ -1281,6 +1301,11 @@ HRESULT CInArchive::ReadLocalItemAfterCdItem(CItemEx &item, bool &isAvail, bool item.Crc = localItem.Crc; headersError = true; } + if ((item.Flags ^ localItem.Flags) & NFileHeader::NFlags::kDescriptorUsedMask) + { + item.Flags = (UInt16)(item.Flags ^ NFileHeader::NFlags::kDescriptorUsedMask); + headersError = true; + } item.FromLocal = true; } catch(...) { return S_FALSE; } @@ -1351,8 +1376,11 @@ HRESULT CInArchive::FindDescriptor(CItemEx &item, unsigned numFiles) { // we write to packSize all these available bytes. // later it's simpler to work with such value than with 0 - if (item.PackSize == 0) + // if (item.PackSize == 0) item.PackSize = packedSize + avail; + if (item.Method == 0) + item.Size = item.PackSize; + SkipLookahed(avail); return S_OK; } @@ -1384,7 +1412,7 @@ HRESULT CInArchive::FindDescriptor(CItemEx &item, unsigned numFiles) && sig != NSignature::kCentralFileHeader) continue; - const UInt64 packSizeCur = packedSize + (p - pStart); + const UInt64 packSizeCur = packedSize + (size_t)(p - pStart); if (descriptorSize4 == kDataDescriptorSize64 + kNextSignatureSize) // if (item.LocalExtra.IsZip64) { const UInt64 descriptorPackSize = Get64(p + 8); @@ -1406,14 +1434,14 @@ HRESULT CInArchive::FindDescriptor(CItemEx &item, unsigned numFiles) item.DescriptorWasRead = true; item.Crc = Get32(p + 4); - const size_t skip = (p - pStart) + descriptorSize4 - kNextSignatureSize; + const size_t skip = (size_t)(p - pStart) + descriptorSize4 - kNextSignatureSize; SkipLookahed(skip); return S_OK; } - const size_t skip = (p - pStart); + const size_t skip = (size_t)(p - pStart); SkipLookahed(skip); packedSize += skip; @@ -1529,7 +1557,7 @@ HRESULT CInArchive::ReadCdItem(CItemEx &item) ReadFileName(nameSize, item.Name); if (extraSize > 0) - ReadExtra(extraSize, item.CentralExtra, item.Size, item.PackSize, item.LocalHeaderPos, item.Disk); + ReadExtra(item, extraSize, item.CentralExtra, item.Size, item.PackSize, item.LocalHeaderPos, item.Disk); // May be these strings must be deleted /* @@ -1549,11 +1577,7 @@ HRESULT CInArchive::TryEcd64(UInt64 offset, CCdInfo &cdInfo) Byte buf[kEcd64_FullSize]; RINOK(SeekToVol(Vols.StreamIndex, offset)); - unsigned processed = 0; - ReadFromCache(buf, kEcd64_FullSize, processed); - - if (processed != kEcd64_FullSize) - return S_FALSE; + RINOK(ReadFromCache_FALSE(buf, kEcd64_FullSize)); if (Get32(buf) != NSignature::kEcd64) return S_FALSE; @@ -1636,8 +1660,12 @@ HRESULT CInArchive::FindCd(bool checkOffsetMode) { CLocator locator; locator.Parse(buf + locatorIndex + 4); - if ((cdInfo.ThisDisk == locator.NumDisks - 1 || ZIP64_IS_16_MAX(cdInfo.ThisDisk)) - && locator.Ecd64Disk < locator.NumDisks) + UInt32 numDisks = locator.NumDisks; + // we ignore the error, where some zip creators use (NumDisks == 0) + if (numDisks == 0) + numDisks = 1; + if ((cdInfo.ThisDisk == numDisks - 1 || ZIP64_IS_16_MAX(cdInfo.ThisDisk)) + && locator.Ecd64Disk < numDisks) { if (locator.Ecd64Disk != cdInfo.ThisDisk && !ZIP64_IS_16_MAX(cdInfo.ThisDisk)) return E_NOTIMPL; @@ -1657,7 +1685,7 @@ HRESULT CInArchive::FindCd(bool checkOffsetMode) if (mainEcd64Size == kEcd64_MainSize) { cdInfo.ParseEcd64e(ecd64 + 12); - ArcInfo.Base = absEcd64 - locator.Ecd64Offset; + ArcInfo.Base = (Int64)(absEcd64 - locator.Ecd64Offset); // ArcInfo.BaseVolIndex = cdInfo.ThisDisk; return S_OK; } @@ -1685,7 +1713,7 @@ HRESULT CInArchive::FindCd(bool checkOffsetMode) { if (TryEcd64(ArcInfo.MarkerPos + locator.Ecd64Offset, cdInfo) == S_OK) { - ArcInfo.Base = ArcInfo.MarkerPos; + ArcInfo.Base = (Int64)ArcInfo.MarkerPos; // ArcInfo.BaseVolIndex = cdInfo.ThisDisk; return S_OK; } @@ -1719,7 +1747,7 @@ HRESULT CInArchive::FindCd(bool checkOffsetMode) } else */ - ArcInfo.Base = absEcdPos - cdEnd; + ArcInfo.Base = (Int64)(absEcdPos - cdEnd); } return S_OK; } @@ -1730,11 +1758,12 @@ HRESULT CInArchive::FindCd(bool checkOffsetMode) HRESULT CInArchive::TryReadCd(CObjectVector<CItemEx> &items, const CCdInfo &cdInfo, UInt64 cdOffset, UInt64 cdSize) { items.Clear(); + IsCdUnsorted = false; // _startLocalFromCd_Disk = (UInt32)(Int32)-1; // _startLocalFromCd_Offset = (UInt64)(Int64)-1; - RINOK(SeekToVol(IsMultiVol ? cdInfo.CdDisk : -1, cdOffset)); + RINOK(SeekToVol(IsMultiVol ? (int)cdInfo.CdDisk : -1, cdOffset)); _inBufMode = true; _cnt = 0; @@ -1767,6 +1796,15 @@ HRESULT CInArchive::TryReadCd(CObjectVector<CItemEx> &items, const CCdInfo &cdIn } */ + if (items.Size() > 0 && !IsCdUnsorted) + { + const CItemEx &prev = items.Back(); + if (cdItem.Disk < prev.Disk + || (cdItem.Disk == prev.Disk && + cdItem.LocalHeaderPos < prev.LocalHeaderPos)) + IsCdUnsorted = true; + } + items.Add(cdItem); } if (Callback && (items.Size() & 0xFFF) == 0) @@ -1793,6 +1831,22 @@ HRESULT CInArchive::TryReadCd(CObjectVector<CItemEx> &items, const CCdInfo &cdIn } +/* +static int CompareCdItems(void *const *elem1, void *const *elem2, void *) +{ + const CItemEx *i1 = *(const CItemEx **)elem1; + const CItemEx *i2 = *(const CItemEx **)elem2; + + if (i1->Disk < i2->Disk) return -1; + if (i1->Disk > i2->Disk) return 1; + if (i1->LocalHeaderPos < i2->LocalHeaderPos) return -1; + if (i1->LocalHeaderPos > i2->LocalHeaderPos) return 1; + if (i1 < i2) return -1; + if (i1 > i2) return 1; + return 0; +} +*/ + HRESULT CInArchive::ReadCd(CObjectVector<CItemEx> &items, UInt32 &cdDisk, UInt64 &cdOffset, UInt64 &cdSize) { bool checkOffsetMode = true; @@ -1801,7 +1855,7 @@ HRESULT CInArchive::ReadCd(CObjectVector<CItemEx> &items, UInt32 &cdDisk, UInt64 { if (Vols.EndVolIndex == -1) return S_FALSE; - Stream = Vols.Streams[Vols.EndVolIndex].Stream; + Stream = Vols.Streams[(unsigned)Vols.EndVolIndex].Stream; if (!Vols.StartIsZip) checkOffsetMode = false; } @@ -1827,7 +1881,7 @@ HRESULT CInArchive::ReadCd(CObjectVector<CItemEx> &items, UInt32 &cdDisk, UInt64 return S_FALSE; } - const UInt64 base = (IsMultiVol ? 0 : ArcInfo.Base); + const UInt64 base = (IsMultiVol ? 0 : (UInt64)ArcInfo.Base); res = TryReadCd(items, cdInfo, base + cdOffset, cdSize); if (res == S_FALSE && !IsMultiVol && base != ArcInfo.MarkerPos) @@ -1835,9 +1889,11 @@ HRESULT CInArchive::ReadCd(CObjectVector<CItemEx> &items, UInt32 &cdDisk, UInt64 // do we need that additional attempt to read cd? res = TryReadCd(items, cdInfo, ArcInfo.MarkerPos + cdOffset, cdSize); if (res == S_OK) - ArcInfo.Base = ArcInfo.MarkerPos; + ArcInfo.Base = (Int64)ArcInfo.MarkerPos; } + // Some rare case files are unsorted + // items.Sort(CompareCdItems, NULL); return res; } @@ -1849,14 +1905,14 @@ static int FindItem(const CObjectVector<CItemEx> &items, const CItemEx &item) { if (left >= right) return -1; - unsigned index = (left + right) / 2; + const unsigned index = (left + right) / 2; const CItemEx &item2 = items[index]; if (item.Disk < item2.Disk) right = index; else if (item.Disk > item2.Disk) left = index + 1; else if (item.LocalHeaderPos == item2.LocalHeaderPos) - return index; + return (int)index; else if (item.LocalHeaderPos < item2.LocalHeaderPos) right = index; else @@ -1921,7 +1977,7 @@ HRESULT CInArchive::ReadLocals(CObjectVector<CItemEx> &items) item.LocalHeaderPos = GetVirtStreamPos() - 4; if (!IsMultiVol) - item.LocalHeaderPos -= ArcInfo.Base; + item.LocalHeaderPos = (UInt64)((Int64)item.LocalHeaderPos - ArcInfo.Base); try { @@ -1950,7 +2006,7 @@ HRESULT CInArchive::ReadLocals(CObjectVector<CItemEx> &items) } catch (CUnexpectEnd &) { - if (items.IsEmpty() || items.Size() == 1 && IsStrangeItem(items[0])) + if (items.IsEmpty() || (items.Size() == 1 && IsStrangeItem(items[0]))) return S_FALSE; throw; } @@ -1986,11 +2042,11 @@ HRESULT CVols::ParseArcName(IArchiveOpenVolumeCallback *volCallback) name = prop.bstrVal; } - int dotPos = name.ReverseFind_Dot(); + const int dotPos = name.ReverseFind_Dot(); if (dotPos < 0) return S_OK; - const UString ext = name.Ptr(dotPos + 1); - name.DeleteFrom(dotPos + 1); + const UString ext = name.Ptr((unsigned)(dotPos + 1)); + name.DeleteFrom((unsigned)(dotPos + 1)); StartVolIndex = (Int32)(-1); @@ -2047,7 +2103,7 @@ HRESULT CVols::ParseArcName(IArchiveOpenVolumeCallback *volCallback) UInt32 volNum = ConvertStringToUInt32(ext.Ptr(1), &end); if (*end != 0 || volNum < 1 || volNum > ((UInt32)1 << 30)) return S_OK; - StartVolIndex = volNum - 1; + StartVolIndex = (Int32)(volNum - 1); BaseName = name; StartIsZ = true; } @@ -2147,7 +2203,7 @@ HRESULT CInArchive::ReadVols2(IArchiveOpenVolumeCallback *volCallback, UInt64 pos; RINOK(stream->Seek(0, STREAM_SEEK_CUR, &pos)); RINOK(stream->Seek(0, STREAM_SEEK_END, &size)); - RINOK(stream->Seek(pos, STREAM_SEEK_SET, NULL)); + RINOK(stream->Seek((Int64)pos, STREAM_SEEK_SET, NULL)); while (i >= Vols.Streams.Size()) Vols.Streams.AddNew(); @@ -2161,7 +2217,7 @@ HRESULT CInArchive::ReadVols2(IArchiveOpenVolumeCallback *volCallback, if ((int)i == zipDisk) { - Vols.EndVolIndex = Vols.Streams.Size() - 1; + Vols.EndVolIndex = (int)(Vols.Streams.Size() - 1); break; } } @@ -2211,7 +2267,7 @@ HRESULT CInArchive::ReadVols() CCdInfo &ecd = Vols.ecd; if (res == S_OK) { - zipDisk = ecd.ThisDisk; + zipDisk = (int)ecd.ThisDisk; Vols.ecd_wasRead = true; // if is not multivol or bad multivol, we return to main single stream code @@ -2220,9 +2276,9 @@ HRESULT CInArchive::ReadVols() || ecd.ThisDisk < ecd.CdDisk) return S_OK; - cdDisk = ecd.CdDisk; + cdDisk = (int)ecd.CdDisk; if (Vols.StartVolIndex < 0) - Vols.StartVolIndex = ecd.ThisDisk; + Vols.StartVolIndex = (Int32)ecd.ThisDisk; else if ((UInt32)Vols.StartVolIndex >= ecd.ThisDisk) return S_OK; @@ -2232,7 +2288,7 @@ HRESULT CInArchive::ReadVols() if (cdDisk != zipDisk) { // get volumes required for cd. - RINOK(ReadVols2(volCallback, cdDisk, zipDisk, zipDisk, 0, numMissingVols)); + RINOK(ReadVols2(volCallback, (unsigned)cdDisk, zipDisk, zipDisk, 0, numMissingVols)); if (numMissingVols != 0) { // cdOK = false; @@ -2269,10 +2325,10 @@ HRESULT CInArchive::ReadVols() if (Vols.StartVolIndex > (1 << 20)) return S_OK; if ((unsigned)Vols.StartVolIndex >= Vols.Streams.Size() - || !Vols.Streams[Vols.StartVolIndex].Stream) + || !Vols.Streams[(unsigned)Vols.StartVolIndex].Stream) { // we get volumes starting from StartVolIndex, if they we not requested before know the volume index (if FindCd() was ok) - RINOK(ReadVols2(volCallback, Vols.StartVolIndex, zipDisk, zipDisk, 0, numMissingVols)); + RINOK(ReadVols2(volCallback, (unsigned)Vols.StartVolIndex, zipDisk, zipDisk, 0, numMissingVols)); } } @@ -2285,7 +2341,7 @@ HRESULT CInArchive::ReadVols() if (zipDisk >= 0) { // we create item in Streams for ZipStream, if we know the volume index (if FindCd() was ok) - RINOK(ReadVols2(volCallback, zipDisk, zipDisk + 1, zipDisk, 0, numMissingVols)); + RINOK(ReadVols2(volCallback, (unsigned)zipDisk, zipDisk + 1, zipDisk, 0, numMissingVols)); } } @@ -2331,7 +2387,7 @@ HRESULT CVols::Read(void *data, UInt32 size, UInt32 *processedSize) return S_OK; if ((unsigned)StreamIndex >= Streams.Size()) return S_OK; - const CVols::CSubStreamInfo &s = Streams[StreamIndex]; + const CVols::CSubStreamInfo &s = Streams[(unsigned)StreamIndex]; if (!s.Stream) return S_FALSE; if (NeedSeek) @@ -2473,7 +2529,7 @@ HRESULT CInArchive::ReadHeaders(CObjectVector<CItemEx> &items) if (!ecd.IsEmptyArc()) return S_FALSE; - ArcInfo.Base = ArcInfo.MarkerPos; + ArcInfo.Base = (Int64)ArcInfo.MarkerPos; IsArc = true; // check it: we need more tests? RINOK(SeekToVol(ArcInfo.MarkerVolIndex, ArcInfo.MarkerPos2)); @@ -2514,16 +2570,44 @@ HRESULT CInArchive::ReadHeaders(CObjectVector<CItemEx> &items) res = S_FALSE; else { - firstItem.LocalHeaderPos = ArcInfo.MarkerPos2 - ArcInfo.Base; - int index = FindItem(items, firstItem); + firstItem.LocalHeaderPos = (UInt64)((Int64)ArcInfo.MarkerPos2 - ArcInfo.Base); + int index = -1; + + UInt32 min_Disk = (UInt32)(Int32)-1; + UInt64 min_LocalHeaderPos = (UInt64)(Int64)-1; + + if (!IsCdUnsorted) + index = FindItem(items, firstItem); + else + { + FOR_VECTOR (i, items) + { + const CItemEx &cdItem = items[i]; + if (cdItem.Disk == firstItem.Disk + && (cdItem.LocalHeaderPos == firstItem.LocalHeaderPos)) + index = (int)i; + + if (i == 0 + || cdItem.Disk < min_Disk + || (cdItem.Disk == min_Disk && cdItem.LocalHeaderPos < min_LocalHeaderPos)) + { + min_Disk = cdItem.Disk; + min_LocalHeaderPos = cdItem.LocalHeaderPos; + } + } + } + if (index == -1) res = S_FALSE; - else if (!AreItemsEqual(firstItem, items[index])) + else if (!AreItemsEqual(firstItem, items[(unsigned)index])) res = S_FALSE; else { ArcInfo.CdWasRead = true; - ArcInfo.FirstItemRelatOffset = items[0].LocalHeaderPos; + if (IsCdUnsorted) + ArcInfo.FirstItemRelatOffset = min_LocalHeaderPos; + else + ArcInfo.FirstItemRelatOffset = items[0].LocalHeaderPos; // ArcInfo.FirstItemRelatOffset = _startLocalFromCd_Offset; } @@ -2588,7 +2672,7 @@ HRESULT CInArchive::ReadHeaders(CObjectVector<CItemEx> &items) The (Base) can be corrected later after ECD reading. But sfx volume with stub and (No)Span-marker in (!IsMultiVol) mode will have incorrect (Base) here. */ - ArcInfo.Base = ArcInfo.MarkerPos2; + ArcInfo.Base = (Int64)ArcInfo.MarkerPos2; } RINOK(SeekToVol(ArcInfo.MarkerVolIndex, ArcInfo.MarkerPos2)); @@ -2607,15 +2691,42 @@ HRESULT CInArchive::ReadHeaders(CObjectVector<CItemEx> &items) // GetVirtStreamPos() - 4 if (items.IsEmpty()) return S_FALSE; - NoCentralDir = true; - HeadersError = true; - return S_OK; + + bool isError = true; + + const UInt32 apkSize = _signature; + const unsigned kApkFooterSize = 16 + 8; + if (apkSize >= kApkFooterSize && apkSize <= (1 << 20)) + { + if (ReadUInt32() == 0) + { + CByteBuffer apk; + apk.Alloc(apkSize); + SafeRead(apk, apkSize); + ReadSignature(); + const Byte *footer = apk + apkSize - kApkFooterSize; + if (_signature == NSignature::kCentralFileHeader) + if (GetUi64(footer) == apkSize) + if (memcmp(footer + 8, "APK Sig Block 42", 16) == 0) + { + isError = false; + IsApk = true; + } + } + } + + if (isError) + { + NoCentralDir = true; + HeadersError = true; + return S_OK; + } } _inBufMode = true; cdAbsOffset = GetVirtStreamPos() - 4; - cdDisk = Vols.StreamIndex; + cdDisk = (UInt32)Vols.StreamIndex; #ifdef ZIP_SELF_CHECK if (!IsMultiVol && _cnt != GetVirtStreamPos() - ArcInfo.MarkerPos2) @@ -2656,7 +2767,7 @@ HRESULT CInArchive::ReadHeaders(CObjectVector<CItemEx> &items) needSetBase = true; numCdItems = cdItems.Size(); - cdRelatOffset = cdAbsOffset - ArcInfo.Base; + cdRelatOffset = (UInt64)((Int64)cdAbsOffset - ArcInfo.Base); if (!cdItems.IsEmpty()) { @@ -2712,6 +2823,8 @@ HRESULT CInArchive::ReadHeaders(CObjectVector<CItemEx> &items) Byte buf[kBufSize]; SafeRead(buf, kBufSize); locator.Parse(buf); + // we ignore the error, where some zip creators use (NumDisks == 0) + // if (locator.NumDisks == 0) HeadersWarning = true; } ReadSignature(); @@ -2764,12 +2877,12 @@ HRESULT CInArchive::ReadHeaders(CObjectVector<CItemEx> &items) if (IsMultiVol) { - if (cdDisk != (int)cdInfo.CdDisk) + if (cdDisk != cdInfo.CdDisk) HeadersError = true; } else if (needSetBase && cdOK) { - const UInt64 oldBase = ArcInfo.Base; + const UInt64 oldBase = (UInt64)ArcInfo.Base; // localsWereRead == true // ArcInfo.Base == ArcInfo.MarkerPos2 // cdRelatOffset == (cdAbsOffset - ArcInfo.Base) @@ -2778,13 +2891,13 @@ HRESULT CInArchive::ReadHeaders(CObjectVector<CItemEx> &items) { if (ecd64Disk == Vols.StartVolIndex) { - const Int64 newBase = (Int64)ecd64AbsOffset - locator.Ecd64Offset; + const Int64 newBase = (Int64)ecd64AbsOffset - (Int64)locator.Ecd64Offset; if (newBase <= (Int64)ecd64AbsOffset) { if (!localsWereRead || newBase <= (Int64)ArcInfo.MarkerPos2) { ArcInfo.Base = newBase; - cdRelatOffset = cdAbsOffset - newBase; + cdRelatOffset = (UInt64)((Int64)cdAbsOffset - newBase); } else cdOK = false; @@ -2795,7 +2908,7 @@ HRESULT CInArchive::ReadHeaders(CObjectVector<CItemEx> &items) { if ((int)cdDisk == Vols.StartVolIndex) { - const Int64 newBase = (Int64)cdAbsOffset - cdInfo.Offset; + const Int64 newBase = (Int64)cdAbsOffset - (Int64)cdInfo.Offset; if (newBase <= (Int64)cdAbsOffset) { if (!localsWereRead || newBase <= (Int64)ArcInfo.MarkerPos2) @@ -2828,7 +2941,7 @@ HRESULT CInArchive::ReadHeaders(CObjectVector<CItemEx> &items) if (localsWereRead) { - const UInt64 delta = oldBase - ArcInfo.Base; + const UInt64 delta = (UInt64)((Int64)oldBase - ArcInfo.Base); if (delta != 0) { FOR_VECTOR (i, items) @@ -2864,7 +2977,7 @@ HRESULT CInArchive::ReadHeaders(CObjectVector<CItemEx> &items) if (isZip64) { - if (cdInfo.ThisDisk == 0 && ecd64AbsOffset != ArcInfo.Base + locator.Ecd64Offset + if ((cdInfo.ThisDisk == 0 && ecd64AbsOffset != (UInt64)(ArcInfo.Base + (Int64)locator.Ecd64Offset)) // || cdInfo.NumEntries_in_ThisDisk != numCdItems || cdInfo.NumEntries != numCdItems || cdInfo.Size != cdSize @@ -2902,10 +3015,10 @@ HRESULT CInArchive::ReadHeaders(CObjectVector<CItemEx> &items) { if ((unsigned)nextLocalIndex < items.Size()) { - CItemEx &item = items[nextLocalIndex]; + CItemEx &item = items[(unsigned)nextLocalIndex]; if (item.Disk == cdItem.Disk && (item.LocalHeaderPos == cdItem.LocalHeaderPos - || Overflow32bit && (UInt32)item.LocalHeaderPos == cdItem.LocalHeaderPos)) + || (Overflow32bit && (UInt32)item.LocalHeaderPos == cdItem.LocalHeaderPos))) index = nextLocalIndex++; else nextLocalIndex = -1; @@ -2924,7 +3037,7 @@ HRESULT CInArchive::ReadHeaders(CObjectVector<CItemEx> &items) continue; } - CItemEx &item = items[index]; + CItemEx &item = items[(unsigned)index]; if (item.Name != cdItem.Name // || item.Name.Len() != cdItem.Name.Len() || item.PackSize != cdItem.PackSize @@ -2965,7 +3078,7 @@ HRESULT CInArchive::ReadHeaders(CObjectVector<CItemEx> &items) if (isZip64) { if (cdInfo.NumEntries != items.Size() - || ecd.NumEntries != items.Size() && ecd.NumEntries != 0xFFFF) + || (ecd.NumEntries != items.Size() && ecd.NumEntries != 0xFFFF)) HeadersError = true; } else @@ -3069,7 +3182,9 @@ HRESULT CInArchive::Open(IInStream *stream, const UInt64 *searchLimit, else { // printf("\nOpen offset = %u\n", (unsigned)startPos); - if (IsMultiVol && (unsigned)Vols.StartParsingVol < Vols.Streams.Size() && Vols.Streams[Vols.StartParsingVol].Stream) + if (IsMultiVol + && (unsigned)Vols.StartParsingVol < Vols.Streams.Size() + && Vols.Streams[(unsigned)Vols.StartParsingVol].Stream) { RINOK(SeekToVol(Vols.StartParsingVol, Vols.StreamIndex == Vols.StartVolIndex ? startPos : 0)); } @@ -3117,7 +3232,7 @@ HRESULT CInArchive::Open(IInStream *stream, const UInt64 *searchLimit, { if ((unsigned)Vols.StartVolIndex < Vols.Streams.Size()) { - Stream = Vols.Streams[Vols.StartVolIndex].Stream; + Stream = Vols.Streams[(unsigned)Vols.StartVolIndex].Stream; if (Stream) { RINOK(Seek_SavePos(curPos)); @@ -3173,7 +3288,7 @@ HRESULT CInArchive::Open(IInStream *stream, const UInt64 *searchLimit, { ArcInfo.FinishPos = ArcInfo.FileEndPos; if ((unsigned)Vols.StreamIndex < Vols.Streams.Size()) - if (GetVirtStreamPos() < Vols.Streams[Vols.StreamIndex].Size) + if (GetVirtStreamPos() < Vols.Streams[(unsigned)Vols.StreamIndex].Size) ArcInfo.ThereIsTail = true; } else @@ -3204,8 +3319,8 @@ HRESULT CInArchive::GetItemStream(const CItemEx &item, bool seekPackData, CMyCom { if (UseDisk_in_SingleVol && item.Disk != EcdVolIndex) return S_OK; - pos += ArcInfo.Base; - RINOK(StreamRef->Seek(pos, STREAM_SEEK_SET, NULL)); + pos = (UInt64)((Int64)pos + ArcInfo.Base); + RINOK(StreamRef->Seek((Int64)pos, STREAM_SEEK_SET, NULL)); stream = StreamRef; return S_OK; } @@ -3216,10 +3331,10 @@ HRESULT CInArchive::GetItemStream(const CItemEx &item, bool seekPackData, CMyCom IInStream *str2 = Vols.Streams[item.Disk].Stream; if (!str2) return S_OK; - RINOK(str2->Seek(pos, STREAM_SEEK_SET, NULL)); + RINOK(str2->Seek((Int64)pos, STREAM_SEEK_SET, NULL)); Vols.NeedSeek = false; - Vols.StreamIndex = item.Disk; + Vols.StreamIndex = (int)item.Disk; CVolStream *volsStreamSpec = new CVolStream; volsStreamSpec->Vols = &Vols; diff --git a/CPP/7zip/Archive/Zip/ZipIn.h b/CPP/7zip/Archive/Zip/ZipIn.h index f46f1f07..31e524b6 100644 --- a/CPP/7zip/Archive/Zip/ZipIn.h +++ b/CPP/7zip/Archive/Zip/ZipIn.h @@ -32,6 +32,11 @@ public: { return LocalFullHeaderSize + GetPackSizeWithDescriptor(); } UInt64 GetDataPosition() const { return LocalHeaderPos + LocalFullHeaderSize; } + + bool IsBadDescriptor() const + { + return !FromCentral && FromLocal && HasDescriptor() && !DescriptorWasRead; + } }; @@ -282,6 +287,7 @@ class CInArchive HRESULT SeekToVol(int volIndex, UInt64 offset); HRESULT ReadFromCache(Byte *data, unsigned size, unsigned &processed); + HRESULT ReadFromCache_FALSE(Byte *data, unsigned size); HRESULT ReadVols2(IArchiveOpenVolumeCallback *volCallback, unsigned start, int lastDisk, int zipDisk, unsigned numMissingVolsMax, unsigned &numMissingVols); @@ -305,7 +311,7 @@ class CInArchive bool ReadFileName(unsigned nameSize, AString &dest); - bool ReadExtra(unsigned extraSize, CExtraBlock &extra, + bool ReadExtra(const CLocalItem &item, unsigned extraSize, CExtraBlock &extra, UInt64 &unpackSize, UInt64 &packSize, UInt64 &localOffset, UInt32 &disk); bool ReadLocalItem(CItemEx &item); HRESULT FindDescriptor(CItemEx &item, unsigned numFiles); @@ -325,6 +331,9 @@ public: bool IsArc; bool IsZip64; + + bool IsApk; + bool IsCdUnsorted; bool HeadersError; bool HeadersWarning; @@ -345,14 +354,19 @@ public: CVols Vols; - CInArchive(): Stream(NULL), StartStream(NULL), Callback(NULL), IsArcOpen(false) {} + CInArchive(): + IsArcOpen(false), + Stream(NULL), + StartStream(NULL), + Callback(NULL) + {} UInt64 GetPhySize() const { if (IsMultiVol) return ArcInfo.FinishPos; else - return ArcInfo.FinishPos - ArcInfo.Base; + return (UInt64)((Int64)ArcInfo.FinishPos - ArcInfo.Base); } UInt64 GetOffset() const @@ -360,7 +374,7 @@ public: if (IsMultiVol) return 0; else - return ArcInfo.Base; + return (UInt64)ArcInfo.Base; } @@ -393,7 +407,7 @@ public: return ArcInfo.FirstItemRelatOffset; if (IsMultiVol) return 0; - return ArcInfo.MarkerPos2 - ArcInfo.Base; + return (UInt64)((Int64)ArcInfo.MarkerPos2 - ArcInfo.Base); } @@ -412,7 +426,9 @@ public: || ArcInfo.Base < 0 || (Int64)ArcInfo.MarkerPos2 < ArcInfo.Base || ArcInfo.ThereIsTail - || GetEmbeddedStubSize() != 0) + || GetEmbeddedStubSize() != 0 + || IsApk + || IsCdUnsorted) return false; // 7-zip probably can update archives with embedded stubs. diff --git a/CPP/7zip/Archive/Zip/ZipItem.cpp b/CPP/7zip/Archive/Zip/ZipItem.cpp index 5cff1735..38921dce 100644 --- a/CPP/7zip/Archive/Zip/ZipItem.cpp +++ b/CPP/7zip/Archive/Zip/ZipItem.cpp @@ -33,9 +33,12 @@ static const CUInt32PCharPair g_ExtraTypes[] = { NExtraID::kStrongEncrypt, "StrongCrypto" }, { NExtraID::kUnixTime, "UT" }, { NExtraID::kUnixExtra, "UX" }, + { NExtraID::kUnix2Extra, "Ux" }, + { NExtraID::kUnix3Extra, "ux" }, { NExtraID::kIzUnicodeComment, "uc" }, { NExtraID::kIzUnicodeName, "up" }, - { NExtraID::kWzAES, "WzAES" } + { NExtraID::kWzAES, "WzAES" }, + { NExtraID::kApkAlign, "ApkAlign" } }; void CExtraSubBlock::PrintInfo(AString &s) const @@ -46,6 +49,22 @@ void CExtraSubBlock::PrintInfo(AString &s) const if (pair.Value == ID) { s += pair.Name; + /* + if (ID == NExtraID::kApkAlign && Data.Size() >= 2) + { + char sz[32]; + sz[0] = ':'; + ConvertUInt32ToHex(GetUi16(Data), sz + 1); + s += sz; + for (unsigned j = 2; j < Data.Size(); j++) + { + char sz[32]; + sz[0] = '-'; + ConvertUInt32ToHex(Data[j], sz + 1); + s += sz; + } + } + */ return; } } @@ -209,6 +228,7 @@ bool CLocalItem::IsDir() const bool CItem::IsDir() const { + // FIXME: we can check InfoZip UTF-8 name at first. if (NItemName::HasTailSlash(Name, GetCodePage())) return true; @@ -315,10 +335,30 @@ bool CItem::GetPosixAttrib(UInt32 &attrib) const return false; } + +bool CExtraSubBlock::CheckIzUnicode(const AString &s) const +{ + size_t size = Data.Size(); + if (size < 1 + 4) + return false; + const Byte *p = (const Byte *)Data; + if (p[0] > 1) + return false; + if (CrcCalc(s, s.Len()) != GetUi32(p + 1)) + return false; + size -= 5; + p += 5; + for (size_t i = 0; i < size; i++) + if (p[i] == 0) + return false; + return Check_UTF8_Buf((const char *)(const void *)p, size, false); +} + + void CItem::GetUnicodeString(UString &res, const AString &s, bool isComment, bool useSpecifiedCodePage, UINT codePage) const { bool isUtf8 = IsUtf8(); - bool ignore_Utf8_Errors = true; + // bool ignore_Utf8_Errors = true; if (!isUtf8) { @@ -333,10 +373,14 @@ void CItem::GetUnicodeString(UString &res, const AString &s, bool isComment, boo const CExtraSubBlock &sb = subBlocks[i]; if (sb.ID == id) { - AString utf; - if (sb.ExtractIzUnicode(CrcCalc(s, s.Len()), utf)) - if (ConvertUTF8ToUnicode(utf, res)) + if (sb.CheckIzUnicode(s)) + { + // const unsigned kIzUnicodeHeaderSize = 5; + if (Convert_UTF8_Buf_To_Unicode( + (const char *)(const void *)(const Byte *)sb.Data + 5, + sb.Data.Size() - 5, res)) return; + } break; } } @@ -351,15 +395,21 @@ void CItem::GetUnicodeString(UString &res, const AString &s, bool isComment, boo We try to get name as UTF-8. Do we need to do it in POSIX version also? */ isUtf8 = true; - ignore_Utf8_Errors = false; + + /* 21.02: we want to ignore UTF-8 errors to support file paths that are mixed + of UTF-8 and non-UTF-8 characters. */ + // ignore_Utf8_Errors = false; + // ignore_Utf8_Errors = true; } #endif } if (isUtf8) - if (ConvertUTF8ToUnicode(s, res) || ignore_Utf8_Errors) - return; + { + ConvertUTF8ToUnicode(s, res); + return; + } MultiByteToUnicodeString2(res, s, useSpecifiedCodePage ? codePage : GetCodePage()); } diff --git a/CPP/7zip/Archive/Zip/ZipItem.h b/CPP/7zip/Archive/Zip/ZipItem.h index e5769711..6ee87658 100644 --- a/CPP/7zip/Archive/Zip/ZipItem.h +++ b/CPP/7zip/Archive/Zip/ZipItem.h @@ -33,23 +33,8 @@ struct CExtraSubBlock bool ExtractNtfsTime(unsigned index, FILETIME &ft) const; bool ExtractUnixTime(bool isCentral, unsigned index, UInt32 &res) const; bool ExtractUnixExtraTime(unsigned index, UInt32 &res) const; - - bool ExtractIzUnicode(UInt32 crc, AString &name) const - { - unsigned size = (unsigned)Data.Size(); - if (size < 1 + 4) - return false; - const Byte *p = (const Byte *)Data; - if (p[0] > 1) - return false; - if (crc != GetUi32(p + 1)) - return false; - size -= 5; - name.SetFrom_CalcLen((const char *)p + 5, size); - if (size != name.Len()) - return false; - return CheckUTF8(name, false); - } + + bool CheckIzUnicode(const AString &s) const; void PrintInfo(AString &s) const; }; @@ -202,8 +187,14 @@ struct CExtraBlock for (unsigned i = SubBlocks.Size(); i != 0;) { i--; - if (SubBlocks[i].ID != NFileHeader::NExtraID::kWzAES) - SubBlocks.Delete(i); + switch (SubBlocks[i].ID) + { + case NFileHeader::NExtraID::kStrongEncrypt: + case NFileHeader::NExtraID::kWzAES: + break; + default: + SubBlocks.Delete(i); + } } } }; @@ -266,9 +257,9 @@ private: void SetFlag(unsigned bitMask, bool enable) { if (enable) - Flags |= bitMask; + Flags = (UInt16)(Flags | bitMask); else - Flags &= ~bitMask; + Flags = (UInt16)(Flags & ~bitMask); } public: @@ -279,7 +270,12 @@ public: // void SetFlag_AltStream(bool isAltStream) { SetFlag(NFileHeader::NFlags::kAltStream, isAltStream); } void SetDescriptorMode(bool useDescriptor) { SetFlag(NFileHeader::NFlags::kDescriptorUsedMask, useDescriptor); } - UINT GetCodePage() const { return CP_OEMCP; } + UINT GetCodePage() const + { + if (IsUtf8()) + return CP_UTF8; + return CP_OEMCP; + } }; @@ -330,10 +326,19 @@ public: } return (Crc != 0 || !IsDir()); } + + bool Is_MadeBy_Unix() const + { + if (!FromCentral) + return false; + return (MadeByVersion.HostOS == NFileHeader::NHostOS::kUnix); + } UINT GetCodePage() const { // 18.06: now we use HostOS only from Central::MadeByVersion + if (IsUtf8()) + return CP_UTF8; if (!FromCentral) return CP_OEMCP; Byte hostOS = MadeByVersion.HostOS; diff --git a/CPP/7zip/Archive/Zip/ZipOut.cpp b/CPP/7zip/Archive/Zip/ZipOut.cpp index 945bd020..efed0a41 100644 --- a/CPP/7zip/Archive/Zip/ZipOut.cpp +++ b/CPP/7zip/Archive/Zip/ZipOut.cpp @@ -2,6 +2,8 @@ #include "StdAfx.h" +#include "../../../../C/7zCrc.h" + #include "../../Common/OffsetStream.h" #include "ZipOut.h" @@ -23,7 +25,7 @@ HRESULT COutArchive::Create(IOutStream *outStream) void COutArchive::SeekToCurPos() { - HRESULT res = m_Stream->Seek(m_Base + m_CurPos, STREAM_SEEK_SET, NULL); + HRESULT res = m_Stream->Seek((Int64)(m_Base + m_CurPos), STREAM_SEEK_SET, NULL); if (res != S_OK) throw CSystemException(res); } @@ -97,6 +99,17 @@ void COutArchive::WriteCommonItemInfo(const CLocalItem &item, bool isZip64) #define WRITE_32_VAL_SPEC(__v, __isZip64) Write32((__isZip64) ? 0xFFFFFFFF : (UInt32)(__v)); +void COutArchive::WriteUtfName(const CItemOut &item) +{ + if (item.Name_Utf.Size() == 0) + return; + Write16(NFileHeader::NExtraID::kIzUnicodeName); + Write16((UInt16)(5 + item.Name_Utf.Size())); + Write8(1); // (1 = version) of that extra field + Write32(CrcCalc(item.Name.Ptr(), item.Name.Len())); + WriteBytes(item.Name_Utf, (UInt16)item.Name_Utf.Size()); +} + void COutArchive::WriteLocalHeader(CItemOut &item, bool needCheck) { m_LocalHeaderPos = m_CurPos; @@ -109,7 +122,10 @@ void COutArchive::WriteLocalHeader(CItemOut &item, bool needCheck) if (needCheck && m_IsZip64) isZip64 = true; - const UInt32 localExtraSize = (UInt32)((isZip64 ? (4 + 8 + 8): 0) + item.LocalExtra.GetSize()); + const UInt32 localExtraSize = (UInt32)( + (isZip64 ? (4 + 8 + 8): 0) + + item.Get_UtfName_ExtraSize() + + item.LocalExtra.GetSize()); if ((UInt16)localExtraSize != localExtraSize) throw CSystemException(E_FAIL); if (needCheck && m_ExtraSize != localExtraSize) @@ -152,6 +168,8 @@ void COutArchive::WriteLocalHeader(CItemOut &item, bool needCheck) Write64(packSize); } + WriteUtfName(item); + WriteExtra(item.LocalExtra); // Why don't we write NTFS timestamps to local header? @@ -230,14 +248,19 @@ void COutArchive::WriteCentralHeader(const CItemOut &item) Write16((UInt16)item.Name.Len()); - UInt16 zip64ExtraSize = (UInt16)((isUnPack64 ? 8: 0) + (isPack64 ? 8: 0) + (isPosition64 ? 8: 0)); + const UInt16 zip64ExtraSize = (UInt16)((isUnPack64 ? 8: 0) + (isPack64 ? 8: 0) + (isPosition64 ? 8: 0)); const UInt16 kNtfsExtraSize = 4 + 2 + 2 + (3 * 8); - const UInt16 centralExtraSize = (UInt16)( - (isZip64 ? 4 + zip64ExtraSize : 0) + - (item.NtfsTimeIsDefined ? 4 + kNtfsExtraSize : 0) + - item.CentralExtra.GetSize()); + const size_t centralExtraSize = + (isZip64 ? 4 + zip64ExtraSize : 0) + + (item.NtfsTimeIsDefined ? 4 + kNtfsExtraSize : 0) + + item.Get_UtfName_ExtraSize() + + item.CentralExtra.GetSize(); + + const UInt16 centralExtraSize16 = (UInt16)centralExtraSize; + if (centralExtraSize16 != centralExtraSize) + throw CSystemException(E_FAIL); - Write16(centralExtraSize); // test it; + Write16(centralExtraSize16); const UInt16 commentSize = (UInt16)item.Comment.Size(); @@ -271,6 +294,8 @@ void COutArchive::WriteCentralHeader(const CItemOut &item) WriteNtfsTime(item.Ntfs_ATime); WriteNtfsTime(item.Ntfs_CTime); } + + WriteUtfName(item); WriteExtra(item.CentralExtra); if (commentSize != 0) diff --git a/CPP/7zip/Archive/Zip/ZipOut.h b/CPP/7zip/Archive/Zip/ZipOut.h index 0a0ac0c8..3546411c 100644 --- a/CPP/7zip/Archive/Zip/ZipOut.h +++ b/CPP/7zip/Archive/Zip/ZipOut.h @@ -21,6 +21,16 @@ public: bool NtfsTimeIsDefined; // It's possible that NtfsTime is not defined, but there is NtfsTime in Extra. + + CByteBuffer Name_Utf; // for Info-Zip (kIzUnicodeName) Extra + + size_t Get_UtfName_ExtraSize() const + { + const size_t size = Name_Utf.Size(); + if (size == 0) + return 0; + return 4 + 5 + size; + } CItemOut(): NtfsTimeIsDefined(false) {} }; @@ -52,6 +62,7 @@ class COutArchive Write32(ft.dwHighDateTime); } + void WriteUtfName(const CItemOut &item); void WriteExtra(const CExtraBlock &extra); void WriteCommonItemInfo(const CLocalItem &item, bool isZip64); void WriteCentralHeader(const CItemOut &item); diff --git a/CPP/7zip/Archive/Zip/ZipUpdate.cpp b/CPP/7zip/Archive/Zip/ZipUpdate.cpp index e65c2b8b..4468c7c5 100644 --- a/CPP/7zip/Archive/Zip/ZipUpdate.cpp +++ b/CPP/7zip/Archive/Zip/ZipUpdate.cpp @@ -62,6 +62,21 @@ static void AddAesExtra(CItem &item, Byte aesKeyMode, UInt16 method) } +static void Copy_From_UpdateItem_To_ItemOut(const CUpdateItem &ui, CItemOut &item) +{ + item.Name = ui.Name; + item.Name_Utf = ui.Name_Utf; + item.Comment = ui.Comment; + item.SetUtf8(ui.IsUtf8); + // item.SetFlag_AltStream(ui.IsAltStream); + // item.ExternalAttrib = ui.Attrib; + item.Time = ui.Time; + item.Ntfs_MTime = ui.Ntfs_MTime; + item.Ntfs_ATime = ui.Ntfs_ATime; + item.Ntfs_CTime = ui.Ntfs_CTime; + item.NtfsTimeIsDefined = ui.NtfsTimeIsDefined; +} + static void SetFileHeader( const CCompressionMethodMode &options, const CUpdateItem &ui, @@ -69,22 +84,15 @@ static void SetFileHeader( CItemOut &item) { item.Size = ui.Size; - bool isDir = ui.IsDir; + const bool isDir = ui.IsDir; item.ClearFlags(); if (ui.NewProps) { - item.Name = ui.Name; - item.Comment = ui.Comment; - item.SetUtf8(ui.IsUtf8); + Copy_From_UpdateItem_To_ItemOut(ui, item); // item.SetFlag_AltStream(ui.IsAltStream); item.ExternalAttrib = ui.Attrib; - item.Time = ui.Time; - item.Ntfs_MTime = ui.Ntfs_MTime; - item.Ntfs_ATime = ui.Ntfs_ATime; - item.Ntfs_CTime = ui.Ntfs_CTime; - item.NtfsTimeIsDefined = ui.NtfsTimeIsDefined; } /* else @@ -148,6 +156,35 @@ static void SetItemInfoFromCompressingResult(const CCompressingResult &compressi #ifndef _7ZIP_ST +struct CMtSem +{ + NWindows::NSynchronization::CSemaphore Semaphore; + NWindows::NSynchronization::CCriticalSection CS; + CIntVector Indexes; + int Head; + + void ReleaseItem(unsigned index) + { + { + CCriticalSectionLock lock(CS); + Indexes[index] = Head; + Head = (int)index; + } + Semaphore.Release(); + } + + int GetFreeItem() + { + int i; + { + CCriticalSectionLock lock(CS); + i = Head; + Head = Indexes[(unsigned)i]; + } + return i; + } +}; + static THREAD_FUNC_DECL CoderThread(void *threadCoderInfo); struct CThreadInfo @@ -156,7 +193,9 @@ struct CThreadInfo NWindows::CThread Thread; NWindows::NSynchronization::CAutoResetEvent CompressEvent; - NWindows::NSynchronization::CAutoResetEvent CompressionCompletedEvent; + CMtSem *MtSem; + unsigned ThreadIndex; + bool ExitThread; CMtCompressProgress *ProgressSpec; @@ -177,34 +216,43 @@ struct CThreadInfo UInt32 FileTime; UInt64 ExpectedDataSize; - CThreadInfo(const CCompressionMethodMode &options): + CThreadInfo(): ExitThread(false), - ProgressSpec(0), - OutStreamSpec(0), - Coder(options), + ProgressSpec(NULL), + OutStreamSpec(NULL), InSeqMode(false), OutSeqMode(false), FileTime(0), ExpectedDataSize((UInt64)(Int64)-1) {} + + void SetOptions(const CCompressionMethodMode &options) + { + Coder.SetOptions(options); + } HRESULT CreateEvents() { - RINOK(CompressEvent.CreateIfNotCreated()); - return CompressionCompletedEvent.CreateIfNotCreated(); + WRes wres = CompressEvent.CreateIfNotCreated_Reset(); + return HRESULT_FROM_WIN32(wres); + } + + HRESULT CreateThread() + { + WRes wres = Thread.Create(CoderThread, this); + return HRESULT_FROM_WIN32(wres); } - HRes CreateThread() { return Thread.Create(CoderThread, this); } void WaitAndCode(); - void StopWaitClose() + + void StopWait_Close() { ExitThread = true; - if (OutStreamSpec != 0) + if (OutStreamSpec) OutStreamSpec->StopWriting(E_ABORT); if (CompressEvent.IsCreated()) CompressEvent.Set(); - Thread.Wait(); - Thread.Close(); + Thread.Wait_Close(); } }; @@ -215,7 +263,7 @@ void CThreadInfo::WaitAndCode() CompressEvent.Lock(); if (ExitThread) return; - + Result = Coder.Compress( EXTERNAL_CODECS_LOC_VARS InStream, OutStream, @@ -224,7 +272,8 @@ void CThreadInfo::WaitAndCode() if (Result == S_OK && Progress) Result = Progress->SetRatioInfo(&CompressingResult.UnpackSize, &CompressingResult.PackSize); - CompressionCompletedEvent.Set(); + + MtSem->ReleaseItem(ThreadIndex); } } @@ -241,7 +290,7 @@ public: ~CThreads() { FOR_VECTOR (i, Threads) - Threads[i].StopWaitClose(); + Threads[i].StopWait_Close(); } }; @@ -253,7 +302,8 @@ struct CMemBlocks2: public CMemLockBlocks bool Finished; CCompressingResult CompressingResult; - CMemBlocks2(): Skip(false), InSeqMode(false), PreDescriptorMode(false), Finished(false) {} + CMemBlocks2(): Skip(false), InSeqMode(false), PreDescriptorMode(false), Finished(false), + CompressingResult() {} }; class CMemRefs @@ -359,7 +409,6 @@ STDMETHODIMP CMtProgressMixer::SetRatioInfo(const UInt64 *inSize, const UInt64 * #endif - static HRESULT UpdateItemOldData( COutArchive &archive, CInArchive *inArchive, @@ -385,21 +434,11 @@ static HRESULT UpdateItemOldData( if (item.HasDescriptor()) return E_NOTIMPL; - // use old name size. - // we keep ExternalAttrib and some another properties from old archive // item.ExternalAttrib = ui.Attrib; - // if we don't change Comment, we keep Comment from OldProperties - item.Comment = ui.Comment; - item.Name = ui.Name; - item.SetUtf8(ui.IsUtf8); + Copy_From_UpdateItem_To_ItemOut(ui, item); // item.SetFlag_AltStream(ui.IsAltStream); - item.Time = ui.Time; - item.Ntfs_MTime = ui.Ntfs_MTime; - item.Ntfs_ATime = ui.Ntfs_ATime; - item.Ntfs_CTime = ui.Ntfs_CTime; - item.NtfsTimeIsDefined = ui.NtfsTimeIsDefined; item.CentralExtra.RemoveUnknownSubBlocks(); item.LocalExtra.RemoveUnknownSubBlocks(); @@ -452,16 +491,16 @@ static void UpdatePropsFromStream(CUpdateItem &item, ISequentialInStream *fileIn FILETIME cTime, aTime, mTime; UInt64 size; - // UInt32 attrib; - if (getProps->GetProps(&size, &cTime, &aTime, &mTime, NULL) != S_OK) + UInt32 attrib; + if (getProps->GetProps(&size, &cTime, &aTime, &mTime, &attrib) != S_OK) return; if (size != item.Size && size != (UInt64)(Int64)-1) { - Int64 newComplexity = totalComplexity + ((Int64)size - (Int64)item.Size); + const Int64 newComplexity = (Int64)totalComplexity + ((Int64)size - (Int64)item.Size); if (newComplexity > 0) { - totalComplexity = newComplexity; + totalComplexity = (UInt64)newComplexity; updateCallback->SetTotal(totalComplexity); } item.Size = size; @@ -481,7 +520,7 @@ static void UpdatePropsFromStream(CUpdateItem &item, ISequentialInStream *fileIn if (!IsZero_FILETIME(cTime)) item.Ntfs_CTime = cTime; if (!IsZero_FILETIME(aTime)) item.Ntfs_ATime = aTime; - // item.Attrib = attrib; + item.Attrib = attrib; } @@ -501,7 +540,8 @@ static HRESULT Update2St( CMyComPtr<ICompressProgressInfo> progress = lps; lps->Init(updateCallback, true); - CAddCommon compressor(*options); + CAddCommon compressor; + compressor.SetOptions(*options); CObjectVector<CItemOut> items; UInt64 unpackSizeTotal = 0, packSizeTotal = 0; @@ -519,7 +559,7 @@ static HRESULT Update2St( { // Note: for (ui.NewProps && !ui.NewData) it copies Props from old archive, // But we will rewrite all important properties later. But we can keep some properties like Comment - itemEx = inputItems[ui.IndexInArc]; + itemEx = inputItems[(unsigned)ui.IndexInArc]; if (inArchive->ReadLocalItemAfterCdItemFull(itemEx) != S_OK) return E_NOTIMPL; (CItem &)item = itemEx; @@ -659,7 +699,7 @@ static HRESULT Update2( } else { - CItemEx inputItem = inputItems[ui.IndexInArc]; + CItemEx inputItem = inputItems[(unsigned)ui.IndexInArc]; if (inArchive->ReadLocalItemAfterCdItemFull(inputItem) != S_OK) return E_NOTIMPL; complexity += inputItem.GetLocalFullSize(); @@ -686,7 +726,8 @@ static HRESULT Update2( options2._methods.AddNew(); } - CAddCommon compressor(options2); + CAddCommon compressor; + compressor.SetOptions(options2); complexity = 0; @@ -715,15 +756,24 @@ static HRESULT Update2( UInt32 numThreads = options._numThreads; - const UInt32 kNumMaxThreads = 64; - if (numThreads > kNumMaxThreads) - numThreads = kNumMaxThreads; - if (numThreads > MAXIMUM_WAIT_OBJECTS) // is 64 in Windows (is it 64 in all versions?) + { + const UInt32 kNumMaxThreads = + #ifdef _WIN32 + 64; // _WIN32 supports only 64 threads in one group. So no need for more threads here + #else + 128; + #endif + if (numThreads > kNumMaxThreads) + numThreads = kNumMaxThreads; + } + /* + if (numThreads > MAXIMUM_WAIT_OBJECTS) // is 64 in Windows numThreads = MAXIMUM_WAIT_OBJECTS; + */ if (numThreads < 1) numThreads = 1; - const size_t kMemPerThread = (1 << 25); + const size_t kMemPerThread = (size_t)1 << 25; const size_t kBlockSize = 1 << 16; bool mtMode = (numThreads > 1); @@ -731,6 +781,8 @@ static HRESULT Update2( if (numFilesToCompress <= 1) mtMode = false; + // mtMode = true; // debug: to test mtMode + if (!mtMode) { FOR_VECTOR (mi, options2._methods) @@ -788,7 +840,7 @@ static HRESULT Update2( if (t > numThreads) t = numThreads; oneMethodMain->AddProp_NumThreads(t); - numXzThreads = t; + numXzThreads = (int)t; } numThreads /= (unsigned)numXzThreads; } @@ -830,8 +882,16 @@ static HRESULT Update2( CMemBlockManagerMt memManager(kBlockSize); CMemRefs refs(&memManager); + CMtSem mtSem; CThreads threads; - CRecordVector<HANDLE> compressingCompletedEvents; + mtSem.Head = -1; + mtSem.Indexes.ClearAndSetSize(numThreads); + { + WRes wres = mtSem.Semaphore.Create(0, numThreads); + if (wres != 0) + return HRESULT_FROM_WIN32(wres); + } + CUIntVector threadIndices; // list threads in order of updateItems { @@ -840,26 +900,32 @@ static HRESULT Update2( refs.Refs.Add(CMemBlocks2()); for (i = 0; i < numThreads; i++) - threads.Threads.Add(CThreadInfo(options2)); + { + threads.Threads.AddNew(); + // mtSem.Indexes[i] = -1; // actually we don't use these values + } for (i = 0; i < numThreads; i++) { CThreadInfo &threadInfo = threads.Threads[i]; + threadInfo.SetOptions(options2); ; #ifdef EXTERNAL_CODECS threadInfo.__externalCodecs = __externalCodecs; #endif RINOK(threadInfo.CreateEvents()); threadInfo.OutStreamSpec = new COutMemStream(&memManager); - RINOK(threadInfo.OutStreamSpec->CreateEvents()); + RINOK(threadInfo.OutStreamSpec->CreateEvents(SYNC_WFMO(&memManager.Synchro))); threadInfo.OutStream = threadInfo.OutStreamSpec; threadInfo.IsFree = true; threadInfo.ProgressSpec = new CMtCompressProgress(); threadInfo.Progress = threadInfo.ProgressSpec; - threadInfo.ProgressSpec->Init(&mtCompressProgressMixer, (int)i); + threadInfo.ProgressSpec->Init(&mtCompressProgressMixer, i); threadInfo.InSeqMode = false; threadInfo.OutSeqMode = false; threadInfo.FileTime = 0; threadInfo.ExpectedDataSize = (UInt64)(Int64)-1; + threadInfo.ThreadIndex = i; + threadInfo.MtSem = &mtSem; RINOK(threadInfo.CreateThread()); } } @@ -890,7 +956,7 @@ static HRESULT Update2( } else { - itemEx = inputItems[ui.IndexInArc]; + itemEx = inputItems[(unsigned)ui.IndexInArc]; if (inArchive->ReadLocalItemAfterCdItemFull(itemEx) != S_OK) return E_NOTIMPL; (CItem &)item = itemEx; @@ -958,10 +1024,9 @@ static HRESULT Update2( threadInfo.OutSeqMode = outSeqMode; threadInfo.FileTime = ui.Time; // FileTime is used for ZipCrypto only in seqMode threadInfo.ExpectedDataSize = ui.Size; - + threadInfo.CompressEvent.Set(); - compressingCompletedEvents.Add(threadInfo.CompressionCompletedEvent); threadIndices.Add(k); } } @@ -982,7 +1047,7 @@ static HRESULT Update2( if (!ui.NewProps || !ui.NewData) { - itemEx = inputItems[ui.IndexInArc]; + itemEx = inputItems[(unsigned)ui.IndexInArc]; if (inArchive->ReadLocalItemAfterCdItemFull(itemEx) != S_OK) return E_NOTIMPL; (CItem &)item = itemEx; @@ -1004,7 +1069,7 @@ static HRESULT Update2( if (memRef.Finished) { if (lastRealStreamItemIndex < (int)itemIndex) - lastRealStreamItemIndex = itemIndex; + lastRealStreamItemIndex = (int)itemIndex; SetFileHeader(options, ui, memRef.CompressingResult.DescriptorMode, item); @@ -1030,7 +1095,7 @@ static HRESULT Update2( { // LocalHeader was not written for current itemIndex still - lastRealStreamItemIndex = itemIndex; + lastRealStreamItemIndex = (int)itemIndex; // thread was started before for that item already, and memRef.SeqMode was set @@ -1060,24 +1125,30 @@ static HRESULT Update2( } } - DWORD result = ::WaitForMultipleObjects(compressingCompletedEvents.Size(), - &compressingCompletedEvents.Front(), FALSE, INFINITE); - if (result == WAIT_FAILED) - { - DWORD lastError = GetLastError(); - return lastError != 0 ? lastError : E_FAIL; - } - - unsigned t = (unsigned)(result - WAIT_OBJECT_0); - if (t >= compressingCompletedEvents.Size()) + WRes wres = mtSem.Semaphore.Lock(); + if (wres != 0) + return HRESULT_FROM_WIN32(wres); + + int ti = mtSem.GetFreeItem(); + if (ti < 0) return E_FAIL; - CThreadInfo &threadInfo = threads.Threads[threadIndices[t]]; + CThreadInfo &threadInfo = threads.Threads[(unsigned)ti]; threadInfo.InStream.Release(); threadInfo.IsFree = true; RINOK(threadInfo.Result); + + unsigned t = 0; + + for (;;) + { + if (t == threadIndices.Size()) + return E_FAIL; + if (threadIndices[t] == (unsigned)ti) + break; + t++; + } threadIndices.Delete(t); - compressingCompletedEvents.Delete(t); if (t == 0) { @@ -1187,7 +1258,7 @@ HRESULT CCacheOutStream::Init(ISequentialOutStream *seqStream, IOutStream *strea { RINOK(_stream->Seek(0, STREAM_SEEK_CUR, &_virtPos)); RINOK(_stream->Seek(0, STREAM_SEEK_END, &_virtSize)); - RINOK(_stream->Seek(_virtPos, STREAM_SEEK_SET, &_virtPos)); + RINOK(_stream->Seek((Int64)_virtPos, STREAM_SEEK_SET, &_virtPos)); } _phyPos = _virtPos; _phySize = _virtSize; @@ -1204,7 +1275,7 @@ HRESULT CCacheOutStream::MyWrite(size_t size) { if (!_stream) return E_FAIL; - RINOK(_stream->Seek(_cachedPos, STREAM_SEEK_SET, &_phyPos)); + RINOK(_stream->Seek((Int64)_cachedPos, STREAM_SEEK_SET, &_phyPos)); } size_t pos = (size_t)_cachedPos & kCacheMask; size_t curSize = MyMin(kCacheSize - pos, _cachedSize); @@ -1233,7 +1304,7 @@ CCacheOutStream::~CCacheOutStream() if (_virtSize != _phySize) _stream->SetSize(_virtSize); if (_virtPos != _phyPos) - _stream->Seek(_virtPos, STREAM_SEEK_SET, NULL); + _stream->Seek((Int64)_virtPos, STREAM_SEEK_SET, NULL); } ::MidFree(_cache); } @@ -1332,9 +1403,9 @@ STDMETHODIMP CCacheOutStream::Seek(Int64 offset, UInt32 seekOrigin, UInt64 *newP } if (offset < 0) return HRESULT_WIN32_ERROR_NEGATIVE_SEEK; - _virtPos = offset; + _virtPos = (UInt64)offset; if (newPosition) - *newPosition = offset; + *newPosition = (UInt64)offset; return S_OK; } @@ -1391,7 +1462,7 @@ HRESULT Update( { IInStream *baseStream = inArchive->GetBaseStream(); RINOK(baseStream->Seek(0, STREAM_SEEK_SET, NULL)); - RINOK(NCompress::CopyStream_ExactSize(baseStream, seqOutStream, inArchive->ArcInfo.Base, NULL)); + RINOK(NCompress::CopyStream_ExactSize(baseStream, seqOutStream, (UInt64)inArchive->ArcInfo.Base, NULL)); } } @@ -1412,7 +1483,7 @@ HRESULT Update( { IInStream *baseStream = inArchive->GetBaseStream(); RINOK(baseStream->Seek(inArchive->ArcInfo.Base, STREAM_SEEK_SET, NULL)); - UInt64 embStubSize = inArchive->ArcInfo.MarkerPos2 - inArchive->ArcInfo.Base; + const UInt64 embStubSize = (UInt64)((Int64)inArchive->ArcInfo.MarkerPos2 - inArchive->ArcInfo.Base); RINOK(NCompress::CopyStream_ExactSize(baseStream, outStream, embStubSize, NULL)); outArchive.MoveCurPos(embStubSize); } diff --git a/CPP/7zip/Archive/Zip/ZipUpdate.h b/CPP/7zip/Archive/Zip/ZipUpdate.h index 8785ae60..95e72a47 100644 --- a/CPP/7zip/Archive/Zip/ZipUpdate.h +++ b/CPP/7zip/Archive/Zip/ZipUpdate.h @@ -34,11 +34,12 @@ struct CUpdateItem bool IsUtf8; // bool IsAltStream; int IndexInArc; - int IndexInClient; + unsigned IndexInClient; UInt32 Attrib; UInt32 Time; UInt64 Size; AString Name; + CByteBuffer Name_Utf; // for Info-Zip (kIzUnicodeName) Extra CByteBuffer Comment; // bool Commented; // CUpdateRange CommentRange; @@ -54,6 +55,7 @@ struct CUpdateItem // IsAltStream = false; Size = 0; Name.Empty(); + Name_Utf.Free(); Comment.Free(); } |