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