OLD | NEW |
1 /* 7zDec.c -- Decoding from 7z folder | 1 /* 7zDec.c -- Decoding from 7z folder |
2 2010-11-02 : Igor Pavlov : Public domain */ | 2 2015-11-18 : Igor Pavlov : Public domain */ |
| 3 |
| 4 #include "Precomp.h" |
3 | 5 |
4 #include <string.h> | 6 #include <string.h> |
5 | 7 |
6 /* #define _7ZIP_PPMD_SUPPPORT */ | 8 /* #define _7ZIP_PPMD_SUPPPORT */ |
7 | 9 |
8 #include "7z.h" | 10 #include "7z.h" |
| 11 #include "7zCrc.h" |
9 | 12 |
10 #include "Bcj2.h" | 13 #include "Bcj2.h" |
11 #include "Bra.h" | 14 #include "Bra.h" |
12 #include "CpuArch.h" | 15 #include "CpuArch.h" |
| 16 #include "Delta.h" |
13 #include "LzmaDec.h" | 17 #include "LzmaDec.h" |
14 #include "Lzma2Dec.h" | 18 #include "Lzma2Dec.h" |
15 #ifdef _7ZIP_PPMD_SUPPPORT | 19 #ifdef _7ZIP_PPMD_SUPPPORT |
16 #include "Ppmd7.h" | 20 #include "Ppmd7.h" |
17 #endif | 21 #endif |
18 | 22 |
19 #define k_Copy 0 | 23 #define k_Copy 0 |
| 24 #define k_Delta 3 |
20 #define k_LZMA2 0x21 | 25 #define k_LZMA2 0x21 |
21 #define k_LZMA 0x30101 | 26 #define k_LZMA 0x30101 |
22 #define k_BCJ 0x03030103 | 27 #define k_BCJ 0x3030103 |
23 #define k_PPC 0x03030205 | 28 #define k_BCJ2 0x303011B |
24 #define k_ARM 0x03030501 | 29 #define k_PPC 0x3030205 |
25 #define k_ARMT 0x03030701 | 30 #define k_IA64 0x3030401 |
26 #define k_SPARC 0x03030805 | 31 #define k_ARM 0x3030501 |
27 #define k_BCJ2 0x0303011B | 32 #define k_ARMT 0x3030701 |
| 33 #define k_SPARC 0x3030805 |
| 34 |
28 | 35 |
29 #ifdef _7ZIP_PPMD_SUPPPORT | 36 #ifdef _7ZIP_PPMD_SUPPPORT |
30 | 37 |
31 #define k_PPMD 0x30401 | 38 #define k_PPMD 0x30401 |
32 | 39 |
33 typedef struct | 40 typedef struct |
34 { | 41 { |
35 IByteIn p; | 42 IByteIn p; |
36 const Byte *cur; | 43 const Byte *cur; |
37 const Byte *end; | 44 const Byte *end; |
(...skipping 18 matching lines...) Expand all Loading... |
56 p->res = p->inStream->Look(p->inStream, (const void **)&p->begin, &size); | 63 p->res = p->inStream->Look(p->inStream, (const void **)&p->begin, &size); |
57 p->cur = p->begin; | 64 p->cur = p->begin; |
58 p->end = p->begin + size; | 65 p->end = p->begin + size; |
59 if (size != 0) | 66 if (size != 0) |
60 return *p->cur++;; | 67 return *p->cur++;; |
61 } | 68 } |
62 p->extra = True; | 69 p->extra = True; |
63 return 0; | 70 return 0; |
64 } | 71 } |
65 | 72 |
66 static SRes SzDecodePpmd(CSzCoderInfo *coder, UInt64 inSize, ILookInStream *inSt
ream, | 73 static SRes SzDecodePpmd(const Byte *props, unsigned propsSize, UInt64 inSize, I
LookInStream *inStream, |
67 Byte *outBuffer, SizeT outSize, ISzAlloc *allocMain) | 74 Byte *outBuffer, SizeT outSize, ISzAlloc *allocMain) |
68 { | 75 { |
69 CPpmd7 ppmd; | 76 CPpmd7 ppmd; |
70 CByteInToLook s; | 77 CByteInToLook s; |
71 SRes res = SZ_OK; | 78 SRes res = SZ_OK; |
72 | 79 |
73 s.p.Read = ReadByte; | 80 s.p.Read = ReadByte; |
74 s.inStream = inStream; | 81 s.inStream = inStream; |
75 s.begin = s.end = s.cur = NULL; | 82 s.begin = s.end = s.cur = NULL; |
76 s.extra = False; | 83 s.extra = False; |
77 s.res = SZ_OK; | 84 s.res = SZ_OK; |
78 s.processed = 0; | 85 s.processed = 0; |
79 | 86 |
80 if (coder->Props.size != 5) | 87 if (propsSize != 5) |
81 return SZ_ERROR_UNSUPPORTED; | 88 return SZ_ERROR_UNSUPPORTED; |
82 | 89 |
83 { | 90 { |
84 unsigned order = coder->Props.data[0]; | 91 unsigned order = props[0]; |
85 UInt32 memSize = GetUi32(coder->Props.data + 1); | 92 UInt32 memSize = GetUi32(props + 1); |
86 if (order < PPMD7_MIN_ORDER || | 93 if (order < PPMD7_MIN_ORDER || |
87 order > PPMD7_MAX_ORDER || | 94 order > PPMD7_MAX_ORDER || |
88 memSize < PPMD7_MIN_MEM_SIZE || | 95 memSize < PPMD7_MIN_MEM_SIZE || |
89 memSize > PPMD7_MAX_MEM_SIZE) | 96 memSize > PPMD7_MAX_MEM_SIZE) |
90 return SZ_ERROR_UNSUPPORTED; | 97 return SZ_ERROR_UNSUPPORTED; |
91 Ppmd7_Construct(&ppmd); | 98 Ppmd7_Construct(&ppmd); |
92 if (!Ppmd7_Alloc(&ppmd, memSize, allocMain)) | 99 if (!Ppmd7_Alloc(&ppmd, memSize, allocMain)) |
93 return SZ_ERROR_MEM; | 100 return SZ_ERROR_MEM; |
94 Ppmd7_Init(&ppmd, order); | 101 Ppmd7_Init(&ppmd, order); |
95 } | 102 } |
(...skipping 21 matching lines...) Expand all Loading... |
117 res = SZ_ERROR_DATA; | 124 res = SZ_ERROR_DATA; |
118 } | 125 } |
119 } | 126 } |
120 Ppmd7_Free(&ppmd, allocMain); | 127 Ppmd7_Free(&ppmd, allocMain); |
121 return res; | 128 return res; |
122 } | 129 } |
123 | 130 |
124 #endif | 131 #endif |
125 | 132 |
126 | 133 |
127 static SRes SzDecodeLzma(CSzCoderInfo *coder, UInt64 inSize, ILookInStream *inSt
ream, | 134 static SRes SzDecodeLzma(const Byte *props, unsigned propsSize, UInt64 inSize, I
LookInStream *inStream, |
128 Byte *outBuffer, SizeT outSize, ISzAlloc *allocMain) | 135 Byte *outBuffer, SizeT outSize, ISzAlloc *allocMain) |
129 { | 136 { |
130 CLzmaDec state; | 137 CLzmaDec state; |
131 SRes res = SZ_OK; | 138 SRes res = SZ_OK; |
132 | 139 |
133 LzmaDec_Construct(&state); | 140 LzmaDec_Construct(&state); |
134 RINOK(LzmaDec_AllocateProbs(&state, coder->Props.data, (unsigned)coder->Props.
size, allocMain)); | 141 RINOK(LzmaDec_AllocateProbs(&state, props, propsSize, allocMain)); |
135 state.dic = outBuffer; | 142 state.dic = outBuffer; |
136 state.dicBufSize = outSize; | 143 state.dicBufSize = outSize; |
137 LzmaDec_Init(&state); | 144 LzmaDec_Init(&state); |
138 | 145 |
139 for (;;) | 146 for (;;) |
140 { | 147 { |
141 Byte *inBuf = NULL; | 148 const void *inBuf = NULL; |
142 size_t lookahead = (1 << 18); | 149 size_t lookahead = (1 << 18); |
143 if (lookahead > inSize) | 150 if (lookahead > inSize) |
144 lookahead = (size_t)inSize; | 151 lookahead = (size_t)inSize; |
145 res = inStream->Look((void *)inStream, (const void **)&inBuf, &lookahead); | 152 res = inStream->Look(inStream, &inBuf, &lookahead); |
146 if (res != SZ_OK) | 153 if (res != SZ_OK) |
147 break; | 154 break; |
148 | 155 |
149 { | 156 { |
150 SizeT inProcessed = (SizeT)lookahead, dicPos = state.dicPos; | 157 SizeT inProcessed = (SizeT)lookahead, dicPos = state.dicPos; |
151 ELzmaStatus status; | 158 ELzmaStatus status; |
152 res = LzmaDec_DecodeToDic(&state, outSize, inBuf, &inProcessed, LZMA_FINIS
H_END, &status); | 159 res = LzmaDec_DecodeToDic(&state, outSize, inBuf, &inProcessed, LZMA_FINIS
H_END, &status); |
153 lookahead -= inProcessed; | 160 lookahead -= inProcessed; |
154 inSize -= inProcessed; | 161 inSize -= inProcessed; |
155 if (res != SZ_OK) | 162 if (res != SZ_OK) |
156 break; | 163 break; |
157 if (state.dicPos == state.dicBufSize || (inProcessed == 0 && dicPos == sta
te.dicPos)) | 164 |
| 165 if (status == LZMA_STATUS_FINISHED_WITH_MARK) |
158 { | 166 { |
159 if (state.dicBufSize != outSize || lookahead != 0 || | 167 if (outSize != state.dicPos || inSize != 0) |
160 (status != LZMA_STATUS_FINISHED_WITH_MARK && | |
161 status != LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK)) | |
162 res = SZ_ERROR_DATA; | 168 res = SZ_ERROR_DATA; |
163 break; | 169 break; |
164 } | 170 } |
| 171 |
| 172 if (outSize == state.dicPos && inSize == 0 && status == LZMA_STATUS_MAYBE_
FINISHED_WITHOUT_MARK) |
| 173 break; |
| 174 |
| 175 if (inProcessed == 0 && dicPos == state.dicPos) |
| 176 { |
| 177 res = SZ_ERROR_DATA; |
| 178 break; |
| 179 } |
| 180 |
165 res = inStream->Skip((void *)inStream, inProcessed); | 181 res = inStream->Skip((void *)inStream, inProcessed); |
166 if (res != SZ_OK) | 182 if (res != SZ_OK) |
167 break; | 183 break; |
168 } | 184 } |
169 } | 185 } |
170 | 186 |
171 LzmaDec_FreeProbs(&state, allocMain); | 187 LzmaDec_FreeProbs(&state, allocMain); |
172 return res; | 188 return res; |
173 } | 189 } |
174 | 190 |
175 static SRes SzDecodeLzma2(CSzCoderInfo *coder, UInt64 inSize, ILookInStream *inS
tream, | 191 |
| 192 #ifndef _7Z_NO_METHOD_LZMA2 |
| 193 |
| 194 static SRes SzDecodeLzma2(const Byte *props, unsigned propsSize, UInt64 inSize,
ILookInStream *inStream, |
176 Byte *outBuffer, SizeT outSize, ISzAlloc *allocMain) | 195 Byte *outBuffer, SizeT outSize, ISzAlloc *allocMain) |
177 { | 196 { |
178 CLzma2Dec state; | 197 CLzma2Dec state; |
179 SRes res = SZ_OK; | 198 SRes res = SZ_OK; |
180 | 199 |
181 Lzma2Dec_Construct(&state); | 200 Lzma2Dec_Construct(&state); |
182 if (coder->Props.size != 1) | 201 if (propsSize != 1) |
183 return SZ_ERROR_DATA; | 202 return SZ_ERROR_DATA; |
184 RINOK(Lzma2Dec_AllocateProbs(&state, coder->Props.data[0], allocMain)); | 203 RINOK(Lzma2Dec_AllocateProbs(&state, props[0], allocMain)); |
185 state.decoder.dic = outBuffer; | 204 state.decoder.dic = outBuffer; |
186 state.decoder.dicBufSize = outSize; | 205 state.decoder.dicBufSize = outSize; |
187 Lzma2Dec_Init(&state); | 206 Lzma2Dec_Init(&state); |
188 | 207 |
189 for (;;) | 208 for (;;) |
190 { | 209 { |
191 Byte *inBuf = NULL; | 210 const void *inBuf = NULL; |
192 size_t lookahead = (1 << 18); | 211 size_t lookahead = (1 << 18); |
193 if (lookahead > inSize) | 212 if (lookahead > inSize) |
194 lookahead = (size_t)inSize; | 213 lookahead = (size_t)inSize; |
195 res = inStream->Look((void *)inStream, (const void **)&inBuf, &lookahead); | 214 res = inStream->Look(inStream, &inBuf, &lookahead); |
196 if (res != SZ_OK) | 215 if (res != SZ_OK) |
197 break; | 216 break; |
198 | 217 |
199 { | 218 { |
200 SizeT inProcessed = (SizeT)lookahead, dicPos = state.decoder.dicPos; | 219 SizeT inProcessed = (SizeT)lookahead, dicPos = state.decoder.dicPos; |
201 ELzmaStatus status; | 220 ELzmaStatus status; |
202 res = Lzma2Dec_DecodeToDic(&state, outSize, inBuf, &inProcessed, LZMA_FINI
SH_END, &status); | 221 res = Lzma2Dec_DecodeToDic(&state, outSize, inBuf, &inProcessed, LZMA_FINI
SH_END, &status); |
203 lookahead -= inProcessed; | 222 lookahead -= inProcessed; |
204 inSize -= inProcessed; | 223 inSize -= inProcessed; |
205 if (res != SZ_OK) | 224 if (res != SZ_OK) |
206 break; | 225 break; |
207 if (state.decoder.dicPos == state.decoder.dicBufSize || (inProcessed == 0
&& dicPos == state.decoder.dicPos)) | 226 |
| 227 if (status == LZMA_STATUS_FINISHED_WITH_MARK) |
208 { | 228 { |
209 if (state.decoder.dicBufSize != outSize || lookahead != 0 || | 229 if (outSize != state.decoder.dicPos || inSize != 0) |
210 (status != LZMA_STATUS_FINISHED_WITH_MARK)) | |
211 res = SZ_ERROR_DATA; | 230 res = SZ_ERROR_DATA; |
212 break; | 231 break; |
213 } | 232 } |
| 233 |
| 234 if (inProcessed == 0 && dicPos == state.decoder.dicPos) |
| 235 { |
| 236 res = SZ_ERROR_DATA; |
| 237 break; |
| 238 } |
| 239 |
214 res = inStream->Skip((void *)inStream, inProcessed); | 240 res = inStream->Skip((void *)inStream, inProcessed); |
215 if (res != SZ_OK) | 241 if (res != SZ_OK) |
216 break; | 242 break; |
217 } | 243 } |
218 } | 244 } |
219 | 245 |
220 Lzma2Dec_FreeProbs(&state, allocMain); | 246 Lzma2Dec_FreeProbs(&state, allocMain); |
221 return res; | 247 return res; |
222 } | 248 } |
223 | 249 |
| 250 #endif |
| 251 |
| 252 |
224 static SRes SzDecodeCopy(UInt64 inSize, ILookInStream *inStream, Byte *outBuffer
) | 253 static SRes SzDecodeCopy(UInt64 inSize, ILookInStream *inStream, Byte *outBuffer
) |
225 { | 254 { |
226 while (inSize > 0) | 255 while (inSize > 0) |
227 { | 256 { |
228 void *inBuf; | 257 const void *inBuf; |
229 size_t curSize = (1 << 18); | 258 size_t curSize = (1 << 18); |
230 if (curSize > inSize) | 259 if (curSize > inSize) |
231 curSize = (size_t)inSize; | 260 curSize = (size_t)inSize; |
232 RINOK(inStream->Look((void *)inStream, (const void **)&inBuf, &curSize)); | 261 RINOK(inStream->Look(inStream, &inBuf, &curSize)); |
233 if (curSize == 0) | 262 if (curSize == 0) |
234 return SZ_ERROR_INPUT_EOF; | 263 return SZ_ERROR_INPUT_EOF; |
235 memcpy(outBuffer, inBuf, curSize); | 264 memcpy(outBuffer, inBuf, curSize); |
236 outBuffer += curSize; | 265 outBuffer += curSize; |
237 inSize -= curSize; | 266 inSize -= curSize; |
238 RINOK(inStream->Skip((void *)inStream, curSize)); | 267 RINOK(inStream->Skip((void *)inStream, curSize)); |
239 } | 268 } |
240 return SZ_OK; | 269 return SZ_OK; |
241 } | 270 } |
242 | 271 |
243 static Bool IS_MAIN_METHOD(UInt32 m) | 272 static Bool IS_MAIN_METHOD(UInt32 m) |
244 { | 273 { |
245 switch(m) | 274 switch (m) |
246 { | 275 { |
247 case k_Copy: | 276 case k_Copy: |
248 case k_LZMA: | 277 case k_LZMA: |
| 278 #ifndef _7Z_NO_METHOD_LZMA2 |
249 case k_LZMA2: | 279 case k_LZMA2: |
| 280 #endif |
250 #ifdef _7ZIP_PPMD_SUPPPORT | 281 #ifdef _7ZIP_PPMD_SUPPPORT |
251 case k_PPMD: | 282 case k_PPMD: |
252 #endif | 283 #endif |
253 return True; | 284 return True; |
254 } | 285 } |
255 return False; | 286 return False; |
256 } | 287 } |
257 | 288 |
258 static Bool IS_SUPPORTED_CODER(const CSzCoderInfo *c) | 289 static Bool IS_SUPPORTED_CODER(const CSzCoderInfo *c) |
259 { | 290 { |
260 return | 291 return |
261 c->NumInStreams == 1 && | 292 c->NumStreams == 1 |
262 c->NumOutStreams == 1 && | 293 /* && c->MethodID <= (UInt32)0xFFFFFFFF */ |
263 c->MethodID <= (UInt32)0xFFFFFFFF && | 294 && IS_MAIN_METHOD((UInt32)c->MethodID); |
264 IS_MAIN_METHOD((UInt32)c->MethodID); | |
265 } | 295 } |
266 | 296 |
267 #define IS_BCJ2(c) ((c)->MethodID == k_BCJ2 && (c)->NumInStreams == 4 && (c)->Nu
mOutStreams == 1) | 297 #define IS_BCJ2(c) ((c)->MethodID == k_BCJ2 && (c)->NumStreams == 4) |
268 | 298 |
269 static SRes CheckSupportedFolder(const CSzFolder *f) | 299 static SRes CheckSupportedFolder(const CSzFolder *f) |
270 { | 300 { |
271 if (f->NumCoders < 1 || f->NumCoders > 4) | 301 if (f->NumCoders < 1 || f->NumCoders > 4) |
272 return SZ_ERROR_UNSUPPORTED; | 302 return SZ_ERROR_UNSUPPORTED; |
273 if (!IS_SUPPORTED_CODER(&f->Coders[0])) | 303 if (!IS_SUPPORTED_CODER(&f->Coders[0])) |
274 return SZ_ERROR_UNSUPPORTED; | 304 return SZ_ERROR_UNSUPPORTED; |
275 if (f->NumCoders == 1) | 305 if (f->NumCoders == 1) |
276 { | 306 { |
277 if (f->NumPackStreams != 1 || f->PackStreams[0] != 0 || f->NumBindPairs != 0
) | 307 if (f->NumPackStreams != 1 || f->PackStreams[0] != 0 || f->NumBonds != 0) |
278 return SZ_ERROR_UNSUPPORTED; | 308 return SZ_ERROR_UNSUPPORTED; |
279 return SZ_OK; | 309 return SZ_OK; |
280 } | 310 } |
| 311 |
| 312 |
| 313 #ifndef _7Z_NO_METHODS_FILTERS |
| 314 |
281 if (f->NumCoders == 2) | 315 if (f->NumCoders == 2) |
282 { | 316 { |
283 CSzCoderInfo *c = &f->Coders[1]; | 317 const CSzCoderInfo *c = &f->Coders[1]; |
284 if (c->MethodID > (UInt32)0xFFFFFFFF || | 318 if ( |
285 c->NumInStreams != 1 || | 319 /* c->MethodID > (UInt32)0xFFFFFFFF || */ |
286 c->NumOutStreams != 1 || | 320 c->NumStreams != 1 |
287 f->NumPackStreams != 1 || | 321 || f->NumPackStreams != 1 |
288 f->PackStreams[0] != 0 || | 322 || f->PackStreams[0] != 0 |
289 f->NumBindPairs != 1 || | 323 || f->NumBonds != 1 |
290 f->BindPairs[0].InIndex != 1 || | 324 || f->Bonds[0].InIndex != 1 |
291 f->BindPairs[0].OutIndex != 0) | 325 || f->Bonds[0].OutIndex != 0) |
292 return SZ_ERROR_UNSUPPORTED; | 326 return SZ_ERROR_UNSUPPORTED; |
293 switch ((UInt32)c->MethodID) | 327 switch ((UInt32)c->MethodID) |
294 { | 328 { |
| 329 case k_Delta: |
295 case k_BCJ: | 330 case k_BCJ: |
| 331 case k_PPC: |
| 332 case k_IA64: |
| 333 case k_SPARC: |
296 case k_ARM: | 334 case k_ARM: |
| 335 case k_ARMT: |
297 break; | 336 break; |
298 default: | 337 default: |
299 return SZ_ERROR_UNSUPPORTED; | 338 return SZ_ERROR_UNSUPPORTED; |
300 } | 339 } |
301 return SZ_OK; | 340 return SZ_OK; |
302 } | 341 } |
| 342 |
| 343 #endif |
| 344 |
| 345 |
303 if (f->NumCoders == 4) | 346 if (f->NumCoders == 4) |
304 { | 347 { |
305 if (!IS_SUPPORTED_CODER(&f->Coders[1]) || | 348 if (!IS_SUPPORTED_CODER(&f->Coders[1]) |
306 !IS_SUPPORTED_CODER(&f->Coders[2]) || | 349 || !IS_SUPPORTED_CODER(&f->Coders[2]) |
307 !IS_BCJ2(&f->Coders[3])) | 350 || !IS_BCJ2(&f->Coders[3])) |
308 return SZ_ERROR_UNSUPPORTED; | 351 return SZ_ERROR_UNSUPPORTED; |
309 if (f->NumPackStreams != 4 || | 352 if (f->NumPackStreams != 4 |
310 f->PackStreams[0] != 2 || | 353 || f->PackStreams[0] != 2 |
311 f->PackStreams[1] != 6 || | 354 || f->PackStreams[1] != 6 |
312 f->PackStreams[2] != 1 || | 355 || f->PackStreams[2] != 1 |
313 f->PackStreams[3] != 0 || | 356 || f->PackStreams[3] != 0 |
314 f->NumBindPairs != 3 || | 357 || f->NumBonds != 3 |
315 f->BindPairs[0].InIndex != 5 || f->BindPairs[0].OutIndex != 0 || | 358 || f->Bonds[0].InIndex != 5 || f->Bonds[0].OutIndex != 0 |
316 f->BindPairs[1].InIndex != 4 || f->BindPairs[1].OutIndex != 1 || | 359 || f->Bonds[1].InIndex != 4 || f->Bonds[1].OutIndex != 1 |
317 f->BindPairs[2].InIndex != 3 || f->BindPairs[2].OutIndex != 2) | 360 || f->Bonds[2].InIndex != 3 || f->Bonds[2].OutIndex != 2) |
318 return SZ_ERROR_UNSUPPORTED; | 361 return SZ_ERROR_UNSUPPORTED; |
319 return SZ_OK; | 362 return SZ_OK; |
320 } | 363 } |
| 364 |
321 return SZ_ERROR_UNSUPPORTED; | 365 return SZ_ERROR_UNSUPPORTED; |
322 } | 366 } |
323 | 367 |
324 static UInt64 GetSum(const UInt64 *values, UInt32 index) | |
325 { | |
326 UInt64 sum = 0; | |
327 UInt32 i; | |
328 for (i = 0; i < index; i++) | |
329 sum += values[i]; | |
330 return sum; | |
331 } | |
332 | |
333 #define CASE_BRA_CONV(isa) case k_ ## isa: isa ## _Convert(outBuffer, outSize, 0
, 0); break; | 368 #define CASE_BRA_CONV(isa) case k_ ## isa: isa ## _Convert(outBuffer, outSize, 0
, 0); break; |
334 | 369 |
335 static SRes SzFolder_Decode2(const CSzFolder *folder, const UInt64 *packSizes, | 370 static SRes SzFolder_Decode2(const CSzFolder *folder, |
| 371 const Byte *propsData, |
| 372 const UInt64 *unpackSizes, |
| 373 const UInt64 *packPositions, |
336 ILookInStream *inStream, UInt64 startPos, | 374 ILookInStream *inStream, UInt64 startPos, |
337 Byte *outBuffer, SizeT outSize, ISzAlloc *allocMain, | 375 Byte *outBuffer, SizeT outSize, ISzAlloc *allocMain, |
338 Byte *tempBuf[]) | 376 Byte *tempBuf[]) |
339 { | 377 { |
340 UInt32 ci; | 378 UInt32 ci; |
341 SizeT tempSizes[3] = { 0, 0, 0}; | 379 SizeT tempSizes[3] = { 0, 0, 0}; |
342 SizeT tempSize3 = 0; | 380 SizeT tempSize3 = 0; |
343 Byte *tempBuf3 = 0; | 381 Byte *tempBuf3 = 0; |
344 | 382 |
345 RINOK(CheckSupportedFolder(folder)); | 383 RINOK(CheckSupportedFolder(folder)); |
346 | 384 |
347 for (ci = 0; ci < folder->NumCoders; ci++) | 385 for (ci = 0; ci < folder->NumCoders; ci++) |
348 { | 386 { |
349 CSzCoderInfo *coder = &folder->Coders[ci]; | 387 const CSzCoderInfo *coder = &folder->Coders[ci]; |
350 | 388 |
351 if (IS_MAIN_METHOD((UInt32)coder->MethodID)) | 389 if (IS_MAIN_METHOD((UInt32)coder->MethodID)) |
352 { | 390 { |
353 UInt32 si = 0; | 391 UInt32 si = 0; |
354 UInt64 offset; | 392 UInt64 offset; |
355 UInt64 inSize; | 393 UInt64 inSize; |
356 Byte *outBufCur = outBuffer; | 394 Byte *outBufCur = outBuffer; |
357 SizeT outSizeCur = outSize; | 395 SizeT outSizeCur = outSize; |
358 if (folder->NumCoders == 4) | 396 if (folder->NumCoders == 4) |
359 { | 397 { |
360 UInt32 indices[] = { 3, 2, 0 }; | 398 UInt32 indices[] = { 3, 2, 0 }; |
361 UInt64 unpackSize = folder->UnpackSizes[ci]; | 399 UInt64 unpackSize = unpackSizes[ci]; |
362 si = indices[ci]; | 400 si = indices[ci]; |
363 if (ci < 2) | 401 if (ci < 2) |
364 { | 402 { |
365 Byte *temp; | 403 Byte *temp; |
366 outSizeCur = (SizeT)unpackSize; | 404 outSizeCur = (SizeT)unpackSize; |
367 if (outSizeCur != unpackSize) | 405 if (outSizeCur != unpackSize) |
368 return SZ_ERROR_MEM; | 406 return SZ_ERROR_MEM; |
369 temp = (Byte *)IAlloc_Alloc(allocMain, outSizeCur); | 407 temp = (Byte *)IAlloc_Alloc(allocMain, outSizeCur); |
370 if (temp == 0 && outSizeCur != 0) | 408 if (!temp && outSizeCur != 0) |
371 return SZ_ERROR_MEM; | 409 return SZ_ERROR_MEM; |
372 outBufCur = tempBuf[1 - ci] = temp; | 410 outBufCur = tempBuf[1 - ci] = temp; |
373 tempSizes[1 - ci] = outSizeCur; | 411 tempSizes[1 - ci] = outSizeCur; |
374 } | 412 } |
375 else if (ci == 2) | 413 else if (ci == 2) |
376 { | 414 { |
377 if (unpackSize > outSize) /* check it */ | 415 if (unpackSize > outSize) /* check it */ |
378 return SZ_ERROR_PARAM; | 416 return SZ_ERROR_PARAM; |
379 tempBuf3 = outBufCur = outBuffer + (outSize - (size_t)unpackSize); | 417 tempBuf3 = outBufCur = outBuffer + (outSize - (size_t)unpackSize); |
380 tempSize3 = outSizeCur = (SizeT)unpackSize; | 418 tempSize3 = outSizeCur = (SizeT)unpackSize; |
381 } | 419 } |
382 else | 420 else |
383 return SZ_ERROR_UNSUPPORTED; | 421 return SZ_ERROR_UNSUPPORTED; |
384 } | 422 } |
385 offset = GetSum(packSizes, si); | 423 offset = packPositions[si]; |
386 inSize = packSizes[si]; | 424 inSize = packPositions[si + 1] - offset; |
387 RINOK(LookInStream_SeekTo(inStream, startPos + offset)); | 425 RINOK(LookInStream_SeekTo(inStream, startPos + offset)); |
388 | 426 |
389 if (coder->MethodID == k_Copy) | 427 if (coder->MethodID == k_Copy) |
390 { | 428 { |
391 if (inSize != outSizeCur) /* check it */ | 429 if (inSize != outSizeCur) /* check it */ |
392 return SZ_ERROR_DATA; | 430 return SZ_ERROR_DATA; |
393 RINOK(SzDecodeCopy(inSize, inStream, outBufCur)); | 431 RINOK(SzDecodeCopy(inSize, inStream, outBufCur)); |
394 } | 432 } |
395 else if (coder->MethodID == k_LZMA) | 433 else if (coder->MethodID == k_LZMA) |
396 { | 434 { |
397 RINOK(SzDecodeLzma(coder, inSize, inStream, outBufCur, outSizeCur, alloc
Main)); | 435 RINOK(SzDecodeLzma(propsData + coder->PropsOffset, coder->PropsSize, inS
ize, inStream, outBufCur, outSizeCur, allocMain)); |
398 } | 436 } |
| 437 #ifndef _7Z_NO_METHOD_LZMA2 |
399 else if (coder->MethodID == k_LZMA2) | 438 else if (coder->MethodID == k_LZMA2) |
400 { | 439 { |
401 RINOK(SzDecodeLzma2(coder, inSize, inStream, outBufCur, outSizeCur, allo
cMain)); | 440 RINOK(SzDecodeLzma2(propsData + coder->PropsOffset, coder->PropsSize, in
Size, inStream, outBufCur, outSizeCur, allocMain)); |
402 } | 441 } |
| 442 #endif |
| 443 #ifdef _7ZIP_PPMD_SUPPPORT |
| 444 else if (coder->MethodID == k_PPMD) |
| 445 { |
| 446 RINOK(SzDecodePpmd(propsData + coder->PropsOffset, coder->PropsSize, inS
ize, inStream, outBufCur, outSizeCur, allocMain)); |
| 447 } |
| 448 #endif |
403 else | 449 else |
404 { | |
405 #ifdef _7ZIP_PPMD_SUPPPORT | |
406 RINOK(SzDecodePpmd(coder, inSize, inStream, outBufCur, outSizeCur, alloc
Main)); | |
407 #else | |
408 return SZ_ERROR_UNSUPPORTED; | 450 return SZ_ERROR_UNSUPPORTED; |
409 #endif | |
410 } | |
411 } | 451 } |
412 else if (coder->MethodID == k_BCJ2) | 452 else if (coder->MethodID == k_BCJ2) |
413 { | 453 { |
414 UInt64 offset = GetSum(packSizes, 1); | 454 UInt64 offset = packPositions[1]; |
415 UInt64 s3Size = packSizes[1]; | 455 UInt64 s3Size = packPositions[2] - offset; |
416 SRes res; | 456 |
417 if (ci != 3) | 457 if (ci != 3) |
418 return SZ_ERROR_UNSUPPORTED; | 458 return SZ_ERROR_UNSUPPORTED; |
419 RINOK(LookInStream_SeekTo(inStream, startPos + offset)); | 459 |
420 tempSizes[2] = (SizeT)s3Size; | 460 tempSizes[2] = (SizeT)s3Size; |
421 if (tempSizes[2] != s3Size) | 461 if (tempSizes[2] != s3Size) |
422 return SZ_ERROR_MEM; | 462 return SZ_ERROR_MEM; |
423 tempBuf[2] = (Byte *)IAlloc_Alloc(allocMain, tempSizes[2]); | 463 tempBuf[2] = (Byte *)IAlloc_Alloc(allocMain, tempSizes[2]); |
424 if (tempBuf[2] == 0 && tempSizes[2] != 0) | 464 if (!tempBuf[2] && tempSizes[2] != 0) |
425 return SZ_ERROR_MEM; | 465 return SZ_ERROR_MEM; |
426 res = SzDecodeCopy(s3Size, inStream, tempBuf[2]); | 466 |
427 RINOK(res) | 467 RINOK(LookInStream_SeekTo(inStream, startPos + offset)); |
| 468 RINOK(SzDecodeCopy(s3Size, inStream, tempBuf[2])); |
428 | 469 |
429 res = Bcj2_Decode( | 470 if ((tempSizes[0] & 3) != 0 || |
430 tempBuf3, tempSize3, | 471 (tempSizes[1] & 3) != 0 || |
431 tempBuf[0], tempSizes[0], | 472 tempSize3 + tempSizes[0] + tempSizes[1] != outSize) |
432 tempBuf[1], tempSizes[1], | 473 return SZ_ERROR_DATA; |
433 tempBuf[2], tempSizes[2], | 474 |
434 outBuffer, outSize); | |
435 RINOK(res) | |
436 } | |
437 else | |
438 { | |
439 if (ci != 1) | |
440 return SZ_ERROR_UNSUPPORTED; | |
441 switch(coder->MethodID) | |
442 { | 475 { |
443 case k_BCJ: | 476 CBcj2Dec p; |
| 477 |
| 478 p.bufs[0] = tempBuf3; p.lims[0] = tempBuf3 + tempSize3; |
| 479 p.bufs[1] = tempBuf[0]; p.lims[1] = tempBuf[0] + tempSizes[0]; |
| 480 p.bufs[2] = tempBuf[1]; p.lims[2] = tempBuf[1] + tempSizes[1]; |
| 481 p.bufs[3] = tempBuf[2]; p.lims[3] = tempBuf[2] + tempSizes[2]; |
| 482 |
| 483 p.dest = outBuffer; |
| 484 p.destLim = outBuffer + outSize; |
| 485 |
| 486 Bcj2Dec_Init(&p); |
| 487 RINOK(Bcj2Dec_Decode(&p)); |
| 488 |
444 { | 489 { |
445 UInt32 state; | 490 unsigned i; |
446 x86_Convert_Init(state); | 491 for (i = 0; i < 4; i++) |
447 x86_Convert(outBuffer, outSize, 0, &state, 0); | 492 if (p.bufs[i] != p.lims[i]) |
448 break; | 493 return SZ_ERROR_DATA; |
| 494 |
| 495 if (!Bcj2Dec_IsFinished(&p)) |
| 496 return SZ_ERROR_DATA; |
| 497 |
| 498 if (p.dest != p.destLim |
| 499 || p.state != BCJ2_STREAM_MAIN) |
| 500 return SZ_ERROR_DATA; |
449 } | 501 } |
450 CASE_BRA_CONV(ARM) | |
451 default: | |
452 return SZ_ERROR_UNSUPPORTED; | |
453 } | 502 } |
454 } | 503 } |
| 504 #ifndef _7Z_NO_METHODS_FILTERS |
| 505 else if (ci == 1) |
| 506 { |
| 507 if (coder->MethodID == k_Delta) |
| 508 { |
| 509 if (coder->PropsSize != 1) |
| 510 return SZ_ERROR_UNSUPPORTED; |
| 511 { |
| 512 Byte state[DELTA_STATE_SIZE]; |
| 513 Delta_Init(state); |
| 514 Delta_Decode(state, (unsigned)(propsData[coder->PropsOffset]) + 1, out
Buffer, outSize); |
| 515 } |
| 516 } |
| 517 else |
| 518 { |
| 519 if (coder->PropsSize != 0) |
| 520 return SZ_ERROR_UNSUPPORTED; |
| 521 switch (coder->MethodID) |
| 522 { |
| 523 case k_BCJ: |
| 524 { |
| 525 UInt32 state; |
| 526 x86_Convert_Init(state); |
| 527 x86_Convert(outBuffer, outSize, 0, &state, 0); |
| 528 break; |
| 529 } |
| 530 CASE_BRA_CONV(PPC) |
| 531 CASE_BRA_CONV(IA64) |
| 532 CASE_BRA_CONV(SPARC) |
| 533 CASE_BRA_CONV(ARM) |
| 534 CASE_BRA_CONV(ARMT) |
| 535 default: |
| 536 return SZ_ERROR_UNSUPPORTED; |
| 537 } |
| 538 } |
| 539 } |
| 540 #endif |
| 541 else |
| 542 return SZ_ERROR_UNSUPPORTED; |
455 } | 543 } |
| 544 |
456 return SZ_OK; | 545 return SZ_OK; |
457 } | 546 } |
458 | 547 |
459 SRes SzFolder_Decode(const CSzFolder *folder, const UInt64 *packSizes, | 548 |
| 549 SRes SzAr_DecodeFolder(const CSzAr *p, UInt32 folderIndex, |
460 ILookInStream *inStream, UInt64 startPos, | 550 ILookInStream *inStream, UInt64 startPos, |
461 Byte *outBuffer, size_t outSize, ISzAlloc *allocMain) | 551 Byte *outBuffer, size_t outSize, |
| 552 ISzAlloc *allocMain) |
462 { | 553 { |
463 Byte *tempBuf[3] = { 0, 0, 0}; | 554 SRes res; |
464 int i; | 555 CSzFolder folder; |
465 SRes res = SzFolder_Decode2(folder, packSizes, inStream, startPos, | 556 CSzData sd; |
466 outBuffer, (SizeT)outSize, allocMain, tempBuf); | 557 |
467 for (i = 0; i < 3; i++) | 558 const Byte *data = p->CodersData + p->FoCodersOffsets[folderIndex]; |
468 IAlloc_Free(allocMain, tempBuf[i]); | 559 sd.Data = data; |
469 return res; | 560 sd.Size = p->FoCodersOffsets[folderIndex + 1] - p->FoCodersOffsets[folderIndex
]; |
| 561 |
| 562 res = SzGetNextFolderItem(&folder, &sd); |
| 563 |
| 564 if (res != SZ_OK) |
| 565 return res; |
| 566 |
| 567 if (sd.Size != 0 |
| 568 || folder.UnpackStream != p->FoToMainUnpackSizeIndex[folderIndex] |
| 569 || outSize != SzAr_GetFolderUnpackSize(p, folderIndex)) |
| 570 return SZ_ERROR_FAIL; |
| 571 { |
| 572 unsigned i; |
| 573 Byte *tempBuf[3] = { 0, 0, 0}; |
| 574 |
| 575 res = SzFolder_Decode2(&folder, data, |
| 576 &p->CoderUnpackSizes[p->FoToCoderUnpackSizes[folderIndex]], |
| 577 p->PackPositions + p->FoStartPackStreamIndex[folderIndex], |
| 578 inStream, startPos, |
| 579 outBuffer, (SizeT)outSize, allocMain, tempBuf); |
| 580 |
| 581 for (i = 0; i < 3; i++) |
| 582 IAlloc_Free(allocMain, tempBuf[i]); |
| 583 |
| 584 if (res == SZ_OK) |
| 585 if (SzBitWithVals_Check(&p->FolderCRCs, folderIndex)) |
| 586 if (CrcCalc(outBuffer, outSize) != p->FolderCRCs.Vals[folderIndex]) |
| 587 res = SZ_ERROR_CRC; |
| 588 |
| 589 return res; |
| 590 } |
470 } | 591 } |
OLD | NEW |