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/Rar/RarIn.cpp')
-rwxr-xr-xCPP/7zip/Archive/Rar/RarIn.cpp199
1 files changed, 77 insertions, 122 deletions
diff --git a/CPP/7zip/Archive/Rar/RarIn.cpp b/CPP/7zip/Archive/Rar/RarIn.cpp
index 7d64c6fd..e4c23752 100755
--- a/CPP/7zip/Archive/Rar/RarIn.cpp
+++ b/CPP/7zip/Archive/Rar/RarIn.cpp
@@ -3,6 +3,7 @@
#include "StdAfx.h"
#include "../../../../C/7zCrc.h"
+#include "../../../../C/CpuArch.h"
#include "Common/StringConvert.h"
#include "Common/UTFConvert.h"
@@ -14,9 +15,16 @@
#include "RarIn.h"
+#define Get16(p) GetUi16(p)
+#define Get32(p) GetUi32(p)
+#define Get64(p) GetUi64(p)
+
namespace NArchive {
namespace NRar {
-
+
+static const char *k_UnexpectedEnd = "Unexpected end of archive";
+static const char *k_DecryptionError = "Decryption Error";
+
void CInArchive::ThrowExceptionWithCode(
CInArchiveException::CCauseType cause)
{
@@ -42,140 +50,80 @@ void CInArchive::Close()
m_Stream.Release();
}
-
-static inline bool TestMarkerCandidate(const void *aTestBytes)
-{
- for (UInt32 i = 0; i < NHeader::kMarkerSize; i++)
- if (((const Byte *)aTestBytes)[i] != NHeader::kMarker[i])
- return false;
- return true;
-}
-
-HRESULT CInArchive::FindAndReadMarker(IInStream *stream, const UInt64 *searchHeaderSizeLimit)
-{
- RINOK(FindSignatureInStream(stream,
- NHeader::kMarker, NHeader::kMarkerSize,
- searchHeaderSizeLimit, m_ArchiveStartPosition));
- m_Stream = stream;
- m_Position = m_ArchiveStartPosition + NHeader::kMarkerSize;
- return m_Stream->Seek(m_Position, STREAM_SEEK_SET, NULL);
-}
-
-void CInArchive::ThrowUnexpectedEndOfArchiveException()
-{
- ThrowExceptionWithCode(CInArchiveException::kUnexpectedEndOfArchive);
-}
-
-bool CInArchive::ReadBytesAndTestSize(void *data, UInt32 size)
+HRESULT CInArchive::ReadBytesSpec(void *data, size_t *resSize)
{
if (m_CryptoMode)
{
+ size_t size = *resSize;
+ *resSize = 0;
const Byte *bufData = m_DecryptedDataAligned;
UInt32 bufSize = m_DecryptedDataSize;
- UInt32 i;
+ size_t i;
for (i = 0; i < size && m_CryptoPos < bufSize; i++)
((Byte *)data)[i] = bufData[m_CryptoPos++];
- return (i == size);
+ *resSize = i;
+ return S_OK;
}
- return (ReadStream_FALSE(m_Stream, data, size) == S_OK);
-}
-
-void CInArchive::ReadBytesAndTestResult(void *data, UInt32 size)
-{
- if(!ReadBytesAndTestSize(data,size))
- ThrowUnexpectedEndOfArchiveException();
-}
-
-HRESULT CInArchive::ReadBytes(void *data, UInt32 size, UInt32 *processedSize)
-{
- size_t realProcessedSize = size;
- HRESULT result = ReadStream(m_Stream, data, &realProcessedSize);
- if (processedSize != NULL)
- *processedSize = (UInt32)realProcessedSize;
- AddToSeekValue(realProcessedSize);
- return result;
-}
-
-static UInt32 CrcUpdateUInt16(UInt32 crc, UInt16 v)
-{
- crc = CRC_UPDATE_BYTE(crc, (Byte)(v & 0xFF));
- crc = CRC_UPDATE_BYTE(crc, (Byte)((v >> 8) & 0xFF));
- return crc;
+ return ReadStream(m_Stream, data, resSize);
}
-static UInt32 CrcUpdateUInt32(UInt32 crc, UInt32 v)
+bool CInArchive::ReadBytesAndTestSize(void *data, UInt32 size)
{
- crc = CRC_UPDATE_BYTE(crc, (Byte)(v & 0xFF));
- crc = CRC_UPDATE_BYTE(crc, (Byte)((v >> 8) & 0xFF));
- crc = CRC_UPDATE_BYTE(crc, (Byte)((v >> 16) & 0xFF));
- crc = CRC_UPDATE_BYTE(crc, (Byte)((v >> 24) & 0xFF));
- return crc;
+ size_t processed = size;
+ if (ReadBytesSpec(data, &processed) != S_OK)
+ return false;
+ return processed == size;
}
-
HRESULT CInArchive::Open2(IInStream *stream, const UInt64 *searchHeaderSizeLimit)
{
m_CryptoMode = false;
RINOK(stream->Seek(0, STREAM_SEEK_SET, &m_StreamStartPosition));
m_Position = m_StreamStartPosition;
- RINOK(FindAndReadMarker(stream, searchHeaderSizeLimit));
+ UInt64 arcStartPos;
+ RINOK(FindSignatureInStream(stream, NHeader::kMarker, NHeader::kMarkerSize,
+ searchHeaderSizeLimit, arcStartPos));
+ m_Position = arcStartPos + NHeader::kMarkerSize;
+ RINOK(stream->Seek(m_Position, STREAM_SEEK_SET, NULL));
+ Byte buf[NHeader::NArchive::kArchiveHeaderSize + 1];
- Byte buf[NHeader::NArchive::kArchiveHeaderSize];
- UInt32 processedSize;
- ReadBytes(buf, sizeof(buf), &processedSize);
- if (processedSize != sizeof(buf))
- return S_FALSE;
- m_CurData = buf;
- m_CurPos = 0;
- m_PosLimit = sizeof(buf);
-
- m_ArchiveHeader.CRC = ReadUInt16();
- m_ArchiveHeader.Type = ReadByte();
- m_ArchiveHeader.Flags = ReadUInt16();
- m_ArchiveHeader.Size = ReadUInt16();
- m_ArchiveHeader.Reserved1 = ReadUInt16();
- m_ArchiveHeader.Reserved2 = ReadUInt32();
- m_ArchiveHeader.EncryptVersion = 0;
-
- UInt32 crc = CRC_INIT_VAL;
- crc = CRC_UPDATE_BYTE(crc, m_ArchiveHeader.Type);
- crc = CrcUpdateUInt16(crc, m_ArchiveHeader.Flags);
- crc = CrcUpdateUInt16(crc, m_ArchiveHeader.Size);
- crc = CrcUpdateUInt16(crc, m_ArchiveHeader.Reserved1);
- crc = CrcUpdateUInt32(crc, m_ArchiveHeader.Reserved2);
-
- if (m_ArchiveHeader.IsThereEncryptVer() && m_ArchiveHeader.Size > NHeader::NArchive::kArchiveHeaderSize)
+ RINOK(ReadStream_FALSE(stream, buf, NHeader::NArchive::kArchiveHeaderSize));
+ AddToSeekValue(NHeader::NArchive::kArchiveHeaderSize);
+
+
+ UInt32 blockSize = Get16(buf + 5);
+
+ _header.EncryptVersion = 0;
+ _header.Flags = Get16(buf + 3);
+
+ UInt32 headerSize = NHeader::NArchive::kArchiveHeaderSize;
+ if (_header.IsThereEncryptVer())
{
- ReadBytes(&m_ArchiveHeader.EncryptVersion, 1, &processedSize);
- if (processedSize != 1)
+ if (blockSize <= headerSize)
return S_FALSE;
- crc = CRC_UPDATE_BYTE(crc, m_ArchiveHeader.EncryptVersion);
+ RINOK(ReadStream_FALSE(stream, buf + NHeader::NArchive::kArchiveHeaderSize, 1));
+ AddToSeekValue(1);
+ _header.EncryptVersion = buf[NHeader::NArchive::kArchiveHeaderSize];
+ headerSize += 1;
}
-
- if(m_ArchiveHeader.CRC != (CRC_GET_DIGEST(crc) & 0xFFFF))
- ThrowExceptionWithCode(CInArchiveException::kArchiveHeaderCRCError);
- if (m_ArchiveHeader.Type != NHeader::NBlockType::kArchiveHeader)
+ if (blockSize < headerSize ||
+ buf[2] != NHeader::NBlockType::kArchiveHeader ||
+ (UInt32)Get16(buf) != (CrcCalc(buf + 2, headerSize - 2) & 0xFFFF))
return S_FALSE;
- m_ArchiveCommentPosition = m_Position;
- m_SeekOnArchiveComment = true;
- return S_OK;
-}
-void CInArchive::SkipArchiveComment()
-{
- if (!m_SeekOnArchiveComment)
- return;
- AddToSeekValue(m_ArchiveHeader.Size - m_ArchiveHeader.GetBaseSize());
- m_SeekOnArchiveComment = false;
+ size_t commentSize = blockSize - headerSize;
+ _comment.SetCapacity(commentSize);
+ RINOK(ReadStream_FALSE(stream, _comment, commentSize));
+ AddToSeekValue(commentSize);
+ m_Stream = stream;
+ _header.StartPosition = arcStartPos;
+ return S_OK;
}
void CInArchive::GetArchiveInfo(CInArchiveInfo &archiveInfo) const
{
- archiveInfo.StartPosition = m_ArchiveStartPosition;
- archiveInfo.Flags = m_ArchiveHeader.Flags;
- archiveInfo.CommentPosition = m_ArchiveCommentPosition;
- archiveInfo.CommentSize = (UInt16)(m_ArchiveHeader.Size - NHeader::NArchive::kArchiveHeaderSize);
+ archiveInfo = _header;
}
static void DecodeUnicodeFileName(const char *name, const Byte *encName,
@@ -375,26 +323,21 @@ void CInArchive::AddToSeekValue(UInt64 addValue)
HRESULT CInArchive::GetNextItem(CItemEx &item, ICryptoGetTextPassword *getTextPassword, bool &decryptionError, AString &errorMessage)
{
decryptionError = false;
- if (m_SeekOnArchiveComment)
- SkipArchiveComment();
for (;;)
{
- if (!SeekInArchive(m_Position))
- return S_FALSE;
- if (!m_CryptoMode && (m_ArchiveHeader.Flags &
+ SeekInArchive(m_Position);
+ if (!m_CryptoMode && (_header.Flags &
NHeader::NArchive::kBlockHeadersAreEncrypted) != 0)
{
m_CryptoMode = false;
if (getTextPassword == 0)
return S_FALSE;
- if(!SeekInArchive(m_Position))
- return S_FALSE;
if (!m_RarAES)
{
m_RarAESSpec = new NCrypto::NRar29::CDecoder;
m_RarAES = m_RarAESSpec;
}
- m_RarAESSpec->SetRar350Mode(m_ArchiveHeader.IsEncryptOld());
+ m_RarAESSpec->SetRar350Mode(_header.IsEncryptOld());
// Salt
const UInt32 kSaltSize = 8;
@@ -438,9 +381,12 @@ HRESULT CInArchive::GetNextItem(CItemEx &item, ICryptoGetTextPassword *getTextPa
}
m_FileHeaderData.EnsureCapacity(7);
- if (!ReadBytesAndTestSize((Byte *)m_FileHeaderData, 7))
+ size_t processed = 7;
+ RINOK(ReadBytesSpec((Byte *)m_FileHeaderData, &processed));
+ if (processed != 7)
{
- errorMessage = "Unexpected end of archive";
+ if (processed != 0)
+ errorMessage = k_UnexpectedEnd;
return S_FALSE;
}
@@ -463,7 +409,12 @@ HRESULT CInArchive::GetNextItem(CItemEx &item, ICryptoGetTextPassword *getTextPa
m_FileHeaderData.EnsureCapacity(m_BlockHeader.HeadSize);
m_CurData = (Byte *)m_FileHeaderData;
m_PosLimit = m_BlockHeader.HeadSize;
- ReadBytesAndTestResult(m_CurData + m_CurPos, m_BlockHeader.HeadSize - 7);
+ if (!ReadBytesAndTestSize(m_CurData + m_CurPos, m_BlockHeader.HeadSize - 7))
+ {
+ errorMessage = k_UnexpectedEnd;
+ return S_FALSE;
+ }
+
ReadHeaderReal(item);
if ((CrcCalc(m_CurData + 2,
m_BlockHeader.HeadSize - item.CommentSize - 2) & 0xFFFF) != m_BlockHeader.CRC)
@@ -478,19 +429,25 @@ HRESULT CInArchive::GetNextItem(CItemEx &item, ICryptoGetTextPassword *getTextPa
if (m_CryptoMode && m_BlockHeader.HeadSize > (1 << 10))
{
decryptionError = true;
+ errorMessage = k_DecryptionError;
return S_FALSE;
}
if ((m_BlockHeader.Flags & NHeader::NBlock::kLongBlock) != 0)
{
m_FileHeaderData.EnsureCapacity(7 + 4);
m_CurData = (Byte *)m_FileHeaderData;
- ReadBytesAndTestResult(m_CurData + m_CurPos, 4); // test it
+ if (!ReadBytesAndTestSize(m_CurData + m_CurPos, 4))
+ {
+ errorMessage = k_UnexpectedEnd;
+ return S_FALSE;
+ }
m_PosLimit = 7 + 4;
UInt32 dataSize = ReadUInt32();
AddToSeekValue(dataSize);
if (m_CryptoMode && dataSize > (1 << 27))
{
decryptionError = true;
+ errorMessage = k_DecryptionError;
return S_FALSE;
}
m_CryptoPos = m_BlockHeader.HeadSize;
@@ -503,11 +460,9 @@ HRESULT CInArchive::GetNextItem(CItemEx &item, ICryptoGetTextPassword *getTextPa
}
}
-bool CInArchive::SeekInArchive(UInt64 position)
+void CInArchive::SeekInArchive(UInt64 position)
{
- UInt64 newPosition;
- m_Stream->Seek(position, STREAM_SEEK_SET, &newPosition);
- return newPosition == position;
+ m_Stream->Seek(position, STREAM_SEEK_SET, NULL);
}
ISequentialInStream* CInArchive::CreateLimitedStream(UInt64 position, UInt64 size)