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