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