xref: /aosp_15_r20/external/lzma/CPP/7zip/Compress/ZlibDecoder.cpp (revision f6dc9357d832569d4d1f5d24eacdb3935a1ae8e6)
1 // ZlibDecoder.cpp
2 
3 #include "StdAfx.h"
4 
5 #include "../../../C/CpuArch.h"
6 
7 #include "../Common/StreamUtils.h"
8 
9 #include "ZlibDecoder.h"
10 
11 namespace NCompress {
12 namespace NZlib {
13 
14 #define DEFLATE_TRY_BEGIN try {
15 #define DEFLATE_TRY_END } catch(...) { return S_FALSE; }
16 
17 #define ADLER_MOD 65521
18 #define ADLER_LOOP_MAX 5550
19 
20 UInt32 Adler32_Update(UInt32 adler, const Byte *data, size_t size);
Adler32_Update(UInt32 adler,const Byte * data,size_t size)21 UInt32 Adler32_Update(UInt32 adler, const Byte *data, size_t size)
22 {
23   if (size == 0)
24     return adler;
25   UInt32 a = adler & 0xffff;
26   UInt32 b = adler >> 16;
27   do
28   {
29     size_t cur = size;
30     if (cur > ADLER_LOOP_MAX)
31         cur = ADLER_LOOP_MAX;
32     size -= cur;
33     const Byte *lim = data + cur;
34     if (cur >= 4)
35     {
36       lim -= 4 - 1;
37       do
38       {
39         a += data[0];  b += a;
40         a += data[1];  b += a;
41         a += data[2];  b += a;
42         a += data[3];  b += a;
43         data += 4;
44       }
45       while (data < lim);
46       lim += 4 - 1;
47     }
48     if (data != lim) { a += *data++;  b += a;
49     if (data != lim) { a += *data++;  b += a;
50     if (data != lim) { a += *data++;  b += a; }}}
51     a %= ADLER_MOD;
52     b %= ADLER_MOD;
53   }
54   while (size);
55   return (b << 16) + a;
56 }
57 
Z7_COM7F_IMF(COutStreamWithAdler::Write (const void * data,UInt32 size,UInt32 * processedSize))58 Z7_COM7F_IMF(COutStreamWithAdler::Write(const void *data, UInt32 size, UInt32 *processedSize))
59 {
60   HRESULT result = S_OK;
61   if (_stream)
62     result = _stream->Write(data, size, &size);
63   _adler = Adler32_Update(_adler, (const Byte *)data, size);
64   _size += size;
65   if (processedSize)
66     *processedSize = size;
67   return result;
68 }
69 
Z7_COM7F_IMF(CDecoder::Code (ISequentialInStream * inStream,ISequentialOutStream * outStream,const UInt64 * inSize,const UInt64 * outSize,ICompressProgressInfo * progress))70 Z7_COM7F_IMF(CDecoder::Code(ISequentialInStream *inStream, ISequentialOutStream *outStream,
71     const UInt64 *inSize, const UInt64 *outSize, ICompressProgressInfo *progress))
72 {
73   DEFLATE_TRY_BEGIN
74   _inputProcessedSize_Additional = 0;
75   AdlerStream.Create_if_Empty();
76   DeflateDecoder.Create_if_Empty();
77   DeflateDecoder->Set_NeedFinishInput(true);
78 
79   if (inSize && *inSize < 2)
80     return S_FALSE;
81   {
82     Byte buf[2];
83     RINOK(ReadStream_FALSE(inStream, buf, 2))
84     if (!IsZlib(buf))
85       return S_FALSE;
86   }
87   _inputProcessedSize_Additional = 2;
88   AdlerStream->SetStream(outStream);
89   AdlerStream->Init();
90   // NDeflate::NDecoder::Code() ignores inSize
91   /*
92   UInt64 inSize2 = 0;
93   if (inSize)
94     inSize2 = *inSize - 2;
95   */
96   const HRESULT res = DeflateDecoder.Interface()->Code(inStream, AdlerStream,
97       /* inSize ? &inSize2 : */ NULL, outSize, progress);
98   AdlerStream->ReleaseStream();
99 
100   if (res == S_OK)
101   {
102     UInt32 footer32[1];
103     UInt32 processedSize;
104     RINOK(DeflateDecoder->ReadUnusedFromInBuf(footer32, 4, &processedSize))
105     if (processedSize != 4)
106     {
107       size_t processedSize2 = 4 - processedSize;
108       RINOK(ReadStream(inStream, (Byte *)(void *)footer32 + processedSize, &processedSize2))
109       _inputProcessedSize_Additional += (Int32)processedSize2;
110       processedSize += (UInt32)processedSize2;
111     }
112 
113     if (processedSize == 4)
114     {
115       const UInt32 adler = GetBe32a(footer32);
116       if (adler != AdlerStream->GetAdler())
117         return S_FALSE; // adler error
118     }
119     else if (!IsAdlerOptional)
120       return S_FALSE; // unexpeced end of stream (can't read adler)
121     else
122     {
123       // IsAdlerOptional == true
124       if (processedSize != 0)
125       {
126          // we exclude adler bytes from processed size:
127         _inputProcessedSize_Additional -= (Int32)processedSize;
128         return S_FALSE;
129       }
130     }
131   }
132   return res;
133   DEFLATE_TRY_END
134 }
135 
136 }}
137