src/third-party/lzma/7zArcIn.c (view raw)
1/* 7zArcIn.c -- 7z Input functions
22015-11-18 : 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 *)IAlloc_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) p = 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, ISzAlloc *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, ISzAlloc *alloc)
79{
80 IAlloc_Free(alloc, p->Defs); p->Defs = NULL;
81 IAlloc_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, ISzAlloc *alloc)
87{
88 IAlloc_Free(alloc, p->Defs); p->Defs = NULL;
89 IAlloc_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, ISzAlloc *alloc)
111{
112 IAlloc_Free(alloc, p->PackPositions);
113 SzBitUi32s_Free(&p->FolderCRCs, alloc);
114
115 IAlloc_Free(alloc, p->FoCodersOffsets);
116 IAlloc_Free(alloc, p->FoStartPackStreamIndex);
117 IAlloc_Free(alloc, p->FoToCoderUnpackSizes);
118 IAlloc_Free(alloc, p->FoToMainUnpackSizeIndex);
119 IAlloc_Free(alloc, p->CoderUnpackSizes);
120
121 IAlloc_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, ISzAlloc *alloc)
151{
152 IAlloc_Free(alloc, p->UnpackPositions);
153 IAlloc_Free(alloc, p->IsDirs);
154
155 IAlloc_Free(alloc, p->FolderToFile);
156 IAlloc_Free(alloc, p->FileToFolder);
157
158 IAlloc_Free(alloc, p->FileNameOffsets);
159 IAlloc_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, ISzAlloc *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[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, ISzAlloc *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, ISzAlloc *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, ISzAlloc *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 ISzAlloc *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(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
792 packStreamIndex += numPackStreams;
793 if (packStreamIndex < numPackStreams)
794 return SZ_ERROR_UNSUPPORTED;
795
796 if (packStreamIndex > p->NumPackStreams)
797 return SZ_ERROR_ARCHIVE;
798 }
799 }
800
801 p->FoToCoderUnpackSizes[fo] = numCodersOutStreams;
802
803 {
804 size_t dataSize = sd.Data - startBufPtr;
805 p->FoStartPackStreamIndex[fo] = packStreamIndex;
806 p->FoCodersOffsets[fo] = dataSize;
807 MY_ALLOC_ZE_AND_CPY(p->CodersData, dataSize, startBufPtr, alloc);
808 }
809
810 if (external != 0)
811 {
812 if (sd.Size != 0)
813 return SZ_ERROR_ARCHIVE;
814 sd = *sd2;
815 }
816
817 RINOK(WaitId(&sd, k7zIdCodersUnpackSize));
818
819 MY_ALLOC_ZE(UInt64, p->CoderUnpackSizes, (size_t)numCodersOutStreams, alloc);
820 {
821 UInt32 i;
822 for (i = 0; i < numCodersOutStreams; i++)
823 {
824 RINOK(ReadNumber(&sd, p->CoderUnpackSizes + i));
825 }
826 }
827
828 for (;;)
829 {
830 UInt64 type;
831 RINOK(ReadID(&sd, &type));
832 if (type == k7zIdEnd)
833 {
834 *sd2 = sd;
835 return SZ_OK;
836 }
837 if (type == k7zIdCRC)
838 {
839 RINOK(ReadBitUi32s(&sd, numFolders, &p->FolderCRCs, alloc));
840 continue;
841 }
842 RINOK(SkipData(&sd));
843 }
844}
845
846
847UInt64 SzAr_GetFolderUnpackSize(const CSzAr *p, UInt32 folderIndex)
848{
849 return p->CoderUnpackSizes[p->FoToCoderUnpackSizes[folderIndex] + p->FoToMainUnpackSizeIndex[folderIndex]];
850}
851
852
853typedef struct
854{
855 UInt32 NumTotalSubStreams;
856 UInt32 NumSubDigests;
857 CSzData sdNumSubStreams;
858 CSzData sdSizes;
859 CSzData sdCRCs;
860} CSubStreamInfo;
861
862
863static SRes ReadSubStreamsInfo(CSzAr *p, CSzData *sd, CSubStreamInfo *ssi)
864{
865 UInt64 type = 0;
866 UInt32 numSubDigests = 0;
867 UInt32 numFolders = p->NumFolders;
868 UInt32 numUnpackStreams = numFolders;
869 UInt32 numUnpackSizesInData = 0;
870
871 for (;;)
872 {
873 RINOK(ReadID(sd, &type));
874 if (type == k7zIdNumUnpackStream)
875 {
876 UInt32 i;
877 ssi->sdNumSubStreams.Data = sd->Data;
878 numUnpackStreams = 0;
879 numSubDigests = 0;
880 for (i = 0; i < numFolders; i++)
881 {
882 UInt32 numStreams;
883 RINOK(SzReadNumber32(sd, &numStreams));
884 if (numUnpackStreams > numUnpackStreams + numStreams)
885 return SZ_ERROR_UNSUPPORTED;
886 numUnpackStreams += numStreams;
887 if (numStreams != 0)
888 numUnpackSizesInData += (numStreams - 1);
889 if (numStreams != 1 || !SzBitWithVals_Check(&p->FolderCRCs, i))
890 numSubDigests += numStreams;
891 }
892 ssi->sdNumSubStreams.Size = sd->Data - ssi->sdNumSubStreams.Data;
893 continue;
894 }
895 if (type == k7zIdCRC || type == k7zIdSize || type == k7zIdEnd)
896 break;
897 RINOK(SkipData(sd));
898 }
899
900 if (!ssi->sdNumSubStreams.Data)
901 {
902 numSubDigests = numFolders;
903 if (p->FolderCRCs.Defs)
904 numSubDigests = numFolders - CountDefinedBits(p->FolderCRCs.Defs, numFolders);
905 }
906
907 ssi->NumTotalSubStreams = numUnpackStreams;
908 ssi->NumSubDigests = numSubDigests;
909
910 if (type == k7zIdSize)
911 {
912 ssi->sdSizes.Data = sd->Data;
913 RINOK(SkipNumbers(sd, numUnpackSizesInData));
914 ssi->sdSizes.Size = sd->Data - ssi->sdSizes.Data;
915 RINOK(ReadID(sd, &type));
916 }
917
918 for (;;)
919 {
920 if (type == k7zIdEnd)
921 return SZ_OK;
922 if (type == k7zIdCRC)
923 {
924 ssi->sdCRCs.Data = sd->Data;
925 RINOK(SkipBitUi32s(sd, numSubDigests));
926 ssi->sdCRCs.Size = sd->Data - ssi->sdCRCs.Data;
927 }
928 else
929 {
930 RINOK(SkipData(sd));
931 }
932 RINOK(ReadID(sd, &type));
933 }
934}
935
936static SRes SzReadStreamsInfo(CSzAr *p,
937 CSzData *sd,
938 UInt32 numFoldersMax, const CBuf *tempBufs, UInt32 numTempBufs,
939 UInt64 *dataOffset,
940 CSubStreamInfo *ssi,
941 ISzAlloc *alloc)
942{
943 UInt64 type;
944
945 SzData_Clear(&ssi->sdSizes);
946 SzData_Clear(&ssi->sdCRCs);
947 SzData_Clear(&ssi->sdNumSubStreams);
948
949 *dataOffset = 0;
950 RINOK(ReadID(sd, &type));
951 if (type == k7zIdPackInfo)
952 {
953 RINOK(ReadNumber(sd, dataOffset));
954 RINOK(ReadPackInfo(p, sd, alloc));
955 RINOK(ReadID(sd, &type));
956 }
957 if (type == k7zIdUnpackInfo)
958 {
959 RINOK(ReadUnpackInfo(p, sd, numFoldersMax, tempBufs, numTempBufs, alloc));
960 RINOK(ReadID(sd, &type));
961 }
962 if (type == k7zIdSubStreamsInfo)
963 {
964 RINOK(ReadSubStreamsInfo(p, sd, ssi));
965 RINOK(ReadID(sd, &type));
966 }
967 else
968 {
969 ssi->NumTotalSubStreams = p->NumFolders;
970 // ssi->NumSubDigests = 0;
971 }
972
973 return (type == k7zIdEnd ? SZ_OK : SZ_ERROR_UNSUPPORTED);
974}
975
976static SRes SzReadAndDecodePackedStreams(
977 ILookInStream *inStream,
978 CSzData *sd,
979 CBuf *tempBufs,
980 UInt32 numFoldersMax,
981 UInt64 baseOffset,
982 CSzAr *p,
983 ISzAlloc *allocTemp)
984{
985 UInt64 dataStartPos;
986 UInt32 fo;
987 CSubStreamInfo ssi;
988
989 RINOK(SzReadStreamsInfo(p, sd, numFoldersMax, NULL, 0, &dataStartPos, &ssi, allocTemp));
990
991 dataStartPos += baseOffset;
992 if (p->NumFolders == 0)
993 return SZ_ERROR_ARCHIVE;
994
995 for (fo = 0; fo < p->NumFolders; fo++)
996 Buf_Init(tempBufs + fo);
997
998 for (fo = 0; fo < p->NumFolders; fo++)
999 {
1000 CBuf *tempBuf = tempBufs + fo;
1001 UInt64 unpackSize = SzAr_GetFolderUnpackSize(p, fo);
1002 if ((size_t)unpackSize != unpackSize)
1003 return SZ_ERROR_MEM;
1004 if (!Buf_Create(tempBuf, (size_t)unpackSize, allocTemp))
1005 return SZ_ERROR_MEM;
1006 }
1007
1008 for (fo = 0; fo < p->NumFolders; fo++)
1009 {
1010 const CBuf *tempBuf = tempBufs + fo;
1011 RINOK(LookInStream_SeekTo(inStream, dataStartPos));
1012 RINOK(SzAr_DecodeFolder(p, fo, inStream, dataStartPos, tempBuf->data, tempBuf->size, allocTemp));
1013 }
1014
1015 return SZ_OK;
1016}
1017
1018static SRes SzReadFileNames(const Byte *data, size_t size, UInt32 numFiles, size_t *offsets)
1019{
1020 size_t pos = 0;
1021 *offsets++ = 0;
1022 if (numFiles == 0)
1023 return (size == 0) ? SZ_OK : SZ_ERROR_ARCHIVE;
1024 if (size < 2)
1025 return SZ_ERROR_ARCHIVE;
1026 if (data[size - 2] != 0 || data[size - 1] != 0)
1027 return SZ_ERROR_ARCHIVE;
1028 do
1029 {
1030 const Byte *p;
1031 if (pos == size)
1032 return SZ_ERROR_ARCHIVE;
1033 for (p = data + pos;
1034 #ifdef _WIN32
1035 *(const UInt16 *)p != 0
1036 #else
1037 p[0] != 0 || p[1] != 0
1038 #endif
1039 ; p += 2);
1040 pos = p - data + 2;
1041 *offsets++ = (pos >> 1);
1042 }
1043 while (--numFiles);
1044 return (pos == size) ? SZ_OK : SZ_ERROR_ARCHIVE;
1045}
1046
1047static MY_NO_INLINE SRes ReadTime(CSzBitUi64s *p, UInt32 num,
1048 CSzData *sd2,
1049 const CBuf *tempBufs, UInt32 numTempBufs,
1050 ISzAlloc *alloc)
1051{
1052 CSzData sd;
1053 UInt32 i;
1054 CNtfsFileTime *vals;
1055 Byte *defs;
1056 Byte external;
1057
1058 RINOK(ReadBitVector(sd2, num, &p->Defs, alloc));
1059
1060 SZ_READ_BYTE_SD(sd2, external);
1061 if (external == 0)
1062 sd = *sd2;
1063 else
1064 {
1065 UInt32 index;
1066 RINOK(SzReadNumber32(sd2, &index));
1067 if (index >= numTempBufs)
1068 return SZ_ERROR_ARCHIVE;
1069 sd.Data = tempBufs[index].data;
1070 sd.Size = tempBufs[index].size;
1071 }
1072
1073 MY_ALLOC_ZE(CNtfsFileTime, p->Vals, num, alloc);
1074 vals = p->Vals;
1075 defs = p->Defs;
1076 for (i = 0; i < num; i++)
1077 if (SzBitArray_Check(defs, i))
1078 {
1079 if (sd.Size < 8)
1080 return SZ_ERROR_ARCHIVE;
1081 vals[i].Low = GetUi32(sd.Data);
1082 vals[i].High = GetUi32(sd.Data + 4);
1083 SKIP_DATA2(sd, 8);
1084 }
1085 else
1086 vals[i].High = vals[i].Low = 0;
1087
1088 if (external == 0)
1089 *sd2 = sd;
1090
1091 return SZ_OK;
1092}
1093
1094
1095#define NUM_ADDITIONAL_STREAMS_MAX 8
1096
1097
1098static SRes SzReadHeader2(
1099 CSzArEx *p, /* allocMain */
1100 CSzData *sd,
1101 ILookInStream *inStream,
1102 CBuf *tempBufs, UInt32 *numTempBufs,
1103 ISzAlloc *allocMain,
1104 ISzAlloc *allocTemp
1105 )
1106{
1107 UInt64 type;
1108 UInt32 numFiles = 0;
1109 UInt32 numEmptyStreams = 0;
1110 CSubStreamInfo ssi;
1111 const Byte *emptyStreams = NULL;
1112 const Byte *emptyFiles = NULL;
1113
1114 SzData_Clear(&ssi.sdSizes);
1115 SzData_Clear(&ssi.sdCRCs);
1116 SzData_Clear(&ssi.sdNumSubStreams);
1117
1118 ssi.NumSubDigests = 0;
1119 ssi.NumTotalSubStreams = 0;
1120
1121 RINOK(ReadID(sd, &type));
1122
1123 if (type == k7zIdArchiveProperties)
1124 {
1125 for (;;)
1126 {
1127 UInt64 type;
1128 RINOK(ReadID(sd, &type));
1129 if (type == k7zIdEnd)
1130 break;
1131 RINOK(SkipData(sd));
1132 }
1133 RINOK(ReadID(sd, &type));
1134 }
1135
1136 if (type == k7zIdAdditionalStreamsInfo)
1137 {
1138 CSzAr tempAr;
1139 SRes res;
1140
1141 SzAr_Init(&tempAr);
1142 res = SzReadAndDecodePackedStreams(inStream, sd, tempBufs, NUM_ADDITIONAL_STREAMS_MAX,
1143 p->startPosAfterHeader, &tempAr, allocTemp);
1144 *numTempBufs = tempAr.NumFolders;
1145 SzAr_Free(&tempAr, allocTemp);
1146
1147 if (res != SZ_OK)
1148 return res;
1149 RINOK(ReadID(sd, &type));
1150 }
1151
1152 if (type == k7zIdMainStreamsInfo)
1153 {
1154 RINOK(SzReadStreamsInfo(&p->db, sd, (UInt32)1 << 30, tempBufs, *numTempBufs,
1155 &p->dataPos, &ssi, allocMain));
1156 p->dataPos += p->startPosAfterHeader;
1157 RINOK(ReadID(sd, &type));
1158 }
1159
1160 if (type == k7zIdEnd)
1161 {
1162 return SZ_OK;
1163 }
1164
1165 if (type != k7zIdFilesInfo)
1166 return SZ_ERROR_ARCHIVE;
1167
1168 RINOK(SzReadNumber32(sd, &numFiles));
1169 p->NumFiles = numFiles;
1170
1171 for (;;)
1172 {
1173 UInt64 type;
1174 UInt64 size;
1175 RINOK(ReadID(sd, &type));
1176 if (type == k7zIdEnd)
1177 break;
1178 RINOK(ReadNumber(sd, &size));
1179 if (size > sd->Size)
1180 return SZ_ERROR_ARCHIVE;
1181
1182 if (type >= ((UInt32)1 << 8))
1183 {
1184 SKIP_DATA(sd, size);
1185 }
1186 else switch ((unsigned)type)
1187 {
1188 case k7zIdName:
1189 {
1190 size_t namesSize;
1191 const Byte *namesData;
1192 Byte external;
1193
1194 SZ_READ_BYTE(external);
1195 if (external == 0)
1196 {
1197 namesSize = (size_t)size - 1;
1198 namesData = sd->Data;
1199 }
1200 else
1201 {
1202 UInt32 index;
1203 RINOK(SzReadNumber32(sd, &index));
1204 if (index >= *numTempBufs)
1205 return SZ_ERROR_ARCHIVE;
1206 namesData = (tempBufs)[index].data;
1207 namesSize = (tempBufs)[index].size;
1208 }
1209
1210 if ((namesSize & 1) != 0)
1211 return SZ_ERROR_ARCHIVE;
1212 MY_ALLOC(size_t, p->FileNameOffsets, numFiles + 1, allocMain);
1213 MY_ALLOC_ZE_AND_CPY(p->FileNames, namesSize, namesData, allocMain);
1214 RINOK(SzReadFileNames(p->FileNames, namesSize, numFiles, p->FileNameOffsets))
1215 if (external == 0)
1216 {
1217 SKIP_DATA(sd, namesSize);
1218 }
1219 break;
1220 }
1221 case k7zIdEmptyStream:
1222 {
1223 RINOK(RememberBitVector(sd, numFiles, &emptyStreams));
1224 numEmptyStreams = CountDefinedBits(emptyStreams, numFiles);
1225 emptyFiles = NULL;
1226 break;
1227 }
1228 case k7zIdEmptyFile:
1229 {
1230 RINOK(RememberBitVector(sd, numEmptyStreams, &emptyFiles));
1231 break;
1232 }
1233 case k7zIdWinAttrib:
1234 {
1235 Byte external;
1236 CSzData sdSwitch;
1237 CSzData *sdPtr;
1238 SzBitUi32s_Free(&p->Attribs, allocMain);
1239 RINOK(ReadBitVector(sd, numFiles, &p->Attribs.Defs, allocMain));
1240
1241 SZ_READ_BYTE(external);
1242 if (external == 0)
1243 sdPtr = sd;
1244 else
1245 {
1246 UInt32 index;
1247 RINOK(SzReadNumber32(sd, &index));
1248 if (index >= *numTempBufs)
1249 return SZ_ERROR_ARCHIVE;
1250 sdSwitch.Data = (tempBufs)[index].data;
1251 sdSwitch.Size = (tempBufs)[index].size;
1252 sdPtr = &sdSwitch;
1253 }
1254 RINOK(ReadUi32s(sdPtr, numFiles, &p->Attribs, allocMain));
1255 break;
1256 }
1257 /*
1258 case k7zParent:
1259 {
1260 SzBitUi32s_Free(&p->Parents, allocMain);
1261 RINOK(ReadBitVector(sd, numFiles, &p->Parents.Defs, allocMain));
1262 RINOK(SzReadSwitch(sd));
1263 RINOK(ReadUi32s(sd, numFiles, &p->Parents, allocMain));
1264 break;
1265 }
1266 */
1267 case k7zIdMTime: RINOK(ReadTime(&p->MTime, numFiles, sd, tempBufs, *numTempBufs, allocMain)); break;
1268 case k7zIdCTime: RINOK(ReadTime(&p->CTime, numFiles, sd, tempBufs, *numTempBufs, allocMain)); break;
1269 default:
1270 {
1271 SKIP_DATA(sd, size);
1272 }
1273 }
1274 }
1275
1276 if (numFiles - numEmptyStreams != ssi.NumTotalSubStreams)
1277 return SZ_ERROR_ARCHIVE;
1278
1279 for (;;)
1280 {
1281 UInt64 type;
1282 RINOK(ReadID(sd, &type));
1283 if (type == k7zIdEnd)
1284 break;
1285 RINOK(SkipData(sd));
1286 }
1287
1288 {
1289 UInt32 i;
1290 UInt32 emptyFileIndex = 0;
1291 UInt32 folderIndex = 0;
1292 UInt32 remSubStreams = 0;
1293 UInt32 numSubStreams = 0;
1294 UInt64 unpackPos = 0;
1295 const Byte *digestsDefs = NULL;
1296 const Byte *digestsVals = NULL;
1297 UInt32 digestsValsIndex = 0;
1298 UInt32 digestIndex;
1299 Byte allDigestsDefined = 0;
1300 Byte isDirMask = 0;
1301 Byte crcMask = 0;
1302 Byte mask = 0x80;
1303
1304 MY_ALLOC(UInt32, p->FolderToFile, p->db.NumFolders + 1, allocMain);
1305 MY_ALLOC_ZE(UInt32, p->FileToFolder, p->NumFiles, allocMain);
1306 MY_ALLOC(UInt64, p->UnpackPositions, p->NumFiles + 1, allocMain);
1307 MY_ALLOC_ZE(Byte, p->IsDirs, (p->NumFiles + 7) >> 3, allocMain);
1308
1309 RINOK(SzBitUi32s_Alloc(&p->CRCs, p->NumFiles, allocMain));
1310
1311 if (ssi.sdCRCs.Size != 0)
1312 {
1313 SZ_READ_BYTE_SD(&ssi.sdCRCs, allDigestsDefined);
1314 if (allDigestsDefined)
1315 digestsVals = ssi.sdCRCs.Data;
1316 else
1317 {
1318 size_t numBytes = (ssi.NumSubDigests + 7) >> 3;
1319 digestsDefs = ssi.sdCRCs.Data;
1320 digestsVals = digestsDefs + numBytes;
1321 }
1322 }
1323
1324 digestIndex = 0;
1325
1326 for (i = 0; i < numFiles; i++, mask >>= 1)
1327 {
1328 if (mask == 0)
1329 {
1330 UInt32 byteIndex = (i - 1) >> 3;
1331 p->IsDirs[byteIndex] = isDirMask;
1332 p->CRCs.Defs[byteIndex] = crcMask;
1333 isDirMask = 0;
1334 crcMask = 0;
1335 mask = 0x80;
1336 }
1337
1338 p->UnpackPositions[i] = unpackPos;
1339 p->CRCs.Vals[i] = 0;
1340
1341 if (emptyStreams && SzBitArray_Check(emptyStreams, i))
1342 {
1343 if (emptyFiles)
1344 {
1345 if (!SzBitArray_Check(emptyFiles, emptyFileIndex))
1346 isDirMask |= mask;
1347 emptyFileIndex++;
1348 }
1349 else
1350 isDirMask |= mask;
1351 if (remSubStreams == 0)
1352 {
1353 p->FileToFolder[i] = (UInt32)-1;
1354 continue;
1355 }
1356 }
1357
1358 if (remSubStreams == 0)
1359 {
1360 for (;;)
1361 {
1362 if (folderIndex >= p->db.NumFolders)
1363 return SZ_ERROR_ARCHIVE;
1364 p->FolderToFile[folderIndex] = i;
1365 numSubStreams = 1;
1366 if (ssi.sdNumSubStreams.Data)
1367 {
1368 RINOK(SzReadNumber32(&ssi.sdNumSubStreams, &numSubStreams));
1369 }
1370 remSubStreams = numSubStreams;
1371 if (numSubStreams != 0)
1372 break;
1373 {
1374 UInt64 folderUnpackSize = SzAr_GetFolderUnpackSize(&p->db, folderIndex);
1375 unpackPos += folderUnpackSize;
1376 if (unpackPos < folderUnpackSize)
1377 return SZ_ERROR_ARCHIVE;
1378 }
1379
1380 folderIndex++;
1381 }
1382 }
1383
1384 p->FileToFolder[i] = folderIndex;
1385
1386 if (emptyStreams && SzBitArray_Check(emptyStreams, i))
1387 continue;
1388
1389 if (--remSubStreams == 0)
1390 {
1391 UInt64 folderUnpackSize = SzAr_GetFolderUnpackSize(&p->db, folderIndex);
1392 UInt64 startFolderUnpackPos = p->UnpackPositions[p->FolderToFile[folderIndex]];
1393 if (folderUnpackSize < unpackPos - startFolderUnpackPos)
1394 return SZ_ERROR_ARCHIVE;
1395 unpackPos = startFolderUnpackPos + folderUnpackSize;
1396 if (unpackPos < folderUnpackSize)
1397 return SZ_ERROR_ARCHIVE;
1398
1399 if (numSubStreams == 1 && SzBitWithVals_Check(&p->db.FolderCRCs, i))
1400 {
1401 p->CRCs.Vals[i] = p->db.FolderCRCs.Vals[folderIndex];
1402 crcMask |= mask;
1403 }
1404 else if (allDigestsDefined || (digestsDefs && SzBitArray_Check(digestsDefs, digestIndex)))
1405 {
1406 p->CRCs.Vals[i] = GetUi32(digestsVals + (size_t)digestsValsIndex * 4);
1407 digestsValsIndex++;
1408 crcMask |= mask;
1409 }
1410
1411 folderIndex++;
1412 }
1413 else
1414 {
1415 UInt64 v;
1416 RINOK(ReadNumber(&ssi.sdSizes, &v));
1417 unpackPos += v;
1418 if (unpackPos < v)
1419 return SZ_ERROR_ARCHIVE;
1420 if (allDigestsDefined || (digestsDefs && SzBitArray_Check(digestsDefs, digestIndex)))
1421 {
1422 p->CRCs.Vals[i] = GetUi32(digestsVals + (size_t)digestsValsIndex * 4);
1423 digestsValsIndex++;
1424 crcMask |= mask;
1425 }
1426 }
1427 }
1428
1429 if (mask != 0x80)
1430 {
1431 UInt32 byteIndex = (i - 1) >> 3;
1432 p->IsDirs[byteIndex] = isDirMask;
1433 p->CRCs.Defs[byteIndex] = crcMask;
1434 }
1435
1436 p->UnpackPositions[i] = unpackPos;
1437
1438 if (remSubStreams != 0)
1439 return SZ_ERROR_ARCHIVE;
1440
1441 for (;;)
1442 {
1443 p->FolderToFile[folderIndex] = i;
1444 if (folderIndex >= p->db.NumFolders)
1445 break;
1446 if (!ssi.sdNumSubStreams.Data)
1447 return SZ_ERROR_ARCHIVE;
1448 RINOK(SzReadNumber32(&ssi.sdNumSubStreams, &numSubStreams));
1449 if (numSubStreams != 0)
1450 return SZ_ERROR_ARCHIVE;
1451 /*
1452 {
1453 UInt64 folderUnpackSize = SzAr_GetFolderUnpackSize(&p->db, folderIndex);
1454 unpackPos += folderUnpackSize;
1455 if (unpackPos < folderUnpackSize)
1456 return SZ_ERROR_ARCHIVE;
1457 }
1458 */
1459 folderIndex++;
1460 }
1461
1462 if (ssi.sdNumSubStreams.Data && ssi.sdNumSubStreams.Size != 0)
1463 return SZ_ERROR_ARCHIVE;
1464 }
1465
1466 return SZ_OK;
1467}
1468
1469
1470static SRes SzReadHeader(
1471 CSzArEx *p,
1472 CSzData *sd,
1473 ILookInStream *inStream,
1474 ISzAlloc *allocMain,
1475 ISzAlloc *allocTemp)
1476{
1477 UInt32 i;
1478 UInt32 numTempBufs = 0;
1479 SRes res;
1480 CBuf tempBufs[NUM_ADDITIONAL_STREAMS_MAX];
1481
1482 for (i = 0; i < NUM_ADDITIONAL_STREAMS_MAX; i++)
1483 Buf_Init(tempBufs + i);
1484
1485 res = SzReadHeader2(p, sd, inStream,
1486 tempBufs, &numTempBufs,
1487 allocMain, allocTemp);
1488
1489 for (i = 0; i < NUM_ADDITIONAL_STREAMS_MAX; i++)
1490 Buf_Free(tempBufs + i, allocTemp);
1491
1492 RINOK(res);
1493
1494 if (sd->Size != 0)
1495 return SZ_ERROR_FAIL;
1496
1497 return res;
1498}
1499
1500static SRes SzArEx_Open2(
1501 CSzArEx *p,
1502 ILookInStream *inStream,
1503 ISzAlloc *allocMain,
1504 ISzAlloc *allocTemp)
1505{
1506 Byte header[k7zStartHeaderSize];
1507 Int64 startArcPos;
1508 UInt64 nextHeaderOffset, nextHeaderSize;
1509 size_t nextHeaderSizeT;
1510 UInt32 nextHeaderCRC;
1511 CBuf buf;
1512 SRes res;
1513
1514 startArcPos = 0;
1515 RINOK(inStream->Seek(inStream, &startArcPos, SZ_SEEK_CUR));
1516
1517 RINOK(LookInStream_Read2(inStream, header, k7zStartHeaderSize, SZ_ERROR_NO_ARCHIVE));
1518
1519 if (!TestSignatureCandidate(header))
1520 return SZ_ERROR_NO_ARCHIVE;
1521 if (header[6] != k7zMajorVersion)
1522 return SZ_ERROR_UNSUPPORTED;
1523
1524 nextHeaderOffset = GetUi64(header + 12);
1525 nextHeaderSize = GetUi64(header + 20);
1526 nextHeaderCRC = GetUi32(header + 28);
1527
1528 p->startPosAfterHeader = startArcPos + k7zStartHeaderSize;
1529
1530 if (CrcCalc(header + 12, 20) != GetUi32(header + 8))
1531 return SZ_ERROR_CRC;
1532
1533 nextHeaderSizeT = (size_t)nextHeaderSize;
1534 if (nextHeaderSizeT != nextHeaderSize)
1535 return SZ_ERROR_MEM;
1536 if (nextHeaderSizeT == 0)
1537 return SZ_OK;
1538 if (nextHeaderOffset > nextHeaderOffset + nextHeaderSize ||
1539 nextHeaderOffset > nextHeaderOffset + nextHeaderSize + k7zStartHeaderSize)
1540 return SZ_ERROR_NO_ARCHIVE;
1541
1542 {
1543 Int64 pos = 0;
1544 RINOK(inStream->Seek(inStream, &pos, SZ_SEEK_END));
1545 if ((UInt64)pos < startArcPos + nextHeaderOffset ||
1546 (UInt64)pos < startArcPos + k7zStartHeaderSize + nextHeaderOffset ||
1547 (UInt64)pos < startArcPos + k7zStartHeaderSize + nextHeaderOffset + nextHeaderSize)
1548 return SZ_ERROR_INPUT_EOF;
1549 }
1550
1551 RINOK(LookInStream_SeekTo(inStream, startArcPos + k7zStartHeaderSize + nextHeaderOffset));
1552
1553 if (!Buf_Create(&buf, nextHeaderSizeT, allocTemp))
1554 return SZ_ERROR_MEM;
1555
1556 res = LookInStream_Read(inStream, buf.data, nextHeaderSizeT);
1557
1558 if (res == SZ_OK)
1559 {
1560 res = SZ_ERROR_ARCHIVE;
1561 if (CrcCalc(buf.data, nextHeaderSizeT) == nextHeaderCRC)
1562 {
1563 CSzData sd;
1564 UInt64 type;
1565 sd.Data = buf.data;
1566 sd.Size = buf.size;
1567
1568 res = ReadID(&sd, &type);
1569
1570 if (res == SZ_OK && type == k7zIdEncodedHeader)
1571 {
1572 CSzAr tempAr;
1573 CBuf tempBuf;
1574 Buf_Init(&tempBuf);
1575
1576 SzAr_Init(&tempAr);
1577 res = SzReadAndDecodePackedStreams(inStream, &sd, &tempBuf, 1, p->startPosAfterHeader, &tempAr, allocTemp);
1578 SzAr_Free(&tempAr, allocTemp);
1579
1580 if (res != SZ_OK)
1581 {
1582 Buf_Free(&tempBuf, allocTemp);
1583 }
1584 else
1585 {
1586 Buf_Free(&buf, allocTemp);
1587 buf.data = tempBuf.data;
1588 buf.size = tempBuf.size;
1589 sd.Data = buf.data;
1590 sd.Size = buf.size;
1591 res = ReadID(&sd, &type);
1592 }
1593 }
1594
1595 if (res == SZ_OK)
1596 {
1597 if (type == k7zIdHeader)
1598 {
1599 /*
1600 CSzData sd2;
1601 unsigned ttt;
1602 for (ttt = 0; ttt < 40000; ttt++)
1603 {
1604 SzArEx_Free(p, allocMain);
1605 sd2 = sd;
1606 res = SzReadHeader(p, &sd2, inStream, allocMain, allocTemp);
1607 if (res != SZ_OK)
1608 break;
1609 }
1610 */
1611 res = SzReadHeader(p, &sd, inStream, allocMain, allocTemp);
1612 }
1613 else
1614 res = SZ_ERROR_UNSUPPORTED;
1615 }
1616 }
1617 }
1618
1619 Buf_Free(&buf, allocTemp);
1620 return res;
1621}
1622
1623
1624SRes SzArEx_Open(CSzArEx *p, ILookInStream *inStream,
1625 ISzAlloc *allocMain, ISzAlloc *allocTemp)
1626{
1627 SRes res = SzArEx_Open2(p, inStream, allocMain, allocTemp);
1628 if (res != SZ_OK)
1629 SzArEx_Free(p, allocMain);
1630 return res;
1631}
1632
1633
1634SRes SzArEx_Extract(
1635 const CSzArEx *p,
1636 ILookInStream *inStream,
1637 UInt32 fileIndex,
1638 UInt32 *blockIndex,
1639 Byte **tempBuf,
1640 size_t *outBufferSize,
1641 size_t *offset,
1642 size_t *outSizeProcessed,
1643 ISzAlloc *allocMain,
1644 ISzAlloc *allocTemp)
1645{
1646 UInt32 folderIndex = p->FileToFolder[fileIndex];
1647 SRes res = SZ_OK;
1648
1649 *offset = 0;
1650 *outSizeProcessed = 0;
1651
1652 if (folderIndex == (UInt32)-1)
1653 {
1654 IAlloc_Free(allocMain, *tempBuf);
1655 *blockIndex = folderIndex;
1656 *tempBuf = NULL;
1657 *outBufferSize = 0;
1658 return SZ_OK;
1659 }
1660
1661 if (*tempBuf == NULL || *blockIndex != folderIndex)
1662 {
1663 UInt64 unpackSizeSpec = SzAr_GetFolderUnpackSize(&p->db, folderIndex);
1664 /*
1665 UInt64 unpackSizeSpec =
1666 p->UnpackPositions[p->FolderToFile[folderIndex + 1]] -
1667 p->UnpackPositions[p->FolderToFile[folderIndex]];
1668 */
1669 size_t unpackSize = (size_t)unpackSizeSpec;
1670
1671 if (unpackSize != unpackSizeSpec)
1672 return SZ_ERROR_MEM;
1673 *blockIndex = folderIndex;
1674 IAlloc_Free(allocMain, *tempBuf);
1675 *tempBuf = NULL;
1676
1677 if (res == SZ_OK)
1678 {
1679 *outBufferSize = unpackSize;
1680 if (unpackSize != 0)
1681 {
1682 *tempBuf = (Byte *)IAlloc_Alloc(allocMain, unpackSize);
1683 if (*tempBuf == NULL)
1684 res = SZ_ERROR_MEM;
1685 }
1686
1687 if (res == SZ_OK)
1688 {
1689 res = SzAr_DecodeFolder(&p->db, folderIndex,
1690 inStream, p->dataPos, *tempBuf, unpackSize, allocTemp);
1691 }
1692 }
1693 }
1694
1695 if (res == SZ_OK)
1696 {
1697 UInt64 unpackPos = p->UnpackPositions[fileIndex];
1698 *offset = (size_t)(unpackPos - p->UnpackPositions[p->FolderToFile[folderIndex]]);
1699 *outSizeProcessed = (size_t)(p->UnpackPositions[fileIndex + 1] - unpackPos);
1700 if (*offset + *outSizeProcessed > *outBufferSize)
1701 return SZ_ERROR_FAIL;
1702 if (SzBitWithVals_Check(&p->CRCs, fileIndex))
1703 if (CrcCalc(*tempBuf + *offset, *outSizeProcessed) != p->CRCs.Vals[fileIndex])
1704 res = SZ_ERROR_CRC;
1705 }
1706
1707 return res;
1708}
1709
1710
1711size_t SzArEx_GetFileNameUtf16(const CSzArEx *p, size_t fileIndex, UInt16 *dest)
1712{
1713 size_t offs = p->FileNameOffsets[fileIndex];
1714 size_t len = p->FileNameOffsets[fileIndex + 1] - offs;
1715 if (dest != 0)
1716 {
1717 size_t i;
1718 const Byte *src = p->FileNames + offs * 2;
1719 for (i = 0; i < len; i++)
1720 dest[i] = GetUi16(src + i * 2);
1721 }
1722 return len;
1723}
1724
1725/*
1726size_t SzArEx_GetFullNameLen(const CSzArEx *p, size_t fileIndex)
1727{
1728 size_t len;
1729 if (!p->FileNameOffsets)
1730 return 1;
1731 len = 0;
1732 for (;;)
1733 {
1734 UInt32 parent = (UInt32)(Int32)-1;
1735 len += p->FileNameOffsets[fileIndex + 1] - p->FileNameOffsets[fileIndex];
1736 if SzBitWithVals_Check(&p->Parents, fileIndex)
1737 parent = p->Parents.Vals[fileIndex];
1738 if (parent == (UInt32)(Int32)-1)
1739 return len;
1740 fileIndex = parent;
1741 }
1742}
1743
1744UInt16 *SzArEx_GetFullNameUtf16_Back(const CSzArEx *p, size_t fileIndex, UInt16 *dest)
1745{
1746 Bool needSlash;
1747 if (!p->FileNameOffsets)
1748 {
1749 *(--dest) = 0;
1750 return dest;
1751 }
1752 needSlash = False;
1753 for (;;)
1754 {
1755 UInt32 parent = (UInt32)(Int32)-1;
1756 size_t curLen = p->FileNameOffsets[fileIndex + 1] - p->FileNameOffsets[fileIndex];
1757 SzArEx_GetFileNameUtf16(p, fileIndex, dest - curLen);
1758 if (needSlash)
1759 *(dest - 1) = '/';
1760 needSlash = True;
1761 dest -= curLen;
1762
1763 if SzBitWithVals_Check(&p->Parents, fileIndex)
1764 parent = p->Parents.Vals[fileIndex];
1765 if (parent == (UInt32)(Int32)-1)
1766 return dest;
1767 fileIndex = parent;
1768 }
1769}
1770*/