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