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