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