Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
stenzek
GitHub Repository: stenzek/duckstation
Path: blob/master/dep/lzma/src/7zArcIn.c
4253 views
1
/* 7zArcIn.c -- 7z Input functions
2
2023-09-07 : Igor Pavlov : Public domain */
3
4
#include "Precomp.h"
5
6
#include <string.h>
7
8
#include "7z.h"
9
#include "7zBuf.h"
10
#include "7zCrc.h"
11
#include "CpuArch.h"
12
13
#define MY_ALLOC(T, p, size, alloc) \
14
{ if ((p = (T *)ISzAlloc_Alloc(alloc, (size) * sizeof(T))) == NULL) return SZ_ERROR_MEM; }
15
16
#define MY_ALLOC_ZE(T, p, size, alloc) \
17
{ if ((size) == 0) p = NULL; else MY_ALLOC(T, p, size, alloc) }
18
19
#define MY_ALLOC_AND_CPY(to, size, from, alloc) \
20
{ MY_ALLOC(Byte, to, size, alloc); memcpy(to, from, size); }
21
22
#define MY_ALLOC_ZE_AND_CPY(to, size, from, alloc) \
23
{ if ((size) == 0) to = NULL; else { MY_ALLOC_AND_CPY(to, size, from, alloc) } }
24
25
#define k7zMajorVersion 0
26
27
enum EIdEnum
28
{
29
k7zIdEnd,
30
k7zIdHeader,
31
k7zIdArchiveProperties,
32
k7zIdAdditionalStreamsInfo,
33
k7zIdMainStreamsInfo,
34
k7zIdFilesInfo,
35
k7zIdPackInfo,
36
k7zIdUnpackInfo,
37
k7zIdSubStreamsInfo,
38
k7zIdSize,
39
k7zIdCRC,
40
k7zIdFolder,
41
k7zIdCodersUnpackSize,
42
k7zIdNumUnpackStream,
43
k7zIdEmptyStream,
44
k7zIdEmptyFile,
45
k7zIdAnti,
46
k7zIdName,
47
k7zIdCTime,
48
k7zIdATime,
49
k7zIdMTime,
50
k7zIdWinAttrib,
51
k7zIdComment,
52
k7zIdEncodedHeader,
53
k7zIdStartPos,
54
k7zIdDummy
55
// k7zNtSecure,
56
// k7zParent,
57
// k7zIsReal
58
};
59
60
const Byte k7zSignature[k7zSignatureSize] = {'7', 'z', 0xBC, 0xAF, 0x27, 0x1C};
61
62
#define SzBitUi32s_INIT(p) { (p)->Defs = NULL; (p)->Vals = NULL; }
63
64
static SRes SzBitUi32s_Alloc(CSzBitUi32s *p, size_t num, ISzAllocPtr alloc)
65
{
66
if (num == 0)
67
{
68
p->Defs = NULL;
69
p->Vals = NULL;
70
}
71
else
72
{
73
MY_ALLOC(Byte, p->Defs, (num + 7) >> 3, alloc)
74
MY_ALLOC(UInt32, p->Vals, num, alloc)
75
}
76
return SZ_OK;
77
}
78
79
static void SzBitUi32s_Free(CSzBitUi32s *p, ISzAllocPtr alloc)
80
{
81
ISzAlloc_Free(alloc, p->Defs); p->Defs = NULL;
82
ISzAlloc_Free(alloc, p->Vals); p->Vals = NULL;
83
}
84
85
#define SzBitUi64s_INIT(p) { (p)->Defs = NULL; (p)->Vals = NULL; }
86
87
static void SzBitUi64s_Free(CSzBitUi64s *p, ISzAllocPtr alloc)
88
{
89
ISzAlloc_Free(alloc, p->Defs); p->Defs = NULL;
90
ISzAlloc_Free(alloc, p->Vals); p->Vals = NULL;
91
}
92
93
94
static void SzAr_Init(CSzAr *p)
95
{
96
p->NumPackStreams = 0;
97
p->NumFolders = 0;
98
99
p->PackPositions = NULL;
100
SzBitUi32s_INIT(&p->FolderCRCs)
101
102
p->FoCodersOffsets = NULL;
103
p->FoStartPackStreamIndex = NULL;
104
p->FoToCoderUnpackSizes = NULL;
105
p->FoToMainUnpackSizeIndex = NULL;
106
p->CoderUnpackSizes = NULL;
107
108
p->CodersData = NULL;
109
110
p->RangeLimit = 0;
111
}
112
113
static void SzAr_Free(CSzAr *p, ISzAllocPtr alloc)
114
{
115
ISzAlloc_Free(alloc, p->PackPositions);
116
SzBitUi32s_Free(&p->FolderCRCs, alloc);
117
118
ISzAlloc_Free(alloc, p->FoCodersOffsets);
119
ISzAlloc_Free(alloc, p->FoStartPackStreamIndex);
120
ISzAlloc_Free(alloc, p->FoToCoderUnpackSizes);
121
ISzAlloc_Free(alloc, p->FoToMainUnpackSizeIndex);
122
ISzAlloc_Free(alloc, p->CoderUnpackSizes);
123
124
ISzAlloc_Free(alloc, p->CodersData);
125
126
SzAr_Init(p);
127
}
128
129
130
void SzArEx_Init(CSzArEx *p)
131
{
132
SzAr_Init(&p->db);
133
134
p->NumFiles = 0;
135
p->dataPos = 0;
136
137
p->UnpackPositions = NULL;
138
p->IsDirs = NULL;
139
140
p->FolderToFile = NULL;
141
p->FileToFolder = NULL;
142
143
p->FileNameOffsets = NULL;
144
p->FileNames = NULL;
145
146
SzBitUi32s_INIT(&p->CRCs)
147
SzBitUi32s_INIT(&p->Attribs)
148
// SzBitUi32s_INIT(&p->Parents)
149
SzBitUi64s_INIT(&p->MTime)
150
SzBitUi64s_INIT(&p->CTime)
151
}
152
153
void SzArEx_Free(CSzArEx *p, ISzAllocPtr alloc)
154
{
155
ISzAlloc_Free(alloc, p->UnpackPositions);
156
ISzAlloc_Free(alloc, p->IsDirs);
157
158
ISzAlloc_Free(alloc, p->FolderToFile);
159
ISzAlloc_Free(alloc, p->FileToFolder);
160
161
ISzAlloc_Free(alloc, p->FileNameOffsets);
162
ISzAlloc_Free(alloc, p->FileNames);
163
164
SzBitUi32s_Free(&p->CRCs, alloc);
165
SzBitUi32s_Free(&p->Attribs, alloc);
166
// SzBitUi32s_Free(&p->Parents, alloc);
167
SzBitUi64s_Free(&p->MTime, alloc);
168
SzBitUi64s_Free(&p->CTime, alloc);
169
170
SzAr_Free(&p->db, alloc);
171
SzArEx_Init(p);
172
}
173
174
175
static int TestSignatureCandidate(const Byte *testBytes)
176
{
177
unsigned i;
178
for (i = 0; i < k7zSignatureSize; i++)
179
if (testBytes[i] != k7zSignature[i])
180
return 0;
181
return 1;
182
}
183
184
#define SzData_CLEAR(p) { (p)->Data = NULL; (p)->Size = 0; }
185
186
#define SZ_READ_BYTE_SD_NOCHECK(_sd_, dest) \
187
(_sd_)->Size--; dest = *(_sd_)->Data++;
188
189
#define SZ_READ_BYTE_SD(_sd_, dest) \
190
if ((_sd_)->Size == 0) return SZ_ERROR_ARCHIVE; \
191
SZ_READ_BYTE_SD_NOCHECK(_sd_, dest)
192
193
#define SZ_READ_BYTE(dest) SZ_READ_BYTE_SD(sd, dest)
194
195
#define SZ_READ_BYTE_2(dest) \
196
if (sd.Size == 0) return SZ_ERROR_ARCHIVE; \
197
sd.Size--; dest = *sd.Data++;
198
199
#define SKIP_DATA(sd, size) { sd->Size -= (size_t)(size); sd->Data += (size_t)(size); }
200
#define SKIP_DATA2(sd, size) { sd.Size -= (size_t)(size); sd.Data += (size_t)(size); }
201
202
#define SZ_READ_32(dest) if (sd.Size < 4) return SZ_ERROR_ARCHIVE; \
203
dest = GetUi32(sd.Data); SKIP_DATA2(sd, 4);
204
205
static Z7_NO_INLINE SRes ReadNumber(CSzData *sd, UInt64 *value)
206
{
207
Byte firstByte, mask;
208
unsigned i;
209
UInt32 v;
210
211
SZ_READ_BYTE(firstByte)
212
if ((firstByte & 0x80) == 0)
213
{
214
*value = firstByte;
215
return SZ_OK;
216
}
217
SZ_READ_BYTE(v)
218
if ((firstByte & 0x40) == 0)
219
{
220
*value = (((UInt32)firstByte & 0x3F) << 8) | v;
221
return SZ_OK;
222
}
223
SZ_READ_BYTE(mask)
224
*value = v | ((UInt32)mask << 8);
225
mask = 0x20;
226
for (i = 2; i < 8; i++)
227
{
228
Byte b;
229
if ((firstByte & mask) == 0)
230
{
231
const UInt64 highPart = (unsigned)firstByte & (unsigned)(mask - 1);
232
*value |= (highPart << (8 * i));
233
return SZ_OK;
234
}
235
SZ_READ_BYTE(b)
236
*value |= ((UInt64)b << (8 * i));
237
mask >>= 1;
238
}
239
return SZ_OK;
240
}
241
242
243
static Z7_NO_INLINE SRes SzReadNumber32(CSzData *sd, UInt32 *value)
244
{
245
Byte firstByte;
246
UInt64 value64;
247
if (sd->Size == 0)
248
return SZ_ERROR_ARCHIVE;
249
firstByte = *sd->Data;
250
if ((firstByte & 0x80) == 0)
251
{
252
*value = firstByte;
253
sd->Data++;
254
sd->Size--;
255
return SZ_OK;
256
}
257
RINOK(ReadNumber(sd, &value64))
258
if (value64 >= (UInt32)0x80000000 - 1)
259
return SZ_ERROR_UNSUPPORTED;
260
if (value64 >= ((UInt64)(1) << ((sizeof(size_t) - 1) * 8 + 4)))
261
return SZ_ERROR_UNSUPPORTED;
262
*value = (UInt32)value64;
263
return SZ_OK;
264
}
265
266
#define ReadID(sd, value) ReadNumber(sd, value)
267
268
static SRes SkipData(CSzData *sd)
269
{
270
UInt64 size;
271
RINOK(ReadNumber(sd, &size))
272
if (size > sd->Size)
273
return SZ_ERROR_ARCHIVE;
274
SKIP_DATA(sd, size)
275
return SZ_OK;
276
}
277
278
static SRes WaitId(CSzData *sd, UInt32 id)
279
{
280
for (;;)
281
{
282
UInt64 type;
283
RINOK(ReadID(sd, &type))
284
if (type == id)
285
return SZ_OK;
286
if (type == k7zIdEnd)
287
return SZ_ERROR_ARCHIVE;
288
RINOK(SkipData(sd))
289
}
290
}
291
292
static SRes RememberBitVector(CSzData *sd, UInt32 numItems, const Byte **v)
293
{
294
const UInt32 numBytes = (numItems + 7) >> 3;
295
if (numBytes > sd->Size)
296
return SZ_ERROR_ARCHIVE;
297
*v = sd->Data;
298
SKIP_DATA(sd, numBytes)
299
return SZ_OK;
300
}
301
302
static UInt32 CountDefinedBits(const Byte *bits, UInt32 numItems)
303
{
304
unsigned b = 0;
305
unsigned m = 0;
306
UInt32 sum = 0;
307
for (; numItems != 0; numItems--)
308
{
309
if (m == 0)
310
{
311
b = *bits++;
312
m = 8;
313
}
314
m--;
315
sum += (UInt32)((b >> m) & 1);
316
}
317
return sum;
318
}
319
320
static Z7_NO_INLINE SRes ReadBitVector(CSzData *sd, UInt32 numItems, Byte **v, ISzAllocPtr alloc)
321
{
322
Byte allAreDefined;
323
Byte *v2;
324
const UInt32 numBytes = (numItems + 7) >> 3;
325
*v = NULL;
326
SZ_READ_BYTE(allAreDefined)
327
if (numBytes == 0)
328
return SZ_OK;
329
if (allAreDefined == 0)
330
{
331
if (numBytes > sd->Size)
332
return SZ_ERROR_ARCHIVE;
333
MY_ALLOC_AND_CPY(*v, numBytes, sd->Data, alloc)
334
SKIP_DATA(sd, numBytes)
335
return SZ_OK;
336
}
337
MY_ALLOC(Byte, *v, numBytes, alloc)
338
v2 = *v;
339
memset(v2, 0xFF, (size_t)numBytes);
340
{
341
const unsigned numBits = (unsigned)numItems & 7;
342
if (numBits != 0)
343
v2[(size_t)numBytes - 1] = (Byte)((((UInt32)1 << numBits) - 1) << (8 - numBits));
344
}
345
return SZ_OK;
346
}
347
348
static Z7_NO_INLINE SRes ReadUi32s(CSzData *sd2, UInt32 numItems, CSzBitUi32s *crcs, ISzAllocPtr alloc)
349
{
350
UInt32 i;
351
CSzData sd;
352
UInt32 *vals;
353
const Byte *defs;
354
MY_ALLOC_ZE(UInt32, crcs->Vals, numItems, alloc)
355
sd = *sd2;
356
defs = crcs->Defs;
357
vals = crcs->Vals;
358
for (i = 0; i < numItems; i++)
359
if (SzBitArray_Check(defs, i))
360
{
361
SZ_READ_32(vals[i])
362
}
363
else
364
vals[i] = 0;
365
*sd2 = sd;
366
return SZ_OK;
367
}
368
369
static SRes ReadBitUi32s(CSzData *sd, UInt32 numItems, CSzBitUi32s *crcs, ISzAllocPtr alloc)
370
{
371
SzBitUi32s_Free(crcs, alloc);
372
RINOK(ReadBitVector(sd, numItems, &crcs->Defs, alloc))
373
return ReadUi32s(sd, numItems, crcs, alloc);
374
}
375
376
static SRes SkipBitUi32s(CSzData *sd, UInt32 numItems)
377
{
378
Byte allAreDefined;
379
UInt32 numDefined = numItems;
380
SZ_READ_BYTE(allAreDefined)
381
if (!allAreDefined)
382
{
383
const size_t numBytes = (numItems + 7) >> 3;
384
if (numBytes > sd->Size)
385
return SZ_ERROR_ARCHIVE;
386
numDefined = CountDefinedBits(sd->Data, numItems);
387
SKIP_DATA(sd, numBytes)
388
}
389
if (numDefined > (sd->Size >> 2))
390
return SZ_ERROR_ARCHIVE;
391
SKIP_DATA(sd, (size_t)numDefined * 4)
392
return SZ_OK;
393
}
394
395
static SRes ReadPackInfo(CSzAr *p, CSzData *sd, ISzAllocPtr alloc)
396
{
397
RINOK(SzReadNumber32(sd, &p->NumPackStreams))
398
399
RINOK(WaitId(sd, k7zIdSize))
400
MY_ALLOC(UInt64, p->PackPositions, (size_t)p->NumPackStreams + 1, alloc)
401
{
402
UInt64 sum = 0;
403
UInt32 i;
404
const UInt32 numPackStreams = p->NumPackStreams;
405
for (i = 0; i < numPackStreams; i++)
406
{
407
UInt64 packSize;
408
p->PackPositions[i] = sum;
409
RINOK(ReadNumber(sd, &packSize))
410
sum += packSize;
411
if (sum < packSize)
412
return SZ_ERROR_ARCHIVE;
413
}
414
p->PackPositions[i] = sum;
415
}
416
417
for (;;)
418
{
419
UInt64 type;
420
RINOK(ReadID(sd, &type))
421
if (type == k7zIdEnd)
422
return SZ_OK;
423
if (type == k7zIdCRC)
424
{
425
/* CRC of packed streams is unused now */
426
RINOK(SkipBitUi32s(sd, p->NumPackStreams))
427
continue;
428
}
429
RINOK(SkipData(sd))
430
}
431
}
432
433
/*
434
static SRes SzReadSwitch(CSzData *sd)
435
{
436
Byte external;
437
RINOK(SzReadByte(sd, &external));
438
return (external == 0) ? SZ_OK: SZ_ERROR_UNSUPPORTED;
439
}
440
*/
441
442
#define k_NumCodersStreams_in_Folder_MAX (SZ_NUM_BONDS_IN_FOLDER_MAX + SZ_NUM_PACK_STREAMS_IN_FOLDER_MAX)
443
444
SRes SzGetNextFolderItem(CSzFolder *f, CSzData *sd)
445
{
446
UInt32 numCoders, i;
447
UInt32 numInStreams = 0;
448
const Byte *dataStart = sd->Data;
449
450
f->NumCoders = 0;
451
f->NumBonds = 0;
452
f->NumPackStreams = 0;
453
f->UnpackStream = 0;
454
455
RINOK(SzReadNumber32(sd, &numCoders))
456
if (numCoders == 0 || numCoders > SZ_NUM_CODERS_IN_FOLDER_MAX)
457
return SZ_ERROR_UNSUPPORTED;
458
459
for (i = 0; i < numCoders; i++)
460
{
461
Byte mainByte;
462
CSzCoderInfo *coder = f->Coders + i;
463
unsigned idSize, j;
464
UInt64 id;
465
466
SZ_READ_BYTE(mainByte)
467
if ((mainByte & 0xC0) != 0)
468
return SZ_ERROR_UNSUPPORTED;
469
470
idSize = (unsigned)(mainByte & 0xF);
471
if (idSize > sizeof(id))
472
return SZ_ERROR_UNSUPPORTED;
473
if (idSize > sd->Size)
474
return SZ_ERROR_ARCHIVE;
475
id = 0;
476
for (j = 0; j < idSize; j++)
477
{
478
id = ((id << 8) | *sd->Data);
479
sd->Data++;
480
sd->Size--;
481
}
482
if (id > (UInt32)0xFFFFFFFF)
483
return SZ_ERROR_UNSUPPORTED;
484
coder->MethodID = (UInt32)id;
485
486
coder->NumStreams = 1;
487
coder->PropsOffset = 0;
488
coder->PropsSize = 0;
489
490
if ((mainByte & 0x10) != 0)
491
{
492
UInt32 numStreams;
493
494
RINOK(SzReadNumber32(sd, &numStreams))
495
if (numStreams > k_NumCodersStreams_in_Folder_MAX)
496
return SZ_ERROR_UNSUPPORTED;
497
coder->NumStreams = (Byte)numStreams;
498
499
RINOK(SzReadNumber32(sd, &numStreams))
500
if (numStreams != 1)
501
return SZ_ERROR_UNSUPPORTED;
502
}
503
504
numInStreams += coder->NumStreams;
505
506
if (numInStreams > k_NumCodersStreams_in_Folder_MAX)
507
return SZ_ERROR_UNSUPPORTED;
508
509
if ((mainByte & 0x20) != 0)
510
{
511
UInt32 propsSize = 0;
512
RINOK(SzReadNumber32(sd, &propsSize))
513
if (propsSize > sd->Size)
514
return SZ_ERROR_ARCHIVE;
515
if (propsSize >= 0x80)
516
return SZ_ERROR_UNSUPPORTED;
517
coder->PropsOffset = (size_t)(sd->Data - dataStart);
518
coder->PropsSize = (Byte)propsSize;
519
sd->Data += (size_t)propsSize;
520
sd->Size -= (size_t)propsSize;
521
}
522
}
523
524
/*
525
if (numInStreams == 1 && numCoders == 1)
526
{
527
f->NumPackStreams = 1;
528
f->PackStreams[0] = 0;
529
}
530
else
531
*/
532
{
533
Byte streamUsed[k_NumCodersStreams_in_Folder_MAX];
534
UInt32 numBonds, numPackStreams;
535
536
numBonds = numCoders - 1;
537
if (numInStreams < numBonds)
538
return SZ_ERROR_ARCHIVE;
539
if (numBonds > SZ_NUM_BONDS_IN_FOLDER_MAX)
540
return SZ_ERROR_UNSUPPORTED;
541
f->NumBonds = numBonds;
542
543
numPackStreams = numInStreams - numBonds;
544
if (numPackStreams > SZ_NUM_PACK_STREAMS_IN_FOLDER_MAX)
545
return SZ_ERROR_UNSUPPORTED;
546
f->NumPackStreams = numPackStreams;
547
548
for (i = 0; i < numInStreams; i++)
549
streamUsed[i] = False;
550
551
if (numBonds != 0)
552
{
553
Byte coderUsed[SZ_NUM_CODERS_IN_FOLDER_MAX];
554
555
for (i = 0; i < numCoders; i++)
556
coderUsed[i] = False;
557
558
for (i = 0; i < numBonds; i++)
559
{
560
CSzBond *bp = f->Bonds + i;
561
562
RINOK(SzReadNumber32(sd, &bp->InIndex))
563
if (bp->InIndex >= numInStreams || streamUsed[bp->InIndex])
564
return SZ_ERROR_ARCHIVE;
565
streamUsed[bp->InIndex] = True;
566
567
RINOK(SzReadNumber32(sd, &bp->OutIndex))
568
if (bp->OutIndex >= numCoders || coderUsed[bp->OutIndex])
569
return SZ_ERROR_ARCHIVE;
570
coderUsed[bp->OutIndex] = True;
571
}
572
573
for (i = 0; i < numCoders; i++)
574
if (!coderUsed[i])
575
{
576
f->UnpackStream = i;
577
break;
578
}
579
580
if (i == numCoders)
581
return SZ_ERROR_ARCHIVE;
582
}
583
584
if (numPackStreams == 1)
585
{
586
for (i = 0; i < numInStreams; i++)
587
if (!streamUsed[i])
588
break;
589
if (i == numInStreams)
590
return SZ_ERROR_ARCHIVE;
591
f->PackStreams[0] = i;
592
}
593
else
594
for (i = 0; i < numPackStreams; i++)
595
{
596
UInt32 index;
597
RINOK(SzReadNumber32(sd, &index))
598
if (index >= numInStreams || streamUsed[index])
599
return SZ_ERROR_ARCHIVE;
600
streamUsed[index] = True;
601
f->PackStreams[i] = index;
602
}
603
}
604
605
f->NumCoders = numCoders;
606
607
return SZ_OK;
608
}
609
610
611
static Z7_NO_INLINE SRes SkipNumbers(CSzData *sd2, UInt32 num)
612
{
613
CSzData sd;
614
sd = *sd2;
615
for (; num != 0; num--)
616
{
617
Byte firstByte, mask;
618
unsigned i;
619
SZ_READ_BYTE_2(firstByte)
620
if ((firstByte & 0x80) == 0)
621
continue;
622
if ((firstByte & 0x40) == 0)
623
{
624
if (sd.Size == 0)
625
return SZ_ERROR_ARCHIVE;
626
sd.Size--;
627
sd.Data++;
628
continue;
629
}
630
mask = 0x20;
631
for (i = 2; i < 8 && (firstByte & mask) != 0; i++)
632
mask >>= 1;
633
if (i > sd.Size)
634
return SZ_ERROR_ARCHIVE;
635
SKIP_DATA2(sd, i)
636
}
637
*sd2 = sd;
638
return SZ_OK;
639
}
640
641
642
#define k_Scan_NumCoders_MAX 64
643
#define k_Scan_NumCodersStreams_in_Folder_MAX 64
644
645
646
static SRes ReadUnpackInfo(CSzAr *p,
647
CSzData *sd2,
648
UInt32 numFoldersMax,
649
const CBuf *tempBufs, UInt32 numTempBufs,
650
ISzAllocPtr alloc)
651
{
652
CSzData sd;
653
654
UInt32 fo, numFolders, numCodersOutStreams, packStreamIndex;
655
const Byte *startBufPtr;
656
Byte external;
657
658
RINOK(WaitId(sd2, k7zIdFolder))
659
660
RINOK(SzReadNumber32(sd2, &numFolders))
661
if (numFolders > numFoldersMax)
662
return SZ_ERROR_UNSUPPORTED;
663
p->NumFolders = numFolders;
664
665
SZ_READ_BYTE_SD(sd2, external)
666
if (external == 0)
667
sd = *sd2;
668
else
669
{
670
UInt32 index;
671
RINOK(SzReadNumber32(sd2, &index))
672
if (index >= numTempBufs)
673
return SZ_ERROR_ARCHIVE;
674
sd.Data = tempBufs[index].data;
675
sd.Size = tempBufs[index].size;
676
}
677
678
MY_ALLOC(size_t, p->FoCodersOffsets, (size_t)numFolders + 1, alloc)
679
MY_ALLOC(UInt32, p->FoStartPackStreamIndex, (size_t)numFolders + 1, alloc)
680
MY_ALLOC(UInt32, p->FoToCoderUnpackSizes, (size_t)numFolders + 1, alloc)
681
MY_ALLOC_ZE(Byte, p->FoToMainUnpackSizeIndex, (size_t)numFolders, alloc)
682
683
startBufPtr = sd.Data;
684
685
packStreamIndex = 0;
686
numCodersOutStreams = 0;
687
688
for (fo = 0; fo < numFolders; fo++)
689
{
690
UInt32 numCoders, ci, numInStreams = 0;
691
692
p->FoCodersOffsets[fo] = (size_t)(sd.Data - startBufPtr);
693
694
RINOK(SzReadNumber32(&sd, &numCoders))
695
if (numCoders == 0 || numCoders > k_Scan_NumCoders_MAX)
696
return SZ_ERROR_UNSUPPORTED;
697
698
for (ci = 0; ci < numCoders; ci++)
699
{
700
Byte mainByte;
701
unsigned idSize;
702
UInt32 coderInStreams;
703
704
SZ_READ_BYTE_2(mainByte)
705
if ((mainByte & 0xC0) != 0)
706
return SZ_ERROR_UNSUPPORTED;
707
idSize = (mainByte & 0xF);
708
if (idSize > 8)
709
return SZ_ERROR_UNSUPPORTED;
710
if (idSize > sd.Size)
711
return SZ_ERROR_ARCHIVE;
712
SKIP_DATA2(sd, idSize)
713
714
coderInStreams = 1;
715
716
if ((mainByte & 0x10) != 0)
717
{
718
UInt32 coderOutStreams;
719
RINOK(SzReadNumber32(&sd, &coderInStreams))
720
RINOK(SzReadNumber32(&sd, &coderOutStreams))
721
if (coderInStreams > k_Scan_NumCodersStreams_in_Folder_MAX || coderOutStreams != 1)
722
return SZ_ERROR_UNSUPPORTED;
723
}
724
725
numInStreams += coderInStreams;
726
727
if ((mainByte & 0x20) != 0)
728
{
729
UInt32 propsSize;
730
RINOK(SzReadNumber32(&sd, &propsSize))
731
if (propsSize > sd.Size)
732
return SZ_ERROR_ARCHIVE;
733
SKIP_DATA2(sd, propsSize)
734
}
735
}
736
737
{
738
UInt32 indexOfMainStream = 0;
739
UInt32 numPackStreams = 1;
740
741
if (numCoders != 1 || numInStreams != 1)
742
{
743
Byte streamUsed[k_Scan_NumCodersStreams_in_Folder_MAX];
744
Byte coderUsed[k_Scan_NumCoders_MAX];
745
746
UInt32 i;
747
const UInt32 numBonds = numCoders - 1;
748
if (numInStreams < numBonds)
749
return SZ_ERROR_ARCHIVE;
750
751
if (numInStreams > k_Scan_NumCodersStreams_in_Folder_MAX)
752
return SZ_ERROR_UNSUPPORTED;
753
754
for (i = 0; i < numInStreams; i++)
755
streamUsed[i] = False;
756
for (i = 0; i < numCoders; i++)
757
coderUsed[i] = False;
758
759
for (i = 0; i < numBonds; i++)
760
{
761
UInt32 index;
762
763
RINOK(SzReadNumber32(&sd, &index))
764
if (index >= numInStreams || streamUsed[index])
765
return SZ_ERROR_ARCHIVE;
766
streamUsed[index] = True;
767
768
RINOK(SzReadNumber32(&sd, &index))
769
if (index >= numCoders || coderUsed[index])
770
return SZ_ERROR_ARCHIVE;
771
coderUsed[index] = True;
772
}
773
774
numPackStreams = numInStreams - numBonds;
775
776
if (numPackStreams != 1)
777
for (i = 0; i < numPackStreams; i++)
778
{
779
UInt32 index;
780
RINOK(SzReadNumber32(&sd, &index))
781
if (index >= numInStreams || streamUsed[index])
782
return SZ_ERROR_ARCHIVE;
783
streamUsed[index] = True;
784
}
785
786
for (i = 0; i < numCoders; i++)
787
if (!coderUsed[i])
788
{
789
indexOfMainStream = i;
790
break;
791
}
792
793
if (i == numCoders)
794
return SZ_ERROR_ARCHIVE;
795
}
796
797
p->FoStartPackStreamIndex[fo] = packStreamIndex;
798
p->FoToCoderUnpackSizes[fo] = numCodersOutStreams;
799
p->FoToMainUnpackSizeIndex[fo] = (Byte)indexOfMainStream;
800
numCodersOutStreams += numCoders;
801
if (numCodersOutStreams < numCoders)
802
return SZ_ERROR_UNSUPPORTED;
803
if (numPackStreams > p->NumPackStreams - packStreamIndex)
804
return SZ_ERROR_ARCHIVE;
805
packStreamIndex += numPackStreams;
806
}
807
}
808
809
p->FoToCoderUnpackSizes[fo] = numCodersOutStreams;
810
811
{
812
const size_t dataSize = (size_t)(sd.Data - startBufPtr);
813
p->FoStartPackStreamIndex[fo] = packStreamIndex;
814
p->FoCodersOffsets[fo] = dataSize;
815
MY_ALLOC_ZE_AND_CPY(p->CodersData, dataSize, startBufPtr, alloc)
816
}
817
818
if (external != 0)
819
{
820
if (sd.Size != 0)
821
return SZ_ERROR_ARCHIVE;
822
sd = *sd2;
823
}
824
825
RINOK(WaitId(&sd, k7zIdCodersUnpackSize))
826
827
MY_ALLOC_ZE(UInt64, p->CoderUnpackSizes, (size_t)numCodersOutStreams, alloc)
828
{
829
UInt32 i;
830
for (i = 0; i < numCodersOutStreams; i++)
831
{
832
RINOK(ReadNumber(&sd, p->CoderUnpackSizes + i))
833
}
834
}
835
836
for (;;)
837
{
838
UInt64 type;
839
RINOK(ReadID(&sd, &type))
840
if (type == k7zIdEnd)
841
{
842
*sd2 = sd;
843
return SZ_OK;
844
}
845
if (type == k7zIdCRC)
846
{
847
RINOK(ReadBitUi32s(&sd, numFolders, &p->FolderCRCs, alloc))
848
continue;
849
}
850
RINOK(SkipData(&sd))
851
}
852
}
853
854
855
UInt64 SzAr_GetFolderUnpackSize(const CSzAr *p, UInt32 folderIndex)
856
{
857
return p->CoderUnpackSizes[p->FoToCoderUnpackSizes[folderIndex] + p->FoToMainUnpackSizeIndex[folderIndex]];
858
}
859
860
861
typedef struct
862
{
863
UInt32 NumTotalSubStreams;
864
UInt32 NumSubDigests;
865
CSzData sdNumSubStreams;
866
CSzData sdSizes;
867
CSzData sdCRCs;
868
} CSubStreamInfo;
869
870
871
static SRes ReadSubStreamsInfo(CSzAr *p, CSzData *sd, CSubStreamInfo *ssi)
872
{
873
UInt64 type = 0;
874
UInt32 numSubDigests = 0;
875
const UInt32 numFolders = p->NumFolders;
876
UInt32 numUnpackStreams = numFolders;
877
UInt32 numUnpackSizesInData = 0;
878
879
for (;;)
880
{
881
RINOK(ReadID(sd, &type))
882
if (type == k7zIdNumUnpackStream)
883
{
884
UInt32 i;
885
ssi->sdNumSubStreams.Data = sd->Data;
886
numUnpackStreams = 0;
887
numSubDigests = 0;
888
for (i = 0; i < numFolders; i++)
889
{
890
UInt32 numStreams;
891
RINOK(SzReadNumber32(sd, &numStreams))
892
if (numUnpackStreams > numUnpackStreams + numStreams)
893
return SZ_ERROR_UNSUPPORTED;
894
numUnpackStreams += numStreams;
895
if (numStreams != 0)
896
numUnpackSizesInData += (numStreams - 1);
897
if (numStreams != 1 || !SzBitWithVals_Check(&p->FolderCRCs, i))
898
numSubDigests += numStreams;
899
}
900
ssi->sdNumSubStreams.Size = (size_t)(sd->Data - ssi->sdNumSubStreams.Data);
901
continue;
902
}
903
if (type == k7zIdCRC || type == k7zIdSize || type == k7zIdEnd)
904
break;
905
RINOK(SkipData(sd))
906
}
907
908
if (!ssi->sdNumSubStreams.Data)
909
{
910
numSubDigests = numFolders;
911
if (p->FolderCRCs.Defs)
912
numSubDigests = numFolders - CountDefinedBits(p->FolderCRCs.Defs, numFolders);
913
}
914
915
ssi->NumTotalSubStreams = numUnpackStreams;
916
ssi->NumSubDigests = numSubDigests;
917
918
if (type == k7zIdSize)
919
{
920
ssi->sdSizes.Data = sd->Data;
921
RINOK(SkipNumbers(sd, numUnpackSizesInData))
922
ssi->sdSizes.Size = (size_t)(sd->Data - ssi->sdSizes.Data);
923
RINOK(ReadID(sd, &type))
924
}
925
926
for (;;)
927
{
928
if (type == k7zIdEnd)
929
return SZ_OK;
930
if (type == k7zIdCRC)
931
{
932
ssi->sdCRCs.Data = sd->Data;
933
RINOK(SkipBitUi32s(sd, numSubDigests))
934
ssi->sdCRCs.Size = (size_t)(sd->Data - ssi->sdCRCs.Data);
935
}
936
else
937
{
938
RINOK(SkipData(sd))
939
}
940
RINOK(ReadID(sd, &type))
941
}
942
}
943
944
static SRes SzReadStreamsInfo(CSzAr *p,
945
CSzData *sd,
946
UInt32 numFoldersMax, const CBuf *tempBufs, UInt32 numTempBufs,
947
UInt64 *dataOffset,
948
CSubStreamInfo *ssi,
949
ISzAllocPtr alloc)
950
{
951
UInt64 type;
952
953
SzData_CLEAR(&ssi->sdSizes)
954
SzData_CLEAR(&ssi->sdCRCs)
955
SzData_CLEAR(&ssi->sdNumSubStreams)
956
957
*dataOffset = 0;
958
RINOK(ReadID(sd, &type))
959
if (type == k7zIdPackInfo)
960
{
961
RINOK(ReadNumber(sd, dataOffset))
962
if (*dataOffset > p->RangeLimit)
963
return SZ_ERROR_ARCHIVE;
964
RINOK(ReadPackInfo(p, sd, alloc))
965
if (p->PackPositions[p->NumPackStreams] > p->RangeLimit - *dataOffset)
966
return SZ_ERROR_ARCHIVE;
967
RINOK(ReadID(sd, &type))
968
}
969
if (type == k7zIdUnpackInfo)
970
{
971
RINOK(ReadUnpackInfo(p, sd, numFoldersMax, tempBufs, numTempBufs, alloc))
972
RINOK(ReadID(sd, &type))
973
}
974
if (type == k7zIdSubStreamsInfo)
975
{
976
RINOK(ReadSubStreamsInfo(p, sd, ssi))
977
RINOK(ReadID(sd, &type))
978
}
979
else
980
{
981
ssi->NumTotalSubStreams = p->NumFolders;
982
// ssi->NumSubDigests = 0;
983
}
984
985
return (type == k7zIdEnd ? SZ_OK : SZ_ERROR_UNSUPPORTED);
986
}
987
988
static SRes SzReadAndDecodePackedStreams(
989
ILookInStreamPtr inStream,
990
CSzData *sd,
991
CBuf *tempBufs,
992
UInt32 numFoldersMax,
993
UInt64 baseOffset,
994
CSzAr *p,
995
ISzAllocPtr allocTemp)
996
{
997
UInt64 dataStartPos;
998
UInt32 fo;
999
CSubStreamInfo ssi;
1000
1001
RINOK(SzReadStreamsInfo(p, sd, numFoldersMax, NULL, 0, &dataStartPos, &ssi, allocTemp))
1002
1003
dataStartPos += baseOffset;
1004
if (p->NumFolders == 0)
1005
return SZ_ERROR_ARCHIVE;
1006
1007
for (fo = 0; fo < p->NumFolders; fo++)
1008
Buf_Init(tempBufs + fo);
1009
1010
for (fo = 0; fo < p->NumFolders; fo++)
1011
{
1012
CBuf *tempBuf = tempBufs + fo;
1013
const UInt64 unpackSize = SzAr_GetFolderUnpackSize(p, fo);
1014
if ((size_t)unpackSize != unpackSize)
1015
return SZ_ERROR_MEM;
1016
if (!Buf_Create(tempBuf, (size_t)unpackSize, allocTemp))
1017
return SZ_ERROR_MEM;
1018
}
1019
1020
for (fo = 0; fo < p->NumFolders; fo++)
1021
{
1022
const CBuf *tempBuf = tempBufs + fo;
1023
RINOK(LookInStream_SeekTo(inStream, dataStartPos))
1024
RINOK(SzAr_DecodeFolder(p, fo, inStream, dataStartPos, tempBuf->data, tempBuf->size, allocTemp))
1025
}
1026
1027
return SZ_OK;
1028
}
1029
1030
static SRes SzReadFileNames(const Byte *data, size_t size, UInt32 numFiles, size_t *offsets)
1031
{
1032
size_t pos = 0;
1033
*offsets++ = 0;
1034
if (numFiles == 0)
1035
return (size == 0) ? SZ_OK : SZ_ERROR_ARCHIVE;
1036
if (size < 2)
1037
return SZ_ERROR_ARCHIVE;
1038
if (data[size - 2] != 0 || data[size - 1] != 0)
1039
return SZ_ERROR_ARCHIVE;
1040
do
1041
{
1042
const Byte *p;
1043
if (pos == size)
1044
return SZ_ERROR_ARCHIVE;
1045
for (p = data + pos;
1046
#ifdef _WIN32
1047
*(const UInt16 *)(const void *)p != 0
1048
#else
1049
p[0] != 0 || p[1] != 0
1050
#endif
1051
; p += 2);
1052
pos = (size_t)(p - data) + 2;
1053
*offsets++ = (pos >> 1);
1054
}
1055
while (--numFiles);
1056
return (pos == size) ? SZ_OK : SZ_ERROR_ARCHIVE;
1057
}
1058
1059
static Z7_NO_INLINE SRes ReadTime(CSzBitUi64s *p, UInt32 num,
1060
CSzData *sd2,
1061
const CBuf *tempBufs, UInt32 numTempBufs,
1062
ISzAllocPtr alloc)
1063
{
1064
CSzData sd;
1065
UInt32 i;
1066
CNtfsFileTime *vals;
1067
Byte *defs;
1068
Byte external;
1069
1070
RINOK(ReadBitVector(sd2, num, &p->Defs, alloc))
1071
1072
SZ_READ_BYTE_SD(sd2, external)
1073
if (external == 0)
1074
sd = *sd2;
1075
else
1076
{
1077
UInt32 index;
1078
RINOK(SzReadNumber32(sd2, &index))
1079
if (index >= numTempBufs)
1080
return SZ_ERROR_ARCHIVE;
1081
sd.Data = tempBufs[index].data;
1082
sd.Size = tempBufs[index].size;
1083
}
1084
1085
MY_ALLOC_ZE(CNtfsFileTime, p->Vals, num, alloc)
1086
vals = p->Vals;
1087
defs = p->Defs;
1088
for (i = 0; i < num; i++)
1089
if (SzBitArray_Check(defs, i))
1090
{
1091
if (sd.Size < 8)
1092
return SZ_ERROR_ARCHIVE;
1093
vals[i].Low = GetUi32(sd.Data);
1094
vals[i].High = GetUi32(sd.Data + 4);
1095
SKIP_DATA2(sd, 8)
1096
}
1097
else
1098
vals[i].High = vals[i].Low = 0;
1099
1100
if (external == 0)
1101
*sd2 = sd;
1102
1103
return SZ_OK;
1104
}
1105
1106
1107
#define NUM_ADDITIONAL_STREAMS_MAX 8
1108
1109
1110
static SRes SzReadHeader2(
1111
CSzArEx *p, /* allocMain */
1112
CSzData *sd,
1113
ILookInStreamPtr inStream,
1114
CBuf *tempBufs, UInt32 *numTempBufs,
1115
ISzAllocPtr allocMain,
1116
ISzAllocPtr allocTemp
1117
)
1118
{
1119
CSubStreamInfo ssi;
1120
1121
{
1122
UInt64 type;
1123
1124
SzData_CLEAR(&ssi.sdSizes)
1125
SzData_CLEAR(&ssi.sdCRCs)
1126
SzData_CLEAR(&ssi.sdNumSubStreams)
1127
1128
ssi.NumSubDigests = 0;
1129
ssi.NumTotalSubStreams = 0;
1130
1131
RINOK(ReadID(sd, &type))
1132
1133
if (type == k7zIdArchiveProperties)
1134
{
1135
for (;;)
1136
{
1137
UInt64 type2;
1138
RINOK(ReadID(sd, &type2))
1139
if (type2 == k7zIdEnd)
1140
break;
1141
RINOK(SkipData(sd))
1142
}
1143
RINOK(ReadID(sd, &type))
1144
}
1145
1146
if (type == k7zIdAdditionalStreamsInfo)
1147
{
1148
CSzAr tempAr;
1149
SRes res;
1150
1151
SzAr_Init(&tempAr);
1152
tempAr.RangeLimit = p->db.RangeLimit;
1153
1154
res = SzReadAndDecodePackedStreams(inStream, sd, tempBufs, NUM_ADDITIONAL_STREAMS_MAX,
1155
p->startPosAfterHeader, &tempAr, allocTemp);
1156
*numTempBufs = tempAr.NumFolders;
1157
SzAr_Free(&tempAr, allocTemp);
1158
1159
if (res != SZ_OK)
1160
return res;
1161
RINOK(ReadID(sd, &type))
1162
}
1163
1164
if (type == k7zIdMainStreamsInfo)
1165
{
1166
RINOK(SzReadStreamsInfo(&p->db, sd, (UInt32)1 << 30, tempBufs, *numTempBufs,
1167
&p->dataPos, &ssi, allocMain))
1168
p->dataPos += p->startPosAfterHeader;
1169
RINOK(ReadID(sd, &type))
1170
}
1171
1172
if (type == k7zIdEnd)
1173
{
1174
return SZ_OK;
1175
}
1176
1177
if (type != k7zIdFilesInfo)
1178
return SZ_ERROR_ARCHIVE;
1179
}
1180
1181
{
1182
UInt32 numFiles = 0;
1183
UInt32 numEmptyStreams = 0;
1184
const Byte *emptyStreams = NULL;
1185
const Byte *emptyFiles = NULL;
1186
1187
RINOK(SzReadNumber32(sd, &numFiles))
1188
p->NumFiles = numFiles;
1189
1190
for (;;)
1191
{
1192
UInt64 type;
1193
UInt64 size;
1194
RINOK(ReadID(sd, &type))
1195
if (type == k7zIdEnd)
1196
break;
1197
RINOK(ReadNumber(sd, &size))
1198
if (size > sd->Size)
1199
return SZ_ERROR_ARCHIVE;
1200
1201
if (type >= ((UInt32)1 << 8))
1202
{
1203
SKIP_DATA(sd, size)
1204
}
1205
else switch ((unsigned)type)
1206
{
1207
case k7zIdName:
1208
{
1209
size_t namesSize;
1210
const Byte *namesData;
1211
Byte external;
1212
1213
SZ_READ_BYTE(external)
1214
if (external == 0)
1215
{
1216
namesSize = (size_t)size - 1;
1217
namesData = sd->Data;
1218
}
1219
else
1220
{
1221
UInt32 index;
1222
RINOK(SzReadNumber32(sd, &index))
1223
if (index >= *numTempBufs)
1224
return SZ_ERROR_ARCHIVE;
1225
namesData = (tempBufs)[index].data;
1226
namesSize = (tempBufs)[index].size;
1227
}
1228
1229
if ((namesSize & 1) != 0)
1230
return SZ_ERROR_ARCHIVE;
1231
MY_ALLOC(size_t, p->FileNameOffsets, numFiles + 1, allocMain)
1232
MY_ALLOC_ZE_AND_CPY(p->FileNames, namesSize, namesData, allocMain)
1233
RINOK(SzReadFileNames(p->FileNames, namesSize, numFiles, p->FileNameOffsets))
1234
if (external == 0)
1235
{
1236
SKIP_DATA(sd, namesSize)
1237
}
1238
break;
1239
}
1240
case k7zIdEmptyStream:
1241
{
1242
RINOK(RememberBitVector(sd, numFiles, &emptyStreams))
1243
numEmptyStreams = CountDefinedBits(emptyStreams, numFiles);
1244
emptyFiles = NULL;
1245
break;
1246
}
1247
case k7zIdEmptyFile:
1248
{
1249
RINOK(RememberBitVector(sd, numEmptyStreams, &emptyFiles))
1250
break;
1251
}
1252
case k7zIdWinAttrib:
1253
{
1254
Byte external;
1255
CSzData sdSwitch;
1256
CSzData *sdPtr;
1257
SzBitUi32s_Free(&p->Attribs, allocMain);
1258
RINOK(ReadBitVector(sd, numFiles, &p->Attribs.Defs, allocMain))
1259
1260
SZ_READ_BYTE(external)
1261
if (external == 0)
1262
sdPtr = sd;
1263
else
1264
{
1265
UInt32 index;
1266
RINOK(SzReadNumber32(sd, &index))
1267
if (index >= *numTempBufs)
1268
return SZ_ERROR_ARCHIVE;
1269
sdSwitch.Data = (tempBufs)[index].data;
1270
sdSwitch.Size = (tempBufs)[index].size;
1271
sdPtr = &sdSwitch;
1272
}
1273
RINOK(ReadUi32s(sdPtr, numFiles, &p->Attribs, allocMain))
1274
break;
1275
}
1276
/*
1277
case k7zParent:
1278
{
1279
SzBitUi32s_Free(&p->Parents, allocMain);
1280
RINOK(ReadBitVector(sd, numFiles, &p->Parents.Defs, allocMain));
1281
RINOK(SzReadSwitch(sd));
1282
RINOK(ReadUi32s(sd, numFiles, &p->Parents, allocMain));
1283
break;
1284
}
1285
*/
1286
case k7zIdMTime: RINOK(ReadTime(&p->MTime, numFiles, sd, tempBufs, *numTempBufs, allocMain)) break;
1287
case k7zIdCTime: RINOK(ReadTime(&p->CTime, numFiles, sd, tempBufs, *numTempBufs, allocMain)) break;
1288
default:
1289
{
1290
SKIP_DATA(sd, size)
1291
}
1292
}
1293
}
1294
1295
if (numFiles - numEmptyStreams != ssi.NumTotalSubStreams)
1296
return SZ_ERROR_ARCHIVE;
1297
1298
for (;;)
1299
{
1300
UInt64 type;
1301
RINOK(ReadID(sd, &type))
1302
if (type == k7zIdEnd)
1303
break;
1304
RINOK(SkipData(sd))
1305
}
1306
1307
{
1308
UInt32 i;
1309
UInt32 emptyFileIndex = 0;
1310
UInt32 folderIndex = 0;
1311
UInt32 remSubStreams = 0;
1312
UInt32 numSubStreams = 0;
1313
UInt64 unpackPos = 0;
1314
const Byte *digestsDefs = NULL;
1315
const Byte *digestsVals = NULL;
1316
UInt32 digestIndex = 0;
1317
Byte isDirMask = 0;
1318
Byte crcMask = 0;
1319
Byte mask = 0x80;
1320
1321
MY_ALLOC(UInt32, p->FolderToFile, p->db.NumFolders + 1, allocMain)
1322
MY_ALLOC_ZE(UInt32, p->FileToFolder, p->NumFiles, allocMain)
1323
MY_ALLOC(UInt64, p->UnpackPositions, p->NumFiles + 1, allocMain)
1324
MY_ALLOC_ZE(Byte, p->IsDirs, (p->NumFiles + 7) >> 3, allocMain)
1325
1326
RINOK(SzBitUi32s_Alloc(&p->CRCs, p->NumFiles, allocMain))
1327
1328
if (ssi.sdCRCs.Size != 0)
1329
{
1330
Byte allDigestsDefined = 0;
1331
SZ_READ_BYTE_SD_NOCHECK(&ssi.sdCRCs, allDigestsDefined)
1332
if (allDigestsDefined)
1333
digestsVals = ssi.sdCRCs.Data;
1334
else
1335
{
1336
const size_t numBytes = (ssi.NumSubDigests + 7) >> 3;
1337
digestsDefs = ssi.sdCRCs.Data;
1338
digestsVals = digestsDefs + numBytes;
1339
}
1340
}
1341
1342
for (i = 0; i < numFiles; i++, mask >>= 1)
1343
{
1344
if (mask == 0)
1345
{
1346
const UInt32 byteIndex = (i - 1) >> 3;
1347
p->IsDirs[byteIndex] = isDirMask;
1348
p->CRCs.Defs[byteIndex] = crcMask;
1349
isDirMask = 0;
1350
crcMask = 0;
1351
mask = 0x80;
1352
}
1353
1354
p->UnpackPositions[i] = unpackPos;
1355
p->CRCs.Vals[i] = 0;
1356
1357
if (emptyStreams && SzBitArray_Check(emptyStreams, i))
1358
{
1359
if (emptyFiles)
1360
{
1361
if (!SzBitArray_Check(emptyFiles, emptyFileIndex))
1362
isDirMask |= mask;
1363
emptyFileIndex++;
1364
}
1365
else
1366
isDirMask |= mask;
1367
if (remSubStreams == 0)
1368
{
1369
p->FileToFolder[i] = (UInt32)-1;
1370
continue;
1371
}
1372
}
1373
1374
if (remSubStreams == 0)
1375
{
1376
for (;;)
1377
{
1378
if (folderIndex >= p->db.NumFolders)
1379
return SZ_ERROR_ARCHIVE;
1380
p->FolderToFile[folderIndex] = i;
1381
numSubStreams = 1;
1382
if (ssi.sdNumSubStreams.Data)
1383
{
1384
RINOK(SzReadNumber32(&ssi.sdNumSubStreams, &numSubStreams))
1385
}
1386
remSubStreams = numSubStreams;
1387
if (numSubStreams != 0)
1388
break;
1389
{
1390
const UInt64 folderUnpackSize = SzAr_GetFolderUnpackSize(&p->db, folderIndex);
1391
unpackPos += folderUnpackSize;
1392
if (unpackPos < folderUnpackSize)
1393
return SZ_ERROR_ARCHIVE;
1394
}
1395
folderIndex++;
1396
}
1397
}
1398
1399
p->FileToFolder[i] = folderIndex;
1400
1401
if (emptyStreams && SzBitArray_Check(emptyStreams, i))
1402
continue;
1403
1404
if (--remSubStreams == 0)
1405
{
1406
const UInt64 folderUnpackSize = SzAr_GetFolderUnpackSize(&p->db, folderIndex);
1407
const UInt64 startFolderUnpackPos = p->UnpackPositions[p->FolderToFile[folderIndex]];
1408
if (folderUnpackSize < unpackPos - startFolderUnpackPos)
1409
return SZ_ERROR_ARCHIVE;
1410
unpackPos = startFolderUnpackPos + folderUnpackSize;
1411
if (unpackPos < folderUnpackSize)
1412
return SZ_ERROR_ARCHIVE;
1413
1414
if (numSubStreams == 1 && SzBitWithVals_Check(&p->db.FolderCRCs, folderIndex))
1415
{
1416
p->CRCs.Vals[i] = p->db.FolderCRCs.Vals[folderIndex];
1417
crcMask |= mask;
1418
}
1419
folderIndex++;
1420
}
1421
else
1422
{
1423
UInt64 v;
1424
RINOK(ReadNumber(&ssi.sdSizes, &v))
1425
unpackPos += v;
1426
if (unpackPos < v)
1427
return SZ_ERROR_ARCHIVE;
1428
}
1429
if ((crcMask & mask) == 0 && digestsVals)
1430
{
1431
if (!digestsDefs || SzBitArray_Check(digestsDefs, digestIndex))
1432
{
1433
p->CRCs.Vals[i] = GetUi32(digestsVals);
1434
digestsVals += 4;
1435
crcMask |= mask;
1436
}
1437
digestIndex++;
1438
}
1439
}
1440
1441
if (mask != 0x80)
1442
{
1443
const UInt32 byteIndex = (i - 1) >> 3;
1444
p->IsDirs[byteIndex] = isDirMask;
1445
p->CRCs.Defs[byteIndex] = crcMask;
1446
}
1447
1448
p->UnpackPositions[i] = unpackPos;
1449
1450
if (remSubStreams != 0)
1451
return SZ_ERROR_ARCHIVE;
1452
1453
for (;;)
1454
{
1455
p->FolderToFile[folderIndex] = i;
1456
if (folderIndex >= p->db.NumFolders)
1457
break;
1458
if (!ssi.sdNumSubStreams.Data)
1459
return SZ_ERROR_ARCHIVE;
1460
RINOK(SzReadNumber32(&ssi.sdNumSubStreams, &numSubStreams))
1461
if (numSubStreams != 0)
1462
return SZ_ERROR_ARCHIVE;
1463
/*
1464
{
1465
UInt64 folderUnpackSize = SzAr_GetFolderUnpackSize(&p->db, folderIndex);
1466
unpackPos += folderUnpackSize;
1467
if (unpackPos < folderUnpackSize)
1468
return SZ_ERROR_ARCHIVE;
1469
}
1470
*/
1471
folderIndex++;
1472
}
1473
1474
if (ssi.sdNumSubStreams.Data && ssi.sdNumSubStreams.Size != 0)
1475
return SZ_ERROR_ARCHIVE;
1476
}
1477
}
1478
return SZ_OK;
1479
}
1480
1481
1482
static SRes SzReadHeader(
1483
CSzArEx *p,
1484
CSzData *sd,
1485
ILookInStreamPtr inStream,
1486
ISzAllocPtr allocMain,
1487
ISzAllocPtr allocTemp)
1488
{
1489
UInt32 i;
1490
UInt32 numTempBufs = 0;
1491
SRes res;
1492
CBuf tempBufs[NUM_ADDITIONAL_STREAMS_MAX];
1493
1494
for (i = 0; i < NUM_ADDITIONAL_STREAMS_MAX; i++)
1495
Buf_Init(tempBufs + i);
1496
1497
res = SzReadHeader2(p, sd, inStream,
1498
tempBufs, &numTempBufs,
1499
allocMain, allocTemp);
1500
1501
for (i = 0; i < NUM_ADDITIONAL_STREAMS_MAX; i++)
1502
Buf_Free(tempBufs + i, allocTemp);
1503
1504
RINOK(res)
1505
1506
if (sd->Size != 0)
1507
return SZ_ERROR_FAIL;
1508
1509
return res;
1510
}
1511
1512
static SRes SzArEx_Open2(
1513
CSzArEx *p,
1514
ILookInStreamPtr inStream,
1515
ISzAllocPtr allocMain,
1516
ISzAllocPtr allocTemp)
1517
{
1518
Byte header[k7zStartHeaderSize];
1519
Int64 startArcPos;
1520
UInt64 nextHeaderOffset, nextHeaderSize;
1521
size_t nextHeaderSizeT;
1522
UInt32 nextHeaderCRC;
1523
CBuf buf;
1524
SRes res;
1525
1526
startArcPos = 0;
1527
RINOK(ILookInStream_Seek(inStream, &startArcPos, SZ_SEEK_CUR))
1528
1529
RINOK(LookInStream_Read2(inStream, header, k7zStartHeaderSize, SZ_ERROR_NO_ARCHIVE))
1530
1531
if (!TestSignatureCandidate(header))
1532
return SZ_ERROR_NO_ARCHIVE;
1533
if (header[6] != k7zMajorVersion)
1534
return SZ_ERROR_UNSUPPORTED;
1535
1536
nextHeaderOffset = GetUi64(header + 12);
1537
nextHeaderSize = GetUi64(header + 20);
1538
nextHeaderCRC = GetUi32(header + 28);
1539
1540
p->startPosAfterHeader = (UInt64)startArcPos + k7zStartHeaderSize;
1541
1542
if (CrcCalc(header + 12, 20) != GetUi32(header + 8))
1543
return SZ_ERROR_CRC;
1544
1545
p->db.RangeLimit = nextHeaderOffset;
1546
1547
nextHeaderSizeT = (size_t)nextHeaderSize;
1548
if (nextHeaderSizeT != nextHeaderSize)
1549
return SZ_ERROR_MEM;
1550
if (nextHeaderSizeT == 0)
1551
return SZ_OK;
1552
if (nextHeaderOffset > nextHeaderOffset + nextHeaderSize ||
1553
nextHeaderOffset > nextHeaderOffset + nextHeaderSize + k7zStartHeaderSize)
1554
return SZ_ERROR_NO_ARCHIVE;
1555
1556
{
1557
Int64 pos = 0;
1558
RINOK(ILookInStream_Seek(inStream, &pos, SZ_SEEK_END))
1559
if ((UInt64)pos < (UInt64)startArcPos + nextHeaderOffset ||
1560
(UInt64)pos < (UInt64)startArcPos + k7zStartHeaderSize + nextHeaderOffset ||
1561
(UInt64)pos < (UInt64)startArcPos + k7zStartHeaderSize + nextHeaderOffset + nextHeaderSize)
1562
return SZ_ERROR_INPUT_EOF;
1563
}
1564
1565
RINOK(LookInStream_SeekTo(inStream, (UInt64)startArcPos + k7zStartHeaderSize + nextHeaderOffset))
1566
1567
if (!Buf_Create(&buf, nextHeaderSizeT, allocTemp))
1568
return SZ_ERROR_MEM;
1569
1570
res = LookInStream_Read(inStream, buf.data, nextHeaderSizeT);
1571
1572
if (res == SZ_OK)
1573
{
1574
res = SZ_ERROR_ARCHIVE;
1575
if (CrcCalc(buf.data, nextHeaderSizeT) == nextHeaderCRC)
1576
{
1577
CSzData sd;
1578
UInt64 type;
1579
sd.Data = buf.data;
1580
sd.Size = buf.size;
1581
1582
res = ReadID(&sd, &type);
1583
1584
if (res == SZ_OK && type == k7zIdEncodedHeader)
1585
{
1586
CSzAr tempAr;
1587
CBuf tempBuf;
1588
Buf_Init(&tempBuf);
1589
1590
SzAr_Init(&tempAr);
1591
tempAr.RangeLimit = p->db.RangeLimit;
1592
1593
res = SzReadAndDecodePackedStreams(inStream, &sd, &tempBuf, 1, p->startPosAfterHeader, &tempAr, allocTemp);
1594
SzAr_Free(&tempAr, allocTemp);
1595
1596
if (res != SZ_OK)
1597
{
1598
Buf_Free(&tempBuf, allocTemp);
1599
}
1600
else
1601
{
1602
Buf_Free(&buf, allocTemp);
1603
buf.data = tempBuf.data;
1604
buf.size = tempBuf.size;
1605
sd.Data = buf.data;
1606
sd.Size = buf.size;
1607
res = ReadID(&sd, &type);
1608
}
1609
}
1610
1611
if (res == SZ_OK)
1612
{
1613
if (type == k7zIdHeader)
1614
{
1615
/*
1616
CSzData sd2;
1617
unsigned ttt;
1618
for (ttt = 0; ttt < 40000; ttt++)
1619
{
1620
SzArEx_Free(p, allocMain);
1621
sd2 = sd;
1622
res = SzReadHeader(p, &sd2, inStream, allocMain, allocTemp);
1623
if (res != SZ_OK)
1624
break;
1625
}
1626
*/
1627
res = SzReadHeader(p, &sd, inStream, allocMain, allocTemp);
1628
}
1629
else
1630
res = SZ_ERROR_UNSUPPORTED;
1631
}
1632
}
1633
}
1634
1635
Buf_Free(&buf, allocTemp);
1636
return res;
1637
}
1638
1639
1640
SRes SzArEx_Open(CSzArEx *p, ILookInStreamPtr inStream,
1641
ISzAllocPtr allocMain, ISzAllocPtr allocTemp)
1642
{
1643
const SRes res = SzArEx_Open2(p, inStream, allocMain, allocTemp);
1644
if (res != SZ_OK)
1645
SzArEx_Free(p, allocMain);
1646
return res;
1647
}
1648
1649
1650
SRes SzArEx_Extract(
1651
const CSzArEx *p,
1652
ILookInStreamPtr inStream,
1653
UInt32 fileIndex,
1654
UInt32 *blockIndex,
1655
Byte **tempBuf,
1656
size_t *outBufferSize,
1657
size_t *offset,
1658
size_t *outSizeProcessed,
1659
ISzAllocPtr allocMain,
1660
ISzAllocPtr allocTemp)
1661
{
1662
const UInt32 folderIndex = p->FileToFolder[fileIndex];
1663
SRes res = SZ_OK;
1664
1665
*offset = 0;
1666
*outSizeProcessed = 0;
1667
1668
if (folderIndex == (UInt32)-1)
1669
{
1670
ISzAlloc_Free(allocMain, *tempBuf);
1671
*blockIndex = folderIndex;
1672
*tempBuf = NULL;
1673
*outBufferSize = 0;
1674
return SZ_OK;
1675
}
1676
1677
if (*tempBuf == NULL || *blockIndex != folderIndex)
1678
{
1679
const UInt64 unpackSizeSpec = SzAr_GetFolderUnpackSize(&p->db, folderIndex);
1680
/*
1681
UInt64 unpackSizeSpec =
1682
p->UnpackPositions[p->FolderToFile[(size_t)folderIndex + 1]] -
1683
p->UnpackPositions[p->FolderToFile[folderIndex]];
1684
*/
1685
const size_t unpackSize = (size_t)unpackSizeSpec;
1686
1687
if (unpackSize != unpackSizeSpec)
1688
return SZ_ERROR_MEM;
1689
*blockIndex = folderIndex;
1690
ISzAlloc_Free(allocMain, *tempBuf);
1691
*tempBuf = NULL;
1692
1693
if (res == SZ_OK)
1694
{
1695
*outBufferSize = unpackSize;
1696
if (unpackSize != 0)
1697
{
1698
*tempBuf = (Byte *)ISzAlloc_Alloc(allocMain, unpackSize);
1699
if (*tempBuf == NULL)
1700
res = SZ_ERROR_MEM;
1701
}
1702
1703
if (res == SZ_OK)
1704
{
1705
res = SzAr_DecodeFolder(&p->db, folderIndex,
1706
inStream, p->dataPos, *tempBuf, unpackSize, allocTemp);
1707
}
1708
}
1709
}
1710
1711
if (res == SZ_OK)
1712
{
1713
const UInt64 unpackPos = p->UnpackPositions[fileIndex];
1714
*offset = (size_t)(unpackPos - p->UnpackPositions[p->FolderToFile[folderIndex]]);
1715
*outSizeProcessed = (size_t)(p->UnpackPositions[(size_t)fileIndex + 1] - unpackPos);
1716
if (*offset + *outSizeProcessed > *outBufferSize)
1717
return SZ_ERROR_FAIL;
1718
if (SzBitWithVals_Check(&p->CRCs, fileIndex))
1719
if (CrcCalc(*tempBuf + *offset, *outSizeProcessed) != p->CRCs.Vals[fileIndex])
1720
res = SZ_ERROR_CRC;
1721
}
1722
1723
return res;
1724
}
1725
1726
1727
size_t SzArEx_GetFileNameUtf16(const CSzArEx *p, size_t fileIndex, UInt16 *dest)
1728
{
1729
const size_t offs = p->FileNameOffsets[fileIndex];
1730
const size_t len = p->FileNameOffsets[fileIndex + 1] - offs;
1731
if (dest != 0)
1732
{
1733
size_t i;
1734
const Byte *src = p->FileNames + offs * 2;
1735
for (i = 0; i < len; i++)
1736
dest[i] = GetUi16(src + i * 2);
1737
}
1738
return len;
1739
}
1740
1741
/*
1742
size_t SzArEx_GetFullNameLen(const CSzArEx *p, size_t fileIndex)
1743
{
1744
size_t len;
1745
if (!p->FileNameOffsets)
1746
return 1;
1747
len = 0;
1748
for (;;)
1749
{
1750
UInt32 parent = (UInt32)(Int32)-1;
1751
len += p->FileNameOffsets[fileIndex + 1] - p->FileNameOffsets[fileIndex];
1752
if SzBitWithVals_Check(&p->Parents, fileIndex)
1753
parent = p->Parents.Vals[fileIndex];
1754
if (parent == (UInt32)(Int32)-1)
1755
return len;
1756
fileIndex = parent;
1757
}
1758
}
1759
1760
UInt16 *SzArEx_GetFullNameUtf16_Back(const CSzArEx *p, size_t fileIndex, UInt16 *dest)
1761
{
1762
BoolInt needSlash;
1763
if (!p->FileNameOffsets)
1764
{
1765
*(--dest) = 0;
1766
return dest;
1767
}
1768
needSlash = False;
1769
for (;;)
1770
{
1771
UInt32 parent = (UInt32)(Int32)-1;
1772
size_t curLen = p->FileNameOffsets[fileIndex + 1] - p->FileNameOffsets[fileIndex];
1773
SzArEx_GetFileNameUtf16(p, fileIndex, dest - curLen);
1774
if (needSlash)
1775
*(dest - 1) = '/';
1776
needSlash = True;
1777
dest -= curLen;
1778
1779
if SzBitWithVals_Check(&p->Parents, fileIndex)
1780
parent = p->Parents.Vals[fileIndex];
1781
if (parent == (UInt32)(Int32)-1)
1782
return dest;
1783
fileIndex = parent;
1784
}
1785
}
1786
*/
1787
1788