Coverage Report

Created: 2025-04-11 06:56

/src/unrar/rarvm.cpp
Line
Count
Source (jump to first uncovered line)
1
#include "rar.hpp"
2
3
RarVM::RarVM()
4
12.7k
{
5
12.7k
  Mem=NULL;
6
12.7k
}
7
8
9
RarVM::~RarVM()
10
12.7k
{
11
12.7k
  delete[] Mem;
12
12.7k
}
13
14
15
void RarVM::Init()
16
71.8k
{
17
71.8k
  if (Mem==NULL)
18
631
    Mem=new byte[VM_MEMSIZE+4];
19
71.8k
}
20
21
22
void RarVM::Execute(VM_PreparedProgram *Prg)
23
21.1k
{
24
21.1k
  memcpy(R,Prg->InitR,sizeof(Prg->InitR));
25
21.1k
  Prg->FilteredData=NULL;
26
21.1k
  if (Prg->Type!=VMSF_NONE)
27
0
  {
28
0
    bool Success=ExecuteStandardFilter(Prg->Type);
29
0
    uint BlockSize=Prg->InitR[4] & VM_MEMMASK;
30
0
    Prg->FilteredDataSize=BlockSize;
31
0
    if (Prg->Type==VMSF_DELTA || Prg->Type==VMSF_RGB || Prg->Type==VMSF_AUDIO)
32
0
      Prg->FilteredData=2*BlockSize>VM_MEMSIZE || !Success ? Mem:Mem+BlockSize;
33
0
    else
34
0
      Prg->FilteredData=Mem;
35
0
  }
36
21.1k
}
37
38
39
void RarVM::Prepare(byte *Code,uint CodeSize,VM_PreparedProgram *Prg)
40
1.80k
{
41
  // Calculate the single byte XOR checksum to check validity of VM code.
42
1.80k
  byte XorSum=0;
43
6.00k
  for (uint I=1;I<CodeSize;I++)
44
4.20k
    XorSum^=Code[I];
45
46
1.80k
  if (XorSum!=Code[0])
47
539
    return;
48
49
1.26k
  struct StandardFilters
50
1.26k
  {
51
1.26k
    uint Length;
52
1.26k
    uint CRC;
53
1.26k
    VM_StandardFilters Type;
54
1.26k
  } static StdList[]={
55
1.26k
    53, 0xad576887, VMSF_E8,
56
1.26k
    57, 0x3cd7e57e, VMSF_E8E9,
57
1.26k
   120, 0x3769893f, VMSF_ITANIUM,
58
1.26k
    29, 0x0e06077d, VMSF_DELTA,
59
1.26k
   149, 0x1c2c5dc8, VMSF_RGB,
60
1.26k
   216, 0xbc85e701, VMSF_AUDIO
61
1.26k
  };
62
1.26k
  uint CodeCRC=CRC32(0xffffffff,Code,CodeSize)^0xffffffff;
63
8.82k
  for (uint I=0;I<ASIZE(StdList);I++)
64
7.56k
    if (StdList[I].CRC==CodeCRC && StdList[I].Length==CodeSize)
65
0
    {
66
0
      Prg->Type=StdList[I].Type;
67
0
      break;
68
0
    }
69
1.26k
}
70
71
72
uint RarVM::ReadData(BitInput &Inp)
73
183k
{
74
183k
  uint Data=Inp.fgetbits();
75
183k
  switch(Data&0xc000)
76
183k
  {
77
133k
    case 0:
78
133k
      Inp.faddbits(6);
79
133k
      return (Data>>10)&0xf;
80
23.8k
    case 0x4000:
81
23.8k
      if ((Data&0x3c00)==0)
82
3.94k
      {
83
3.94k
        Data=0xffffff00|((Data>>2)&0xff);
84
3.94k
        Inp.faddbits(14);
85
3.94k
      }
86
19.8k
      else
87
19.8k
      {
88
19.8k
        Data=(Data>>6)&0xff;
89
19.8k
        Inp.faddbits(10);
90
19.8k
      }
91
23.8k
      return Data;
92
13.3k
    case 0x8000:
93
13.3k
      Inp.faddbits(2);
94
13.3k
      Data=Inp.fgetbits();
95
13.3k
      Inp.faddbits(16);
96
13.3k
      return Data;
97
12.7k
    default:
98
12.7k
      Inp.faddbits(2);
99
12.7k
      Data=(Inp.fgetbits()<<16);
100
12.7k
      Inp.faddbits(16);
101
12.7k
      Data|=Inp.fgetbits();
102
12.7k
      Inp.faddbits(16);
103
12.7k
      return Data;
104
183k
  }
105
183k
}
106
107
108
void RarVM::SetMemory(size_t Pos,byte *Data,size_t DataSize)
109
25.9k
{
110
25.9k
  if (Pos<VM_MEMSIZE && Data!=Mem+Pos)
111
24.6k
  {
112
    // We can have NULL Data for invalid filters with DataSize==0. While most
113
    // sensible memmove implementations do not care about data if size is 0,
114
    // let's follow the standard and check the size first.
115
24.6k
    size_t CopySize=Min(DataSize,VM_MEMSIZE-Pos);
116
24.6k
    if (CopySize!=0)
117
23.0k
      memmove(Mem+Pos,Data,CopySize);
118
24.6k
  }
119
25.9k
}
120
121
122
bool RarVM::ExecuteStandardFilter(VM_StandardFilters FilterType)
123
0
{
124
0
  switch(FilterType)
125
0
  {
126
0
    case VMSF_E8:
127
0
    case VMSF_E8E9:
128
0
      {
129
0
        byte *Data=Mem;
130
0
        uint DataSize=R[4],FileOffset=R[6];
131
132
0
        if (DataSize>VM_MEMSIZE || DataSize<4)
133
0
          return false;
134
135
0
        const uint FileSize=0x1000000;
136
0
        byte CmpByte2=FilterType==VMSF_E8E9 ? 0xe9:0xe8;
137
0
        for (uint CurPos=0;CurPos<DataSize-4;)
138
0
        {
139
0
          byte CurByte=*(Data++);
140
0
          CurPos++;
141
0
          if (CurByte==0xe8 || CurByte==CmpByte2)
142
0
          {
143
0
            uint Offset=CurPos+FileOffset;
144
0
            uint Addr=RawGet4(Data);
145
146
            // We check 0x80000000 bit instead of '< 0' comparison
147
            // not assuming int32 presence or uint size and endianness.
148
0
            if ((Addr & 0x80000000)!=0)              // Addr<0
149
0
            {
150
0
              if (((Addr+Offset) & 0x80000000)==0)   // Addr+Offset>=0
151
0
                RawPut4(Addr+FileSize,Data);
152
0
            }
153
0
            else
154
0
              if (((Addr-FileSize) & 0x80000000)!=0) // Addr<FileSize
155
0
                RawPut4(Addr-Offset,Data);
156
0
            Data+=4;
157
0
            CurPos+=4;
158
0
          }
159
0
        }
160
0
      }
161
0
      break;
162
0
    case VMSF_ITANIUM:
163
0
      {
164
0
        byte *Data=Mem;
165
0
        uint DataSize=R[4],FileOffset=R[6];
166
167
0
        if (DataSize>VM_MEMSIZE || DataSize<21)
168
0
          return false;
169
170
0
        uint CurPos=0;
171
172
0
        FileOffset>>=4;
173
174
0
        while (CurPos<DataSize-21)
175
0
        {
176
0
          int Byte=(Data[0]&0x1f)-0x10;
177
0
          if (Byte>=0)
178
0
          {
179
0
            static byte Masks[16]={4,4,6,6,0,0,7,7,4,4,0,0,4,4,0,0};
180
0
            byte CmdMask=Masks[Byte];
181
0
            if (CmdMask!=0)
182
0
              for (uint I=0;I<=2;I++)
183
0
                if (CmdMask & (1<<I))
184
0
                {
185
0
                  uint StartPos=I*41+5;
186
0
                  uint OpType=FilterItanium_GetBits(Data,StartPos+37,4);
187
0
                  if (OpType==5)
188
0
                  {
189
0
                    uint Offset=FilterItanium_GetBits(Data,StartPos+13,20);
190
0
                    FilterItanium_SetBits(Data,(Offset-FileOffset)&0xfffff,StartPos+13,20);
191
0
                  }
192
0
                }
193
0
          }
194
0
          Data+=16;
195
0
          CurPos+=16;
196
0
          FileOffset++;
197
0
        }
198
0
      }
199
0
      break;
200
0
    case VMSF_DELTA:
201
0
      {
202
0
        uint DataSize=R[4],Channels=R[0],SrcPos=0,Border=DataSize*2;
203
0
        if (DataSize>VM_MEMSIZE/2 || Channels>MAX3_UNPACK_CHANNELS || Channels==0)
204
0
          return false;
205
206
        // Bytes from same channels are grouped to continual data blocks,
207
        // so we need to place them back to their interleaving positions.
208
0
        for (uint CurChannel=0;CurChannel<Channels;CurChannel++)
209
0
        {
210
0
          byte PrevByte=0;
211
0
          for (uint DestPos=DataSize+CurChannel;DestPos<Border;DestPos+=Channels)
212
0
            Mem[DestPos]=(PrevByte-=Mem[SrcPos++]);
213
0
        }
214
0
      }
215
0
      break;
216
0
    case VMSF_RGB:
217
0
      {
218
0
        uint DataSize=R[4],Width=R[0]-3,PosR=R[1];
219
0
        if (DataSize>VM_MEMSIZE/2 || DataSize<3 || Width>DataSize || PosR>2)
220
0
          return false;
221
0
        byte *SrcData=Mem,*DestData=SrcData+DataSize;
222
0
        const uint Channels=3;
223
0
        for (uint CurChannel=0;CurChannel<Channels;CurChannel++)
224
0
        {
225
0
          uint PrevByte=0;
226
227
0
          for (uint I=CurChannel;I<DataSize;I+=Channels)
228
0
          {
229
0
            uint Predicted;
230
0
            if (I>=Width+3)
231
0
            {
232
0
              byte *UpperData=DestData+I-Width;
233
0
              uint UpperByte=*UpperData;
234
0
              uint UpperLeftByte=*(UpperData-3);
235
0
              Predicted=PrevByte+UpperByte-UpperLeftByte;
236
0
              int pa=abs((int)(Predicted-PrevByte));
237
0
              int pb=abs((int)(Predicted-UpperByte));
238
0
              int pc=abs((int)(Predicted-UpperLeftByte));
239
0
              if (pa<=pb && pa<=pc)
240
0
                Predicted=PrevByte;
241
0
              else
242
0
                if (pb<=pc)
243
0
                  Predicted=UpperByte;
244
0
                else
245
0
                  Predicted=UpperLeftByte;
246
0
            }
247
0
            else
248
0
              Predicted=PrevByte;
249
0
            PrevByte=DestData[I]=(byte)(Predicted-*(SrcData++));
250
0
          }
251
0
        }
252
0
        for (uint I=PosR,Border=DataSize-2;I<Border;I+=3)
253
0
        {
254
0
          byte G=DestData[I+1];
255
0
          DestData[I]+=G;
256
0
          DestData[I+2]+=G;
257
0
        }
258
0
      }
259
0
      break;
260
0
    case VMSF_AUDIO:
261
0
      {
262
0
        uint DataSize=R[4],Channels=R[0];
263
0
        byte *SrcData=Mem,*DestData=SrcData+DataSize;
264
        // In fact, audio channels never exceed 4.
265
0
        if (DataSize>VM_MEMSIZE/2 || Channels>128 || Channels==0)
266
0
          return false;
267
0
        for (uint CurChannel=0;CurChannel<Channels;CurChannel++)
268
0
        {
269
0
          uint PrevByte=0,PrevDelta=0,Dif[7];
270
0
          int D1=0,D2=0,D3;
271
0
          int K1=0,K2=0,K3=0;
272
0
          memset(Dif,0,sizeof(Dif));
273
274
0
          for (uint I=CurChannel,ByteCount=0;I<DataSize;I+=Channels,ByteCount++)
275
0
          {
276
0
            D3=D2;
277
0
            D2=PrevDelta-D1;
278
0
            D1=PrevDelta;
279
280
0
            uint Predicted=8*PrevByte+K1*D1+K2*D2+K3*D3;
281
0
            Predicted=(Predicted>>3) & 0xff;
282
283
0
            uint CurByte=*(SrcData++);
284
285
0
            Predicted-=CurByte;
286
0
            DestData[I]=Predicted;
287
0
            PrevDelta=(signed char)(Predicted-PrevByte);
288
0
            PrevByte=Predicted;
289
290
0
            int D=(signed char)CurByte;
291
            // Left shift of negative value is undefined behavior in C++,
292
            // so we cast it to unsigned to follow the standard.
293
0
            D=(uint)D<<3;
294
295
0
            Dif[0]+=abs(D);
296
0
            Dif[1]+=abs(D-D1);
297
0
            Dif[2]+=abs(D+D1);
298
0
            Dif[3]+=abs(D-D2);
299
0
            Dif[4]+=abs(D+D2);
300
0
            Dif[5]+=abs(D-D3);
301
0
            Dif[6]+=abs(D+D3);
302
303
0
            if ((ByteCount & 0x1f)==0)
304
0
            {
305
0
              uint MinDif=Dif[0],NumMinDif=0;
306
0
              Dif[0]=0;
307
0
              for (uint J=1;J<ASIZE(Dif);J++)
308
0
              {
309
0
                if (Dif[J]<MinDif)
310
0
                {
311
0
                  MinDif=Dif[J];
312
0
                  NumMinDif=J;
313
0
                }
314
0
                Dif[J]=0;
315
0
              }
316
0
              switch(NumMinDif)
317
0
              {
318
0
                case 1: if (K1>=-16) K1--; break;
319
0
                case 2: if (K1 < 16) K1++; break;
320
0
                case 3: if (K2>=-16) K2--; break;
321
0
                case 4: if (K2 < 16) K2++; break;
322
0
                case 5: if (K3>=-16) K3--; break;
323
0
                case 6: if (K3 < 16) K3++; break;
324
0
              }
325
0
            }
326
0
          }
327
0
        }
328
0
      }
329
0
      break;
330
0
  }
331
0
  return true;
332
0
}
333
334
335
uint RarVM::FilterItanium_GetBits(byte *Data,uint BitPos,uint BitCount)
336
0
{
337
0
  uint InAddr=BitPos/8;
338
0
  uint InBit=BitPos&7;
339
0
  uint BitField=(uint)Data[InAddr++];
340
0
  BitField|=(uint)Data[InAddr++] << 8;
341
0
  BitField|=(uint)Data[InAddr++] << 16;
342
0
  BitField|=(uint)Data[InAddr] << 24;
343
0
  BitField >>= InBit;
344
0
  return BitField & (0xffffffff>>(32-BitCount));
345
0
}
346
347
348
void RarVM::FilterItanium_SetBits(byte *Data,uint BitField,uint BitPos,uint BitCount)
349
0
{
350
0
  uint InAddr=BitPos/8;
351
0
  uint InBit=BitPos&7;
352
0
  uint AndMask=0xffffffff>>(32-BitCount);
353
0
  AndMask=~(AndMask<<InBit);
354
355
0
  BitField<<=InBit;
356
357
0
  for (uint I=0;I<4;I++)
358
0
  {
359
0
    Data[InAddr+I]&=AndMask;
360
0
    Data[InAddr+I]|=BitField;
361
0
    AndMask=(AndMask>>8)|0xff000000;
362
0
    BitField>>=8;
363
0
  }
364
0
}