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