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