Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
stenzek
GitHub Repository: stenzek/duckstation
Path: blob/master/dep/lzma/src/7zDec.c
4253 views
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
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
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
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
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
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
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
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
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
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
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
674