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