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