• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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