xref: /aosp_15_r20/external/lzma/CPP/7zip/Compress/Rar3Decoder.cpp (revision f6dc9357d832569d4d1f5d24eacdb3935a1ae8e6)
1 // Rar3Decoder.cpp
2 // According to unRAR license, this code may not be used to develop
3 // a program that creates RAR archives
4 
5 /* This code uses Carryless rangecoder (1999): Dmitry Subbotin : Public domain */
6 
7 #include "StdAfx.h"
8 
9 #include "../../../C/Alloc.h"
10 
11 #include "../Common/StreamUtils.h"
12 
13 #include "Rar3Decoder.h"
14 
15 namespace NCompress {
16 namespace NRar3 {
17 
18 static const UInt32 kNumAlignReps = 15;
19 
20 static const unsigned kSymbolReadTable = 256;
21 static const unsigned kSymbolRep = 259;
22 
23 static const Byte kDistDirectBits[kDistTableSize] =
24   {0,0,0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7,8,8,9,9,10,10,11,11,12,12,13,13,14,14,15,15,
25   16,16,16,16,16,16,16,16,16,16,16,16,16,16,
26   18,18,18,18,18,18,18,18,18,18,18,18};
27 
28 static const Byte kLen2DistStarts[kNumLen2Symbols] = {0,4,8,16,32,64,128,192};
29 static const Byte kLen2DistDirectBits[kNumLen2Symbols] = {2,2,3, 4, 5, 6,  6,  6};
30 
31 static const UInt32 kDistLimit3 = 0x2000 - 2;
32 static const UInt32 kDistLimit4 = 0x40000 - 2;
33 
34 static const UInt32 kNormalMatchMinLen = 3;
35 
36 static const UInt32 kVmDataSizeMax = 1 << 16;
37 static const UInt32 kVmCodeSizeMax = 1 << 16;
38 
39 extern "C" {
40 
Wrap_ReadByte(IByteInPtr pp)41 static Byte Wrap_ReadByte(IByteInPtr pp) throw()
42 {
43   CByteIn *p = Z7_CONTAINER_FROM_VTBL_CLS(pp, CByteIn, IByteIn_obj);
44   return p->BitDecoder.Stream.ReadByte();
45 }
46 
Wrap_ReadBits8(IByteInPtr pp)47 static Byte Wrap_ReadBits8(IByteInPtr pp) throw()
48 {
49   CByteIn *p = Z7_CONTAINER_FROM_VTBL_CLS(pp, CByteIn, IByteIn_obj);
50   return (Byte)p->BitDecoder.ReadByteFromAligned();
51 }
52 
53 }
54 
55 
CDecoder()56 CDecoder::CDecoder():
57   _isSolid(false),
58   _solidAllowed(false),
59   _window(NULL),
60   _winPos(0),
61   _wrPtr(0),
62   _lzSize(0),
63   _writtenFileSize(0),
64   _vmData(NULL),
65   _vmCode(NULL)
66 {
67   Ppmd7_Construct(&_ppmd);
68 
69   UInt32 start = 0;
70   for (UInt32 i = 0; i < kDistTableSize; i++)
71   {
72     kDistStart[i] = start;
73     start += ((UInt32)1 << kDistDirectBits[i]);
74   }
75 }
76 
~CDecoder()77 CDecoder::~CDecoder()
78 {
79   InitFilters();
80   ::MidFree(_vmData);
81   ::MidFree(_window);
82   Ppmd7_Free(&_ppmd, &g_BigAlloc);
83 }
84 
WriteDataToStream(const Byte * data,UInt32 size)85 HRESULT CDecoder::WriteDataToStream(const Byte *data, UInt32 size)
86 {
87   return WriteStream(_outStream, data, size);
88 }
89 
WriteData(const Byte * data,UInt32 size)90 HRESULT CDecoder::WriteData(const Byte *data, UInt32 size)
91 {
92   HRESULT res = S_OK;
93   if (_writtenFileSize < _unpackSize)
94   {
95     UInt32 curSize = size;
96     UInt64 remain = _unpackSize - _writtenFileSize;
97     if (remain < curSize)
98       curSize = (UInt32)remain;
99     res = WriteDataToStream(data, curSize);
100   }
101   _writtenFileSize += size;
102   return res;
103 }
104 
WriteArea(UInt32 startPtr,UInt32 endPtr)105 HRESULT CDecoder::WriteArea(UInt32 startPtr, UInt32 endPtr)
106 {
107   if (startPtr <= endPtr)
108     return WriteData(_window + startPtr, endPtr - startPtr);
109   RINOK(WriteData(_window + startPtr, kWindowSize - startPtr))
110   return WriteData(_window, endPtr);
111 }
112 
ExecuteFilter(unsigned tempFilterIndex,NVm::CBlockRef & outBlockRef)113 void CDecoder::ExecuteFilter(unsigned tempFilterIndex, NVm::CBlockRef &outBlockRef)
114 {
115   CTempFilter *tempFilter = _tempFilters[tempFilterIndex];
116   tempFilter->InitR[6] = (UInt32)_writtenFileSize;
117   NVm::SetValue32(&tempFilter->GlobalData[0x24], (UInt32)_writtenFileSize);
118   NVm::SetValue32(&tempFilter->GlobalData[0x28], (UInt32)(_writtenFileSize >> 32));
119   CFilter *filter = _filters[tempFilter->FilterIndex];
120   if (!filter->IsSupported)
121     _unsupportedFilter = true;
122   if (!_vm.Execute(filter, tempFilter, outBlockRef, filter->GlobalData))
123     _unsupportedFilter = true;
124   delete tempFilter;
125   _tempFilters[tempFilterIndex] = NULL;
126   _numEmptyTempFilters++;
127 }
128 
WriteBuf()129 HRESULT CDecoder::WriteBuf()
130 {
131   UInt32 writtenBorder = _wrPtr;
132   UInt32 writeSize = (_winPos - writtenBorder) & kWindowMask;
133   FOR_VECTOR (i, _tempFilters)
134   {
135     CTempFilter *filter = _tempFilters[i];
136     if (!filter)
137       continue;
138     if (filter->NextWindow)
139     {
140       filter->NextWindow = false;
141       continue;
142     }
143     UInt32 blockStart = filter->BlockStart;
144     UInt32 blockSize = filter->BlockSize;
145     if (((blockStart - writtenBorder) & kWindowMask) < writeSize)
146     {
147       if (writtenBorder != blockStart)
148       {
149         RINOK(WriteArea(writtenBorder, blockStart))
150         writtenBorder = blockStart;
151         writeSize = (_winPos - writtenBorder) & kWindowMask;
152       }
153       if (blockSize <= writeSize)
154       {
155         UInt32 blockEnd = (blockStart + blockSize) & kWindowMask;
156         if (blockStart < blockEnd || blockEnd == 0)
157           _vm.SetMemory(0, _window + blockStart, blockSize);
158         else
159         {
160           UInt32 tailSize = kWindowSize - blockStart;
161           _vm.SetMemory(0, _window + blockStart, tailSize);
162           _vm.SetMemory(tailSize, _window, blockEnd);
163         }
164         NVm::CBlockRef outBlockRef;
165         ExecuteFilter(i, outBlockRef);
166         while (i + 1 < _tempFilters.Size())
167         {
168           CTempFilter *nextFilter = _tempFilters[i + 1];
169           if (!nextFilter
170               || nextFilter->BlockStart != blockStart
171               || nextFilter->BlockSize != outBlockRef.Size
172               || nextFilter->NextWindow)
173             break;
174           _vm.SetMemory(0, _vm.GetDataPointer(outBlockRef.Offset), outBlockRef.Size);
175           ExecuteFilter(++i, outBlockRef);
176         }
177         WriteDataToStream(_vm.GetDataPointer(outBlockRef.Offset), outBlockRef.Size);
178         _writtenFileSize += outBlockRef.Size;
179         writtenBorder = blockEnd;
180         writeSize = (_winPos - writtenBorder) & kWindowMask;
181       }
182       else
183       {
184         for (unsigned j = i; j < _tempFilters.Size(); j++)
185         {
186           CTempFilter *filter2 = _tempFilters[j];
187           if (filter2 && filter2->NextWindow)
188             filter2->NextWindow = false;
189         }
190         _wrPtr = writtenBorder;
191         return S_OK; // check it
192       }
193     }
194   }
195 
196   _wrPtr = _winPos;
197   return WriteArea(writtenBorder, _winPos);
198 }
199 
InitFilters()200 void CDecoder::InitFilters()
201 {
202   _lastFilter = 0;
203   _numEmptyTempFilters = 0;
204   unsigned i;
205   for (i = 0; i < _tempFilters.Size(); i++)
206     delete _tempFilters[i];
207   _tempFilters.Clear();
208   for (i = 0; i < _filters.Size(); i++)
209     delete _filters[i];
210   _filters.Clear();
211 }
212 
213 static const unsigned MAX_UNPACK_FILTERS = 8192;
214 
AddVmCode(UInt32 firstByte,UInt32 codeSize)215 bool CDecoder::AddVmCode(UInt32 firstByte, UInt32 codeSize)
216 {
217   CMemBitDecoder inp;
218   inp.Init(_vmData, codeSize);
219 
220   UInt32 filterIndex;
221 
222   if (firstByte & 0x80)
223   {
224     filterIndex = inp.ReadEncodedUInt32();
225     if (filterIndex == 0)
226       InitFilters();
227     else
228       filterIndex--;
229   }
230   else
231     filterIndex = _lastFilter;
232 
233   if (filterIndex > (UInt32)_filters.Size())
234     return false;
235   _lastFilter = filterIndex;
236   bool newFilter = (filterIndex == (UInt32)_filters.Size());
237 
238   CFilter *filter;
239   if (newFilter)
240   {
241     // check if too many filters
242     if (filterIndex > MAX_UNPACK_FILTERS)
243       return false;
244     filter = new CFilter;
245     _filters.Add(filter);
246   }
247   else
248   {
249     filter = _filters[filterIndex];
250     filter->ExecCount++;
251   }
252 
253   if (_numEmptyTempFilters != 0)
254   {
255     const unsigned num = _tempFilters.Size();
256     CTempFilter **tempFilters = _tempFilters.NonConstData();
257 
258     unsigned w = 0;
259     for (unsigned i = 0; i < num; i++)
260     {
261       CTempFilter *tf = tempFilters[i];
262       if (tf)
263         tempFilters[w++] = tf;
264     }
265 
266     _tempFilters.DeleteFrom(w);
267     _numEmptyTempFilters = 0;
268   }
269 
270   if (_tempFilters.Size() > MAX_UNPACK_FILTERS)
271     return false;
272   CTempFilter *tempFilter = new CTempFilter;
273   _tempFilters.Add(tempFilter);
274   tempFilter->FilterIndex = filterIndex;
275 
276   UInt32 blockStart = inp.ReadEncodedUInt32();
277   if (firstByte & 0x40)
278     blockStart += 258;
279   tempFilter->BlockStart = (blockStart + _winPos) & kWindowMask;
280   if (firstByte & 0x20)
281     filter->BlockSize = inp.ReadEncodedUInt32();
282   tempFilter->BlockSize = filter->BlockSize;
283   tempFilter->NextWindow = _wrPtr != _winPos && ((_wrPtr - _winPos) & kWindowMask) <= blockStart;
284 
285   memset(tempFilter->InitR, 0, sizeof(tempFilter->InitR));
286   tempFilter->InitR[3] = NVm::kGlobalOffset;
287   tempFilter->InitR[4] = tempFilter->BlockSize;
288   tempFilter->InitR[5] = filter->ExecCount;
289   if (firstByte & 0x10)
290   {
291     UInt32 initMask = inp.ReadBits(NVm::kNumGpRegs);
292     for (unsigned i = 0; i < NVm::kNumGpRegs; i++)
293       if (initMask & (1 << i))
294         tempFilter->InitR[i] = inp.ReadEncodedUInt32();
295   }
296 
297   bool isOK = true;
298   if (newFilter)
299   {
300     UInt32 vmCodeSize = inp.ReadEncodedUInt32();
301     if (vmCodeSize >= kVmCodeSizeMax || vmCodeSize == 0)
302       return false;
303     for (UInt32 i = 0; i < vmCodeSize; i++)
304       _vmCode[i] = (Byte)inp.ReadBits(8);
305     isOK = filter->PrepareProgram(_vmCode, vmCodeSize);
306   }
307 
308   {
309     Byte *globalData = &tempFilter->GlobalData[0];
310     for (unsigned i = 0; i < NVm::kNumGpRegs; i++)
311       NVm::SetValue32(&globalData[i * 4], tempFilter->InitR[i]);
312     NVm::SetValue32(&globalData[NVm::NGlobalOffset::kBlockSize], tempFilter->BlockSize);
313     NVm::SetValue32(&globalData[NVm::NGlobalOffset::kBlockPos], 0); // It was commented. why?
314     NVm::SetValue32(&globalData[NVm::NGlobalOffset::kExecCount], filter->ExecCount);
315   }
316 
317   if (firstByte & 8)
318   {
319     UInt32 dataSize = inp.ReadEncodedUInt32();
320     if (dataSize > NVm::kGlobalSize - NVm::kFixedGlobalSize)
321       return false;
322     CRecordVector<Byte> &globalData = tempFilter->GlobalData;
323     unsigned requiredSize = (unsigned)(dataSize + NVm::kFixedGlobalSize);
324     if (globalData.Size() < requiredSize)
325       globalData.ChangeSize_KeepData(requiredSize);
326     Byte *dest = &globalData[NVm::kFixedGlobalSize];
327     for (UInt32 i = 0; i < dataSize; i++)
328       dest[i] = (Byte)inp.ReadBits(8);
329   }
330 
331   return isOK;
332 }
333 
ReadVmCodeLZ()334 bool CDecoder::ReadVmCodeLZ()
335 {
336   UInt32 firstByte = ReadBits(8);
337   UInt32 len = (firstByte & 7) + 1;
338   if (len == 7)
339     len = ReadBits(8) + 7;
340   else if (len == 8)
341     len = ReadBits(16);
342   if (len > kVmDataSizeMax)
343     return false;
344   for (UInt32 i = 0; i < len; i++)
345     _vmData[i] = (Byte)ReadBits(8);
346   return AddVmCode(firstByte, len);
347 }
348 
349 
350 // int CDecoder::DecodePpmSymbol() { return Ppmd7a_DecodeSymbol(&_ppmd); }
351 #define DecodePpmSymbol() Ppmd7a_DecodeSymbol(&_ppmd)
352 
353 
ReadVmCodePPM()354 bool CDecoder::ReadVmCodePPM()
355 {
356   const int firstByte = DecodePpmSymbol();
357   if (firstByte < 0)
358     return false;
359   UInt32 len = (firstByte & 7) + 1;
360   if (len == 7)
361   {
362     const int b1 = DecodePpmSymbol();
363     if (b1 < 0)
364       return false;
365     len = (unsigned)b1 + 7;
366   }
367   else if (len == 8)
368   {
369     const int b1 = DecodePpmSymbol();
370     if (b1 < 0)
371       return false;
372     const int b2 = DecodePpmSymbol();
373     if (b2 < 0)
374       return false;
375     len = (unsigned)b1 * 256 + (unsigned)b2;
376   }
377   if (len > kVmDataSizeMax)
378     return false;
379   if (InputEofError_Fast())
380     return false;
381   for (UInt32 i = 0; i < len; i++)
382   {
383     const int b = DecodePpmSymbol();
384     if (b < 0)
385       return false;
386     _vmData[i] = (Byte)b;
387   }
388   return AddVmCode((unsigned)firstByte, len);
389 }
390 
391 #define RIF(x) { if (!(x)) return S_FALSE; }
392 
ReadBits(unsigned numBits)393 UInt32 CDecoder::ReadBits(unsigned numBits) { return m_InBitStream.BitDecoder.ReadBits(numBits); }
394 
395 // ---------- PPM ----------
396 
InitPPM()397 HRESULT CDecoder::InitPPM()
398 {
399   unsigned maxOrder = (unsigned)ReadBits(7);
400 
401   const bool reset = ((maxOrder & 0x20) != 0);
402   UInt32 maxMB = 0;
403   if (reset)
404     maxMB = (Byte)Wrap_ReadBits8(&m_InBitStream.IByteIn_obj);
405   else
406   {
407     if (PpmError || !Ppmd7_WasAllocated(&_ppmd))
408       return S_FALSE;
409   }
410   if (maxOrder & 0x40)
411     PpmEscChar = (Byte)Wrap_ReadBits8(&m_InBitStream.IByteIn_obj);
412 
413   _ppmd.rc.dec.Stream = &m_InBitStream.IByteIn_obj;
414   m_InBitStream.IByteIn_obj.Read = Wrap_ReadBits8;
415 
416   Ppmd7a_RangeDec_Init(&_ppmd.rc.dec);
417 
418   m_InBitStream.IByteIn_obj.Read = Wrap_ReadByte;
419 
420   if (reset)
421   {
422     PpmError = true;
423     maxOrder = (maxOrder & 0x1F) + 1;
424     if (maxOrder > 16)
425       maxOrder = 16 + (maxOrder - 16) * 3;
426     if (maxOrder == 1)
427     {
428       Ppmd7_Free(&_ppmd, &g_BigAlloc);
429       return S_FALSE;
430     }
431     if (!Ppmd7_Alloc(&_ppmd, (maxMB + 1) << 20, &g_BigAlloc))
432       return E_OUTOFMEMORY;
433     Ppmd7_Init(&_ppmd, maxOrder);
434     PpmError = false;
435   }
436   return S_OK;
437 }
438 
439 
DecodePPM(Int32 num,bool & keepDecompressing)440 HRESULT CDecoder::DecodePPM(Int32 num, bool &keepDecompressing)
441 {
442   keepDecompressing = false;
443   if (PpmError)
444     return S_FALSE;
445   do
446   {
447     if (((_wrPtr - _winPos) & kWindowMask) < 260 && _wrPtr != _winPos)
448     {
449       RINOK(WriteBuf())
450       if (_writtenFileSize > _unpackSize)
451       {
452         keepDecompressing = false;
453         return S_OK;
454       }
455     }
456     if (InputEofError_Fast())
457       return false;
458     const int c = DecodePpmSymbol();
459     if (c < 0)
460     {
461       PpmError = true;
462       return S_FALSE;
463     }
464     if (c == PpmEscChar)
465     {
466       const int nextCh = DecodePpmSymbol();
467       if (nextCh < 0)
468       {
469         PpmError = true;
470         return S_FALSE;
471       }
472       if (nextCh == 0)
473         return ReadTables(keepDecompressing);
474       if (nextCh == 2 || nextCh == -1)
475         return S_OK;
476       if (nextCh == 3)
477       {
478         if (!ReadVmCodePPM())
479         {
480           PpmError = true;
481           return S_FALSE;
482         }
483         continue;
484       }
485       if (nextCh == 4 || nextCh == 5)
486       {
487         UInt32 dist = 0;
488         UInt32 len = 4;
489         if (nextCh == 4)
490         {
491           for (int i = 0; i < 3; i++)
492           {
493             const int c2 = DecodePpmSymbol();
494             if (c2 < 0)
495             {
496               PpmError = true;
497               return S_FALSE;
498             }
499             dist = (dist << 8) + (Byte)c2;
500           }
501           dist++;
502           len += 28;
503         }
504         const int c2 = DecodePpmSymbol();
505         if (c2 < 0)
506         {
507           PpmError = true;
508           return S_FALSE;
509         }
510         len += (unsigned)c2;
511         if (dist >= _lzSize)
512           return S_FALSE;
513         CopyBlock(dist, len);
514         num -= (Int32)len;
515         continue;
516       }
517     }
518     PutByte((Byte)c);
519     num--;
520   }
521   while (num >= 0);
522   keepDecompressing = true;
523   return S_OK;
524 }
525 
526 // ---------- LZ ----------
527 
ReadTables(bool & keepDecompressing)528 HRESULT CDecoder::ReadTables(bool &keepDecompressing)
529 {
530   keepDecompressing = true;
531   m_InBitStream.BitDecoder.AlignToByte();
532   if (ReadBits(1) != 0)
533   {
534     _lzMode = false;
535     return InitPPM();
536   }
537 
538   TablesRead = false;
539   TablesOK = false;
540 
541   _lzMode = true;
542   PrevAlignBits = 0;
543   PrevAlignCount = 0;
544 
545   const unsigned kLevelTableSize = 20;
546   Byte levelLevels[kLevelTableSize];
547   Byte lens[kTablesSizesSum];
548 
549   if (ReadBits(1) == 0)
550     memset(m_LastLevels, 0, kTablesSizesSum);
551 
552   unsigned i;
553 
554   for (i = 0; i < kLevelTableSize; i++)
555   {
556     const UInt32 len = ReadBits(4);
557     if (len == 15)
558     {
559       UInt32 zeroCount = ReadBits(4);
560       if (zeroCount != 0)
561       {
562         zeroCount += 2;
563         while (zeroCount-- > 0 && i < kLevelTableSize)
564           levelLevels[i++]=0;
565         i--;
566         continue;
567       }
568     }
569     levelLevels[i] = (Byte)len;
570   }
571 
572   NHuffman::CDecoder256<kNumHuffmanBits, kLevelTableSize, 6> m_LevelDecoder;
573   RIF(m_LevelDecoder.Build(levelLevels, NHuffman::k_BuildMode_Full))
574 
575   i = 0;
576 
577   do
578   {
579     const unsigned sym = m_LevelDecoder.DecodeFull(&m_InBitStream.BitDecoder);
580     if (sym < 16)
581     {
582       lens[i] = Byte((sym + m_LastLevels[i]) & 15);
583       i++;
584     }
585 #if 0
586     else if (sym > kLevelTableSize)
587       return S_FALSE;
588 #endif
589     else
590     {
591       unsigned num = ((sym /* - 16 */) & 1) * 4;
592       num += num + 3 + (unsigned)ReadBits(num + 3);
593       num += i;
594       if (num > kTablesSizesSum)
595         num = kTablesSizesSum;
596       Byte v = 0;
597       if (sym < 16 + 2)
598       {
599         if (i == 0)
600           return S_FALSE;
601         v = lens[(size_t)i - 1];
602       }
603       do
604         lens[i++] = v;
605       while (i < num);
606     }
607   }
608   while (i < kTablesSizesSum);
609 
610   if (InputEofError())
611     return S_FALSE;
612 
613   TablesRead = true;
614 
615   // original code has check here:
616   /*
617   if (InAddr > ReadTop)
618   {
619     keepDecompressing = false;
620     return true;
621   }
622   */
623 
624   RIF(m_MainDecoder.Build(&lens[0]))
625   RIF(m_DistDecoder.Build(&lens[kMainTableSize]))
626   RIF(m_AlignDecoder.Build(&lens[kMainTableSize + kDistTableSize]))
627   RIF(m_LenDecoder.Build(&lens[kMainTableSize + kDistTableSize + kAlignTableSize]))
628 
629   memcpy(m_LastLevels, lens, kTablesSizesSum);
630 
631   TablesOK = true;
632 
633   return S_OK;
634 }
635 
636 /*
637 class CCoderReleaser
638 {
639   CDecoder *m_Coder;
640 public:
641   CCoderReleaser(CDecoder *coder): m_Coder(coder) {}
642   ~CCoderReleaser()
643   {
644     m_Coder->ReleaseStreams();
645   }
646 };
647 */
648 
ReadEndOfBlock(bool & keepDecompressing)649 HRESULT CDecoder::ReadEndOfBlock(bool &keepDecompressing)
650 {
651   if (ReadBits(1) == 0)
652   {
653     // new file
654     keepDecompressing = false;
655     TablesRead = (ReadBits(1) == 0);
656     return S_OK;
657   }
658   TablesRead = false;
659   return ReadTables(keepDecompressing);
660 }
661 
662 
DecodeLZ(bool & keepDecompressing)663 HRESULT CDecoder::DecodeLZ(bool &keepDecompressing)
664 {
665   UInt32 rep0 = _reps[0];
666   UInt32 rep1 = _reps[1];
667   UInt32 rep2 = _reps[2];
668   UInt32 rep3 = _reps[3];
669   UInt32 len = _lastLength;
670   for (;;)
671   {
672     if (((_wrPtr - _winPos) & kWindowMask) < 260 && _wrPtr != _winPos)
673     {
674       RINOK(WriteBuf())
675       if (_writtenFileSize > _unpackSize)
676       {
677         keepDecompressing = false;
678         return S_OK;
679       }
680     }
681 
682     if (InputEofError_Fast())
683       return S_FALSE;
684 
685     unsigned sym = m_MainDecoder.Decode(&m_InBitStream.BitDecoder);
686     if (sym < 256)
687     {
688       PutByte((Byte)sym);
689       continue;
690     }
691     else if (sym == kSymbolReadTable)
692     {
693       RINOK(ReadEndOfBlock(keepDecompressing))
694       break;
695     }
696     else if (sym == 257)
697     {
698       if (!ReadVmCodeLZ())
699         return S_FALSE;
700       continue;
701     }
702     else if (sym == 258)
703     {
704       if (len == 0)
705         return S_FALSE;
706     }
707     else if (sym < kSymbolRep + 4)
708     {
709       if (sym != kSymbolRep)
710       {
711         UInt32 dist;
712         if (sym == kSymbolRep + 1)
713           dist = rep1;
714         else
715         {
716           if (sym == kSymbolRep + 2)
717             dist = rep2;
718           else
719           {
720             dist = rep3;
721             rep3 = rep2;
722           }
723           rep2 = rep1;
724         }
725         rep1 = rep0;
726         rep0 = dist;
727       }
728 
729       const unsigned sym2 = m_LenDecoder.Decode(&m_InBitStream.BitDecoder);
730       if (sym2 >= kLenTableSize)
731         return S_FALSE;
732       len = 2 + sym2;
733       if (sym2 >= 8)
734       {
735         const unsigned num = (sym2 >> 2) - 1;
736         len = 2 + (UInt32)((4 + (sym2 & 3)) << num) + m_InBitStream.BitDecoder.ReadBits_upto8(num);
737       }
738     }
739     else
740     {
741       rep3 = rep2;
742       rep2 = rep1;
743       rep1 = rep0;
744       if (sym < 271)
745       {
746         sym -= 263;
747         rep0 = kLen2DistStarts[sym] + m_InBitStream.BitDecoder.ReadBits_upto8(kLen2DistDirectBits[sym]);
748         len = 2;
749       }
750       else if (sym < 299)
751       {
752         sym -= 271;
753         len = kNormalMatchMinLen + sym;
754         if (sym >= 8)
755         {
756           const unsigned num = (sym >> 2) - 1;
757           len = kNormalMatchMinLen + (UInt32)((4 + (sym & 3)) << num) + m_InBitStream.BitDecoder.ReadBits_upto8(num);
758         }
759         const unsigned sym2 = m_DistDecoder.Decode(&m_InBitStream.BitDecoder);
760         if (sym2 >= kDistTableSize)
761           return S_FALSE;
762         rep0 = kDistStart[sym2];
763         unsigned numBits = kDistDirectBits[sym2];
764         if (sym2 >= (kNumAlignBits * 2) + 2)
765         {
766           if (numBits > kNumAlignBits)
767             rep0 += (m_InBitStream.BitDecoder.ReadBits(numBits - kNumAlignBits) << kNumAlignBits);
768           if (PrevAlignCount > 0)
769           {
770             PrevAlignCount--;
771             rep0 += PrevAlignBits;
772           }
773           else
774           {
775             const unsigned sym3 = m_AlignDecoder.Decode(&m_InBitStream.BitDecoder);
776             if (sym3 < (1 << kNumAlignBits))
777             {
778               rep0 += sym3;
779               PrevAlignBits = sym3;
780             }
781             else if (sym3 == (1 << kNumAlignBits))
782             {
783               PrevAlignCount = kNumAlignReps;
784               rep0 += PrevAlignBits;
785             }
786             else
787               return S_FALSE;
788           }
789         }
790         else
791           rep0 += m_InBitStream.BitDecoder.ReadBits_upto8(numBits);
792         len += ((UInt32)(kDistLimit4 - rep0) >> 31) + ((UInt32)(kDistLimit3 - rep0) >> 31);
793       }
794       else
795         return S_FALSE;
796     }
797     if (rep0 >= _lzSize)
798       return S_FALSE;
799     CopyBlock(rep0, len);
800   }
801   _reps[0] = rep0;
802   _reps[1] = rep1;
803   _reps[2] = rep2;
804   _reps[3] = rep3;
805   _lastLength = len;
806 
807   return S_OK;
808 }
809 
810 
CodeReal(ICompressProgressInfo * progress)811 HRESULT CDecoder::CodeReal(ICompressProgressInfo *progress)
812 {
813   _writtenFileSize = 0;
814   _unsupportedFilter = false;
815 
816   if (!_isSolid)
817   {
818     _lzSize = 0;
819     _winPos = 0;
820     _wrPtr = 0;
821     for (unsigned i = 0; i < kNumReps; i++)
822       _reps[i] = 0;
823     _lastLength = 0;
824     memset(m_LastLevels, 0, kTablesSizesSum);
825     TablesRead = false;
826     PpmEscChar = 2;
827     PpmError = true;
828     InitFilters();
829     // _errorMode = false;
830   }
831 
832   /*
833   if (_errorMode)
834     return S_FALSE;
835   */
836 
837   if (!_isSolid || !TablesRead)
838   {
839     bool keepDecompressing;
840     RINOK(ReadTables(keepDecompressing))
841     if (!keepDecompressing)
842     {
843       _solidAllowed = true;
844       return S_OK;
845     }
846   }
847 
848   for (;;)
849   {
850     bool keepDecompressing;
851     if (_lzMode)
852     {
853       if (!TablesOK)
854         return S_FALSE;
855       RINOK(DecodeLZ(keepDecompressing))
856     }
857     else
858     {
859       RINOK(DecodePPM(1 << 18, keepDecompressing))
860     }
861 
862     if (InputEofError())
863       return S_FALSE;
864 
865     const UInt64 packSize = m_InBitStream.BitDecoder.GetProcessedSize();
866     RINOK(progress->SetRatioInfo(&packSize, &_writtenFileSize))
867     if (!keepDecompressing)
868       break;
869   }
870 
871   _solidAllowed = true;
872 
873   RINOK(WriteBuf())
874   const UInt64 packSize = m_InBitStream.BitDecoder.GetProcessedSize();
875   RINOK(progress->SetRatioInfo(&packSize, &_writtenFileSize))
876   if (_writtenFileSize < _unpackSize)
877     return S_FALSE;
878 
879   if (_unsupportedFilter)
880     return E_NOTIMPL;
881 
882   return S_OK;
883 }
884 
Z7_COM7F_IMF(CDecoder::Code (ISequentialInStream * inStream,ISequentialOutStream * outStream,const UInt64 * inSize,const UInt64 * outSize,ICompressProgressInfo * progress))885 Z7_COM7F_IMF(CDecoder::Code(ISequentialInStream *inStream, ISequentialOutStream *outStream,
886     const UInt64 *inSize, const UInt64 *outSize, ICompressProgressInfo *progress))
887 {
888   try
889   {
890     if (!inSize)
891       return E_INVALIDARG;
892 
893     if (_isSolid && !_solidAllowed)
894       return S_FALSE;
895     _solidAllowed = false;
896 
897     if (!_vmData)
898     {
899       _vmData = (Byte *)::MidAlloc(kVmDataSizeMax + kVmCodeSizeMax);
900       if (!_vmData)
901         return E_OUTOFMEMORY;
902       _vmCode = _vmData + kVmDataSizeMax;
903     }
904 
905     if (!_window)
906     {
907       _window = (Byte *)::MidAlloc(kWindowSize);
908       if (!_window)
909         return E_OUTOFMEMORY;
910     }
911     if (!m_InBitStream.BitDecoder.Create(1 << 20))
912       return E_OUTOFMEMORY;
913     if (!_vm.Create())
914       return E_OUTOFMEMORY;
915 
916 
917     m_InBitStream.BitDecoder.SetStream(inStream);
918     m_InBitStream.BitDecoder.Init();
919     _outStream = outStream;
920 
921     // CCoderReleaser coderReleaser(this);
922     _unpackSize = outSize ? *outSize : (UInt64)(Int64)-1;
923     return CodeReal(progress);
924   }
925   catch(const CInBufferException &e)  { /* _errorMode = true; */ return e.ErrorCode; }
926   catch(...) { /* _errorMode = true; */ return S_FALSE; }
927   // CNewException is possible here. But probably CNewException is caused
928   // by error in data stream.
929 }
930 
Z7_COM7F_IMF(CDecoder::SetDecoderProperties2 (const Byte * data,UInt32 size))931 Z7_COM7F_IMF(CDecoder::SetDecoderProperties2(const Byte *data, UInt32 size))
932 {
933   if (size < 1)
934     return E_INVALIDARG;
935   _isSolid = ((data[0] & 1) != 0);
936   return S_OK;
937 }
938 
939 }}
940