~ubuntu-branches/ubuntu/trusty/unrar-nonfree/trusty-security

1.2.14 by Martin Meredith
Import upstream version 5.0.10
1
void Unpack::Unpack5(bool Solid)
2
{
3
  FileExtracted=true;
4
5
  if (!Suspended)
6
  {
7
    UnpInitData(Solid);
8
    if (!UnpReadBuf())
9
      return;
10
    if (!ReadBlockHeader(Inp,BlockHeader) || !ReadTables(Inp,BlockHeader,BlockTables))
11
      return;
12
  }
13
14
  while (true)
15
  {
16
    UnpPtr&=MaxWinMask;
17
18
    if (Inp.InAddr>=ReadBorder)
19
    {
20
      bool FileDone=false;
21
22
      // We use 'while', because for empty block containing only Huffman table,
23
      // we'll be on the block border once again just after reading the table.
24
      while (Inp.InAddr>BlockHeader.BlockStart+BlockHeader.BlockSize-1 || 
25
             Inp.InAddr==BlockHeader.BlockStart+BlockHeader.BlockSize-1 && 
26
             Inp.InBit>=BlockHeader.BlockBitSize)
27
      {
28
        if (BlockHeader.LastBlockInFile)
29
        {
30
          FileDone=true;
31
          break;
32
        }
33
        if (!ReadBlockHeader(Inp,BlockHeader) || !ReadTables(Inp,BlockHeader,BlockTables))
34
          return;
35
      }
36
      if (FileDone || !UnpReadBuf())
37
        break;
38
    }
39
40
    if (((WriteBorder-UnpPtr) & MaxWinMask)<MAX_LZ_MATCH+3 && WriteBorder!=UnpPtr)
41
    {
42
      UnpWriteBuf();
43
      if (WrittenFileSize>DestUnpSize)
44
        return;
45
      if (Suspended)
46
      {
47
        FileExtracted=false;
48
        return;
49
      }
50
    }
51
52
    uint MainSlot=DecodeNumber(Inp,&BlockTables.LD);
53
    if (MainSlot<256)
54
    {
55
      if (Fragmented)
56
        FragWindow[UnpPtr++]=(byte)MainSlot;
57
      else
58
        Window[UnpPtr++]=(byte)MainSlot;
59
      continue;
60
    }
61
    if (MainSlot>=262)
62
    {
63
      uint Length=SlotToLength(Inp,MainSlot-262);
64
65
      uint DBits,Distance=1,DistSlot=DecodeNumber(Inp,&BlockTables.DD);
66
      if (DistSlot<4)
67
      {
68
        DBits=0;
69
        Distance+=DistSlot;
70
      }
71
      else
72
      {
73
        DBits=DistSlot/2 - 1;
74
        Distance+=(2 | (DistSlot & 1)) << DBits;
75
      }
76
77
      if (DBits>0)
78
      {
79
        if (DBits>=4)
80
        {
81
          if (DBits>4)
82
          {
83
            Distance+=((Inp.getbits32()>>(36-DBits))<<4);
84
            Inp.addbits(DBits-4);
85
          }
86
          uint LowDist=DecodeNumber(Inp,&BlockTables.LDD);
87
          Distance+=LowDist;
88
        }
89
        else
90
        {
91
          Distance+=Inp.getbits32()>>(32-DBits);
92
          Inp.addbits(DBits);
93
        }
94
      }
95
96
      if (Distance>0x100)
97
      {
98
        Length++;
99
        if (Distance>0x2000)
100
        {
101
          Length++;
102
          if (Distance>0x40000)
103
            Length++;
104
        }
105
      }
106
107
      InsertOldDist(Distance);
108
      LastLength=Length;
109
      if (Fragmented)
110
        FragWindow.CopyString(Length,Distance,UnpPtr,MaxWinMask);
111
      else
112
        CopyString(Length,Distance);
113
      continue;
114
    }
115
    if (MainSlot==256)
116
    {
117
      UnpackFilter Filter;
118
      if (!ReadFilter(Inp,Filter) || !AddFilter(Filter))
119
        break;
120
      continue;
121
    }
122
    if (MainSlot==257)
123
    {
124
      if (LastLength!=0)
125
        if (Fragmented)
126
          FragWindow.CopyString(LastLength,OldDist[0],UnpPtr,MaxWinMask);
127
        else
128
          CopyString(LastLength,OldDist[0]);
129
      continue;
130
    }
131
    if (MainSlot<262)
132
    {
133
      uint DistNum=MainSlot-258;
134
      uint Distance=OldDist[DistNum];
135
      for (uint I=DistNum;I>0;I--)
136
        OldDist[I]=OldDist[I-1];
137
      OldDist[0]=Distance;
138
139
      uint LengthSlot=DecodeNumber(Inp,&BlockTables.RD);
140
      uint Length=SlotToLength(Inp,LengthSlot);
141
      LastLength=Length;
142
      if (Fragmented)
143
        FragWindow.CopyString(Length,Distance,UnpPtr,MaxWinMask);
144
      else
145
        CopyString(Length,Distance);
146
      continue;
147
    }
148
  }
149
  UnpWriteBuf();
150
}
151
152
153
uint Unpack::ReadFilterData(BitInput &Inp)
154
{
155
  uint ByteCount=(Inp.fgetbits()>>14)+1;
156
  Inp.addbits(2);
157
158
  uint Data=0;
159
  for (uint I=0;I<ByteCount;I++)
160
  {
161
    Data+=(Inp.fgetbits()>>8)<<(I*8);
162
    Inp.addbits(8);
163
  }
164
  return Data;
165
}
166
167
168
bool Unpack::ReadFilter(BitInput &Inp,UnpackFilter &Filter)
169
{
170
  if (!Inp.ExternalBuffer && Inp.InAddr>ReadTop-16)
171
    if (!UnpReadBuf())
172
      return false;
173
174
  Filter.BlockStart=ReadFilterData(Inp);
175
  Filter.BlockLength=ReadFilterData(Inp);
176
177
  Filter.Type=Inp.fgetbits()>>13;
178
  Inp.faddbits(3);
179
180
  if (Filter.Type==FILTER_DELTA || Filter.Type==FILTER_AUDIO)
181
  {
182
    Filter.Channels=(Inp.fgetbits()>>11)+1;
183
    Inp.faddbits(5);
184
  }
185
186
  if (Filter.Type==FILTER_RGB)
187
  {
188
    Filter.Channels=3;
189
    Filter.Width=Inp.fgetbits()+1;
190
    Inp.faddbits(16);
191
    Filter.PosR=Inp.fgetbits()>>14;
192
    Inp.faddbits(2);
193
  }
194
195
  return true;
196
}
197
198
199
bool Unpack::AddFilter(UnpackFilter &Filter)
200
{
201
  if (Filters.Size()>=MAX_UNPACK_FILTERS-1)
202
    UnpWriteBuf(); // Write data, apply and flush filters.
203
204
  // If distance to filter start is that large that due to circular dictionary
205
  // mode it points to old not written yet data, then we set 'NextWindow'
206
  // flag and process this filter only after processing that older data.
207
  Filter.NextWindow=WrPtr!=UnpPtr && ((WrPtr-UnpPtr)&MaxWinMask)<=Filter.BlockStart;
208
209
  Filter.BlockStart=uint((Filter.BlockStart+UnpPtr)&MaxWinMask);
210
  Filters.Push(Filter);
211
  return true;
212
}
213
214
215
bool Unpack::UnpReadBuf()
216
{
217
  int DataSize=ReadTop-Inp.InAddr; // Data left to process.
218
  if (DataSize<0)
219
    return false;
220
  BlockHeader.BlockSize-=Inp.InAddr-BlockHeader.BlockStart;
221
  if (Inp.InAddr>BitInput::MAX_SIZE/2)
222
  {
223
    // If we already processed more than half of buffer, let's move
224
    // remaining data into beginning to free more space for new data
225
    // and ensure that calling function does not cross the buffer border
226
    // even if we did not read anything here. Also it ensures that read size
227
    // is not less than CRYPT_BLOCK_SIZE, so we can align it without risk
228
    // to make it zero.
229
    if (DataSize>0)
230
      memmove(Inp.InBuf,Inp.InBuf+Inp.InAddr,DataSize);
231
    Inp.InAddr=0;
232
    ReadTop=DataSize;
233
  }
234
  else
235
    DataSize=ReadTop;
236
  int ReadCode=UnpIO->UnpRead(Inp.InBuf+DataSize,BitInput::MAX_SIZE-DataSize);
237
  if (ReadCode>0)
238
    ReadTop+=ReadCode;
239
  ReadBorder=ReadTop-30;
240
  BlockHeader.BlockStart=Inp.InAddr;
241
  if (BlockHeader.BlockSize!=-1) // '-1' means not defined yet.
242
    ReadBorder=Min(ReadBorder,BlockHeader.BlockStart+BlockHeader.BlockSize-1);
243
  return ReadCode!=-1;
244
}
245
246
247
void Unpack::UnpWriteBuf()
248
{
249
  size_t WrittenBorder=WrPtr;
250
  size_t FullWriteSize=(UnpPtr-WrittenBorder)&MaxWinMask;
251
  size_t WriteSizeLeft=FullWriteSize;
252
  bool NotAllFiltersProcessed=false;
253
  for (size_t I=0;I<Filters.Size();I++)
254
  {
255
    // Here we apply filters to data which we need to write.
256
    // We always copy data to virtual machine memory before processing.
257
    // We cannot process them just in place in Window buffer, because
258
    // these data can be used for future string matches, so we must
259
    // preserve them in original form.
260
261
    UnpackFilter *flt=&Filters[I];
262
    if (flt->Type==FILTER_NONE)
263
      continue;
264
    if (flt->NextWindow)
265
    {
266
      // Here we skip filters which have block start in current data range
267
      // due to address warp around in circular dictionary, but actually
268
      // belong to next dictionary block. If such filter start position
269
      // is included to current write range, then we reset 'NextWindow' flag.
270
      // In fact we can reset it even without such check, because current
271
      // implementation seems to guarantee 'NextWindow' flag reset after
272
      // buffer writing for all existing filters. But let's keep this check
273
      // just in case. Compressor guarantees that distance between
274
      // filter block start and filter storing position cannot exceed
275
      // the dictionary size. So if we covered the filter block start with
276
      // our write here, we can safely assume that filter is applicable
277
      // to next block on no further wrap arounds is possible.
278
      if (((flt->BlockStart-WrPtr)&MaxWinMask)<=FullWriteSize)
279
        flt->NextWindow=false;
280
      continue;
281
    }
282
    uint BlockStart=flt->BlockStart;
283
    uint BlockLength=flt->BlockLength;
284
    if (((BlockStart-WrittenBorder)&MaxWinMask)<WriteSizeLeft)
285
    {
286
      if (WrittenBorder!=BlockStart)
287
      {
288
        UnpWriteArea(WrittenBorder,BlockStart);
289
        WrittenBorder=BlockStart;
290
        WriteSizeLeft=(UnpPtr-WrittenBorder)&MaxWinMask;
291
      }
292
      if (BlockLength<=WriteSizeLeft)
293
      {
294
        if (BlockLength>0)
295
        {
296
          uint BlockEnd=(BlockStart+BlockLength)&MaxWinMask;
297
298
          FilterSrcMemory.Alloc(BlockLength);
299
          byte *Mem=&FilterSrcMemory[0];
300
          if (BlockStart<BlockEnd || BlockEnd==0)
301
          {
302
            if (Fragmented)
303
              FragWindow.CopyData(Mem,BlockStart,BlockLength);
304
            else
305
              memcpy(Mem,Window+BlockStart,BlockLength);
306
          }
307
          else
308
          {
309
            size_t FirstPartLength=size_t(MaxWinSize-BlockStart);
310
            if (Fragmented)
311
            {
312
              FragWindow.CopyData(Mem,BlockStart,FirstPartLength);
313
              FragWindow.CopyData(Mem+FirstPartLength,0,BlockEnd);
314
            }
315
            else
316
            {
317
              memcpy(Mem,Window+BlockStart,FirstPartLength);
318
              memcpy(Mem+FirstPartLength,Window,BlockEnd);
319
            }
320
          }
321
322
          byte *OutMem=ApplyFilter(Mem,BlockLength,flt);
323
324
          Filters[I].Type=FILTER_NONE;
325
326
          if (OutMem!=NULL)
327
            UnpIO->UnpWrite(OutMem,BlockLength);
328
329
          UnpSomeRead=true;
330
          WrittenFileSize+=BlockLength;
331
          WrittenBorder=BlockEnd;
332
          WriteSizeLeft=(UnpPtr-WrittenBorder)&MaxWinMask;
333
        }
334
      }
335
      else
336
      {
337
        // Current filter intersects the window write border, so we adjust
338
        // the window border to process this filter next time, not now.
339
        WrPtr=WrittenBorder;
340
341
        // Since Filter start position can only increase, we quit processing
342
        // all following filters for this data block and reset 'NextWindow'
343
        // flag for them.
344
        for (size_t J=I;J<Filters.Size();J++)
345
        {
346
          UnpackFilter *flt=&Filters[J];
347
          if (flt->Type!=FILTER_NONE)
348
            flt->NextWindow=false;
349
        }
350
351
        // Do not write data left after current filter now.
352
        NotAllFiltersProcessed=true;
353
        break;
354
      }
355
    }
356
  }
357
358
  // Remove processed filters from queue.
359
  size_t EmptyCount=0;
360
  for (size_t I=0;I<Filters.Size();I++)
361
  {
362
    if (EmptyCount>0)
363
      Filters[I-EmptyCount]=Filters[I];
364
    if (Filters[I].Type==FILTER_NONE)
365
      EmptyCount++;
366
  }
367
  if (EmptyCount>0)
368
    Filters.Alloc(Filters.Size()-EmptyCount);
369
370
  if (!NotAllFiltersProcessed) // Only if all filters are processed.
371
  {
372
    // Write data left after last filter.
373
    UnpWriteArea(WrittenBorder,UnpPtr);
374
    WrPtr=UnpPtr;
375
  }
376
377
  // We prefer to write data in blocks not exceeding UNPACK_MAX_WRITE
378
  // instead of potentially huge MaxWinSize blocks.
379
  WriteBorder=(UnpPtr+Min(MaxWinSize,UNPACK_MAX_WRITE))&MaxWinMask;
380
381
  // Choose the nearest among WriteBorder and WrPtr actual written border.
382
  // If border is equal to UnpPtr, it means that we have MaxWinSize data ahead.
383
  if (WriteBorder==UnpPtr || 
384
      WrPtr!=UnpPtr && ((WrPtr-UnpPtr)&MaxWinMask)<((WriteBorder-UnpPtr)&MaxWinMask))
385
    WriteBorder=WrPtr;
386
}
387
388
389
uint Unpack::FilterItanium_GetBits(byte *Data,int BitPos,int BitCount)
390
{
391
  int InAddr=BitPos/8;
392
  int InBit=BitPos&7;
393
  uint BitField=(uint)Data[InAddr++];
394
  BitField|=(uint)Data[InAddr++] << 8;
395
  BitField|=(uint)Data[InAddr++] << 16;
396
  BitField|=(uint)Data[InAddr] << 24;
397
  BitField >>= InBit;
398
  return(BitField & (0xffffffff>>(32-BitCount)));
399
}
400
401
402
void Unpack::FilterItanium_SetBits(byte *Data,uint BitField,int BitPos,int BitCount)
403
{
404
  int InAddr=BitPos/8;
405
  int InBit=BitPos&7;
406
  uint AndMask=0xffffffff>>(32-BitCount);
407
  AndMask=~(AndMask<<InBit);
408
409
  BitField<<=InBit;
410
411
  for (uint I=0;I<4;I++)
412
  {
413
    Data[InAddr+I]&=AndMask;
414
    Data[InAddr+I]|=BitField;
415
    AndMask=(AndMask>>8)|0xff000000;
416
    BitField>>=8;
417
  }
418
}
419
420
421
inline uint GetFiltData32(byte *Data)
422
{
423
#if defined(BIG_ENDIAN) || !defined(ALLOW_NOT_ALIGNED_INT) || !defined(PRESENT_INT32)
424
  uint Value=GET_UINT32((uint)Data[0]|((uint)Data[1]<<8)|((uint)Data[2]<<16)|((uint)Data[3]<<24));
425
#else
426
  uint Value=GET_UINT32(*(uint32 *)Data);
427
#endif
428
  return Value;
429
}
430
431
432
inline void SetFiltData32(byte *Data,uint Value)
433
{
434
#if defined(BIG_ENDIAN) || !defined(ALLOW_NOT_ALIGNED_INT) || !defined(PRESENT_INT32)
435
   Data[0]=(byte)Value;
436
   Data[1]=(byte)(Value>>8);
437
   Data[2]=(byte)(Value>>16);
438
   Data[3]=(byte)(Value>>24);
439
#else
440
   *(int32 *)Data=Value;
441
#endif
442
}
443
444
445
byte* Unpack::ApplyFilter(byte *Data,uint DataSize,UnpackFilter *Flt)
446
{
447
  byte *SrcData=Data;
448
  switch(Flt->Type)
449
  {
450
    case FILTER_E8:
451
    case FILTER_E8E9:
452
      {
453
        uint FileOffset=(uint)WrittenFileSize;
454
455
        const int FileSize=0x1000000;
456
        byte CmpByte2=Flt->Type==FILTER_E8E9 ? 0xe9:0xe8;
457
        for (uint CurPos=0;(int)CurPos<(int)DataSize-4;)
458
        {
459
          byte CurByte=*(Data++);
460
          CurPos++;
461
          if (CurByte==0xe8 || CurByte==CmpByte2)
462
          {
463
            uint Offset=(CurPos+FileOffset)%FileSize;
464
            uint Addr=GetFiltData32(Data);
465
466
            // We check 0x80000000 bit instead of '< 0' comparison
467
            // not assuming int32 presence or uint size and endianness.
468
            if ((Addr & 0x80000000)!=0)              // Addr<0
469
            {
470
              if (((Addr+Offset) & 0x80000000)==0)   // Addr+Offset>=0
471
                SetFiltData32(Data,Addr+FileSize);
472
            }
473
            else
474
              if (((Addr-FileSize) & 0x80000000)!=0) // Addr<FileSize
475
                SetFiltData32(Data,Addr-Offset);
476
477
            Data+=4;
478
            CurPos+=4;
479
          }
480
        }
481
      }
482
      return SrcData;
483
    case FILTER_ARM:
484
      {
485
        uint FileOffset=(uint)WrittenFileSize;
486
        for (uint CurPos=0;(int)CurPos<(int)DataSize-3;CurPos+=4)
487
        {
488
          byte *D=Data+CurPos;
489
          if (D[3]==0xeb) // BL command with '1110' (Always) condition.
490
          {
491
            uint Offset=D[0]+uint(D[1])*0x100+uint(D[2])*0x10000;
492
            Offset-=(FileOffset+CurPos)/4;
493
            D[0]=(byte)Offset;
494
            D[1]=(byte)(Offset>>8);
495
            D[2]=(byte)(Offset>>16);
496
          }
497
        }
498
      }
499
      return SrcData;
500
    case FILTER_ITANIUM:
501
      {
502
        uint FileOffset=(uint)WrittenFileSize;
503
504
        uint CurPos=0;
505
506
        FileOffset>>=4;
507
508
        while ((int)CurPos<(int)DataSize-21)
509
        {
510
          int Byte=(Data[0]&0x1f)-0x10;
511
          if (Byte>=0)
512
          {
513
            static byte Masks[16]={4,4,6,6,0,0,7,7,4,4,0,0,4,4,0,0};
514
            byte CmdMask=Masks[Byte];
515
            if (CmdMask!=0)
516
              for (int I=0;I<=2;I++)
517
                if (CmdMask & (1<<I))
518
                {
519
                  int StartPos=I*41+5;
520
                  int OpType=FilterItanium_GetBits(Data,StartPos+37,4);
521
                  if (OpType==5)
522
                  {
523
                    int Offset=FilterItanium_GetBits(Data,StartPos+13,20);
524
                    FilterItanium_SetBits(Data,(Offset-FileOffset)&0xfffff,StartPos+13,20);
525
                  }
526
                }
527
          }
528
          Data+=16;
529
          CurPos+=16;
530
          FileOffset++;
531
        }
532
      }
533
      return SrcData;
534
    case FILTER_AUDIO:
535
      {
536
        uint Channels=Flt->Channels;
537
538
        byte *SrcData=Data;
539
540
        FilterDstMemory.Alloc(DataSize);
541
        byte *DstData=&FilterDstMemory[0];
542
        
543
        for (uint CurChannel=0;CurChannel<Channels;CurChannel++)
544
        {
545
          uint PrevByte=0,PrevDelta=0,Dif[7];
546
          int D1=0,D2=0,D3;
547
          int K1=0,K2=0,K3=0;
548
          memset(Dif,0,sizeof(Dif));
549
550
          for (uint I=CurChannel,ByteCount=0;I<DataSize;I+=Channels,ByteCount++)
551
          {
552
            D3=D2;
553
            D2=PrevDelta-D1;
554
            D1=PrevDelta;
555
556
            uint Predicted=8*PrevByte+K1*D1+K2*D2+K3*D3;
557
            Predicted=(Predicted>>3) & 0xff;
558
559
            uint CurByte=*(SrcData++);
560
561
            Predicted-=CurByte;
562
            DstData[I]=Predicted;
563
            PrevDelta=(signed char)(Predicted-PrevByte);
564
            PrevByte=Predicted;
565
566
            int D=((signed char)CurByte)<<3;
567
568
            Dif[0]+=abs(D);
569
            Dif[1]+=abs(D-D1);
570
            Dif[2]+=abs(D+D1);
571
            Dif[3]+=abs(D-D2);
572
            Dif[4]+=abs(D+D2);
573
            Dif[5]+=abs(D-D3);
574
            Dif[6]+=abs(D+D3);
575
576
            if ((ByteCount & 0x1f)==0)
577
            {
578
              uint MinDif=Dif[0],NumMinDif=0;
579
              Dif[0]=0;
580
              for (uint J=1;J<ASIZE(Dif);J++)
581
              {
582
                if (Dif[J]<MinDif)
583
                {
584
                  MinDif=Dif[J];
585
                  NumMinDif=J;
586
                }
587
                Dif[J]=0;
588
              }
589
              switch(NumMinDif)
590
              {
591
                case 1: if (K1>=-16) K1--; break;
592
                case 2: if (K1 < 16) K1++; break;
593
                case 3: if (K2>=-16) K2--; break;
594
                case 4: if (K2 < 16) K2++; break;
595
                case 5: if (K3>=-16) K3--; break;
596
                case 6: if (K3 < 16) K3++; break;
597
              }
598
            }
599
          }
600
        }
601
        return DstData;
602
      }
603
    case FILTER_DELTA:
604
      {
605
        uint Channels=Flt->Channels,SrcPos=0;
606
607
        FilterDstMemory.Alloc(DataSize);
608
        byte *DstData=&FilterDstMemory[0];
609
610
        // Bytes from same channels are grouped to continual data blocks,
611
        // so we need to place them back to their interleaving positions.
612
        for (uint CurChannel=0;CurChannel<Channels;CurChannel++)
613
        {
614
          byte PrevByte=0;
615
          for (uint DestPos=CurChannel;DestPos<DataSize;DestPos+=Channels)
616
            DstData[DestPos]=(PrevByte-=Data[SrcPos++]);
617
        }
618
        return DstData;
619
      }
620
    case FILTER_RGB:
621
      {
622
        uint Width=Flt->Width,PosR=Flt->PosR;
623
624
        byte *SrcData=Data;
625
626
        FilterDstMemory.Alloc(DataSize);
627
        byte *DstData=&FilterDstMemory[0];
628
        
629
        const int Channels=3;
630
631
        for (uint CurChannel=0;CurChannel<Channels;CurChannel++)
632
        {
633
          uint PrevByte=0;
634
635
          for (uint I=CurChannel;I<DataSize;I+=Channels)
636
          {
637
            uint Predicted;
638
            int UpperPos=I-Width;
639
            if (UpperPos>=3)
640
            {
641
              byte *UpperData=DstData+UpperPos;
642
              uint UpperByte=*UpperData;
643
              uint UpperLeftByte=*(UpperData-3);
644
              Predicted=PrevByte+UpperByte-UpperLeftByte;
645
              int pa=abs((int)(Predicted-PrevByte));
646
              int pb=abs((int)(Predicted-UpperByte));
647
              int pc=abs((int)(Predicted-UpperLeftByte));
648
              if (pa<=pb && pa<=pc)
649
                Predicted=PrevByte;
650
              else
651
                if (pb<=pc)
652
                  Predicted=UpperByte;
653
                else
654
                  Predicted=UpperLeftByte;
655
            }
656
            else
657
              Predicted=PrevByte;
658
            DstData[I]=PrevByte=(byte)(Predicted-*(SrcData++));
659
          }
660
        }
661
        for (uint I=PosR,Border=DataSize-2;I<Border;I+=3)
662
        {
663
          byte G=DstData[I+1];
664
          DstData[I]+=G;
665
          DstData[I+2]+=G;
666
        }
667
        return DstData;
668
      }
669
670
  }
671
  return NULL;
672
}
673
674
675
void Unpack::UnpWriteArea(size_t StartPtr,size_t EndPtr)
676
{
677
  if (EndPtr!=StartPtr)
678
    UnpSomeRead=true;
679
  if (EndPtr<StartPtr)
680
    UnpAllBuf=true;
681
682
  if (Fragmented)
683
  {
684
    size_t SizeToWrite=(EndPtr-StartPtr) & MaxWinMask;
685
    while (SizeToWrite>0)
686
    {
687
      size_t BlockSize=FragWindow.GetBlockSize(StartPtr,SizeToWrite);
688
      UnpWriteData(&FragWindow[StartPtr],BlockSize);
689
      SizeToWrite-=BlockSize;
690
      StartPtr=(StartPtr+BlockSize) & MaxWinMask;
691
    }
692
  }
693
  else
694
    if (EndPtr<StartPtr)
695
    {
696
      UnpWriteData(Window+StartPtr,MaxWinSize-StartPtr);
697
      UnpWriteData(Window,EndPtr);
698
    }
699
    else
700
      UnpWriteData(Window+StartPtr,EndPtr-StartPtr);
701
}
702
703
704
void Unpack::UnpWriteData(byte *Data,size_t Size)
705
{
706
  if (WrittenFileSize>=DestUnpSize)
707
    return;
708
  size_t WriteSize=Size;
709
  int64 LeftToWrite=DestUnpSize-WrittenFileSize;
710
  if ((int64)WriteSize>LeftToWrite)
711
    WriteSize=(size_t)LeftToWrite;
712
  UnpIO->UnpWrite(Data,WriteSize);
713
  WrittenFileSize+=Size;
714
}
715
716
717
bool Unpack::ReadBlockHeader(BitInput &Inp,UnpackBlockHeader &Header)
718
{
719
  Header.HeaderSize=0;
720
721
  if (!Inp.ExternalBuffer && Inp.InAddr>ReadTop-7)
722
    if (!UnpReadBuf())
723
      return false;
724
  Inp.faddbits((8-Inp.InBit)&7);
725
  
726
  byte BlockFlags=Inp.fgetbits()>>8;
727
  Inp.faddbits(8);
728
  uint ByteCount=((BlockFlags>>3)&3)+1; // Block size byte count.
729
  
730
  if (ByteCount==4)
731
    return false;
732
733
  Header.HeaderSize=2+ByteCount;
734
735
  Header.BlockBitSize=(BlockFlags&7)+1;
736
737
  byte SavedCheckSum=Inp.fgetbits()>>8;
738
  Inp.faddbits(8);
739
740
  int BlockSize=0;
741
  for (uint I=0;I<ByteCount;I++)
742
  {
743
    BlockSize+=(Inp.fgetbits()>>8)<<(I*8);
744
    Inp.addbits(8);
745
  }
746
747
  Header.BlockSize=BlockSize;
748
  byte CheckSum=byte(0x5a^BlockFlags^BlockSize^(BlockSize>>8)^(BlockSize>>16));
749
  if (CheckSum!=SavedCheckSum)
750
    return false;
751
752
  Header.BlockStart=Inp.InAddr;
753
  ReadBorder=Min(ReadBorder,Header.BlockStart+Header.BlockSize-1);
754
755
  Header.LastBlockInFile=(BlockFlags & 0x40)!=0;
756
  Header.TablePresent=(BlockFlags & 0x80)!=0;
757
  return true;
758
}
759
760
761
bool Unpack::ReadTables(BitInput &Inp,UnpackBlockHeader &Header,UnpackBlockTables &Tables)
762
{
763
  if (!Header.TablePresent)
764
    return true;
765
766
  if (!Inp.ExternalBuffer && Inp.InAddr>ReadTop-25)
767
    if (!UnpReadBuf())
768
      return false;
769
770
  byte BitLength[BC];
771
  for (int I=0;I<BC;I++)
772
  {
773
    int Length=(byte)(Inp.fgetbits() >> 12);
774
    Inp.faddbits(4);
775
    if (Length==15)
776
    {
777
      int ZeroCount=(byte)(Inp.fgetbits() >> 12);
778
      Inp.faddbits(4);
779
      if (ZeroCount==0)
780
        BitLength[I]=15;
781
      else
782
      {
783
        ZeroCount+=2;
784
        while (ZeroCount-- > 0 && I<sizeof(BitLength)/sizeof(BitLength[0]))
785
          BitLength[I++]=0;
786
        I--;
787
      }
788
    }
789
    else
790
      BitLength[I]=Length;
791
  }
792
793
  MakeDecodeTables(BitLength,&Tables.BD,BC);
794
795
  byte Table[HUFF_TABLE_SIZE];
796
  const int TableSize=HUFF_TABLE_SIZE;
797
  for (int I=0;I<TableSize;)
798
  {
799
    if (!Inp.ExternalBuffer && Inp.InAddr>ReadTop-5)
800
      if (!UnpReadBuf())
801
        return(false);
802
    int Number=DecodeNumber(Inp,&Tables.BD);
803
    if (Number<16)
804
    {
805
      Table[I]=Number;
806
      I++;
807
    }
808
    else
809
      if (Number<18)
810
      {
811
        int N;
812
        if (Number==16)
813
        {
814
          N=(Inp.fgetbits() >> 13)+3;
815
          Inp.faddbits(3);
816
        }
817
        else
818
        {
819
          N=(Inp.fgetbits() >> 9)+11;
820
          Inp.faddbits(7);
821
        }
822
        if (I>0)
823
          while (N-- > 0 && I<TableSize)
824
          {
825
            Table[I]=Table[I-1];
826
            I++;
827
          }
828
      }
829
      else
830
      {
831
        int N;
832
        if (Number==18)
833
        {
834
          N=(Inp.fgetbits() >> 13)+3;
835
          Inp.faddbits(3);
836
        }
837
        else
838
        {
839
          N=(Inp.fgetbits() >> 9)+11;
840
          Inp.faddbits(7);
841
        }
842
        while (N-- > 0 && I<TableSize)
843
          Table[I++]=0;
844
      }
845
  }
846
  if (!Inp.ExternalBuffer && Inp.InAddr>ReadTop)
847
    return(false);
848
  MakeDecodeTables(&Table[0],&Tables.LD,NC);
849
  MakeDecodeTables(&Table[NC],&Tables.DD,DC);
850
  MakeDecodeTables(&Table[NC+DC],&Tables.LDD,LDC);
851
  MakeDecodeTables(&Table[NC+DC+LDC],&Tables.RD,RC);
852
  return(true);
853
}
854
855
856
void Unpack::InitFilters()
857
{
858
  Filters.Reset();
859
}