diff options
Diffstat (limited to 'CPP/7zip/Archive/Cab/CabBlockInStream.cpp')
-rw-r--r--[-rwxr-xr-x] | CPP/7zip/Archive/Cab/CabBlockInStream.cpp | 191 |
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; } }} |