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