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