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