~ubuntu-branches/ubuntu/saucy/clamav/saucy-backports

« back to all changes in this revision

Viewing changes to libclamav/7z/XzDec.c

  • Committer: Package Import Robot
  • Author(s): Scott Kitterman
  • Date: 2014-07-15 01:08:10 UTC
  • mfrom: (0.35.47 sid)
  • Revision ID: package-import@ubuntu.com-20140715010810-ru66ek4fun2iseba
Tags: 0.98.4+dfsg-2~ubuntu13.10.1
No-change backport to saucy (LP: #1341962)

Show diffs side-by-side

added added

removed removed

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