summaryrefslogtreecommitdiffstatshomepage
path: root/3rdparty/lzma/CPP/7zip/Archive/7z/7zIn.cpp
diff options
context:
space:
mode:
Diffstat (limited to '3rdparty/lzma/CPP/7zip/Archive/7z/7zIn.cpp')
-rw-r--r--3rdparty/lzma/CPP/7zip/Archive/7z/7zIn.cpp482
1 files changed, 298 insertions, 184 deletions
diff --git a/3rdparty/lzma/CPP/7zip/Archive/7z/7zIn.cpp b/3rdparty/lzma/CPP/7zip/Archive/7z/7zIn.cpp
index d8c2717501c..4defd272b39 100644
--- a/3rdparty/lzma/CPP/7zip/Archive/7z/7zIn.cpp
+++ b/3rdparty/lzma/CPP/7zip/Archive/7z/7zIn.cpp
@@ -11,6 +11,9 @@
#include "../../../../C/7zCrc.h"
#include "../../../../C/CpuArch.h"
+#include "../../../Common/MyBuffer2.h"
+// #include "../../../Common/UTFConvert.h"
+
#include "../../Common/StreamObjects.h"
#include "../../Common/StreamUtils.h"
@@ -22,7 +25,7 @@
#define Get64(p) GetUi64(p)
// define FORMAT_7Z_RECOVERY if you want to recover multivolume archives with empty StartHeader
-#ifndef _SFX
+#ifndef Z7_SFX
#define FORMAT_7Z_RECOVERY
#endif
@@ -32,6 +35,25 @@ using namespace NCOM;
namespace NArchive {
namespace N7z {
+#define k_Scan_NumCoders_MAX 64
+#define k_Scan_NumCodersStreams_in_Folder_MAX 64
+
+unsigned BoolVector_CountSum(const CBoolVector &v);
+unsigned BoolVector_CountSum(const CBoolVector &v)
+{
+ unsigned sum = 0;
+ const unsigned size = v.Size();
+ for (unsigned i = 0; i < size; i++)
+ if (v[i])
+ sum++;
+ return sum;
+}
+
+static inline bool BoolVector_Item_IsValidAndTrue(const CBoolVector &v, unsigned i)
+{
+ return (i < v.Size() ? v[i] : false);
+}
+
static void BoolVector_Fill_False(CBoolVector &v, unsigned size)
{
v.ClearAndSetSize(size);
@@ -40,12 +62,17 @@ static void BoolVector_Fill_False(CBoolVector &v, unsigned size)
p[i] = false;
}
+
class CInArchiveException {};
class CUnsupportedFeatureException: public CInArchiveException {};
+Z7_ATTR_NORETURN
static void ThrowException() { throw CInArchiveException(); }
+Z7_ATTR_NORETURN
static inline void ThrowEndOfData() { ThrowException(); }
+Z7_ATTR_NORETURN
static inline void ThrowUnsupported() { throw CUnsupportedFeatureException(); }
+Z7_ATTR_NORETURN
static inline void ThrowIncorrect() { ThrowException(); }
class CStreamSwitch
@@ -90,12 +117,12 @@ void CStreamSwitch::Set(CInArchive *archive, const CByteBuffer &byteBuffer)
void CStreamSwitch::Set(CInArchive *archive, const CObjectVector<CByteBuffer> *dataVector)
{
Remove();
- Byte external = archive->ReadByte();
+ const Byte external = archive->ReadByte();
if (external != 0)
{
if (!dataVector)
ThrowIncorrect();
- CNum dataIndex = archive->ReadNum();
+ const CNum dataIndex = archive->ReadNum();
if (dataIndex >= dataVector->Size())
ThrowIncorrect();
Set(archive, (*dataVector)[dataIndex]);
@@ -148,7 +175,7 @@ static UInt64 ReadNumberSpec(const Byte *p, size_t size, size_t &processed)
return 0;
}
- unsigned b = *p++;
+ const unsigned b = *p++;
size--;
if ((b & 0x80) == 0)
@@ -169,10 +196,10 @@ static UInt64 ReadNumberSpec(const Byte *p, size_t size, size_t &processed)
for (unsigned i = 1; i < 8; i++)
{
- unsigned mask = (unsigned)0x80 >> i;
+ const unsigned mask = (unsigned)0x80 >> i;
if ((b & mask) == 0)
{
- UInt64 high = b & (mask - 1);
+ const UInt64 high = b & (mask - 1);
value |= (high << (i * 8));
processed = i + 1;
return value;
@@ -196,7 +223,7 @@ static UInt64 ReadNumberSpec(const Byte *p, size_t size, size_t &processed)
UInt64 CInByte2::ReadNumber()
{
size_t processed;
- UInt64 res = ReadNumberSpec(_buffer + _pos, _size - _pos, processed);
+ const UInt64 res = ReadNumberSpec(_buffer + _pos, _size - _pos, processed);
if (processed == 0)
ThrowEndOfData();
_pos += processed;
@@ -216,7 +243,7 @@ CNum CInByte2::ReadNum()
}
}
*/
- UInt64 value = ReadNumber();
+ const UInt64 value = ReadNumber();
if (value > kNumMax)
ThrowUnsupported();
return (CNum)value;
@@ -226,7 +253,7 @@ UInt32 CInByte2::ReadUInt32()
{
if (_pos + 4 > _size)
ThrowEndOfData();
- UInt32 res = Get32(_buffer + _pos);
+ const UInt32 res = Get32(_buffer + _pos);
_pos += 4;
return res;
}
@@ -235,54 +262,101 @@ UInt64 CInByte2::ReadUInt64()
{
if (_pos + 8 > _size)
ThrowEndOfData();
- UInt64 res = Get64(_buffer + _pos);
+ const UInt64 res = Get64(_buffer + _pos);
_pos += 8;
return res;
}
-#define CHECK_SIGNATURE if (p[0] != '7' || p[1] != 'z' || p[2] != 0xBC || p[3] != 0xAF || p[4] != 0x27 || p[5] != 0x1C) return false;
+#define Y0 '7'
+#define Y1 'z'
+#define Y2 0xBC
+#define Y3 0xAF
+#define Y4 0x27
+#define Y5 0x1C
+
+#define IS_SIGNATURE(p)( \
+ (p)[2] == Y2 && \
+ (p)[3] == Y3 && \
+ (p)[5] == Y5 && \
+ (p)[4] == Y4 && \
+ (p)[1] == Y1 && \
+ (p)[0] == Y0)
+
+/* FindSignature_10() is allowed to access data up to and including &limit[9].
+ limit[10] access is not allowed.
+ return:
+ (return_ptr < limit) : signature was found at (return_ptr)
+ (return_ptr >= limit) : limit was reached or crossed. So no signature found before limit
+*/
+Z7_NO_INLINE
+static const Byte *FindSignature_10(const Byte *p, const Byte *limit)
+{
+ for (;;)
+ {
+ for (;;)
+ {
+ if (p >= limit)
+ return limit;
+ const Byte b = p[5];
+ p += 6;
+ if (b == Y0) { break; }
+ if (b == Y1) { p -= 1; break; }
+ if (b == Y2) { p -= 2; break; }
+ if (b == Y3) { p -= 3; break; }
+ if (b == Y4) { p -= 4; break; }
+ if (b == Y5) { p -= 5; break; }
+ }
+ if (IS_SIGNATURE(p - 1))
+ return p - 1;
+ }
+}
-static inline bool TestSignature(const Byte *p)
+
+static inline bool TestStartCrc(const Byte *p)
{
- CHECK_SIGNATURE
return CrcCalc(p + 12, 20) == Get32(p + 8);
}
-#ifdef FORMAT_7Z_RECOVERY
static inline bool TestSignature2(const Byte *p)
{
- CHECK_SIGNATURE;
- if (CrcCalc(p + 12, 20) == Get32(p + 8))
+ if (!IS_SIGNATURE(p))
+ return false;
+ #ifdef FORMAT_7Z_RECOVERY
+ if (TestStartCrc(p))
return true;
for (unsigned i = 8; i < kHeaderSize; i++)
if (p[i] != 0)
return false;
return (p[6] != 0 || p[7] != 0);
+ #else
+ return TestStartCrc(p);
+ #endif
}
-#else
-#define TestSignature2(p) TestSignature(p)
-#endif
+
HRESULT CInArchive::FindAndReadSignature(IInStream *stream, const UInt64 *searchHeaderSizeLimit)
{
- RINOK(ReadStream_FALSE(stream, _header, kHeaderSize));
+ RINOK(ReadStream_FALSE(stream, _header, kHeaderSize))
if (TestSignature2(_header))
return S_OK;
if (searchHeaderSizeLimit && *searchHeaderSizeLimit == 0)
return S_FALSE;
- const UInt32 kBufSize = 1 << 15;
- CByteArr buf(kBufSize);
+ const UInt32 kBufSize = (1 << 15) + kHeaderSize; // must be > (kHeaderSize * 2)
+ CAlignedBuffer1 buf(kBufSize);
memcpy(buf, _header, kHeaderSize);
UInt64 offset = 0;
for (;;)
{
- UInt32 readSize = kBufSize - kHeaderSize;
+ UInt32 readSize =
+ (offset == 0) ?
+ kBufSize - kHeaderSize - kHeaderSize :
+ kBufSize - kHeaderSize;
if (searchHeaderSizeLimit)
{
- UInt64 rem = *searchHeaderSizeLimit - offset;
+ const UInt64 rem = *searchHeaderSizeLimit - offset;
if (readSize > rem)
readSize = (UInt32)rem;
if (readSize == 0)
@@ -290,29 +364,28 @@ HRESULT CInArchive::FindAndReadSignature(IInStream *stream, const UInt64 *search
}
UInt32 processed = 0;
- RINOK(stream->Read(buf + kHeaderSize, readSize, &processed));
+ RINOK(stream->Read(buf + kHeaderSize, readSize, &processed))
if (processed == 0)
return S_FALSE;
+
+ /* &buf[0] was already tested for signature before.
+ So first search here will be for &buf[1] */
for (UInt32 pos = 0;;)
{
const Byte *p = buf + pos + 1;
- const Byte *lim = buf + processed;
- for (; p <= lim; p += 4)
- {
- if (p[0] == '7') break;
- if (p[1] == '7') { p += 1; break; }
- if (p[2] == '7') { p += 2; break; }
- if (p[3] == '7') { p += 3; break; }
- };
- if (p > lim)
+ const Byte *lim = buf + processed + 1;
+ /* we have (kHeaderSize - 1 = 31) filled bytes starting from (lim),
+ and it's safe to access just 10 bytes in that reserved area */
+ p = FindSignature_10(p, lim);
+ if (p >= lim)
break;
pos = (UInt32)(p - buf);
- if (TestSignature(p))
+ if (TestStartCrc(p))
{
memcpy(_header, p, kHeaderSize);
_arhiveBeginStreamPosition += offset + pos;
- return stream->Seek(_arhiveBeginStreamPosition + kHeaderSize, STREAM_SEEK_SET, NULL);
+ return InStream_SeekSet(stream, _arhiveBeginStreamPosition + kHeaderSize);
}
}
@@ -326,10 +399,8 @@ HRESULT CInArchive::Open(IInStream *stream, const UInt64 *searchHeaderSizeLimit)
{
HeadersSize = 0;
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(FindAndReadSignature(stream, searchHeaderSizeLimit));
+ RINOK(InStream_GetPos_GetSize(stream, _arhiveBeginStreamPosition, _fileEndPosition))
+ RINOK(FindAndReadSignature(stream, searchHeaderSizeLimit))
_stream = stream;
return S_OK;
}
@@ -355,9 +426,9 @@ void CInArchive::ReadArchiveProperties(CInArchiveInfo & /* archiveInfo */)
void CInByte2::ParseFolder(CFolder &folder)
{
- UInt32 numCoders = ReadNum();
+ const UInt32 numCoders = ReadNum();
- if (numCoders == 0)
+ if (numCoders == 0 || numCoders > k_Scan_NumCoders_MAX)
ThrowUnsupported();
folder.Coders.SetSize(numCoders);
@@ -368,10 +439,10 @@ void CInByte2::ParseFolder(CFolder &folder)
{
CCoderInfo &coder = folder.Coders[i];
{
- Byte mainByte = ReadByte();
+ const Byte mainByte = ReadByte();
if ((mainByte & 0xC0) != 0)
ThrowUnsupported();
- unsigned idSize = (mainByte & 0xF);
+ const unsigned idSize = (mainByte & 0xF);
if (idSize > 8 || idSize > GetRem())
ThrowUnsupported();
const Byte *longID = GetPtr();
@@ -384,7 +455,9 @@ void CInByte2::ParseFolder(CFolder &folder)
if ((mainByte & 0x10) != 0)
{
coder.NumStreams = ReadNum();
+ // if (coder.NumStreams > k_Scan_NumCodersStreams_in_Folder_MAX) ThrowUnsupported();
/* numOutStreams = */ ReadNum();
+ // if (ReadNum() != 1) // numOutStreams ThrowUnsupported();
}
else
{
@@ -393,7 +466,7 @@ void CInByte2::ParseFolder(CFolder &folder)
if ((mainByte & 0x20) != 0)
{
- CNum propsSize = ReadNum();
+ const CNum propsSize = ReadNum();
coder.Props.Alloc((size_t)propsSize);
ReadBytes((Byte *)coder.Props, (size_t)propsSize);
}
@@ -403,7 +476,7 @@ void CInByte2::ParseFolder(CFolder &folder)
numInStreams += coder.NumStreams;
}
- UInt32 numBonds = numCoders - 1;
+ const UInt32 numBonds = numCoders - 1;
folder.Bonds.SetSize(numBonds);
for (i = 0; i < numBonds; i++)
{
@@ -414,7 +487,7 @@ void CInByte2::ParseFolder(CFolder &folder)
if (numInStreams < numBonds)
ThrowUnsupported();
- UInt32 numPackStreams = numInStreams - numBonds;
+ const UInt32 numPackStreams = numInStreams - numBonds;
folder.PackStreams.SetSize(numPackStreams);
if (numPackStreams == 1)
@@ -435,7 +508,7 @@ void CInByte2::ParseFolder(CFolder &folder)
void CFolders::ParseFolderInfo(unsigned folderIndex, CFolder &folder) const
{
- size_t startPos = FoCodersDataOffset[folderIndex];
+ const size_t startPos = FoCodersDataOffset[folderIndex];
CInByte2 inByte;
inByte.Init(CodersData + startPos, FoCodersDataOffset[folderIndex + 1] - startPos);
inByte.ParseFolder(folder);
@@ -450,8 +523,8 @@ void CDatabase::GetPath(unsigned index, UString &path) const
if (!NameOffsets || !NamesBuf)
return;
- size_t offset = NameOffsets[index];
- size_t size = NameOffsets[index + 1] - offset;
+ const size_t offset = NameOffsets[index];
+ const size_t size = NameOffsets[index + 1] - offset;
if (size >= (1 << 28))
return;
@@ -462,7 +535,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
@@ -484,16 +557,33 @@ HRESULT CDatabase::GetPath_Prop(unsigned index, PROPVARIANT *path) const throw()
if (!NameOffsets || !NamesBuf)
return S_OK;
- size_t offset = NameOffsets[index];
- size_t size = NameOffsets[index + 1] - offset;
+ const size_t offset = NameOffsets[index];
+ const size_t size = NameOffsets[index + 1] - offset;
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++)
{
@@ -502,10 +592,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;
/*
@@ -557,7 +651,7 @@ void CInArchive::WaitId(UInt64 id)
{
for (;;)
{
- UInt64 type = ReadID();
+ const UInt64 type = ReadID();
if (type == id)
return;
if (type == NID::kEnd)
@@ -566,27 +660,33 @@ void CInArchive::WaitId(UInt64 id)
}
}
-void CInArchive::ReadHashDigests(unsigned numItems, CUInt32DefVector &crcs)
+
+void CInArchive::Read_UInt32_Vector(CUInt32DefVector &v)
{
- ReadBoolVector2(numItems, crcs.Defs);
- crcs.Vals.ClearAndSetSize(numItems);
- UInt32 *p = &crcs.Vals[0];
- const bool *defs = &crcs.Defs[0];
+ const unsigned numItems = v.Defs.Size();
+ v.Vals.ClearAndSetSize(numItems);
+ UInt32 *p = &v.Vals[0];
+ const bool *defs = &v.Defs[0];
for (unsigned i = 0; i < numItems; i++)
{
- UInt32 crc = 0;
+ UInt32 a = 0;
if (defs[i])
- crc = ReadUInt32();
- p[i] = crc;
+ a = ReadUInt32();
+ p[i] = a;
}
}
-#define k_Scan_NumCoders_MAX 64
-#define k_Scan_NumCodersStreams_in_Folder_MAX 64
+
+void CInArchive::ReadHashDigests(unsigned numItems, CUInt32DefVector &crcs)
+{
+ ReadBoolVector2(numItems, crcs.Defs);
+ Read_UInt32_Vector(crcs);
+}
+
void CInArchive::ReadPackInfo(CFolders &f)
{
- CNum numPackStreams = ReadNum();
+ const CNum numPackStreams = ReadNum();
WaitId(NID::kSize);
f.PackPositions.Alloc(numPackStreams + 1);
@@ -595,7 +695,7 @@ void CInArchive::ReadPackInfo(CFolders &f)
for (CNum i = 0; i < numPackStreams; i++)
{
f.PackPositions[i] = sum;
- UInt64 packSize = ReadNumber();
+ const UInt64 packSize = ReadNumber();
sum += packSize;
if (sum < packSize)
ThrowIncorrect();
@@ -623,7 +723,7 @@ void CInArchive::ReadUnpackInfo(
CFolders &folders)
{
WaitId(NID::kFolder);
- CNum numFolders = ReadNum();
+ const CNum numFolders = ReadNum();
CNum numCodersOutStreams = 0;
{
@@ -648,21 +748,21 @@ 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();
+ const CNum numCoders = inByte->ReadNum();
if (numCoders == 0 || numCoders > k_Scan_NumCoders_MAX)
ThrowUnsupported();
for (CNum ci = 0; ci < numCoders; ci++)
{
- Byte mainByte = inByte->ReadByte();
+ const Byte mainByte = inByte->ReadByte();
if ((mainByte & 0xC0) != 0)
ThrowUnsupported();
- unsigned idSize = (mainByte & 0xF);
+ const unsigned idSize = (mainByte & 0xF);
if (idSize > 8)
ThrowUnsupported();
if (idSize > inByte->GetRem())
@@ -691,18 +791,18 @@ void CInArchive::ReadUnpackInfo(
if ((mainByte & 0x20) != 0)
{
- CNum propsSize = inByte->ReadNum();
+ const CNum propsSize = inByte->ReadNum();
if (propsSize > inByte->GetRem())
ThrowEndOfData();
if (id == k_LZMA2 && propsSize == 1)
{
- Byte v = *_inByteBack->GetPtr();
+ const Byte v = *_inByteBack->GetPtr();
if (folders.ParsedMethods.Lzma2Prop < v)
folders.ParsedMethods.Lzma2Prop = v;
}
else if (id == k_LZMA && propsSize == 5)
{
- UInt32 dicSize = GetUi32(_inByteBack->GetPtr() + 1);
+ const UInt32 dicSize = GetUi32(_inByteBack->GetPtr() + 1);
if (folders.ParsedMethods.LzmaDic < dicSize)
folders.ParsedMethods.LzmaDic = dicSize;
}
@@ -718,7 +818,7 @@ void CInArchive::ReadUnpackInfo(
else
{
UInt32 i;
- CNum numBonds = numCoders - 1;
+ const CNum numBonds = numCoders - 1;
if (numInStreams < numBonds)
ThrowUnsupported();
@@ -743,7 +843,7 @@ void CInArchive::ReadUnpackInfo(
if (numPackStreams != 1)
for (i = 0; i < numPackStreams; i++)
{
- CNum index = inByte->ReadNum(); // PackStreams
+ const CNum index = inByte->ReadNum(); // PackStreams
if (index >= numInStreams || StreamUsed[index])
ThrowUnsupported();
StreamUsed[index] = true;
@@ -769,10 +869,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();
@@ -785,7 +885,7 @@ void CInArchive::ReadUnpackInfo(
for (;;)
{
- UInt64 type = ReadID();
+ const UInt64 type = ReadID();
if (type == NID::kEnd)
return;
if (type == NID::kCRC)
@@ -829,19 +929,19 @@ void CInArchive::ReadSubStreamsInfo(
{
// v3.13 incorrectly worked with empty folders
// v4.07: we check that folder is empty
- CNum numSubstreams = folders.NumUnpackStreamsVector[i];
+ const CNum numSubstreams = folders.NumUnpackStreamsVector[i];
if (numSubstreams == 0)
continue;
UInt64 sum = 0;
for (CNum j = 1; j < numSubstreams; j++)
{
- UInt64 size = ReadNumber();
+ const UInt64 size = ReadNumber();
unpackSizes.Add(size);
sum += size;
if (sum < size)
ThrowIncorrect();
}
- UInt64 folderUnpackSize = folders.GetFolderUnpackSize(i);
+ const UInt64 folderUnpackSize = folders.GetFolderUnpackSize(i);
if (folderUnpackSize < sum)
ThrowIncorrect();
unpackSizes.Add(folderUnpackSize - sum);
@@ -854,7 +954,7 @@ void CInArchive::ReadSubStreamsInfo(
{
/* v9.26 - v9.29 incorrectly worked:
if (folders.NumUnpackStreamsVector[i] == 0), it threw error */
- CNum val = folders.NumUnpackStreamsVector[i];
+ const CNum val = folders.NumUnpackStreamsVector[i];
if (val > 1)
ThrowIncorrect();
if (val == 1)
@@ -865,7 +965,7 @@ void CInArchive::ReadSubStreamsInfo(
unsigned numDigests = 0;
for (i = 0; i < folders.NumFolders; i++)
{
- CNum numSubstreams = folders.NumUnpackStreamsVector[i];
+ const CNum numSubstreams = folders.NumUnpackStreamsVector[i];
if (numSubstreams != 1 || !folders.FolderCRCs.ValidAndDefined(i))
numDigests += numSubstreams;
}
@@ -888,7 +988,7 @@ void CInArchive::ReadSubStreamsInfo(
for (i = 0; i < folders.NumFolders; i++)
{
- CNum numSubstreams = folders.NumUnpackStreamsVector[i];
+ const CNum numSubstreams = folders.NumUnpackStreamsVector[i];
if (numSubstreams == 1 && folders.FolderCRCs.ValidAndDefined(i))
{
digests.Defs[k] = true;
@@ -920,7 +1020,7 @@ void CInArchive::ReadSubStreamsInfo(
unsigned k = 0;
for (i = 0; i < folders.NumFolders; i++)
{
- CNum numSubstreams = folders.NumUnpackStreamsVector[i];
+ const CNum numSubstreams = folders.NumUnpackStreamsVector[i];
if (numSubstreams == 1 && folders.FolderCRCs.ValidAndDefined(i))
{
digests.Defs[k] = true;
@@ -937,6 +1037,8 @@ void CInArchive::ReadSubStreamsInfo(
}
}
+
+
void CInArchive::ReadStreamsInfo(
const CObjectVector<CByteBuffer> *dataVector,
UInt64 &dataOffset,
@@ -949,7 +1051,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();
}
@@ -1004,13 +1110,13 @@ void CInArchive::ReadBoolVector(unsigned numItems, CBoolVector &v)
mask = 0x80;
}
p[i] = ((b & mask) != 0);
- mask >>= 1;
+ mask = (Byte)(mask >> 1);
}
}
void CInArchive::ReadBoolVector2(unsigned numItems, CBoolVector &v)
{
- Byte allAreDefined = ReadByte();
+ const Byte allAreDefined = ReadByte();
if (allAreDefined == 0)
{
ReadBoolVector(numItems, v);
@@ -1047,7 +1153,7 @@ HRESULT CInArchive::ReadAndDecodePackedStreams(
DECL_EXTERNAL_CODECS_LOC_VARS
UInt64 baseOffset,
UInt64 &dataOffset, CObjectVector<CByteBuffer> &dataVector
- _7Z_DECODER_CRYPRO_VARS_DECL
+ Z7_7Z_DECODER_CRYPRO_VARS_DECL
)
{
CFolders folders;
@@ -1065,8 +1171,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);
@@ -1075,24 +1181,36 @@ HRESULT CInArchive::ReadAndDecodePackedStreams(
CMyComPtr<ISequentialOutStream> outStream = outStreamSpec;
outStreamSpec->Init(data, unpackSize);
+ bool dataAfterEnd_Error = false;
+
HRESULT result = decoder.Decode(
EXTERNAL_CODECS_LOC_VARS
_stream, baseOffset + dataOffset,
folders, i,
- NULL, // *unpackSize
+ NULL, // &unpackSize64
outStream,
NULL, // *compressProgress
+
NULL // **inStreamMainRes
+ , dataAfterEnd_Error
- _7Z_DECODER_CRYPRO_VARS
- #if !defined(_7ZIP_ST) && !defined(_SFX)
+ Z7_7Z_DECODER_CRYPRO_VARS
+ #if !defined(Z7_ST)
, false // mtMode
, 1 // numThreads
+ , 0 // memUsage
#endif
);
- RINOK(result);
+ RINOK(result)
+
+ if (dataAfterEnd_Error)
+ ThereIsHeaderError = true;
+
+ if (unpackSize != outStreamSpec->GetPos())
+ ThrowIncorrect();
+
if (folders.FolderCRCs.ValidAndDefined(i))
if (CrcCalc(data, unpackSize) != folders.FolderCRCs.Vals[i])
ThrowIncorrect();
@@ -1107,7 +1225,7 @@ HRESULT CInArchive::ReadAndDecodePackedStreams(
HRESULT CInArchive::ReadHeader(
DECL_EXTERNAL_CODECS_LOC_VARS
CDbEx &db
- _7Z_DECODER_CRYPRO_VARS_DECL
+ Z7_7Z_DECODER_CRYPRO_VARS_DECL
)
{
UInt64 type = ReadID();
@@ -1122,14 +1240,14 @@ HRESULT CInArchive::ReadHeader(
if (type == NID::kAdditionalStreamsInfo)
{
- HRESULT result = ReadAndDecodePackedStreams(
+ const HRESULT result = ReadAndDecodePackedStreams(
EXTERNAL_CODECS_LOC_VARS
db.ArcInfo.StartPositionAfterHeader,
db.ArcInfo.DataStartPosition2,
dataVector
- _7Z_DECODER_CRYPRO_VARS
+ Z7_7Z_DECODER_CRYPRO_VARS
);
- RINOK(result);
+ RINOK(result)
db.ArcInfo.DataStartPosition2 += db.ArcInfo.StartPositionAfterHeader;
type = ReadID();
}
@@ -1148,19 +1266,10 @@ HRESULT CInArchive::ReadHeader(
type = ReadID();
}
- db.Files.Clear();
-
if (type == NID::kFilesInfo)
{
const CNum numFiles = ReadNum();
- db.Files.ClearAndSetSize(numFiles);
- /*
- db.Files.Reserve(numFiles);
- CNum i;
- for (i = 0; i < numFiles; i++)
- db.Files.Add(CFileItem());
- */
db.ArcInfo.FileInfoPopIDs.Add(NID::kSize);
// if (!db.PackSizes.IsEmpty())
@@ -1169,7 +1278,6 @@ HRESULT CInArchive::ReadHeader(
db.ArcInfo.FileInfoPopIDs.Add(NID::kCRC);
CBoolVector emptyStreamVector;
- BoolVector_Fill_False(emptyStreamVector, (unsigned)numFiles);
CBoolVector emptyFileVector;
CBoolVector antiFileVector;
CNum numEmptyStreams = 0;
@@ -1179,7 +1287,7 @@ HRESULT CInArchive::ReadHeader(
const UInt64 type2 = ReadID();
if (type2 == NID::kEnd)
break;
- UInt64 size = ReadNumber();
+ const UInt64 size = ReadNumber();
if (size > _inByteBack->GetRem())
ThrowIncorrect();
CStreamSwitch switchProp;
@@ -1194,16 +1302,16 @@ HRESULT CInArchive::ReadHeader(
{
CStreamSwitch streamSwitch;
streamSwitch.Set(this, &dataVector);
- size_t rem = _inByteBack->GetRem();
+ const size_t rem = _inByteBack->GetRem();
db.NamesBuf.Alloc(rem);
ReadBytes(db.NamesBuf, rem);
- db.NameOffsets.Alloc(db.Files.Size() + 1);
+ db.NameOffsets.Alloc(numFiles + 1);
size_t pos = 0;
unsigned i;
- for (i = 0; i < db.Files.Size(); 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)
@@ -1216,36 +1324,31 @@ HRESULT CInArchive::ReadHeader(
ThereIsHeaderError = true;
break;
}
+
case NID::kWinAttrib:
{
- CBoolVector boolVector;
- ReadBoolVector2(db.Files.Size(), boolVector);
+ ReadBoolVector2(numFiles, db.Attrib.Defs);
CStreamSwitch streamSwitch;
streamSwitch.Set(this, &dataVector);
- for (CNum i = 0; i < numFiles; i++)
- {
- CFileItem &file = db.Files[i];
- file.AttribDefined = boolVector[i];
- if (file.AttribDefined)
- file.Attrib = ReadUInt32();
- }
+ Read_UInt32_Vector(db.Attrib);
break;
}
+
/*
case NID::kIsAux:
{
- ReadBoolVector(db.Files.Size(), db.IsAux);
+ ReadBoolVector(numFiles, db.IsAux);
break;
}
case NID::kParent:
{
db.IsTree = true;
// CBoolVector boolVector;
- // ReadBoolVector2(db.Files.Size(), boolVector);
+ // ReadBoolVector2(numFiles, boolVector);
// CStreamSwitch streamSwitch;
// streamSwitch.Set(this, &dataVector);
CBoolVector boolVector;
- ReadBoolVector2(db.Files.Size(), boolVector);
+ ReadBoolVector2(numFiles, boolVector);
db.ThereAreAltStreams = false;
for (i = 0; i < numFiles; i++)
@@ -1264,14 +1367,9 @@ HRESULT CInArchive::ReadHeader(
case NID::kEmptyStream:
{
ReadBoolVector(numFiles, emptyStreamVector);
- numEmptyStreams = 0;
- for (CNum i = 0; i < (CNum)emptyStreamVector.Size(); i++)
- if (emptyStreamVector[i])
- numEmptyStreams++;
-
- BoolVector_Fill_False(emptyFileVector, numEmptyStreams);
- BoolVector_Fill_False(antiFileVector, numEmptyStreams);
-
+ numEmptyStreams = BoolVector_CountSum(emptyStreamVector);
+ emptyFileVector.Clear();
+ antiFileVector.Clear();
break;
}
case NID::kEmptyFile: ReadBoolVector(numEmptyStreams, emptyFileVector); break;
@@ -1314,7 +1412,7 @@ HRESULT CInArchive::ReadHeader(
ReadBytes(db.SecureBuf + offset, db.SecureOffsets[i + 1] - offset);
}
db.SecureIDs.Clear();
- for (unsigned i = 0; i < db.Files.Size(); i++)
+ for (unsigned i = 0; i < numFiles; i++)
{
db.SecureIDs.Add(ReadNum());
// db.SecureIDs.Add(ReadUInt32());
@@ -1359,22 +1457,21 @@ HRESULT CInArchive::ReadHeader(
CNum emptyFileIndex = 0;
CNum sizeIndex = 0;
- CNum numAntiItems = 0;
+ const CNum numAntiItems = BoolVector_CountSum(antiFileVector);
- CNum i;
+ if (numAntiItems != 0)
+ db.IsAnti.ClearAndSetSize(numFiles);
- for (i = 0; i < numEmptyStreams; i++)
- if (antiFileVector[i])
- numAntiItems++;
+ db.Files.ClearAndSetSize(numFiles);
- for (i = 0; i < numFiles; i++)
+ for (CNum i = 0; i < numFiles; i++)
{
CFileItem &file = db.Files[i];
bool isAnti;
- file.HasStream = !emptyStreamVector[i];
file.Crc = 0;
- if (file.HasStream)
+ if (!BoolVector_Item_IsValidAndTrue(emptyStreamVector, i))
{
+ file.HasStream = true;
file.IsDir = false;
isAnti = false;
file.Size = unpackSizes[sizeIndex];
@@ -1385,26 +1482,31 @@ HRESULT CInArchive::ReadHeader(
}
else
{
- file.IsDir = !emptyFileVector[emptyFileIndex];
- isAnti = antiFileVector[emptyFileIndex];
+ file.HasStream = false;
+ file.IsDir = !BoolVector_Item_IsValidAndTrue(emptyFileVector, emptyFileIndex);
+ isAnti = BoolVector_Item_IsValidAndTrue(antiFileVector, emptyFileIndex);
emptyFileIndex++;
file.Size = 0;
file.CrcDefined = false;
}
if (numAntiItems != 0)
- db.IsAnti.Add(isAnti);
+ db.IsAnti[i] = isAnti;
}
+
}
+
db.FillLinks();
- /*
- if (type != NID::kEnd)
- ThrowIncorrect();
- if (_inByteBack->GetRem() != 0)
- ThrowIncorrect();
- */
+
+ if (type != NID::kEnd || _inByteBack->GetRem() != 0)
+ {
+ db.UnsupportedFeatureWarning = true;
+ // ThrowIncorrect();
+ }
+
return S_OK;
}
+
void CDbEx::FillLinks()
{
FolderStartFileIndex.Alloc(NumFolders);
@@ -1416,7 +1518,7 @@ void CDbEx::FillLinks()
for (i = 0; i < Files.Size(); i++)
{
- bool emptyStream = !Files[i].HasStream;
+ const bool emptyStream = !Files[i].HasStream;
if (indexInFolder == 0)
{
if (emptyStream)
@@ -1447,29 +1549,33 @@ void CDbEx::FillLinks()
}
if (indexInFolder != 0)
+ {
folderIndex++;
- /*
- if (indexInFolder != 0)
- ThrowIncorrect();
- */
+ // 18.06
+ ThereIsHeaderError = true;
+ // ThrowIncorrect();
+ }
for (;;)
{
if (folderIndex >= NumFolders)
return;
FolderStartFileIndex[folderIndex] = i;
- /*
if (NumUnpackStreamsVector[folderIndex] != 0)
- ThrowIncorrect();;
- */
+ {
+ // 18.06
+ ThereIsHeaderError = true;
+ // ThrowIncorrect();
+ }
folderIndex++;
}
}
+
HRESULT CInArchive::ReadDatabase2(
DECL_EXTERNAL_CODECS_LOC_VARS
CDbEx &db
- _7Z_DECODER_CRYPRO_VARS_DECL
+ Z7_7Z_DECODER_CRYPRO_VARS_DECL
)
{
db.Clear();
@@ -1489,22 +1595,22 @@ HRESULT CInArchive::ReadDatabase2(
UInt32 nextHeaderCRC = Get32(_header + 28);
#ifdef FORMAT_7Z_RECOVERY
- UInt32 crcFromArc = Get32(_header + 8);
+ const UInt32 crcFromArc = Get32(_header + 8);
if (crcFromArc == 0 && nextHeaderOffset == 0 && nextHeaderSize == 0 && nextHeaderCRC == 0)
{
UInt64 cur, fileSize;
- RINOK(_stream->Seek(0, STREAM_SEEK_CUR, &cur));
+ RINOK(InStream_GetPos(_stream, cur))
const unsigned kCheckSize = 512;
Byte buf[kCheckSize];
- RINOK(_stream->Seek(0, STREAM_SEEK_END, &fileSize));
- UInt64 rem = fileSize - cur;
+ RINOK(InStream_GetSize_SeekToEnd(_stream, fileSize))
+ 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(ReadStream_FALSE(_stream, buf, (size_t)checkSize));
+ RINOK(InStream_SeekSet(_stream, fileSize - checkSize))
+ RINOK(ReadStream_FALSE(_stream, buf, (size_t)checkSize))
if (buf[checkSize - 1] != 0)
return S_FALSE;
@@ -1512,8 +1618,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;
@@ -1521,7 +1627,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(InStream_SeekSet(_stream, cur))
db.StartHeaderWasRecovered = true;
}
else
@@ -1538,32 +1644,39 @@ 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;
+ const size_t nextHeaderSize_t = (size_t)nextHeaderSize;
if (nextHeaderSize_t != nextHeaderSize)
return E_OUTOFMEMORY;
CByteBuffer buffer2(nextHeaderSize_t);
- RINOK(ReadStream_FALSE(_stream, buffer2, nextHeaderSize_t));
+ RINOK(ReadStream_FALSE(_stream, buffer2, nextHeaderSize_t))
if (CrcCalc(buffer2, nextHeaderSize_t) != nextHeaderCRC)
ThrowIncorrect();
@@ -1576,19 +1689,19 @@ HRESULT CInArchive::ReadDatabase2(
CObjectVector<CByteBuffer> dataVector;
- UInt64 type = ReadID();
+ const UInt64 type = ReadID();
if (type != NID::kHeader)
{
if (type != NID::kEncodedHeader)
ThrowIncorrect();
- HRESULT result = ReadAndDecodePackedStreams(
+ const HRESULT result = ReadAndDecodePackedStreams(
EXTERNAL_CODECS_LOC_VARS
db.ArcInfo.StartPositionAfterHeader,
db.ArcInfo.DataStartPosition2,
dataVector
- _7Z_DECODER_CRYPRO_VARS
+ Z7_7Z_DECODER_CRYPRO_VARS
);
- RINOK(result);
+ RINOK(result)
if (dataVector.Size() == 0)
return S_OK;
if (dataVector.Size() > 1)
@@ -1606,21 +1719,22 @@ HRESULT CInArchive::ReadDatabase2(
return ReadHeader(
EXTERNAL_CODECS_LOC_VARS
db
- _7Z_DECODER_CRYPRO_VARS
+ Z7_7Z_DECODER_CRYPRO_VARS
);
}
+
HRESULT CInArchive::ReadDatabase(
DECL_EXTERNAL_CODECS_LOC_VARS
CDbEx &db
- _7Z_DECODER_CRYPRO_VARS_DECL
+ Z7_7Z_DECODER_CRYPRO_VARS_DECL
)
{
try
{
- HRESULT res = ReadDatabase2(
+ const HRESULT res = ReadDatabase2(
EXTERNAL_CODECS_LOC_VARS db
- _7Z_DECODER_CRYPRO_VARS
+ Z7_7Z_DECODER_CRYPRO_VARS
);
if (ThereIsHeaderError)
db.ThereIsHeaderError = true;