1 // DeflateDecoder.cpp
2 
3 #include "StdAfx.h"
4 
5 #include "DeflateDecoder.h"
6 
7 namespace NCompress {
8 namespace NDeflate {
9 namespace NDecoder {
10 
CCoder(bool deflate64Mode)11 CCoder::CCoder(bool deflate64Mode):
12     _deflateNSIS(false),
13     _deflate64Mode(deflate64Mode),
14     _keepHistory(false),
15     _needFinishInput(false),
16     _needInitInStream(true),
17     _outSizeDefined(false),
18     _outStartPos(0),
19     ZlibMode(false) {}
20 
ReadBits(unsigned numBits)21 UInt32 CCoder::ReadBits(unsigned numBits)
22 {
23   return m_InBitStream.ReadBits(numBits);
24 }
25 
ReadAlignedByte()26 Byte CCoder::ReadAlignedByte()
27 {
28   return m_InBitStream.ReadAlignedByte();
29 }
30 
DecodeLevels(Byte * levels,unsigned numSymbols)31 bool CCoder::DecodeLevels(Byte *levels, unsigned numSymbols)
32 {
33   unsigned i = 0;
34 
35   do
36   {
37     UInt32 sym = m_LevelDecoder.Decode(&m_InBitStream);
38     if (sym < kTableDirectLevels)
39       levels[i++] = (Byte)sym;
40     else
41     {
42       if (sym >= kLevelTableSize)
43         return false;
44 
45       unsigned num;
46       unsigned numBits;
47       Byte symbol;
48 
49       if (sym == kTableLevelRepNumber)
50       {
51         if (i == 0)
52           return false;
53         numBits = 2;
54         num = 0;
55         symbol = levels[(size_t)i - 1];
56       }
57       else
58       {
59         sym -= kTableLevel0Number;
60         sym <<= 2;
61         numBits = 3 + (unsigned)sym;
62         num = ((unsigned)sym << 1);
63         symbol = 0;
64       }
65 
66       num += i + 3 + ReadBits(numBits);
67       if (num > numSymbols)
68         return false;
69       do
70         levels[i++] = symbol;
71       while (i < num);
72     }
73   }
74   while (i < numSymbols);
75 
76   return true;
77 }
78 
79 #define RIF(x) { if (!(x)) return false; }
80 
ReadTables(void)81 bool CCoder::ReadTables(void)
82 {
83   m_FinalBlock = (ReadBits(kFinalBlockFieldSize) == NFinalBlockField::kFinalBlock);
84   if (m_InBitStream.ExtraBitsWereRead())
85     return false;
86   UInt32 blockType = ReadBits(kBlockTypeFieldSize);
87   if (blockType > NBlockType::kDynamicHuffman)
88     return false;
89   if (m_InBitStream.ExtraBitsWereRead())
90     return false;
91 
92   if (blockType == NBlockType::kStored)
93   {
94     m_StoredMode = true;
95     m_InBitStream.AlignToByte();
96     m_StoredBlockSize = ReadAligned_UInt16(); // ReadBits(kStoredBlockLengthFieldSize)
97     if (_deflateNSIS)
98       return true;
99     return (m_StoredBlockSize == (UInt16)~ReadAligned_UInt16());
100   }
101 
102   m_StoredMode = false;
103 
104   CLevels levels;
105   if (blockType == NBlockType::kFixedHuffman)
106   {
107     levels.SetFixedLevels();
108     _numDistLevels = _deflate64Mode ? kDistTableSize64 : kDistTableSize32;
109   }
110   else
111   {
112     unsigned numLitLenLevels = ReadBits(kNumLenCodesFieldSize) + kNumLitLenCodesMin;
113     _numDistLevels = ReadBits(kNumDistCodesFieldSize) + kNumDistCodesMin;
114     unsigned numLevelCodes = ReadBits(kNumLevelCodesFieldSize) + kNumLevelCodesMin;
115 
116     if (!_deflate64Mode)
117       if (_numDistLevels > kDistTableSize32)
118         return false;
119 
120     Byte levelLevels[kLevelTableSize];
121     for (unsigned i = 0; i < kLevelTableSize; i++)
122     {
123       unsigned position = kCodeLengthAlphabetOrder[i];
124       if (i < numLevelCodes)
125         levelLevels[position] = (Byte)ReadBits(kLevelFieldSize);
126       else
127         levelLevels[position] = 0;
128     }
129 
130     if (m_InBitStream.ExtraBitsWereRead())
131       return false;
132 
133     RIF(m_LevelDecoder.Build(levelLevels));
134 
135     Byte tmpLevels[kFixedMainTableSize + kFixedDistTableSize];
136     if (!DecodeLevels(tmpLevels, numLitLenLevels + _numDistLevels))
137       return false;
138 
139     if (m_InBitStream.ExtraBitsWereRead())
140       return false;
141 
142     levels.SubClear();
143     memcpy(levels.litLenLevels, tmpLevels, numLitLenLevels);
144     memcpy(levels.distLevels, tmpLevels + numLitLenLevels, _numDistLevels);
145   }
146   RIF(m_MainDecoder.Build(levels.litLenLevels));
147   return m_DistDecoder.Build(levels.distLevels);
148 }
149 
150 
InitInStream(bool needInit)151 HRESULT CCoder::InitInStream(bool needInit)
152 {
153   if (needInit)
154   {
155     // for HDD-Windows:
156     // (1 << 15) - best for reading only prefetch
157     // (1 << 22) - best for real reading / writing
158     if (!m_InBitStream.Create(1 << 20))
159       return E_OUTOFMEMORY;
160     m_InBitStream.Init();
161     _needInitInStream = false;
162   }
163   return S_OK;
164 }
165 
166 
CodeSpec(UInt32 curSize,bool finishInputStream,UInt32 inputProgressLimit)167 HRESULT CCoder::CodeSpec(UInt32 curSize, bool finishInputStream, UInt32 inputProgressLimit)
168 {
169   if (_remainLen == kLenIdFinished)
170     return S_OK;
171 
172   if (_remainLen == kLenIdNeedInit)
173   {
174     if (!_keepHistory)
175       if (!m_OutWindowStream.Create(_deflate64Mode ? kHistorySize64: kHistorySize32))
176         return E_OUTOFMEMORY;
177     RINOK(InitInStream(_needInitInStream));
178     m_OutWindowStream.Init(_keepHistory);
179 
180     m_FinalBlock = false;
181     _remainLen = 0;
182     _needReadTable = true;
183   }
184 
185   while (_remainLen > 0 && curSize > 0)
186   {
187     _remainLen--;
188     Byte b = m_OutWindowStream.GetByte(_rep0);
189     m_OutWindowStream.PutByte(b);
190     curSize--;
191   }
192 
193   UInt64 inputStart = 0;
194   if (inputProgressLimit != 0)
195     inputStart = m_InBitStream.GetProcessedSize();
196 
197   while (curSize > 0 || finishInputStream)
198   {
199     if (m_InBitStream.ExtraBitsWereRead())
200       return S_FALSE;
201 
202     if (_needReadTable)
203     {
204       if (m_FinalBlock)
205       {
206         _remainLen = kLenIdFinished;
207         break;
208       }
209 
210       if (inputProgressLimit != 0)
211         if (m_InBitStream.GetProcessedSize() - inputStart >= inputProgressLimit)
212           return S_OK;
213 
214       if (!ReadTables())
215         return S_FALSE;
216       if (m_InBitStream.ExtraBitsWereRead())
217         return S_FALSE;
218       _needReadTable = false;
219     }
220 
221     if (m_StoredMode)
222     {
223       if (finishInputStream && curSize == 0 && m_StoredBlockSize != 0)
224         return S_FALSE;
225       /* NSIS version contains some bits in bitl bits buffer.
226          So we must read some first bytes via ReadAlignedByte */
227       for (; m_StoredBlockSize > 0 && curSize > 0 && m_InBitStream.ThereAreDataInBitsBuffer(); m_StoredBlockSize--, curSize--)
228         m_OutWindowStream.PutByte(ReadAlignedByte());
229       for (; m_StoredBlockSize > 0 && curSize > 0; m_StoredBlockSize--, curSize--)
230         m_OutWindowStream.PutByte(m_InBitStream.ReadDirectByte());
231       _needReadTable = (m_StoredBlockSize == 0);
232       continue;
233     }
234 
235     while (curSize > 0)
236     {
237       if (m_InBitStream.ExtraBitsWereRead_Fast())
238         return S_FALSE;
239 
240       UInt32 sym = m_MainDecoder.Decode(&m_InBitStream);
241 
242       if (sym < 0x100)
243       {
244         m_OutWindowStream.PutByte((Byte)sym);
245         curSize--;
246         continue;
247       }
248       else if (sym == kSymbolEndOfBlock)
249       {
250         _needReadTable = true;
251         break;
252       }
253       else if (sym < kMainTableSize)
254       {
255         sym -= kSymbolMatch;
256         UInt32 len;
257         {
258           unsigned numBits;
259           if (_deflate64Mode)
260           {
261             len = kLenStart64[sym];
262             numBits = kLenDirectBits64[sym];
263           }
264           else
265           {
266             len = kLenStart32[sym];
267             numBits = kLenDirectBits32[sym];
268           }
269           len += kMatchMinLen + m_InBitStream.ReadBits(numBits);
270         }
271         UInt32 locLen = len;
272         if (locLen > curSize)
273           locLen = (UInt32)curSize;
274         sym = m_DistDecoder.Decode(&m_InBitStream);
275         if (sym >= _numDistLevels)
276           return S_FALSE;
277         sym = kDistStart[sym] + m_InBitStream.ReadBits(kDistDirectBits[sym]);
278         /*
279         if (sym >= 4)
280         {
281           // sym &= 31;
282           const unsigned numDirectBits = (unsigned)(((sym >> 1) - 1));
283           sym = (2 | (sym & 1)) << numDirectBits;
284           sym += m_InBitStream.ReadBits(numDirectBits);
285         }
286         */
287         if (!m_OutWindowStream.CopyBlock(sym, locLen))
288           return S_FALSE;
289         curSize -= locLen;
290         len -= locLen;
291         if (len != 0)
292         {
293           _remainLen = (Int32)len;
294           _rep0 = sym;
295           break;
296         }
297       }
298       else
299         return S_FALSE;
300     }
301 
302     if (finishInputStream && curSize == 0)
303     {
304       if (m_MainDecoder.Decode(&m_InBitStream) != kSymbolEndOfBlock)
305         return S_FALSE;
306       _needReadTable = true;
307     }
308   }
309 
310   if (m_InBitStream.ExtraBitsWereRead())
311     return S_FALSE;
312 
313   return S_OK;
314 }
315 
316 
317 #ifdef _NO_EXCEPTIONS
318 
319 #define DEFLATE_TRY_BEGIN
320 #define DEFLATE_TRY_END(res)
321 
322 #else
323 
324 #define DEFLATE_TRY_BEGIN try {
325 #define DEFLATE_TRY_END(res) } \
326   catch(const CSystemException &e) { res = e.ErrorCode; } \
327   catch(...) { res = S_FALSE; }
328 
329   // catch(const CInBufferException &e)  { res = e.ErrorCode; }
330   // catch(const CLzOutWindowException &e)  { res = e.ErrorCode; }
331 
332 #endif
333 
334 
CodeReal(ISequentialOutStream * outStream,ICompressProgressInfo * progress)335 HRESULT CCoder::CodeReal(ISequentialOutStream *outStream, ICompressProgressInfo *progress)
336 {
337   HRESULT res;
338 
339   DEFLATE_TRY_BEGIN
340 
341   m_OutWindowStream.SetStream(outStream);
342   CCoderReleaser flusher(this);
343 
344   const UInt64 inStart = _needInitInStream ? 0 : m_InBitStream.GetProcessedSize();
345 
346   for (;;)
347   {
348     const UInt32 kInputProgressLimit = 1 << 21;
349     UInt32 curSize = 1 << 20;
350     bool finishInputStream = false;
351     if (_outSizeDefined)
352     {
353       const UInt64 rem = _outSize - GetOutProcessedCur();
354       if (curSize >= rem)
355       {
356         curSize = (UInt32)rem;
357         if (ZlibMode || _needFinishInput)
358           finishInputStream = true;
359       }
360     }
361     if (!finishInputStream && curSize == 0)
362       break;
363 
364     RINOK(CodeSpec(curSize, finishInputStream, progress ? kInputProgressLimit : 0));
365 
366     if (_remainLen == kLenIdFinished)
367       break;
368 
369     if (progress)
370     {
371       const UInt64 inSize = m_InBitStream.GetProcessedSize() - inStart;
372       const UInt64 nowPos64 = GetOutProcessedCur();
373       RINOK(progress->SetRatioInfo(&inSize, &nowPos64));
374     }
375   }
376 
377   if (_remainLen == kLenIdFinished && ZlibMode)
378   {
379     m_InBitStream.AlignToByte();
380     for (unsigned i = 0; i < 4; i++)
381       ZlibFooter[i] = ReadAlignedByte();
382   }
383 
384   flusher.NeedFlush = false;
385   res = Flush();
386   if (res == S_OK && _remainLen != kLenIdNeedInit && InputEofError())
387     return S_FALSE;
388 
389   DEFLATE_TRY_END(res)
390 
391   return res;
392 }
393 
394 
Code(ISequentialInStream * inStream,ISequentialOutStream * outStream,const UInt64 *,const UInt64 * outSize,ICompressProgressInfo * progress)395 HRESULT CCoder::Code(ISequentialInStream *inStream, ISequentialOutStream *outStream,
396     const UInt64 * /* inSize */, const UInt64 *outSize, ICompressProgressInfo *progress)
397 {
398   SetInStream(inStream);
399   SetOutStreamSize(outSize);
400   HRESULT res = CodeReal(outStream, progress);
401   ReleaseInStream();
402   /*
403   if (res == S_OK)
404     if (_needFinishInput && inSize && *inSize != m_InBitStream.GetProcessedSize())
405       res = S_FALSE;
406   */
407   return res;
408 }
409 
410 
SetFinishMode(UInt32 finishMode)411 STDMETHODIMP CCoder::SetFinishMode(UInt32 finishMode)
412 {
413   Set_NeedFinishInput(finishMode != 0);
414   return S_OK;
415 }
416 
417 
GetInStreamProcessedSize(UInt64 * value)418 STDMETHODIMP CCoder::GetInStreamProcessedSize(UInt64 *value)
419 {
420   *value = m_InBitStream.GetStreamSize();
421   return S_OK;
422 }
423 
424 
ReadUnusedFromInBuf(void * data,UInt32 size,UInt32 * processedSize)425 STDMETHODIMP CCoder::ReadUnusedFromInBuf(void *data, UInt32 size, UInt32 *processedSize)
426 {
427   AlignToByte();
428   UInt32 i = 0;
429   if (!m_InBitStream.ExtraBitsWereRead())
430   {
431     for (i = 0; i < size; i++)
432     {
433       if (!m_InBitStream.ReadAlignedByte_FromBuf(((Byte *)data)[i]))
434         break;
435     }
436   }
437   if (processedSize)
438     *processedSize = i;
439   return S_OK;
440 }
441 
442 
SetInStream(ISequentialInStream * inStream)443 STDMETHODIMP CCoder::SetInStream(ISequentialInStream *inStream)
444 {
445   m_InStreamRef = inStream;
446   m_InBitStream.SetStream(inStream);
447   return S_OK;
448 }
449 
450 
ReleaseInStream()451 STDMETHODIMP CCoder::ReleaseInStream()
452 {
453   m_InStreamRef.Release();
454   return S_OK;
455 }
456 
457 
SetOutStreamSizeResume(const UInt64 * outSize)458 void CCoder::SetOutStreamSizeResume(const UInt64 *outSize)
459 {
460   _outSizeDefined = (outSize != NULL);
461   _outSize = 0;
462   if (_outSizeDefined)
463     _outSize = *outSize;
464 
465   m_OutWindowStream.Init(_keepHistory);
466   _outStartPos = m_OutWindowStream.GetProcessedSize();
467 
468   _remainLen = kLenIdNeedInit;
469 }
470 
471 
SetOutStreamSize(const UInt64 * outSize)472 STDMETHODIMP CCoder::SetOutStreamSize(const UInt64 *outSize)
473 {
474   /*
475     18.06:
476     We want to support GetInputProcessedSize() before CCoder::Read()
477     So we call m_InBitStream.Init() even before buffer allocations
478     m_InBitStream.Init() just sets variables to default values
479     But later we will call m_InBitStream.Init() again with real buffer pointers
480   */
481   m_InBitStream.Init();
482   _needInitInStream = true;
483   SetOutStreamSizeResume(outSize);
484   return S_OK;
485 }
486 
487 
488 #ifndef NO_READ_FROM_CODER
489 
Read(void * data,UInt32 size,UInt32 * processedSize)490 STDMETHODIMP CCoder::Read(void *data, UInt32 size, UInt32 *processedSize)
491 {
492   HRESULT res;
493 
494   if (processedSize)
495     *processedSize = 0;
496   const UInt64 outPos = GetOutProcessedCur();
497 
498   bool finishInputStream = false;
499   if (_outSizeDefined)
500   {
501     const UInt64 rem = _outSize - outPos;
502     if (size >= rem)
503     {
504       size = (UInt32)rem;
505       if (ZlibMode || _needFinishInput)
506         finishInputStream = true;
507     }
508   }
509   if (!finishInputStream && size == 0)
510     return S_OK;
511 
512   DEFLATE_TRY_BEGIN
513 
514   m_OutWindowStream.SetMemStream((Byte *)data);
515 
516   res = CodeSpec(size, finishInputStream);
517 
518   DEFLATE_TRY_END(res)
519 
520   {
521     HRESULT res2 = Flush();
522     if (res2 != S_OK)
523       res = res2;
524   }
525 
526   if (processedSize)
527     *processedSize = (UInt32)(GetOutProcessedCur() - outPos);
528 
529   m_OutWindowStream.SetMemStream(NULL);
530   return res;
531 }
532 
533 #endif
534 
535 
CodeResume(ISequentialOutStream * outStream,const UInt64 * outSize,ICompressProgressInfo * progress)536 HRESULT CCoder::CodeResume(ISequentialOutStream *outStream, const UInt64 *outSize, ICompressProgressInfo *progress)
537 {
538   SetOutStreamSizeResume(outSize);
539   return CodeReal(outStream, progress);
540 }
541 
542 }}}
543