Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/kornelski/7z.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'CPP/7zip/Archive/Cab/CabBlockInStream.cpp')
-rw-r--r--[-rwxr-xr-x]CPP/7zip/Archive/Cab/CabBlockInStream.cpp191
1 files changed, 45 insertions, 146 deletions
diff --git a/CPP/7zip/Archive/Cab/CabBlockInStream.cpp b/CPP/7zip/Archive/Cab/CabBlockInStream.cpp
index 12c73eb5..cebec610 100755..100644
--- a/CPP/7zip/Archive/Cab/CabBlockInStream.cpp
+++ b/CPP/7zip/Archive/Cab/CabBlockInStream.cpp
@@ -3,8 +3,7 @@
#include "StdAfx.h"
#include "../../../../C/Alloc.h"
-
-#include "Common/Defs.h"
+#include "../../../../C/CpuArch.h"
#include "../../Common/StreamUtils.h"
@@ -17,173 +16,73 @@ static const UInt32 kBlockSize = (1 << 16);
bool CCabBlockInStream::Create()
{
- if (!_buffer)
- _buffer = (Byte *)::MyAlloc(kBlockSize);
- return (_buffer != 0);
+ if (!_buf)
+ _buf = (Byte *)::MyAlloc(kBlockSize);
+ return _buf != 0;
}
CCabBlockInStream::~CCabBlockInStream()
{
- MyFree(_buffer);
+ ::MyFree(_buf);
}
-class CCheckSum2
-{
- UInt32 m_Value;
- int m_Pos;
- Byte m_Hist[4];
-public:
- CCheckSum2(): m_Value(0){};
- void Init() { m_Value = 0; m_Pos = 0; }
- void Update(const void *data, UInt32 size);
- void FinishDataUpdate()
- {
- for (int i = 0; i < m_Pos; i++)
- m_Value ^= ((UInt32)(m_Hist[i])) << (8 * (m_Pos - i - 1));
- }
- void UpdateUInt32(UInt32 v) { m_Value ^= v; }
- UInt32 GetResult() const { return m_Value; }
-};
-
-void CCheckSum2::Update(const void *data, UInt32 size)
+static UInt32 CheckSum(const Byte *p, UInt32 size)
{
- UInt32 checkSum = m_Value;
- const Byte *dataPointer = (const Byte *)data;
-
- while (size != 0 && m_Pos != 0)
- {
- m_Hist[m_Pos] = *dataPointer++;
- m_Pos = (m_Pos + 1) & 3;
- size--;
- if (m_Pos == 0)
- for (int i = 0; i < 4; i++)
- checkSum ^= ((UInt32)m_Hist[i]) << (8 * i);
- }
-
- int numWords = size / 4;
-
- while (numWords-- != 0)
+ UInt32 sum = 0;
+ for (UInt32 i = size >> 2; i != 0; i--)
{
- UInt32 temp = *dataPointer++;
- temp |= ((UInt32)(*dataPointer++)) << 8;
- temp |= ((UInt32)(*dataPointer++)) << 16;
- temp |= ((UInt32)(*dataPointer++)) << 24;
- checkSum ^= temp;
+ sum ^= GetUi32(p);
+ p += 4;
}
- m_Value = checkSum;
-
size &= 3;
-
- while (size != 0)
- {
- m_Hist[m_Pos] = *dataPointer++;
- m_Pos = (m_Pos + 1) & 3;
- size--;
- }
+ if (size > 2) sum ^= (UInt32)(*p++) << 16;
+ if (size > 1) sum ^= (UInt32)(*p++) << 8;
+ if (size > 0) sum ^= (UInt32)(*p++);
+ return sum;
}
-static const UInt32 kDataBlockHeaderSize = 8;
-
-class CTempCabInBuffer2
+HRESULT CCabBlockInStream::PreRead(ISequentialInStream *stream, UInt32 &packSize, UInt32 &unpackSize)
{
-public:
- Byte Buffer[kDataBlockHeaderSize];
- UInt32 Pos;
- Byte ReadByte()
- {
- return Buffer[Pos++];
- }
- UInt32 ReadUInt32()
- {
- UInt32 value = 0;
- for (int i = 0; i < 4; i++)
- value |= (((UInt32)ReadByte()) << (8 * i));
- return value;
- }
- UInt16 ReadUInt16()
- {
- UInt16 value = 0;
- for (int i = 0; i < 2; i++)
- value |= (((UInt16)ReadByte()) << (8 * i));
- return value;
- }
-};
-
-HRESULT CCabBlockInStream::PreRead(UInt32 &packSize, UInt32 &unpackSize)
-{
- CTempCabInBuffer2 inBuffer;
- inBuffer.Pos = 0;
- RINOK(ReadStream_FALSE(_stream, inBuffer.Buffer, kDataBlockHeaderSize))
-
- UInt32 checkSum = inBuffer.ReadUInt32();
- packSize = inBuffer.ReadUInt16();
- unpackSize = inBuffer.ReadUInt16();
- if (ReservedSize != 0)
- {
- RINOK(ReadStream_FALSE(_stream, _buffer, ReservedSize));
- }
- _pos = 0;
- CCheckSum2 checkSumCalc;
- checkSumCalc.Init();
- UInt32 packSize2 = packSize;
- if (MsZip && _size == 0)
+ const UInt32 kHeaderSize = 8;
+ const UInt32 kReservedMax = 256;
+ Byte header[kHeaderSize + kReservedMax];
+ RINOK(ReadStream_FALSE(stream, header, kHeaderSize + ReservedSize))
+ packSize = GetUi16(header + 4);
+ unpackSize = GetUi16(header + 6);
+ if (packSize > kBlockSize - _size)
+ return S_FALSE;
+ RINOK(ReadStream_FALSE(stream, _buf + _size, packSize));
+
+ if (MsZip)
{
- if (packSize < 2)
- return S_FALSE; // bad block;
- Byte sig[2];
- RINOK(ReadStream_FALSE(_stream, sig, 2));
- if (sig[0] != 0x43 || sig[1] != 0x4B)
+ if (_size == 0)
+ {
+ if (packSize < 2 || _buf[0] != 0x43 || _buf[1] != 0x4B)
+ return S_FALSE;
+ _pos = 2;
+ }
+ if (_size + packSize > ((UInt32)1 << 15) + 12) /* v9.31 fix. MSZIP specification */
return S_FALSE;
- packSize2 -= 2;
- checkSumCalc.Update(sig, 2);
}
- if (kBlockSize - _size < packSize2)
- return S_FALSE;
-
- UInt32 curSize = packSize2;
- if (curSize != 0)
- {
- size_t processedSizeLoc = curSize;
- RINOK(ReadStream(_stream, _buffer + _size, &processedSizeLoc));
- checkSumCalc.Update(_buffer + _size, (UInt32)processedSizeLoc);
- _size += (UInt32)processedSizeLoc;
- if (processedSizeLoc != curSize)
+ if (GetUi32(header) != 0) // checkSum
+ if (CheckSum(header, kHeaderSize + ReservedSize) != CheckSum(_buf + _size, packSize))
return S_FALSE;
- }
- TotalPackSize = _size;
- checkSumCalc.FinishDataUpdate();
-
- bool dataError;
- if (checkSum == 0)
- dataError = false;
- else
- {
- checkSumCalc.UpdateUInt32(packSize | (((UInt32)unpackSize) << 16));
- dataError = (checkSumCalc.GetResult() != checkSum);
- }
- DataError |= dataError;
- return dataError ? S_FALSE : S_OK;
+ _size += packSize;
+ return S_OK;
}
STDMETHODIMP CCabBlockInStream::Read(void *data, UInt32 size, UInt32 *processedSize)
{
- if (processedSize != 0)
- *processedSize = 0;
- if (size == 0)
- return S_OK;
- if (_size != 0)
- {
- size = MyMin(_size, size);
- memmove(data, _buffer + _pos, size);
- _pos += size;
- _size -= size;
- if (processedSize != 0)
- *processedSize = size;
- return S_OK;
- }
- return S_OK; // no blocks data
+ UInt32 rem = _size - _pos;
+ if (size > rem)
+ size = rem;
+ memcpy(data, _buf + _pos, size);
+ _pos += size;
+ if (processedSize)
+ *processedSize = size;
+ return S_OK;
}
}}