xref: /aosp_15_r20/external/lzma/CPP/7zip/Archive/Cab/CabBlockInStream.cpp (revision f6dc9357d832569d4d1f5d24eacdb3935a1ae8e6)
1 // CabBlockInStream.cpp
2 
3 #include "StdAfx.h"
4 
5 #include "../../../../C/Alloc.h"
6 #include "../../../../C/CpuArch.h"
7 
8 #include "../../Common/StreamUtils.h"
9 
10 #include "CabBlockInStream.h"
11 
12 namespace NArchive {
13 namespace NCab {
14 
15 static const UInt32 kBlockSize = 1 << 16;
16 static const unsigned k_OverReadPadZone_Size = 32;
17 static const unsigned kHeaderSize = 8;
18 static const unsigned kReservedMax = 256;
19 static const unsigned kHeaderOffset = kBlockSize + k_OverReadPadZone_Size;
20 
Create()21 bool CBlockPackData::Create() throw()
22 {
23   if (!_buf)
24     _buf = (Byte *)z7_AlignedAlloc(kBlockSize + k_OverReadPadZone_Size + kHeaderSize + kReservedMax);
25   return _buf != NULL;
26 }
27 
~CBlockPackData()28 CBlockPackData::~CBlockPackData() throw()
29 {
30   z7_AlignedFree(_buf);
31 }
32 
CheckSum(const Byte * p,UInt32 size)33 static UInt32 CheckSum(const Byte *p, UInt32 size) throw()
34 {
35 #ifdef MY_CPU_64BIT
36 
37   UInt64 sum64 = 0;
38   if (size >= 16)
39   {
40     const Byte *lim = p + (size_t)size - 16;
41     do
42     {
43       sum64 ^= GetUi64(p) ^ GetUi64(p + 8);
44       p += 16;
45     }
46     while (p <= lim);
47     size = (UInt32)(lim + 16 - p);
48   }
49   if (size >= 8)
50   {
51     sum64 ^= GetUi64(p);
52     p += 8;
53     size -= 8;
54   }
55 
56   UInt32 sum = (UInt32)(sum64 >> 32) ^ (UInt32)sum64;
57 
58 #else
59 
60   UInt32 sum = 0;
61   if (size >= 16)
62   {
63     const Byte *lim = p + (size_t)size - 16;
64     do
65     {
66       sum ^= GetUi32(p)
67            ^ GetUi32(p + 4)
68            ^ GetUi32(p + 8)
69            ^ GetUi32(p + 12);
70       p += 16;
71     }
72     while (p <= lim);
73     size = (UInt32)(lim + 16 - p);
74   }
75   if (size >= 8)
76   {
77     sum ^= GetUi32(p + 0) ^ GetUi32(p + 4);
78     p += 8;
79     size -= 8;
80   }
81 
82 #endif
83 
84   if (size >= 4)
85   {
86     sum ^= GetUi32(p);
87     p += 4;
88   }
89   if (size &= 3)
90   {
91     if (size >= 2)
92     {
93       if (size > 2)
94         sum ^= (UInt32)(*p++) << 16;
95       sum ^= (UInt32)(*p++) << 8;
96     }
97     sum ^= (UInt32)(*p++);
98   }
99   return sum;
100 }
101 
102 
Read(ISequentialInStream * stream,Byte ReservedSize,UInt32 & packSizeRes,UInt32 & unpackSize)103 HRESULT CBlockPackData::Read(ISequentialInStream *stream, Byte ReservedSize, UInt32 &packSizeRes, UInt32 &unpackSize) throw()
104 {
105   const UInt32 reserved8 = kHeaderSize + ReservedSize;
106   const Byte *header = _buf + kHeaderOffset;
107   RINOK(ReadStream_FALSE(stream, (void *)header, reserved8))
108   unpackSize = GetUi16a(header + 6);
109   const UInt32 packSize = GetUi16a(header + 4);
110   packSizeRes = packSize;
111   if (packSize > kBlockSize - _size)
112     return S_FALSE;
113   RINOK(ReadStream_FALSE(stream, _buf + _size, packSize))
114   memset(_buf + _size + packSize, 0xff, k_OverReadPadZone_Size);
115   if (*(const UInt32 *)(const void *)header != 0) // checkSum
116     if (CheckSum(header, reserved8) != CheckSum(_buf + _size, packSize))
117       return S_FALSE;
118   _size += packSize;
119   return S_OK;
120 }
121 
122 }}
123