1 /* XzDec.c -- Xz Decode
2 2015-11-09 : 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   unsigned i, limit;
36   *value = 0;
37   limit = (maxSize > 9) ? 9 : (unsigned)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 static 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 static SRes BraState_SetProps(void *pp, const Byte *props, size_t propSize, ISzAlloc *alloc)
75 {
76   CBraState *p = ((CBraState *)pp);
77   UNUSED_VAR(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 static 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   UNUSED_VAR(finishMode);
133   *destLen = 0;
134   *srcLen = 0;
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   UNUSED_VAR(pp);
239   UNUSED_VAR(props);
240   UNUSED_VAR(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   UNUSED_VAR(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   UNUSED_VAR(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   unsigned i;
334   p->alloc = alloc;
335   p->buf = NULL;
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   unsigned 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 = NULL; /* 9.31: the BUG was fixed */
355   }
356 }
357 
MixCoder_Init(CMixCoder * p)358 void MixCoder_Init(CMixCoder *p)
359 {
360   unsigned i;
361   for (i = 0; i < MIXCODER_NUM_FILTERS_MAX - 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,unsigned coderIndex,UInt64 methodId)374 SRes MixCoder_SetFromMethod(CMixCoder *p, unsigned 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)
402   {
403     p->buf = (Byte *)p->alloc->Alloc(p->alloc, CODER_BUF_SIZE * (MIXCODER_NUM_FILTERS_MAX - 1));
404     if (!p->buf)
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     unsigned 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   unsigned numFilters, i;
524   unsigned headerSize = (unsigned)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[%u] = %2X: ", i, (unsigned)filter->id);
559     {
560       unsigned 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   unsigned i;
576   Bool needReInit = True;
577   unsigned numFilters = XzBlock_GetNumFilters(block);
578 
579   if (numFilters == p->numCoders)
580   {
581     for (i = 0; i < numFilters; i++)
582       if (p->ids[i] != block->filters[numFilters - 1 - i].id)
583         break;
584     needReInit = (i != numFilters);
585   }
586 
587   if (needReInit)
588   {
589     MixCoder_Free(p);
590     p->numCoders = numFilters;
591     for (i = 0; i < numFilters; i++)
592     {
593       const CXzFilter *f = &block->filters[numFilters - 1 - i];
594       RINOK(MixCoder_SetFromMethod(p, i, f->id));
595     }
596   }
597 
598   for (i = 0; i < numFilters; i++)
599   {
600     const CXzFilter *f = &block->filters[numFilters - 1 - i];
601     IStateCoder *sc = &p->coders[i];
602     RINOK(sc->SetProps(sc->p, f->props, f->propsSize, p->alloc));
603   }
604 
605   MixCoder_Init(p);
606   return SZ_OK;
607 }
608 
XzUnpacker_Init(CXzUnpacker * p)609 void XzUnpacker_Init(CXzUnpacker *p)
610 {
611   p->state = XZ_STATE_STREAM_HEADER;
612   p->pos = 0;
613   p->numStartedStreams = 0;
614   p->numFinishedStreams = 0;
615   p->numTotalBlocks = 0;
616   p->padSize = 0;
617 }
618 
XzUnpacker_Construct(CXzUnpacker * p,ISzAlloc * alloc)619 void XzUnpacker_Construct(CXzUnpacker *p, ISzAlloc *alloc)
620 {
621   MixCoder_Construct(&p->decoder, alloc);
622   XzUnpacker_Init(p);
623 }
624 
XzUnpacker_Free(CXzUnpacker * p)625 void XzUnpacker_Free(CXzUnpacker *p)
626 {
627   MixCoder_Free(&p->decoder);
628 }
629 
XzUnpacker_Code(CXzUnpacker * p,Byte * dest,SizeT * destLen,const Byte * src,SizeT * srcLen,ECoderFinishMode finishMode,ECoderStatus * status)630 SRes XzUnpacker_Code(CXzUnpacker *p, Byte *dest, SizeT *destLen,
631     const Byte *src, SizeT *srcLen, ECoderFinishMode finishMode, ECoderStatus *status)
632 {
633   SizeT destLenOrig = *destLen;
634   SizeT srcLenOrig = *srcLen;
635   *destLen = 0;
636   *srcLen = 0;
637   *status = CODER_STATUS_NOT_SPECIFIED;
638   for (;;)
639   {
640     SizeT srcRem = srcLenOrig - *srcLen;
641 
642     if (p->state == XZ_STATE_BLOCK)
643     {
644       SizeT destLen2 = destLenOrig - *destLen;
645       SizeT srcLen2 = srcLenOrig - *srcLen;
646       SRes res;
647       if (srcLen2 == 0 && destLen2 == 0)
648       {
649         *status = CODER_STATUS_NOT_FINISHED;
650         return SZ_OK;
651       }
652 
653       res = MixCoder_Code(&p->decoder, dest, &destLen2, src, &srcLen2, False, finishMode, status);
654       XzCheck_Update(&p->check, dest, destLen2);
655 
656       (*srcLen) += srcLen2;
657       src += srcLen2;
658       p->packSize += srcLen2;
659 
660       (*destLen) += destLen2;
661       dest += destLen2;
662       p->unpackSize += destLen2;
663 
664       RINOK(res);
665 
666       if (*status == CODER_STATUS_FINISHED_WITH_MARK)
667       {
668         Byte temp[32];
669         unsigned num = Xz_WriteVarInt(temp, p->packSize + p->blockHeaderSize + XzFlags_GetCheckSize(p->streamFlags));
670         num += Xz_WriteVarInt(temp + num, p->unpackSize);
671         Sha256_Update(&p->sha, temp, num);
672         p->indexSize += num;
673         p->numBlocks++;
674 
675         p->state = XZ_STATE_BLOCK_FOOTER;
676         p->pos = 0;
677         p->alignPos = 0;
678       }
679       else if (srcLen2 == 0 && destLen2 == 0)
680         return SZ_OK;
681 
682       continue;
683     }
684 
685     if (srcRem == 0)
686     {
687       *status = CODER_STATUS_NEEDS_MORE_INPUT;
688       return SZ_OK;
689     }
690 
691     switch (p->state)
692     {
693       case XZ_STATE_STREAM_HEADER:
694       {
695         if (p->pos < XZ_STREAM_HEADER_SIZE)
696         {
697           if (p->pos < XZ_SIG_SIZE && *src != XZ_SIG[p->pos])
698             return SZ_ERROR_NO_ARCHIVE;
699           p->buf[p->pos++] = *src++;
700           (*srcLen)++;
701         }
702         else
703         {
704           RINOK(Xz_ParseHeader(&p->streamFlags, p->buf));
705           p->numStartedStreams++;
706           p->state = XZ_STATE_BLOCK_HEADER;
707           Sha256_Init(&p->sha);
708           p->indexSize = 0;
709           p->numBlocks = 0;
710           p->pos = 0;
711         }
712         break;
713       }
714 
715       case XZ_STATE_BLOCK_HEADER:
716       {
717         if (p->pos == 0)
718         {
719           p->buf[p->pos++] = *src++;
720           (*srcLen)++;
721           if (p->buf[0] == 0)
722           {
723             p->indexPreSize = 1 + Xz_WriteVarInt(p->buf + 1, p->numBlocks);
724             p->indexPos = p->indexPreSize;
725             p->indexSize += p->indexPreSize;
726             Sha256_Final(&p->sha, p->shaDigest);
727             Sha256_Init(&p->sha);
728             p->crc = CrcUpdate(CRC_INIT_VAL, p->buf, p->indexPreSize);
729             p->state = XZ_STATE_STREAM_INDEX;
730           }
731           p->blockHeaderSize = ((UInt32)p->buf[0] << 2) + 4;
732         }
733         else if (p->pos != p->blockHeaderSize)
734         {
735           UInt32 cur = p->blockHeaderSize - p->pos;
736           if (cur > srcRem)
737             cur = (UInt32)srcRem;
738           memcpy(p->buf + p->pos, src, cur);
739           p->pos += cur;
740           (*srcLen) += cur;
741           src += cur;
742         }
743         else
744         {
745           RINOK(XzBlock_Parse(&p->block, p->buf));
746           p->numTotalBlocks++;
747           p->state = XZ_STATE_BLOCK;
748           p->packSize = 0;
749           p->unpackSize = 0;
750           XzCheck_Init(&p->check, XzFlags_GetCheckType(p->streamFlags));
751           RINOK(XzDec_Init(&p->decoder, &p->block));
752         }
753         break;
754       }
755 
756       case XZ_STATE_BLOCK_FOOTER:
757       {
758         if (((p->packSize + p->alignPos) & 3) != 0)
759         {
760           (*srcLen)++;
761           p->alignPos++;
762           if (*src++ != 0)
763             return SZ_ERROR_CRC;
764         }
765         else
766         {
767           UInt32 checkSize = XzFlags_GetCheckSize(p->streamFlags);
768           UInt32 cur = checkSize - p->pos;
769           if (cur != 0)
770           {
771             if (cur > srcRem)
772               cur = (UInt32)srcRem;
773             memcpy(p->buf + p->pos, src, cur);
774             p->pos += cur;
775             (*srcLen) += cur;
776             src += cur;
777           }
778           else
779           {
780             Byte digest[XZ_CHECK_SIZE_MAX];
781             p->state = XZ_STATE_BLOCK_HEADER;
782             p->pos = 0;
783             if (XzCheck_Final(&p->check, digest) && memcmp(digest, p->buf, checkSize) != 0)
784               return SZ_ERROR_CRC;
785           }
786         }
787         break;
788       }
789 
790       case XZ_STATE_STREAM_INDEX:
791       {
792         if (p->pos < p->indexPreSize)
793         {
794           (*srcLen)++;
795           if (*src++ != p->buf[p->pos++])
796             return SZ_ERROR_CRC;
797         }
798         else
799         {
800           if (p->indexPos < p->indexSize)
801           {
802             UInt64 cur = p->indexSize - p->indexPos;
803             if (srcRem > cur)
804               srcRem = (SizeT)cur;
805             p->crc = CrcUpdate(p->crc, src, srcRem);
806             Sha256_Update(&p->sha, src, srcRem);
807             (*srcLen) += srcRem;
808             src += srcRem;
809             p->indexPos += srcRem;
810           }
811           else if ((p->indexPos & 3) != 0)
812           {
813             Byte b = *src++;
814             p->crc = CRC_UPDATE_BYTE(p->crc, b);
815             (*srcLen)++;
816             p->indexPos++;
817             p->indexSize++;
818             if (b != 0)
819               return SZ_ERROR_CRC;
820           }
821           else
822           {
823             Byte digest[SHA256_DIGEST_SIZE];
824             p->state = XZ_STATE_STREAM_INDEX_CRC;
825             p->indexSize += 4;
826             p->pos = 0;
827             Sha256_Final(&p->sha, digest);
828             if (memcmp(digest, p->shaDigest, SHA256_DIGEST_SIZE) != 0)
829               return SZ_ERROR_CRC;
830           }
831         }
832         break;
833       }
834 
835       case XZ_STATE_STREAM_INDEX_CRC:
836       {
837         if (p->pos < 4)
838         {
839           (*srcLen)++;
840           p->buf[p->pos++] = *src++;
841         }
842         else
843         {
844           p->state = XZ_STATE_STREAM_FOOTER;
845           p->pos = 0;
846           if (CRC_GET_DIGEST(p->crc) != GetUi32(p->buf))
847             return SZ_ERROR_CRC;
848         }
849         break;
850       }
851 
852       case XZ_STATE_STREAM_FOOTER:
853       {
854         UInt32 cur = XZ_STREAM_FOOTER_SIZE - p->pos;
855         if (cur > srcRem)
856           cur = (UInt32)srcRem;
857         memcpy(p->buf + p->pos, src, cur);
858         p->pos += cur;
859         (*srcLen) += cur;
860         src += cur;
861         if (p->pos == XZ_STREAM_FOOTER_SIZE)
862         {
863           p->state = XZ_STATE_STREAM_PADDING;
864           p->numFinishedStreams++;
865           p->padSize = 0;
866           if (!Xz_CheckFooter(p->streamFlags, p->indexSize, p->buf))
867             return SZ_ERROR_CRC;
868         }
869         break;
870       }
871 
872       case XZ_STATE_STREAM_PADDING:
873       {
874         if (*src != 0)
875         {
876           if (((UInt32)p->padSize & 3) != 0)
877             return SZ_ERROR_NO_ARCHIVE;
878           p->pos = 0;
879           p->state = XZ_STATE_STREAM_HEADER;
880         }
881         else
882         {
883           (*srcLen)++;
884           src++;
885           p->padSize++;
886         }
887         break;
888       }
889 
890       case XZ_STATE_BLOCK: break; /* to disable GCC warning */
891     }
892   }
893   /*
894   if (p->state == XZ_STATE_FINISHED)
895     *status = CODER_STATUS_FINISHED_WITH_MARK;
896   return SZ_OK;
897   */
898 }
899 
XzUnpacker_IsStreamWasFinished(CXzUnpacker * p)900 Bool XzUnpacker_IsStreamWasFinished(CXzUnpacker *p)
901 {
902   return (p->state == XZ_STATE_STREAM_PADDING) && (((UInt32)p->padSize & 3) == 0);
903 }
904 
XzUnpacker_GetExtraSize(CXzUnpacker * p)905 UInt64 XzUnpacker_GetExtraSize(CXzUnpacker *p)
906 {
907   UInt64 num = 0;
908   if (p->state == XZ_STATE_STREAM_PADDING)
909     num += p->padSize;
910   else if (p->state == XZ_STATE_STREAM_HEADER)
911     num += p->padSize + p->pos;
912   return num;
913 }
914