Coverage Report

Created: 2023-06-07 06:02

/src/unrar/unpack20.cpp
Line
Count
Source (jump to first uncovered line)
1
#include "rar.hpp"
2
3
void Unpack::CopyString20(uint Length,uint Distance)
4
0
{
5
0
  LastDist=OldDist[OldDistPtr++]=Distance;
6
0
  OldDistPtr = OldDistPtr & 3; // Needed if RAR 1.5 file is called after RAR 2.0.
7
0
  LastLength=Length;
8
0
  DestUnpSize-=Length;
9
0
  CopyString(Length,Distance);
10
0
}
11
12
13
void Unpack::Unpack20(bool Solid)
14
0
{
15
0
  static unsigned char LDecode[]={0,1,2,3,4,5,6,7,8,10,12,14,16,20,24,28,32,40,48,56,64,80,96,112,128,160,192,224};
16
0
  static unsigned char LBits[]=  {0,0,0,0,0,0,0,0,1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 4, 4, 4,  4,  5,  5,  5,  5};
17
0
  static uint DDecode[]={0,1,2,3,4,6,8,12,16,24,32,48,64,96,128,192,256,384,512,768,1024,1536,2048,3072,4096,6144,8192,12288,16384,24576,32768U,49152U,65536,98304,131072,196608,262144,327680,393216,458752,524288,589824,655360,720896,786432,851968,917504,983040};
18
0
  static unsigned char DBits[]=  {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,    16,    16,    16,    16,    16,    16,    16,    16,    16,    16,    16,    16,    16,    16};
19
0
  static unsigned char SDDecode[]={0,4,8,16,32,64,128,192};
20
0
  static unsigned char SDBits[]=  {2,2,3, 4, 5, 6,  6,  6};
21
0
  uint Bits;
22
23
0
  if (Suspended)
24
0
    UnpPtr=WrPtr;
25
0
  else
26
0
  {
27
0
    UnpInitData(Solid);
28
0
    if (!UnpReadBuf())
29
0
      return;
30
0
    if ((!Solid || !TablesRead2) && !ReadTables20())
31
0
      return;
32
0
    --DestUnpSize;
33
0
  }
34
35
0
  while (DestUnpSize>=0)
36
0
  {
37
0
    UnpPtr&=MaxWinMask;
38
39
0
    if (Inp.InAddr>ReadTop-30)
40
0
      if (!UnpReadBuf())
41
0
        break;
42
0
    if (((WrPtr-UnpPtr) & MaxWinMask)<270 && WrPtr!=UnpPtr)
43
0
    {
44
0
      UnpWriteBuf20();
45
0
      if (Suspended)
46
0
        return;
47
0
    }
48
0
    if (UnpAudioBlock)
49
0
    {
50
0
      uint AudioNumber=DecodeNumber(Inp,&MD[UnpCurChannel]);
51
52
0
      if (AudioNumber==256)
53
0
      {
54
0
        if (!ReadTables20())
55
0
          break;
56
0
        continue;
57
0
      }
58
0
      Window[UnpPtr++]=DecodeAudio((int)AudioNumber);
59
0
      if (++UnpCurChannel==UnpChannels)
60
0
        UnpCurChannel=0;
61
0
      --DestUnpSize;
62
0
      continue;
63
0
    }
64
65
0
    uint Number=DecodeNumber(Inp,&BlockTables.LD);
66
0
    if (Number<256)
67
0
    {
68
0
      Window[UnpPtr++]=(byte)Number;
69
0
      --DestUnpSize;
70
0
      continue;
71
0
    }
72
0
    if (Number>269)
73
0
    {
74
0
      uint Length=LDecode[Number-=270]+3;
75
0
      if ((Bits=LBits[Number])>0)
76
0
      {
77
0
        Length+=Inp.getbits()>>(16-Bits);
78
0
        Inp.addbits(Bits);
79
0
      }
80
81
0
      uint DistNumber=DecodeNumber(Inp,&BlockTables.DD);
82
0
      uint Distance=DDecode[DistNumber]+1;
83
0
      if ((Bits=DBits[DistNumber])>0)
84
0
      {
85
0
        Distance+=Inp.getbits()>>(16-Bits);
86
0
        Inp.addbits(Bits);
87
0
      }
88
89
0
      if (Distance>=0x2000)
90
0
      {
91
0
        Length++;
92
0
        if (Distance>=0x40000L)
93
0
          Length++;
94
0
      }
95
96
0
      CopyString20(Length,Distance);
97
0
      continue;
98
0
    }
99
0
    if (Number==269)
100
0
    {
101
0
      if (!ReadTables20())
102
0
        break;
103
0
      continue;
104
0
    }
105
0
    if (Number==256)
106
0
    {
107
0
      CopyString20(LastLength,LastDist);
108
0
      continue;
109
0
    }
110
0
    if (Number<261)
111
0
    {
112
0
      uint Distance=OldDist[(OldDistPtr-(Number-256)) & 3];
113
0
      uint LengthNumber=DecodeNumber(Inp,&BlockTables.RD);
114
0
      uint Length=LDecode[LengthNumber]+2;
115
0
      if ((Bits=LBits[LengthNumber])>0)
116
0
      {
117
0
        Length+=Inp.getbits()>>(16-Bits);
118
0
        Inp.addbits(Bits);
119
0
      }
120
0
      if (Distance>=0x101)
121
0
      {
122
0
        Length++;
123
0
        if (Distance>=0x2000)
124
0
        {
125
0
          Length++;
126
0
          if (Distance>=0x40000)
127
0
            Length++;
128
0
        }
129
0
      }
130
0
      CopyString20(Length,Distance);
131
0
      continue;
132
0
    }
133
0
    if (Number<270)
134
0
    {
135
0
      uint Distance=SDDecode[Number-=261]+1;
136
0
      if ((Bits=SDBits[Number])>0)
137
0
      {
138
0
        Distance+=Inp.getbits()>>(16-Bits);
139
0
        Inp.addbits(Bits);
140
0
      }
141
0
      CopyString20(2,Distance);
142
0
      continue;
143
0
   }
144
0
  }
145
0
  ReadLastTables();
146
0
  UnpWriteBuf20();
147
0
}
148
149
150
void Unpack::UnpWriteBuf20()
151
0
{
152
0
  if (UnpPtr!=WrPtr)
153
0
    UnpSomeRead=true;
154
0
  if (UnpPtr<WrPtr)
155
0
  {
156
0
    UnpIO->UnpWrite(&Window[WrPtr],-(int)WrPtr & MaxWinMask);
157
0
    UnpIO->UnpWrite(Window,UnpPtr);
158
0
    UnpAllBuf=true;
159
0
  }
160
0
  else
161
0
    UnpIO->UnpWrite(&Window[WrPtr],UnpPtr-WrPtr);
162
0
  WrPtr=UnpPtr;
163
0
}
164
165
166
bool Unpack::ReadTables20()
167
0
{
168
0
  byte BitLength[BC20];
169
0
  byte Table[MC20*4];
170
0
  if (Inp.InAddr>ReadTop-25)
171
0
    if (!UnpReadBuf())
172
0
      return false;
173
0
  uint BitField=Inp.getbits();
174
0
  UnpAudioBlock=(BitField & 0x8000)!=0;
175
176
0
  if (!(BitField & 0x4000))
177
0
    memset(UnpOldTable20,0,sizeof(UnpOldTable20));
178
0
  Inp.addbits(2);
179
180
0
  uint TableSize;
181
0
  if (UnpAudioBlock)
182
0
  {
183
0
    UnpChannels=((BitField>>12) & 3)+1;
184
0
    if (UnpCurChannel>=UnpChannels)
185
0
      UnpCurChannel=0;
186
0
    Inp.addbits(2);
187
0
    TableSize=MC20*UnpChannels;
188
0
  }
189
0
  else
190
0
    TableSize=NC20+DC20+RC20;
191
192
0
  for (uint I=0;I<BC20;I++)
193
0
  {
194
0
    BitLength[I]=(byte)(Inp.getbits() >> 12);
195
0
    Inp.addbits(4);
196
0
  }
197
0
  MakeDecodeTables(BitLength,&BlockTables.BD,BC20);
198
0
  for (uint I=0;I<TableSize;)
199
0
  {
200
0
    if (Inp.InAddr>ReadTop-5)
201
0
      if (!UnpReadBuf())
202
0
        return false;
203
0
    uint Number=DecodeNumber(Inp,&BlockTables.BD);
204
0
    if (Number<16)
205
0
    {
206
0
      Table[I]=(Number+UnpOldTable20[I]) & 0xf;
207
0
      I++;
208
0
    }
209
0
    else
210
0
      if (Number==16)
211
0
      {
212
0
        uint N=(Inp.getbits() >> 14)+3;
213
0
        Inp.addbits(2);
214
0
        if (I==0)
215
0
          return false; // We cannot have "repeat previous" code at the first position.
216
0
        else
217
0
          while (N-- > 0 && I<TableSize)
218
0
          {
219
0
            Table[I]=Table[I-1];
220
0
            I++;
221
0
          }
222
0
      }
223
0
      else
224
0
      {
225
0
        uint N;
226
0
        if (Number==17)
227
0
        {
228
0
          N=(Inp.getbits() >> 13)+3;
229
0
          Inp.addbits(3);
230
0
        }
231
0
        else
232
0
        {
233
0
          N=(Inp.getbits() >> 9)+11;
234
0
          Inp.addbits(7);
235
0
        }
236
0
        while (N-- > 0 && I<TableSize)
237
0
          Table[I++]=0;
238
0
      }
239
0
  }
240
0
  TablesRead2=true;
241
0
  if (Inp.InAddr>ReadTop)
242
0
    return true;
243
0
  if (UnpAudioBlock)
244
0
    for (uint I=0;I<UnpChannels;I++)
245
0
      MakeDecodeTables(&Table[I*MC20],&MD[I],MC20);
246
0
  else
247
0
  {
248
0
    MakeDecodeTables(&Table[0],&BlockTables.LD,NC20);
249
0
    MakeDecodeTables(&Table[NC20],&BlockTables.DD,DC20);
250
0
    MakeDecodeTables(&Table[NC20+DC20],&BlockTables.RD,RC20);
251
0
  }
252
0
  memcpy(UnpOldTable20,Table,TableSize);
253
0
  return true;
254
0
}
255
256
257
void Unpack::ReadLastTables()
258
0
{
259
0
  if (ReadTop>=Inp.InAddr+5)
260
0
    if (UnpAudioBlock)
261
0
    {
262
0
      if (DecodeNumber(Inp,&MD[UnpCurChannel])==256)
263
0
        ReadTables20();
264
0
    }
265
0
    else
266
0
      if (DecodeNumber(Inp,&BlockTables.LD)==269)
267
0
        ReadTables20();
268
0
}
269
270
271
void Unpack::UnpInitData20(int Solid)
272
2
{
273
2
  if (!Solid)
274
2
  {
275
2
    TablesRead2=false;
276
2
    UnpAudioBlock=false;
277
2
    UnpChannelDelta=0;
278
2
    UnpCurChannel=0;
279
2
    UnpChannels=1;
280
281
2
    memset(AudV,0,sizeof(AudV));
282
2
    memset(UnpOldTable20,0,sizeof(UnpOldTable20));
283
2
    memset(MD,0,sizeof(MD));
284
2
  }
285
2
}
286
287
288
byte Unpack::DecodeAudio(int Delta)
289
0
{
290
0
  struct AudioVariables *V=&AudV[UnpCurChannel];
291
0
  V->ByteCount++;
292
0
  V->D4=V->D3;
293
0
  V->D3=V->D2;
294
0
  V->D2=V->LastDelta-V->D1;
295
0
  V->D1=V->LastDelta;
296
0
  int PCh=8*V->LastChar+V->K1*V->D1+V->K2*V->D2+V->K3*V->D3+V->K4*V->D4+V->K5*UnpChannelDelta;
297
0
  PCh=(PCh>>3) & 0xFF;
298
299
0
  uint Ch=PCh-Delta;
300
301
0
  int D=(signed char)Delta;
302
  // Left shift of negative value is undefined behavior in C++,
303
  // so we cast it to unsigned to follow the standard.
304
0
  D=(uint)D<<3;
305
306
0
  V->Dif[0]+=abs(D);
307
0
  V->Dif[1]+=abs(D-V->D1);
308
0
  V->Dif[2]+=abs(D+V->D1);
309
0
  V->Dif[3]+=abs(D-V->D2);
310
0
  V->Dif[4]+=abs(D+V->D2);
311
0
  V->Dif[5]+=abs(D-V->D3);
312
0
  V->Dif[6]+=abs(D+V->D3);
313
0
  V->Dif[7]+=abs(D-V->D4);
314
0
  V->Dif[8]+=abs(D+V->D4);
315
0
  V->Dif[9]+=abs(D-UnpChannelDelta);
316
0
  V->Dif[10]+=abs(D+UnpChannelDelta);
317
318
0
  UnpChannelDelta=V->LastDelta=(signed char)(Ch-V->LastChar);
319
0
  V->LastChar=Ch;
320
321
0
  if ((V->ByteCount & 0x1F)==0)
322
0
  {
323
0
    uint MinDif=V->Dif[0],NumMinDif=0;
324
0
    V->Dif[0]=0;
325
0
    for (uint I=1;I<ASIZE(V->Dif);I++)
326
0
    {
327
0
      if (V->Dif[I]<MinDif)
328
0
      {
329
0
        MinDif=V->Dif[I];
330
0
        NumMinDif=I;
331
0
      }
332
0
      V->Dif[I]=0;
333
0
    }
334
0
    switch(NumMinDif)
335
0
    {
336
0
      case 1:
337
0
        if (V->K1>=-16)
338
0
          V->K1--;
339
0
        break;
340
0
      case 2:
341
0
        if (V->K1<16)
342
0
          V->K1++;
343
0
        break;
344
0
      case 3:
345
0
        if (V->K2>=-16)
346
0
          V->K2--;
347
0
        break;
348
0
      case 4:
349
0
        if (V->K2<16)
350
0
          V->K2++;
351
0
        break;
352
0
      case 5:
353
0
        if (V->K3>=-16)
354
0
          V->K3--;
355
0
        break;
356
0
      case 6:
357
0
        if (V->K3<16)
358
0
          V->K3++;
359
0
        break;
360
0
      case 7:
361
0
        if (V->K4>=-16)
362
0
          V->K4--;
363
0
        break;
364
0
      case 8:
365
0
        if (V->K4<16)
366
0
          V->K4++;
367
0
        break;
368
0
      case 9:
369
0
        if (V->K5>=-16)
370
0
          V->K5--;
371
0
        break;
372
0
      case 10:
373
0
        if (V->K5<16)
374
0
          V->K5++;
375
0
        break;
376
0
    }
377
0
  }
378
0
  return (byte)Ch;
379
0
}