ce188d4d |
1 | /* XzDec.c -- Xz Decode\r |
2 | 2015-11-09 : Igor Pavlov : Public domain */\r |
3 | \r |
4 | #include "Precomp.h"\r |
5 | \r |
6 | /* #define XZ_DUMP */\r |
7 | \r |
8 | #ifdef XZ_DUMP\r |
9 | #include <stdio.h>\r |
10 | #endif\r |
11 | \r |
12 | #include <stdlib.h>\r |
13 | #include <string.h>\r |
14 | \r |
15 | #include "7zCrc.h"\r |
16 | #include "Alloc.h"\r |
17 | #include "Bra.h"\r |
18 | #include "CpuArch.h"\r |
19 | #include "Delta.h"\r |
20 | #include "Lzma2Dec.h"\r |
21 | \r |
22 | #ifdef USE_SUBBLOCK\r |
23 | #include "Bcj3Dec.c"\r |
24 | #include "SbDec.c"\r |
25 | #endif\r |
26 | \r |
27 | #include "Xz.h"\r |
28 | \r |
29 | #define XZ_CHECK_SIZE_MAX 64\r |
30 | \r |
31 | #define CODER_BUF_SIZE (1 << 17)\r |
32 | \r |
33 | unsigned Xz_ReadVarInt(const Byte *p, size_t maxSize, UInt64 *value)\r |
34 | {\r |
35 | unsigned i, limit;\r |
36 | *value = 0;\r |
37 | limit = (maxSize > 9) ? 9 : (unsigned)maxSize;\r |
38 | \r |
39 | for (i = 0; i < limit;)\r |
40 | {\r |
41 | Byte b = p[i];\r |
42 | *value |= (UInt64)(b & 0x7F) << (7 * i++);\r |
43 | if ((b & 0x80) == 0)\r |
44 | return (b == 0 && i != 1) ? 0 : i;\r |
45 | }\r |
46 | return 0;\r |
47 | }\r |
48 | \r |
49 | /* ---------- BraState ---------- */\r |
50 | \r |
51 | #define BRA_BUF_SIZE (1 << 14)\r |
52 | \r |
53 | typedef struct\r |
54 | {\r |
55 | size_t bufPos;\r |
56 | size_t bufConv;\r |
57 | size_t bufTotal;\r |
58 | \r |
59 | UInt32 methodId;\r |
60 | int encodeMode;\r |
61 | UInt32 delta;\r |
62 | UInt32 ip;\r |
63 | UInt32 x86State;\r |
64 | Byte deltaState[DELTA_STATE_SIZE];\r |
65 | \r |
66 | Byte buf[BRA_BUF_SIZE];\r |
67 | } CBraState;\r |
68 | \r |
69 | static void BraState_Free(void *pp, ISzAlloc *alloc)\r |
70 | {\r |
71 | alloc->Free(alloc, pp);\r |
72 | }\r |
73 | \r |
74 | static SRes BraState_SetProps(void *pp, const Byte *props, size_t propSize, ISzAlloc *alloc)\r |
75 | {\r |
76 | CBraState *p = ((CBraState *)pp);\r |
77 | UNUSED_VAR(alloc);\r |
78 | p->ip = 0;\r |
79 | if (p->methodId == XZ_ID_Delta)\r |
80 | {\r |
81 | if (propSize != 1)\r |
82 | return SZ_ERROR_UNSUPPORTED;\r |
83 | p->delta = (unsigned)props[0] + 1;\r |
84 | }\r |
85 | else\r |
86 | {\r |
87 | if (propSize == 4)\r |
88 | {\r |
89 | UInt32 v = GetUi32(props);\r |
90 | switch (p->methodId)\r |
91 | {\r |
92 | case XZ_ID_PPC:\r |
93 | case XZ_ID_ARM:\r |
94 | case XZ_ID_SPARC:\r |
95 | if ((v & 3) != 0)\r |
96 | return SZ_ERROR_UNSUPPORTED;\r |
97 | break;\r |
98 | case XZ_ID_ARMT:\r |
99 | if ((v & 1) != 0)\r |
100 | return SZ_ERROR_UNSUPPORTED;\r |
101 | break;\r |
102 | case XZ_ID_IA64:\r |
103 | if ((v & 0xF) != 0)\r |
104 | return SZ_ERROR_UNSUPPORTED;\r |
105 | break;\r |
106 | }\r |
107 | p->ip = v;\r |
108 | }\r |
109 | else if (propSize != 0)\r |
110 | return SZ_ERROR_UNSUPPORTED;\r |
111 | }\r |
112 | return SZ_OK;\r |
113 | }\r |
114 | \r |
115 | static void BraState_Init(void *pp)\r |
116 | {\r |
117 | CBraState *p = ((CBraState *)pp);\r |
118 | p->bufPos = p->bufConv = p->bufTotal = 0;\r |
119 | x86_Convert_Init(p->x86State);\r |
120 | if (p->methodId == XZ_ID_Delta)\r |
121 | Delta_Init(p->deltaState);\r |
122 | }\r |
123 | \r |
124 | #define CASE_BRA_CONV(isa) case XZ_ID_ ## isa: p->bufConv = isa ## _Convert(p->buf, p->bufTotal, p->ip, p->encodeMode); break;\r |
125 | \r |
126 | static SRes BraState_Code(void *pp, Byte *dest, SizeT *destLen, const Byte *src, SizeT *srcLen,\r |
127 | int srcWasFinished, ECoderFinishMode finishMode, int *wasFinished)\r |
128 | {\r |
129 | CBraState *p = ((CBraState *)pp);\r |
130 | SizeT destLenOrig = *destLen;\r |
131 | SizeT srcLenOrig = *srcLen;\r |
132 | UNUSED_VAR(finishMode);\r |
133 | *destLen = 0;\r |
134 | *srcLen = 0;\r |
135 | *wasFinished = 0;\r |
136 | while (destLenOrig > 0)\r |
137 | {\r |
138 | if (p->bufPos != p->bufConv)\r |
139 | {\r |
140 | size_t curSize = p->bufConv - p->bufPos;\r |
141 | if (curSize > destLenOrig)\r |
142 | curSize = destLenOrig;\r |
143 | memcpy(dest, p->buf + p->bufPos, curSize);\r |
144 | p->bufPos += curSize;\r |
145 | *destLen += curSize;\r |
146 | dest += curSize;\r |
147 | destLenOrig -= curSize;\r |
148 | continue;\r |
149 | }\r |
150 | p->bufTotal -= p->bufPos;\r |
151 | memmove(p->buf, p->buf + p->bufPos, p->bufTotal);\r |
152 | p->bufPos = 0;\r |
153 | p->bufConv = 0;\r |
154 | {\r |
155 | size_t curSize = BRA_BUF_SIZE - p->bufTotal;\r |
156 | if (curSize > srcLenOrig)\r |
157 | curSize = srcLenOrig;\r |
158 | memcpy(p->buf + p->bufTotal, src, curSize);\r |
159 | *srcLen += curSize;\r |
160 | src += curSize;\r |
161 | srcLenOrig -= curSize;\r |
162 | p->bufTotal += curSize;\r |
163 | }\r |
164 | if (p->bufTotal == 0)\r |
165 | break;\r |
166 | switch (p->methodId)\r |
167 | {\r |
168 | case XZ_ID_Delta:\r |
169 | if (p->encodeMode)\r |
170 | Delta_Encode(p->deltaState, p->delta, p->buf, p->bufTotal);\r |
171 | else\r |
172 | Delta_Decode(p->deltaState, p->delta, p->buf, p->bufTotal);\r |
173 | p->bufConv = p->bufTotal;\r |
174 | break;\r |
175 | case XZ_ID_X86:\r |
176 | p->bufConv = x86_Convert(p->buf, p->bufTotal, p->ip, &p->x86State, p->encodeMode);\r |
177 | break;\r |
178 | CASE_BRA_CONV(PPC)\r |
179 | CASE_BRA_CONV(IA64)\r |
180 | CASE_BRA_CONV(ARM)\r |
181 | CASE_BRA_CONV(ARMT)\r |
182 | CASE_BRA_CONV(SPARC)\r |
183 | default:\r |
184 | return SZ_ERROR_UNSUPPORTED;\r |
185 | }\r |
186 | p->ip += (UInt32)p->bufConv;\r |
187 | \r |
188 | if (p->bufConv == 0)\r |
189 | {\r |
190 | if (!srcWasFinished)\r |
191 | break;\r |
192 | p->bufConv = p->bufTotal;\r |
193 | }\r |
194 | }\r |
195 | if (p->bufTotal == p->bufPos && srcLenOrig == 0 && srcWasFinished)\r |
196 | *wasFinished = 1;\r |
197 | return SZ_OK;\r |
198 | }\r |
199 | \r |
200 | SRes BraState_SetFromMethod(IStateCoder *p, UInt64 id, int encodeMode, ISzAlloc *alloc)\r |
201 | {\r |
202 | CBraState *decoder;\r |
203 | if (id != XZ_ID_Delta &&\r |
204 | id != XZ_ID_X86 &&\r |
205 | id != XZ_ID_PPC &&\r |
206 | id != XZ_ID_IA64 &&\r |
207 | id != XZ_ID_ARM &&\r |
208 | id != XZ_ID_ARMT &&\r |
209 | id != XZ_ID_SPARC)\r |
210 | return SZ_ERROR_UNSUPPORTED;\r |
211 | p->p = 0;\r |
212 | decoder = (CBraState *)alloc->Alloc(alloc, sizeof(CBraState));\r |
213 | if (decoder == 0)\r |
214 | return SZ_ERROR_MEM;\r |
215 | decoder->methodId = (UInt32)id;\r |
216 | decoder->encodeMode = encodeMode;\r |
217 | p->p = decoder;\r |
218 | p->Free = BraState_Free;\r |
219 | p->SetProps = BraState_SetProps;\r |
220 | p->Init = BraState_Init;\r |
221 | p->Code = BraState_Code;\r |
222 | return SZ_OK;\r |
223 | }\r |
224 | \r |
225 | /* ---------- SbState ---------- */\r |
226 | \r |
227 | #ifdef USE_SUBBLOCK\r |
228 | \r |
229 | static void SbState_Free(void *pp, ISzAlloc *alloc)\r |
230 | {\r |
231 | CSbDec *p = (CSbDec *)pp;\r |
232 | SbDec_Free(p);\r |
233 | alloc->Free(alloc, pp);\r |
234 | }\r |
235 | \r |
236 | static SRes SbState_SetProps(void *pp, const Byte *props, size_t propSize, ISzAlloc *alloc)\r |
237 | {\r |
238 | UNUSED_VAR(pp);\r |
239 | UNUSED_VAR(props);\r |
240 | UNUSED_VAR(alloc);\r |
241 | return (propSize == 0) ? SZ_OK : SZ_ERROR_UNSUPPORTED;\r |
242 | }\r |
243 | \r |
244 | static void SbState_Init(void *pp)\r |
245 | {\r |
246 | SbDec_Init((CSbDec *)pp);\r |
247 | }\r |
248 | \r |
249 | static SRes SbState_Code(void *pp, Byte *dest, SizeT *destLen, const Byte *src, SizeT *srcLen,\r |
250 | int srcWasFinished, ECoderFinishMode finishMode, int *wasFinished)\r |
251 | {\r |
252 | CSbDec *p = (CSbDec *)pp;\r |
253 | SRes res;\r |
254 | UNUSED_VAR(srcWasFinished);\r |
255 | p->dest = dest;\r |
256 | p->destLen = *destLen;\r |
257 | p->src = src;\r |
258 | p->srcLen = *srcLen;\r |
259 | p->finish = finishMode; /* change it */\r |
260 | res = SbDec_Decode((CSbDec *)pp);\r |
261 | *destLen -= p->destLen;\r |
262 | *srcLen -= p->srcLen;\r |
263 | *wasFinished = (*destLen == 0 && *srcLen == 0); /* change it */\r |
264 | return res;\r |
265 | }\r |
266 | \r |
267 | SRes SbState_SetFromMethod(IStateCoder *p, ISzAlloc *alloc)\r |
268 | {\r |
269 | CSbDec *decoder;\r |
270 | p->p = 0;\r |
271 | decoder = alloc->Alloc(alloc, sizeof(CSbDec));\r |
272 | if (decoder == 0)\r |
273 | return SZ_ERROR_MEM;\r |
274 | p->p = decoder;\r |
275 | p->Free = SbState_Free;\r |
276 | p->SetProps = SbState_SetProps;\r |
277 | p->Init = SbState_Init;\r |
278 | p->Code = SbState_Code;\r |
279 | SbDec_Construct(decoder);\r |
280 | SbDec_SetAlloc(decoder, alloc);\r |
281 | return SZ_OK;\r |
282 | }\r |
283 | #endif\r |
284 | \r |
285 | /* ---------- Lzma2State ---------- */\r |
286 | \r |
287 | static void Lzma2State_Free(void *pp, ISzAlloc *alloc)\r |
288 | {\r |
289 | Lzma2Dec_Free((CLzma2Dec *)pp, alloc);\r |
290 | alloc->Free(alloc, pp);\r |
291 | }\r |
292 | \r |
293 | static SRes Lzma2State_SetProps(void *pp, const Byte *props, size_t propSize, ISzAlloc *alloc)\r |
294 | {\r |
295 | if (propSize != 1)\r |
296 | return SZ_ERROR_UNSUPPORTED;\r |
297 | return Lzma2Dec_Allocate((CLzma2Dec *)pp, props[0], alloc);\r |
298 | }\r |
299 | \r |
300 | static void Lzma2State_Init(void *pp)\r |
301 | {\r |
302 | Lzma2Dec_Init((CLzma2Dec *)pp);\r |
303 | }\r |
304 | \r |
305 | static SRes Lzma2State_Code(void *pp, Byte *dest, SizeT *destLen, const Byte *src, SizeT *srcLen,\r |
306 | int srcWasFinished, ECoderFinishMode finishMode, int *wasFinished)\r |
307 | {\r |
308 | ELzmaStatus status;\r |
309 | /* ELzmaFinishMode fm = (finishMode == LZMA_FINISH_ANY) ? LZMA_FINISH_ANY : LZMA_FINISH_END; */\r |
310 | SRes res = Lzma2Dec_DecodeToBuf((CLzma2Dec *)pp, dest, destLen, src, srcLen, (ELzmaFinishMode)finishMode, &status);\r |
311 | UNUSED_VAR(srcWasFinished);\r |
312 | *wasFinished = (status == LZMA_STATUS_FINISHED_WITH_MARK);\r |
313 | return res;\r |
314 | }\r |
315 | \r |
316 | static SRes Lzma2State_SetFromMethod(IStateCoder *p, ISzAlloc *alloc)\r |
317 | {\r |
318 | CLzma2Dec *decoder = (CLzma2Dec *)alloc->Alloc(alloc, sizeof(CLzma2Dec));\r |
319 | p->p = decoder;\r |
320 | if (decoder == 0)\r |
321 | return SZ_ERROR_MEM;\r |
322 | p->Free = Lzma2State_Free;\r |
323 | p->SetProps = Lzma2State_SetProps;\r |
324 | p->Init = Lzma2State_Init;\r |
325 | p->Code = Lzma2State_Code;\r |
326 | Lzma2Dec_Construct(decoder);\r |
327 | return SZ_OK;\r |
328 | }\r |
329 | \r |
330 | \r |
331 | void MixCoder_Construct(CMixCoder *p, ISzAlloc *alloc)\r |
332 | {\r |
333 | unsigned i;\r |
334 | p->alloc = alloc;\r |
335 | p->buf = NULL;\r |
336 | p->numCoders = 0;\r |
337 | for (i = 0; i < MIXCODER_NUM_FILTERS_MAX; i++)\r |
338 | p->coders[i].p = NULL;\r |
339 | }\r |
340 | \r |
341 | void MixCoder_Free(CMixCoder *p)\r |
342 | {\r |
343 | unsigned i;\r |
344 | for (i = 0; i < p->numCoders; i++)\r |
345 | {\r |
346 | IStateCoder *sc = &p->coders[i];\r |
347 | if (p->alloc && sc->p)\r |
348 | sc->Free(sc->p, p->alloc);\r |
349 | }\r |
350 | p->numCoders = 0;\r |
351 | if (p->buf)\r |
352 | {\r |
353 | p->alloc->Free(p->alloc, p->buf);\r |
354 | p->buf = NULL; /* 9.31: the BUG was fixed */\r |
355 | }\r |
356 | }\r |
357 | \r |
358 | void MixCoder_Init(CMixCoder *p)\r |
359 | {\r |
360 | unsigned i;\r |
361 | for (i = 0; i < MIXCODER_NUM_FILTERS_MAX - 1; i++)\r |
362 | {\r |
363 | p->size[i] = 0;\r |
364 | p->pos[i] = 0;\r |
365 | p->finished[i] = 0;\r |
366 | }\r |
367 | for (i = 0; i < p->numCoders; i++)\r |
368 | {\r |
369 | IStateCoder *coder = &p->coders[i];\r |
370 | coder->Init(coder->p);\r |
371 | }\r |
372 | }\r |
373 | \r |
374 | SRes MixCoder_SetFromMethod(CMixCoder *p, unsigned coderIndex, UInt64 methodId)\r |
375 | {\r |
376 | IStateCoder *sc = &p->coders[coderIndex];\r |
377 | p->ids[coderIndex] = methodId;\r |
378 | switch (methodId)\r |
379 | {\r |
380 | case XZ_ID_LZMA2: return Lzma2State_SetFromMethod(sc, p->alloc);\r |
381 | #ifdef USE_SUBBLOCK\r |
382 | case XZ_ID_Subblock: return SbState_SetFromMethod(sc, p->alloc);\r |
383 | #endif\r |
384 | }\r |
385 | if (coderIndex == 0)\r |
386 | return SZ_ERROR_UNSUPPORTED;\r |
387 | return BraState_SetFromMethod(sc, methodId, 0, p->alloc);\r |
388 | }\r |
389 | \r |
390 | SRes MixCoder_Code(CMixCoder *p, Byte *dest, SizeT *destLen,\r |
391 | const Byte *src, SizeT *srcLen, int srcWasFinished,\r |
392 | ECoderFinishMode finishMode, ECoderStatus *status)\r |
393 | {\r |
394 | SizeT destLenOrig = *destLen;\r |
395 | SizeT srcLenOrig = *srcLen;\r |
396 | Bool allFinished = True;\r |
397 | *destLen = 0;\r |
398 | *srcLen = 0;\r |
399 | *status = CODER_STATUS_NOT_FINISHED;\r |
400 | \r |
401 | if (!p->buf)\r |
402 | {\r |
403 | p->buf = (Byte *)p->alloc->Alloc(p->alloc, CODER_BUF_SIZE * (MIXCODER_NUM_FILTERS_MAX - 1));\r |
404 | if (!p->buf)\r |
405 | return SZ_ERROR_MEM;\r |
406 | }\r |
407 | \r |
408 | if (p->numCoders != 1)\r |
409 | finishMode = CODER_FINISH_ANY;\r |
410 | \r |
411 | for (;;)\r |
412 | {\r |
413 | Bool processed = False;\r |
414 | unsigned i;\r |
415 | /*\r |
416 | if (p->numCoders == 1 && *destLen == destLenOrig && finishMode == LZMA_FINISH_ANY)\r |
417 | break;\r |
418 | */\r |
419 | \r |
420 | for (i = 0; i < p->numCoders; i++)\r |
421 | {\r |
422 | SRes res;\r |
423 | IStateCoder *coder = &p->coders[i];\r |
424 | Byte *destCur;\r |
425 | SizeT destLenCur, srcLenCur;\r |
426 | const Byte *srcCur;\r |
427 | int srcFinishedCur;\r |
428 | int encodingWasFinished;\r |
429 | \r |
430 | if (i == 0)\r |
431 | {\r |
432 | srcCur = src;\r |
433 | srcLenCur = srcLenOrig - *srcLen;\r |
434 | srcFinishedCur = srcWasFinished;\r |
435 | }\r |
436 | else\r |
437 | {\r |
438 | srcCur = p->buf + (CODER_BUF_SIZE * (i - 1)) + p->pos[i - 1];\r |
439 | srcLenCur = p->size[i - 1] - p->pos[i - 1];\r |
440 | srcFinishedCur = p->finished[i - 1];\r |
441 | }\r |
442 | \r |
443 | if (i == p->numCoders - 1)\r |
444 | {\r |
445 | destCur = dest;\r |
446 | destLenCur = destLenOrig - *destLen;\r |
447 | }\r |
448 | else\r |
449 | {\r |
450 | if (p->pos[i] != p->size[i])\r |
451 | continue;\r |
452 | destCur = p->buf + (CODER_BUF_SIZE * i);\r |
453 | destLenCur = CODER_BUF_SIZE;\r |
454 | }\r |
455 | \r |
456 | res = coder->Code(coder->p, destCur, &destLenCur, srcCur, &srcLenCur, srcFinishedCur, finishMode, &encodingWasFinished);\r |
457 | \r |
458 | if (!encodingWasFinished)\r |
459 | allFinished = False;\r |
460 | \r |
461 | if (i == 0)\r |
462 | {\r |
463 | *srcLen += srcLenCur;\r |
464 | src += srcLenCur;\r |
465 | }\r |
466 | else\r |
467 | {\r |
468 | p->pos[i - 1] += srcLenCur;\r |
469 | }\r |
470 | \r |
471 | if (i == p->numCoders - 1)\r |
472 | {\r |
473 | *destLen += destLenCur;\r |
474 | dest += destLenCur;\r |
475 | }\r |
476 | else\r |
477 | {\r |
478 | p->size[i] = destLenCur;\r |
479 | p->pos[i] = 0;\r |
480 | p->finished[i] = encodingWasFinished;\r |
481 | }\r |
482 | \r |
483 | if (res != SZ_OK)\r |
484 | return res;\r |
485 | \r |
486 | if (destLenCur != 0 || srcLenCur != 0)\r |
487 | processed = True;\r |
488 | }\r |
489 | if (!processed)\r |
490 | break;\r |
491 | }\r |
492 | if (allFinished)\r |
493 | *status = CODER_STATUS_FINISHED_WITH_MARK;\r |
494 | return SZ_OK;\r |
495 | }\r |
496 | \r |
497 | SRes Xz_ParseHeader(CXzStreamFlags *p, const Byte *buf)\r |
498 | {\r |
499 | *p = (CXzStreamFlags)GetBe16(buf + XZ_SIG_SIZE);\r |
500 | if (CrcCalc(buf + XZ_SIG_SIZE, XZ_STREAM_FLAGS_SIZE) !=\r |
501 | GetUi32(buf + XZ_SIG_SIZE + XZ_STREAM_FLAGS_SIZE))\r |
502 | return SZ_ERROR_NO_ARCHIVE;\r |
503 | return XzFlags_IsSupported(*p) ? SZ_OK : SZ_ERROR_UNSUPPORTED;\r |
504 | }\r |
505 | \r |
506 | static Bool Xz_CheckFooter(CXzStreamFlags flags, UInt64 indexSize, const Byte *buf)\r |
507 | {\r |
508 | return\r |
509 | indexSize == (((UInt64)GetUi32(buf + 4) + 1) << 2) &&\r |
510 | (GetUi32(buf) == CrcCalc(buf + 4, 6) &&\r |
511 | flags == GetBe16(buf + 8) &&\r |
512 | memcmp(buf + 10, XZ_FOOTER_SIG, XZ_FOOTER_SIG_SIZE) == 0);\r |
513 | }\r |
514 | \r |
515 | #define READ_VARINT_AND_CHECK(buf, pos, size, res) \\r |
516 | { unsigned s = Xz_ReadVarInt(buf + pos, size - pos, res); \\r |
517 | if (s == 0) return SZ_ERROR_ARCHIVE; pos += s; }\r |
518 | \r |
519 | \r |
520 | SRes XzBlock_Parse(CXzBlock *p, const Byte *header)\r |
521 | {\r |
522 | unsigned pos;\r |
523 | unsigned numFilters, i;\r |
524 | unsigned headerSize = (unsigned)header[0] << 2;\r |
525 | \r |
526 | if (CrcCalc(header, headerSize) != GetUi32(header + headerSize))\r |
527 | return SZ_ERROR_ARCHIVE;\r |
528 | \r |
529 | pos = 1;\r |
530 | if (pos == headerSize)\r |
531 | return SZ_ERROR_ARCHIVE;\r |
532 | p->flags = header[pos++];\r |
533 | \r |
534 | if (XzBlock_HasPackSize(p))\r |
535 | {\r |
536 | READ_VARINT_AND_CHECK(header, pos, headerSize, &p->packSize);\r |
537 | if (p->packSize == 0 || p->packSize + headerSize >= (UInt64)1 << 63)\r |
538 | return SZ_ERROR_ARCHIVE;\r |
539 | }\r |
540 | \r |
541 | if (XzBlock_HasUnpackSize(p))\r |
542 | READ_VARINT_AND_CHECK(header, pos, headerSize, &p->unpackSize);\r |
543 | \r |
544 | numFilters = XzBlock_GetNumFilters(p);\r |
545 | for (i = 0; i < numFilters; i++)\r |
546 | {\r |
547 | CXzFilter *filter = p->filters + i;\r |
548 | UInt64 size;\r |
549 | READ_VARINT_AND_CHECK(header, pos, headerSize, &filter->id);\r |
550 | READ_VARINT_AND_CHECK(header, pos, headerSize, &size);\r |
551 | if (size > headerSize - pos || size > XZ_FILTER_PROPS_SIZE_MAX)\r |
552 | return SZ_ERROR_ARCHIVE;\r |
553 | filter->propsSize = (UInt32)size;\r |
554 | memcpy(filter->props, header + pos, (size_t)size);\r |
555 | pos += (unsigned)size;\r |
556 | \r |
557 | #ifdef XZ_DUMP\r |
558 | printf("\nf[%u] = %2X: ", i, (unsigned)filter->id);\r |
559 | {\r |
560 | unsigned i;\r |
561 | for (i = 0; i < size; i++)\r |
562 | printf(" %2X", filter->props[i]);\r |
563 | }\r |
564 | #endif\r |
565 | }\r |
566 | \r |
567 | while (pos < headerSize)\r |
568 | if (header[pos++] != 0)\r |
569 | return SZ_ERROR_ARCHIVE;\r |
570 | return SZ_OK;\r |
571 | }\r |
572 | \r |
573 | SRes XzDec_Init(CMixCoder *p, const CXzBlock *block)\r |
574 | {\r |
575 | unsigned i;\r |
576 | Bool needReInit = True;\r |
577 | unsigned numFilters = XzBlock_GetNumFilters(block);\r |
578 | \r |
579 | if (numFilters == p->numCoders)\r |
580 | {\r |
581 | for (i = 0; i < numFilters; i++)\r |
582 | if (p->ids[i] != block->filters[numFilters - 1 - i].id)\r |
583 | break;\r |
584 | needReInit = (i != numFilters);\r |
585 | }\r |
586 | \r |
587 | if (needReInit)\r |
588 | {\r |
589 | MixCoder_Free(p);\r |
590 | p->numCoders = numFilters;\r |
591 | for (i = 0; i < numFilters; i++)\r |
592 | {\r |
593 | const CXzFilter *f = &block->filters[numFilters - 1 - i];\r |
594 | RINOK(MixCoder_SetFromMethod(p, i, f->id));\r |
595 | }\r |
596 | }\r |
597 | \r |
598 | for (i = 0; i < numFilters; i++)\r |
599 | {\r |
600 | const CXzFilter *f = &block->filters[numFilters - 1 - i];\r |
601 | IStateCoder *sc = &p->coders[i];\r |
602 | RINOK(sc->SetProps(sc->p, f->props, f->propsSize, p->alloc));\r |
603 | }\r |
604 | \r |
605 | MixCoder_Init(p);\r |
606 | return SZ_OK;\r |
607 | }\r |
608 | \r |
609 | void XzUnpacker_Init(CXzUnpacker *p)\r |
610 | {\r |
611 | p->state = XZ_STATE_STREAM_HEADER;\r |
612 | p->pos = 0;\r |
613 | p->numStartedStreams = 0;\r |
614 | p->numFinishedStreams = 0;\r |
615 | p->numTotalBlocks = 0;\r |
616 | p->padSize = 0;\r |
617 | }\r |
618 | \r |
619 | void XzUnpacker_Construct(CXzUnpacker *p, ISzAlloc *alloc)\r |
620 | {\r |
621 | MixCoder_Construct(&p->decoder, alloc);\r |
622 | XzUnpacker_Init(p);\r |
623 | }\r |
624 | \r |
625 | void XzUnpacker_Free(CXzUnpacker *p)\r |
626 | {\r |
627 | MixCoder_Free(&p->decoder);\r |
628 | }\r |
629 | \r |
630 | SRes XzUnpacker_Code(CXzUnpacker *p, Byte *dest, SizeT *destLen,\r |
631 | const Byte *src, SizeT *srcLen, ECoderFinishMode finishMode, ECoderStatus *status)\r |
632 | {\r |
633 | SizeT destLenOrig = *destLen;\r |
634 | SizeT srcLenOrig = *srcLen;\r |
635 | *destLen = 0;\r |
636 | *srcLen = 0;\r |
637 | *status = CODER_STATUS_NOT_SPECIFIED;\r |
638 | for (;;)\r |
639 | {\r |
640 | SizeT srcRem = srcLenOrig - *srcLen;\r |
641 | \r |
642 | if (p->state == XZ_STATE_BLOCK)\r |
643 | {\r |
644 | SizeT destLen2 = destLenOrig - *destLen;\r |
645 | SizeT srcLen2 = srcLenOrig - *srcLen;\r |
646 | SRes res;\r |
647 | if (srcLen2 == 0 && destLen2 == 0)\r |
648 | {\r |
649 | *status = CODER_STATUS_NOT_FINISHED;\r |
650 | return SZ_OK;\r |
651 | }\r |
652 | \r |
653 | res = MixCoder_Code(&p->decoder, dest, &destLen2, src, &srcLen2, False, finishMode, status);\r |
654 | XzCheck_Update(&p->check, dest, destLen2);\r |
655 | \r |
656 | (*srcLen) += srcLen2;\r |
657 | src += srcLen2;\r |
658 | p->packSize += srcLen2;\r |
659 | \r |
660 | (*destLen) += destLen2;\r |
661 | dest += destLen2;\r |
662 | p->unpackSize += destLen2;\r |
663 | \r |
664 | RINOK(res);\r |
665 | \r |
666 | if (*status == CODER_STATUS_FINISHED_WITH_MARK)\r |
667 | {\r |
668 | Byte temp[32];\r |
669 | unsigned num = Xz_WriteVarInt(temp, p->packSize + p->blockHeaderSize + XzFlags_GetCheckSize(p->streamFlags));\r |
670 | num += Xz_WriteVarInt(temp + num, p->unpackSize);\r |
671 | Sha256_Update(&p->sha, temp, num);\r |
672 | p->indexSize += num;\r |
673 | p->numBlocks++;\r |
674 | \r |
675 | p->state = XZ_STATE_BLOCK_FOOTER;\r |
676 | p->pos = 0;\r |
677 | p->alignPos = 0;\r |
678 | }\r |
679 | else if (srcLen2 == 0 && destLen2 == 0)\r |
680 | return SZ_OK;\r |
681 | \r |
682 | continue;\r |
683 | }\r |
684 | \r |
685 | if (srcRem == 0)\r |
686 | {\r |
687 | *status = CODER_STATUS_NEEDS_MORE_INPUT;\r |
688 | return SZ_OK;\r |
689 | }\r |
690 | \r |
691 | switch (p->state)\r |
692 | {\r |
693 | case XZ_STATE_STREAM_HEADER:\r |
694 | {\r |
695 | if (p->pos < XZ_STREAM_HEADER_SIZE)\r |
696 | {\r |
697 | if (p->pos < XZ_SIG_SIZE && *src != XZ_SIG[p->pos])\r |
698 | return SZ_ERROR_NO_ARCHIVE;\r |
699 | p->buf[p->pos++] = *src++;\r |
700 | (*srcLen)++;\r |
701 | }\r |
702 | else\r |
703 | {\r |
704 | RINOK(Xz_ParseHeader(&p->streamFlags, p->buf));\r |
705 | p->numStartedStreams++;\r |
706 | p->state = XZ_STATE_BLOCK_HEADER;\r |
707 | Sha256_Init(&p->sha);\r |
708 | p->indexSize = 0;\r |
709 | p->numBlocks = 0;\r |
710 | p->pos = 0;\r |
711 | }\r |
712 | break;\r |
713 | }\r |
714 | \r |
715 | case XZ_STATE_BLOCK_HEADER:\r |
716 | {\r |
717 | if (p->pos == 0)\r |
718 | {\r |
719 | p->buf[p->pos++] = *src++;\r |
720 | (*srcLen)++;\r |
721 | if (p->buf[0] == 0)\r |
722 | {\r |
723 | p->indexPreSize = 1 + Xz_WriteVarInt(p->buf + 1, p->numBlocks);\r |
724 | p->indexPos = p->indexPreSize;\r |
725 | p->indexSize += p->indexPreSize;\r |
726 | Sha256_Final(&p->sha, p->shaDigest);\r |
727 | Sha256_Init(&p->sha);\r |
728 | p->crc = CrcUpdate(CRC_INIT_VAL, p->buf, p->indexPreSize);\r |
729 | p->state = XZ_STATE_STREAM_INDEX;\r |
730 | }\r |
731 | p->blockHeaderSize = ((UInt32)p->buf[0] << 2) + 4;\r |
732 | }\r |
733 | else if (p->pos != p->blockHeaderSize)\r |
734 | {\r |
735 | UInt32 cur = p->blockHeaderSize - p->pos;\r |
736 | if (cur > srcRem)\r |
737 | cur = (UInt32)srcRem;\r |
738 | memcpy(p->buf + p->pos, src, cur);\r |
739 | p->pos += cur;\r |
740 | (*srcLen) += cur;\r |
741 | src += cur;\r |
742 | }\r |
743 | else\r |
744 | {\r |
745 | RINOK(XzBlock_Parse(&p->block, p->buf));\r |
746 | p->numTotalBlocks++;\r |
747 | p->state = XZ_STATE_BLOCK;\r |
748 | p->packSize = 0;\r |
749 | p->unpackSize = 0;\r |
750 | XzCheck_Init(&p->check, XzFlags_GetCheckType(p->streamFlags));\r |
751 | RINOK(XzDec_Init(&p->decoder, &p->block));\r |
752 | }\r |
753 | break;\r |
754 | }\r |
755 | \r |
756 | case XZ_STATE_BLOCK_FOOTER:\r |
757 | {\r |
758 | if (((p->packSize + p->alignPos) & 3) != 0)\r |
759 | {\r |
760 | (*srcLen)++;\r |
761 | p->alignPos++;\r |
762 | if (*src++ != 0)\r |
763 | return SZ_ERROR_CRC;\r |
764 | }\r |
765 | else\r |
766 | {\r |
767 | UInt32 checkSize = XzFlags_GetCheckSize(p->streamFlags);\r |
768 | UInt32 cur = checkSize - p->pos;\r |
769 | if (cur != 0)\r |
770 | {\r |
771 | if (cur > srcRem)\r |
772 | cur = (UInt32)srcRem;\r |
773 | memcpy(p->buf + p->pos, src, cur);\r |
774 | p->pos += cur;\r |
775 | (*srcLen) += cur;\r |
776 | src += cur;\r |
777 | }\r |
778 | else\r |
779 | {\r |
780 | Byte digest[XZ_CHECK_SIZE_MAX];\r |
781 | p->state = XZ_STATE_BLOCK_HEADER;\r |
782 | p->pos = 0;\r |
783 | if (XzCheck_Final(&p->check, digest) && memcmp(digest, p->buf, checkSize) != 0)\r |
784 | return SZ_ERROR_CRC;\r |
785 | }\r |
786 | }\r |
787 | break;\r |
788 | }\r |
789 | \r |
790 | case XZ_STATE_STREAM_INDEX:\r |
791 | {\r |
792 | if (p->pos < p->indexPreSize)\r |
793 | {\r |
794 | (*srcLen)++;\r |
795 | if (*src++ != p->buf[p->pos++])\r |
796 | return SZ_ERROR_CRC;\r |
797 | }\r |
798 | else\r |
799 | {\r |
800 | if (p->indexPos < p->indexSize)\r |
801 | {\r |
802 | UInt64 cur = p->indexSize - p->indexPos;\r |
803 | if (srcRem > cur)\r |
804 | srcRem = (SizeT)cur;\r |
805 | p->crc = CrcUpdate(p->crc, src, srcRem);\r |
806 | Sha256_Update(&p->sha, src, srcRem);\r |
807 | (*srcLen) += srcRem;\r |
808 | src += srcRem;\r |
809 | p->indexPos += srcRem;\r |
810 | }\r |
811 | else if ((p->indexPos & 3) != 0)\r |
812 | {\r |
813 | Byte b = *src++;\r |
814 | p->crc = CRC_UPDATE_BYTE(p->crc, b);\r |
815 | (*srcLen)++;\r |
816 | p->indexPos++;\r |
817 | p->indexSize++;\r |
818 | if (b != 0)\r |
819 | return SZ_ERROR_CRC;\r |
820 | }\r |
821 | else\r |
822 | {\r |
823 | Byte digest[SHA256_DIGEST_SIZE];\r |
824 | p->state = XZ_STATE_STREAM_INDEX_CRC;\r |
825 | p->indexSize += 4;\r |
826 | p->pos = 0;\r |
827 | Sha256_Final(&p->sha, digest);\r |
828 | if (memcmp(digest, p->shaDigest, SHA256_DIGEST_SIZE) != 0)\r |
829 | return SZ_ERROR_CRC;\r |
830 | }\r |
831 | }\r |
832 | break;\r |
833 | }\r |
834 | \r |
835 | case XZ_STATE_STREAM_INDEX_CRC:\r |
836 | {\r |
837 | if (p->pos < 4)\r |
838 | {\r |
839 | (*srcLen)++;\r |
840 | p->buf[p->pos++] = *src++;\r |
841 | }\r |
842 | else\r |
843 | {\r |
844 | p->state = XZ_STATE_STREAM_FOOTER;\r |
845 | p->pos = 0;\r |
846 | if (CRC_GET_DIGEST(p->crc) != GetUi32(p->buf))\r |
847 | return SZ_ERROR_CRC;\r |
848 | }\r |
849 | break;\r |
850 | }\r |
851 | \r |
852 | case XZ_STATE_STREAM_FOOTER:\r |
853 | {\r |
854 | UInt32 cur = XZ_STREAM_FOOTER_SIZE - p->pos;\r |
855 | if (cur > srcRem)\r |
856 | cur = (UInt32)srcRem;\r |
857 | memcpy(p->buf + p->pos, src, cur);\r |
858 | p->pos += cur;\r |
859 | (*srcLen) += cur;\r |
860 | src += cur;\r |
861 | if (p->pos == XZ_STREAM_FOOTER_SIZE)\r |
862 | {\r |
863 | p->state = XZ_STATE_STREAM_PADDING;\r |
864 | p->numFinishedStreams++;\r |
865 | p->padSize = 0;\r |
866 | if (!Xz_CheckFooter(p->streamFlags, p->indexSize, p->buf))\r |
867 | return SZ_ERROR_CRC;\r |
868 | }\r |
869 | break;\r |
870 | }\r |
871 | \r |
872 | case XZ_STATE_STREAM_PADDING:\r |
873 | {\r |
874 | if (*src != 0)\r |
875 | {\r |
876 | if (((UInt32)p->padSize & 3) != 0)\r |
877 | return SZ_ERROR_NO_ARCHIVE;\r |
878 | p->pos = 0;\r |
879 | p->state = XZ_STATE_STREAM_HEADER;\r |
880 | }\r |
881 | else\r |
882 | {\r |
883 | (*srcLen)++;\r |
884 | src++;\r |
885 | p->padSize++;\r |
886 | }\r |
887 | break;\r |
888 | }\r |
889 | \r |
890 | case XZ_STATE_BLOCK: break; /* to disable GCC warning */\r |
891 | }\r |
892 | }\r |
893 | /*\r |
894 | if (p->state == XZ_STATE_FINISHED)\r |
895 | *status = CODER_STATUS_FINISHED_WITH_MARK;\r |
896 | return SZ_OK;\r |
897 | */\r |
898 | }\r |
899 | \r |
900 | Bool XzUnpacker_IsStreamWasFinished(CXzUnpacker *p)\r |
901 | {\r |
902 | return (p->state == XZ_STATE_STREAM_PADDING) && (((UInt32)p->padSize & 3) == 0);\r |
903 | }\r |
904 | \r |
905 | UInt64 XzUnpacker_GetExtraSize(CXzUnpacker *p)\r |
906 | {\r |
907 | UInt64 num = 0;\r |
908 | if (p->state == XZ_STATE_STREAM_PADDING)\r |
909 | num += p->padSize;\r |
910 | else if (p->state == XZ_STATE_STREAM_HEADER)\r |
911 | num += p->padSize + p->pos;\r |
912 | return num;\r |
913 | }\r |