Coverage Report

Created: 2026-09-14 06:17

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/perfetto/buildtools/lzma/C/XzDec.c
Line
Count
Source
1
/* XzDec.c -- Xz Decode
2
2018-04-24 : Igor Pavlov : Public domain */
3
4
#include "Precomp.h"
5
6
// #include <stdio.h>
7
8
// #define XZ_DUMP
9
10
/* #define XZ_DUMP */
11
12
#ifdef XZ_DUMP
13
#include <stdio.h>
14
#endif
15
16
// #define SHOW_DEBUG_INFO
17
18
#ifdef SHOW_DEBUG_INFO
19
#include <stdio.h>
20
#endif
21
22
#ifdef SHOW_DEBUG_INFO
23
#define PRF(x) x
24
#else
25
#define PRF(x)
26
#endif
27
28
#define PRF_STR(s) PRF(printf("\n" s "\n"))
29
#define PRF_STR_INT(s, d) PRF(printf("\n" s " %d\n", (unsigned)d))
30
31
#include <stdlib.h>
32
#include <string.h>
33
34
#include "7zCrc.h"
35
#include "Alloc.h"
36
#include "Bra.h"
37
#include "CpuArch.h"
38
#include "Delta.h"
39
#include "Lzma2Dec.h"
40
41
// #define USE_SUBBLOCK
42
43
#ifdef USE_SUBBLOCK
44
#include "Bcj3Dec.c"
45
#include "SbDec.h"
46
#endif
47
48
#include "Xz.h"
49
50
#define XZ_CHECK_SIZE_MAX 64
51
52
0
#define CODER_BUF_SIZE ((size_t)1 << 17)
53
54
unsigned Xz_ReadVarInt(const Byte *p, size_t maxSize, UInt64 *value)
55
0
{
56
0
  unsigned i, limit;
57
0
  *value = 0;
58
0
  limit = (maxSize > 9) ? 9 : (unsigned)maxSize;
59
60
0
  for (i = 0; i < limit;)
61
0
  {
62
0
    Byte b = p[i];
63
0
    *value |= (UInt64)(b & 0x7F) << (7 * i++);
64
0
    if ((b & 0x80) == 0)
65
0
      return (b == 0 && i != 1) ? 0 : i;
66
0
  }
67
0
  return 0;
68
0
}
69
70
/* ---------- BraState ---------- */
71
72
0
#define BRA_BUF_SIZE (1 << 14)
73
74
typedef struct
75
{
76
  size_t bufPos;
77
  size_t bufConv;
78
  size_t bufTotal;
79
80
  int encodeMode;
81
82
  UInt32 methodId;
83
  UInt32 delta;
84
  UInt32 ip;
85
  UInt32 x86State;
86
  Byte deltaState[DELTA_STATE_SIZE];
87
88
  Byte buf[BRA_BUF_SIZE];
89
} CBraState;
90
91
static void BraState_Free(void *pp, ISzAllocPtr alloc)
92
0
{
93
0
  ISzAlloc_Free(alloc, pp);
94
0
}
95
96
static SRes BraState_SetProps(void *pp, const Byte *props, size_t propSize, ISzAllocPtr alloc)
97
0
{
98
0
  CBraState *p = ((CBraState *)pp);
99
0
  UNUSED_VAR(alloc);
100
0
  p->ip = 0;
101
0
  if (p->methodId == XZ_ID_Delta)
102
0
  {
103
0
    if (propSize != 1)
104
0
      return SZ_ERROR_UNSUPPORTED;
105
0
    p->delta = (unsigned)props[0] + 1;
106
0
  }
107
0
  else
108
0
  {
109
0
    if (propSize == 4)
110
0
    {
111
0
      UInt32 v = GetUi32(props);
112
0
      switch (p->methodId)
113
0
      {
114
0
        case XZ_ID_PPC:
115
0
        case XZ_ID_ARM:
116
0
        case XZ_ID_SPARC:
117
0
          if ((v & 3) != 0)
118
0
            return SZ_ERROR_UNSUPPORTED;
119
0
          break;
120
0
        case XZ_ID_ARMT:
121
0
          if ((v & 1) != 0)
122
0
            return SZ_ERROR_UNSUPPORTED;
123
0
          break;
124
0
        case XZ_ID_IA64:
125
0
          if ((v & 0xF) != 0)
126
0
            return SZ_ERROR_UNSUPPORTED;
127
0
          break;
128
0
      }
129
0
      p->ip = v;
130
0
    }
131
0
    else if (propSize != 0)
132
0
      return SZ_ERROR_UNSUPPORTED;
133
0
  }
134
0
  return SZ_OK;
135
0
}
136
137
static void BraState_Init(void *pp)
138
0
{
139
0
  CBraState *p = ((CBraState *)pp);
140
0
  p->bufPos = p->bufConv = p->bufTotal = 0;
141
0
  x86_Convert_Init(p->x86State);
142
0
  if (p->methodId == XZ_ID_Delta)
143
0
    Delta_Init(p->deltaState);
144
0
}
145
146
147
0
#define CASE_BRA_CONV(isa) case XZ_ID_ ## isa: size = isa ## _Convert(data, size, p->ip, p->encodeMode); break;
148
149
static SizeT BraState_Filter(void *pp, Byte *data, SizeT size)
150
0
{
151
0
  CBraState *p = ((CBraState *)pp);
152
0
  switch (p->methodId)
153
0
  {
154
0
    case XZ_ID_Delta:
155
0
      if (p->encodeMode)
156
0
        Delta_Encode(p->deltaState, p->delta, data, size);
157
0
      else
158
0
        Delta_Decode(p->deltaState, p->delta, data, size);
159
0
      break;
160
0
    case XZ_ID_X86:
161
0
      size = x86_Convert(data, size, p->ip, &p->x86State, p->encodeMode);
162
0
      break;
163
0
    CASE_BRA_CONV(PPC)
164
0
    CASE_BRA_CONV(IA64)
165
0
    CASE_BRA_CONV(ARM)
166
0
    CASE_BRA_CONV(ARMT)
167
0
    CASE_BRA_CONV(SPARC)
168
0
  }
169
0
  p->ip += (UInt32)size;
170
0
  return size;
171
0
}
172
173
174
static SRes BraState_Code2(void *pp,
175
    Byte *dest, SizeT *destLen,
176
    const Byte *src, SizeT *srcLen, int srcWasFinished,
177
    ECoderFinishMode finishMode,
178
    // int *wasFinished
179
    ECoderStatus *status)
180
0
{
181
0
  CBraState *p = ((CBraState *)pp);
182
0
  SizeT destRem = *destLen;
183
0
  SizeT srcRem = *srcLen;
184
0
  UNUSED_VAR(finishMode);
185
186
0
  *destLen = 0;
187
0
  *srcLen = 0;
188
  // *wasFinished = False;
189
0
  *status = CODER_STATUS_NOT_FINISHED;
190
  
191
0
  while (destRem > 0)
192
0
  {
193
0
    if (p->bufPos != p->bufConv)
194
0
    {
195
0
      size_t size = p->bufConv - p->bufPos;
196
0
      if (size > destRem)
197
0
        size = destRem;
198
0
      memcpy(dest, p->buf + p->bufPos, size);
199
0
      p->bufPos += size;
200
0
      *destLen += size;
201
0
      dest += size;
202
0
      destRem -= size;
203
0
      continue;
204
0
    }
205
    
206
0
    p->bufTotal -= p->bufPos;
207
0
    memmove(p->buf, p->buf + p->bufPos, p->bufTotal);
208
0
    p->bufPos = 0;
209
0
    p->bufConv = 0;
210
0
    {
211
0
      size_t size = BRA_BUF_SIZE - p->bufTotal;
212
0
      if (size > srcRem)
213
0
        size = srcRem;
214
0
      memcpy(p->buf + p->bufTotal, src, size);
215
0
      *srcLen += size;
216
0
      src += size;
217
0
      srcRem -= size;
218
0
      p->bufTotal += size;
219
0
    }
220
0
    if (p->bufTotal == 0)
221
0
      break;
222
    
223
0
    p->bufConv = BraState_Filter(pp, p->buf, p->bufTotal);
224
225
0
    if (p->bufConv == 0)
226
0
    {
227
0
      if (!srcWasFinished)
228
0
        break;
229
0
      p->bufConv = p->bufTotal;
230
0
    }
231
0
  }
232
233
0
  if (p->bufTotal == p->bufPos && srcRem == 0 && srcWasFinished)
234
0
  {
235
0
    *status = CODER_STATUS_FINISHED_WITH_MARK;
236
    // *wasFinished = 1;
237
0
  }
238
239
0
  return SZ_OK;
240
0
}
241
242
243
SRes BraState_SetFromMethod(IStateCoder *p, UInt64 id, int encodeMode, ISzAllocPtr alloc)
244
0
{
245
0
  CBraState *decoder;
246
0
  if (id < XZ_ID_Delta || id > XZ_ID_SPARC)
247
0
    return SZ_ERROR_UNSUPPORTED;
248
0
  decoder = p->p;
249
0
  if (!decoder)
250
0
  {
251
0
    decoder = (CBraState *)ISzAlloc_Alloc(alloc, sizeof(CBraState));
252
0
    if (!decoder)
253
0
      return SZ_ERROR_MEM;
254
0
    p->p = decoder;
255
0
    p->Free = BraState_Free;
256
0
    p->SetProps = BraState_SetProps;
257
0
    p->Init = BraState_Init;
258
0
    p->Code2 = BraState_Code2;
259
0
    p->Filter = BraState_Filter;
260
0
  }
261
0
  decoder->methodId = (UInt32)id;
262
0
  decoder->encodeMode = encodeMode;
263
0
  return SZ_OK;
264
0
}
265
266
267
268
/* ---------- SbState ---------- */
269
270
#ifdef USE_SUBBLOCK
271
272
static void SbState_Free(void *pp, ISzAllocPtr alloc)
273
{
274
  CSbDec *p = (CSbDec *)pp;
275
  SbDec_Free(p);
276
  ISzAlloc_Free(alloc, pp);
277
}
278
279
static SRes SbState_SetProps(void *pp, const Byte *props, size_t propSize, ISzAllocPtr alloc)
280
{
281
  UNUSED_VAR(pp);
282
  UNUSED_VAR(props);
283
  UNUSED_VAR(alloc);
284
  return (propSize == 0) ? SZ_OK : SZ_ERROR_UNSUPPORTED;
285
}
286
287
static void SbState_Init(void *pp)
288
{
289
  SbDec_Init((CSbDec *)pp);
290
}
291
292
static SRes SbState_Code2(void *pp, Byte *dest, SizeT *destLen, const Byte *src, SizeT *srcLen,
293
    int srcWasFinished, ECoderFinishMode finishMode,
294
    // int *wasFinished
295
    ECoderStatus *status)
296
{
297
  CSbDec *p = (CSbDec *)pp;
298
  SRes res;
299
  UNUSED_VAR(srcWasFinished);
300
  p->dest = dest;
301
  p->destLen = *destLen;
302
  p->src = src;
303
  p->srcLen = *srcLen;
304
  p->finish = finishMode; /* change it */
305
  res = SbDec_Decode((CSbDec *)pp);
306
  *destLen -= p->destLen;
307
  *srcLen -= p->srcLen;
308
  // *wasFinished = (*destLen == 0 && *srcLen == 0); /* change it */
309
  *status = (*destLen == 0 && *srcLen == 0) ?
310
      CODER_STATUS_FINISHED_WITH_MARK :
311
      CODER_STATUS_NOT_FINISHED;
312
  return res;
313
}
314
315
static SRes SbState_SetFromMethod(IStateCoder *p, ISzAllocPtr alloc)
316
{
317
  CSbDec *decoder = (CSbDec *)p->p;
318
  if (!decoder)
319
  {
320
    decoder = (CSbDec *)ISzAlloc_Alloc(alloc, sizeof(CSbDec));
321
    if (!decoder)
322
      return SZ_ERROR_MEM;
323
    p->p = decoder;
324
    p->Free = SbState_Free;
325
    p->SetProps = SbState_SetProps;
326
    p->Init = SbState_Init;
327
    p->Code2 = SbState_Code2;
328
    p->Filter = NULL;
329
  }
330
  SbDec_Construct(decoder);
331
  SbDec_SetAlloc(decoder, alloc);
332
  return SZ_OK;
333
}
334
335
#endif
336
337
338
339
/* ---------- Lzma2 ---------- */
340
341
typedef struct
342
{
343
  CLzma2Dec decoder;
344
  Bool outBufMode;
345
} CLzma2Dec_Spec;
346
347
348
static void Lzma2State_Free(void *pp, ISzAllocPtr alloc)
349
0
{
350
0
  CLzma2Dec_Spec *p = (CLzma2Dec_Spec *)pp;
351
0
  if (p->outBufMode)
352
0
    Lzma2Dec_FreeProbs(&p->decoder, alloc);
353
0
  else
354
0
    Lzma2Dec_Free(&p->decoder, alloc);
355
0
  ISzAlloc_Free(alloc, pp);
356
0
}
357
358
static SRes Lzma2State_SetProps(void *pp, const Byte *props, size_t propSize, ISzAllocPtr alloc)
359
0
{
360
0
  if (propSize != 1)
361
0
    return SZ_ERROR_UNSUPPORTED;
362
0
  {
363
0
    CLzma2Dec_Spec *p = (CLzma2Dec_Spec *)pp;
364
0
    if (p->outBufMode)
365
0
      return Lzma2Dec_AllocateProbs(&p->decoder, props[0], alloc);
366
0
    else
367
0
      return Lzma2Dec_Allocate(&p->decoder, props[0], alloc);
368
0
  }
369
0
}
370
371
static void Lzma2State_Init(void *pp)
372
0
{
373
0
  Lzma2Dec_Init(&((CLzma2Dec_Spec *)pp)->decoder);
374
0
}
375
376
377
/*
378
  if (outBufMode), then (dest) is not used. Use NULL.
379
         Data is unpacked to (spec->decoder.decoder.dic) output buffer.
380
*/
381
382
static SRes Lzma2State_Code2(void *pp, Byte *dest, SizeT *destLen, const Byte *src, SizeT *srcLen,
383
    int srcWasFinished, ECoderFinishMode finishMode,
384
    // int *wasFinished,
385
    ECoderStatus *status)
386
0
{
387
0
  CLzma2Dec_Spec *spec = (CLzma2Dec_Spec *)pp;
388
0
  ELzmaStatus status2;
389
  /* ELzmaFinishMode fm = (finishMode == LZMA_FINISH_ANY) ? LZMA_FINISH_ANY : LZMA_FINISH_END; */
390
0
  SRes res;
391
0
  UNUSED_VAR(srcWasFinished);
392
0
  if (spec->outBufMode)
393
0
  {
394
0
    SizeT dicPos = spec->decoder.decoder.dicPos;
395
0
    SizeT dicLimit = dicPos + *destLen;
396
0
    res = Lzma2Dec_DecodeToDic(&spec->decoder, dicLimit, src, srcLen, (ELzmaFinishMode)finishMode, &status2);
397
0
    *destLen = spec->decoder.decoder.dicPos - dicPos;
398
0
  }
399
0
  else
400
0
    res = Lzma2Dec_DecodeToBuf(&spec->decoder, dest, destLen, src, srcLen, (ELzmaFinishMode)finishMode, &status2);
401
  // *wasFinished = (status2 == LZMA_STATUS_FINISHED_WITH_MARK);
402
  // ECoderStatus values are identical to ELzmaStatus values of LZMA2 decoder
403
0
  *status = status2;
404
0
  return res;
405
0
}
406
407
408
static SRes Lzma2State_SetFromMethod(IStateCoder *p, Byte *outBuf, size_t outBufSize, ISzAllocPtr alloc)
409
0
{
410
0
  CLzma2Dec_Spec *spec = (CLzma2Dec_Spec *)p->p;
411
0
  if (!spec)
412
0
  {
413
0
    spec = (CLzma2Dec_Spec *)ISzAlloc_Alloc(alloc, sizeof(CLzma2Dec_Spec));
414
0
    if (!spec)
415
0
      return SZ_ERROR_MEM;
416
0
    p->p = spec;
417
0
    p->Free = Lzma2State_Free;
418
0
    p->SetProps = Lzma2State_SetProps;
419
0
    p->Init = Lzma2State_Init;
420
0
    p->Code2 = Lzma2State_Code2;
421
0
    p->Filter = NULL;
422
0
    Lzma2Dec_Construct(&spec->decoder);
423
0
  }
424
0
  spec->outBufMode = False;
425
0
  if (outBuf)
426
0
  {
427
0
    spec->outBufMode = True;
428
0
    spec->decoder.decoder.dic = outBuf;
429
0
    spec->decoder.decoder.dicBufSize = outBufSize;
430
0
  }
431
0
  return SZ_OK;
432
0
}
433
434
435
static SRes Lzma2State_ResetOutBuf(IStateCoder *p, Byte *outBuf, size_t outBufSize)
436
0
{
437
0
  CLzma2Dec_Spec *spec = (CLzma2Dec_Spec *)p->p;
438
0
  if ((spec->outBufMode && !outBuf) || (!spec->outBufMode && outBuf))
439
0
    return SZ_ERROR_FAIL;
440
0
  if (outBuf)
441
0
  {
442
0
    spec->decoder.decoder.dic = outBuf;
443
0
    spec->decoder.decoder.dicBufSize = outBufSize;
444
0
  }
445
0
  return SZ_OK;
446
0
}
447
448
449
450
static void MixCoder_Construct(CMixCoder *p, ISzAllocPtr alloc)
451
0
{
452
0
  unsigned i;
453
0
  p->alloc = alloc;
454
0
  p->buf = NULL;
455
0
  p->numCoders = 0;
456
  
457
0
  p->outBufSize = 0;
458
0
  p->outBuf = NULL;
459
  // p->SingleBufMode = False;
460
461
0
  for (i = 0; i < MIXCODER_NUM_FILTERS_MAX; i++)
462
0
    p->coders[i].p = NULL;
463
0
}
464
465
466
static void MixCoder_Free(CMixCoder *p)
467
0
{
468
0
  unsigned i;
469
0
  p->numCoders = 0;
470
0
  for (i = 0; i < MIXCODER_NUM_FILTERS_MAX; i++)
471
0
  {
472
0
    IStateCoder *sc = &p->coders[i];
473
0
    if (sc->p)
474
0
    {
475
0
      sc->Free(sc->p, p->alloc);
476
0
      sc->p = NULL;
477
0
    }
478
0
  }
479
0
  if (p->buf)
480
0
  {
481
0
    ISzAlloc_Free(p->alloc, p->buf);
482
0
    p->buf = NULL; /* 9.31: the BUG was fixed */
483
0
  }
484
0
}
485
486
static void MixCoder_Init(CMixCoder *p)
487
0
{
488
0
  unsigned i;
489
0
  for (i = 0; i < MIXCODER_NUM_FILTERS_MAX - 1; i++)
490
0
  {
491
0
    p->size[i] = 0;
492
0
    p->pos[i] = 0;
493
0
    p->finished[i] = 0;
494
0
  }
495
0
  for (i = 0; i < p->numCoders; i++)
496
0
  {
497
0
    IStateCoder *coder = &p->coders[i];
498
0
    coder->Init(coder->p);
499
0
    p->results[i] = SZ_OK;
500
0
  }
501
0
  p->outWritten = 0;
502
0
  p->wasFinished = False;
503
0
  p->res = SZ_OK;
504
0
  p->status = CODER_STATUS_NOT_SPECIFIED;
505
0
}
506
507
508
static SRes MixCoder_SetFromMethod(CMixCoder *p, unsigned coderIndex, UInt64 methodId, Byte *outBuf, size_t outBufSize)
509
0
{
510
0
  IStateCoder *sc = &p->coders[coderIndex];
511
0
  p->ids[coderIndex] = methodId;
512
0
  switch (methodId)
513
0
  {
514
0
    case XZ_ID_LZMA2: return Lzma2State_SetFromMethod(sc, outBuf, outBufSize, p->alloc);
515
    #ifdef USE_SUBBLOCK
516
    case XZ_ID_Subblock: return SbState_SetFromMethod(sc, p->alloc);
517
    #endif
518
0
  }
519
0
  if (coderIndex == 0)
520
0
    return SZ_ERROR_UNSUPPORTED;
521
0
  return BraState_SetFromMethod(sc, methodId, 0, p->alloc);
522
0
}
523
524
525
static SRes MixCoder_ResetFromMethod(CMixCoder *p, unsigned coderIndex, UInt64 methodId, Byte *outBuf, size_t outBufSize)
526
0
{
527
0
  IStateCoder *sc = &p->coders[coderIndex];
528
0
  switch (methodId)
529
0
  {
530
0
    case XZ_ID_LZMA2: return Lzma2State_ResetOutBuf(sc, outBuf, outBufSize);
531
0
  }
532
0
  return SZ_ERROR_UNSUPPORTED;
533
0
}
534
535
536
537
/*
538
 if (destFinish) - then unpack data block is finished at (*destLen) position,
539
                   and we can return data that were not processed by filter
540
541
output (status) can be :
542
  CODER_STATUS_NOT_FINISHED
543
  CODER_STATUS_FINISHED_WITH_MARK
544
  CODER_STATUS_NEEDS_MORE_INPUT - not implemented still
545
*/
546
547
static SRes MixCoder_Code(CMixCoder *p,
548
    Byte *dest, SizeT *destLen, int destFinish,
549
    const Byte *src, SizeT *srcLen, int srcWasFinished,
550
    ECoderFinishMode finishMode)
551
0
{
552
0
  SizeT destLenOrig = *destLen;
553
0
  SizeT srcLenOrig = *srcLen;
554
555
0
  *destLen = 0;
556
0
  *srcLen = 0;
557
558
0
  if (p->wasFinished)
559
0
    return p->res;
560
  
561
0
  p->status = CODER_STATUS_NOT_FINISHED;
562
563
  // if (p->SingleBufMode)
564
0
  if (p->outBuf)
565
0
  {
566
0
    SRes res;
567
0
    SizeT destLen2, srcLen2;
568
0
    int wasFinished;
569
    
570
0
    PRF_STR("------- MixCoder Single ----------");
571
      
572
0
    srcLen2 = srcLenOrig;
573
0
    destLen2 = destLenOrig;
574
    
575
0
    {
576
0
      IStateCoder *coder = &p->coders[0];
577
0
      res = coder->Code2(coder->p, NULL, &destLen2, src, &srcLen2, srcWasFinished, finishMode,
578
          // &wasFinished,
579
0
          &p->status);
580
0
      wasFinished = (p->status == CODER_STATUS_FINISHED_WITH_MARK);
581
0
    }
582
    
583
0
    p->res = res;
584
    
585
    /*
586
    if (wasFinished)
587
      p->status = CODER_STATUS_FINISHED_WITH_MARK;
588
    else
589
    {
590
      if (res == SZ_OK)
591
        if (destLen2 != destLenOrig)
592
          p->status = CODER_STATUS_NEEDS_MORE_INPUT;
593
    }
594
    */
595
596
    
597
0
    *srcLen = srcLen2;
598
0
    src += srcLen2;
599
0
    p->outWritten += destLen2;
600
    
601
0
    if (res != SZ_OK || srcWasFinished || wasFinished)
602
0
      p->wasFinished = True;
603
    
604
0
    if (p->numCoders == 1)
605
0
      *destLen = destLen2;
606
0
    else if (p->wasFinished)
607
0
    {
608
0
      unsigned i;
609
0
      size_t processed = p->outWritten;
610
      
611
0
      for (i = 1; i < p->numCoders; i++)
612
0
      {
613
0
        IStateCoder *coder = &p->coders[i];
614
0
        processed = coder->Filter(coder->p, p->outBuf, processed);
615
0
        if (wasFinished || (destFinish && p->outWritten == destLenOrig))
616
0
          processed = p->outWritten;
617
0
        PRF_STR_INT("filter", i);
618
0
      }
619
0
      *destLen = processed;
620
0
    }
621
0
    return res;
622
0
  }
623
624
0
  PRF_STR("standard mix");
625
626
0
  if (p->numCoders != 1)
627
0
  {
628
0
    if (!p->buf)
629
0
    {
630
0
      p->buf = (Byte *)ISzAlloc_Alloc(p->alloc, CODER_BUF_SIZE * (MIXCODER_NUM_FILTERS_MAX - 1));
631
0
      if (!p->buf)
632
0
        return SZ_ERROR_MEM;
633
0
    }
634
    
635
0
    finishMode = CODER_FINISH_ANY;
636
0
  }
637
638
0
  for (;;)
639
0
  {
640
0
    Bool processed = False;
641
0
    Bool allFinished = True;
642
0
    SRes resMain = SZ_OK;
643
0
    unsigned i;
644
645
0
    p->status = CODER_STATUS_NOT_FINISHED;
646
    /*
647
    if (p->numCoders == 1 && *destLen == destLenOrig && finishMode == LZMA_FINISH_ANY)
648
      break;
649
    */
650
651
0
    for (i = 0; i < p->numCoders; i++)
652
0
    {
653
0
      SRes res;
654
0
      IStateCoder *coder = &p->coders[i];
655
0
      Byte *dest2;
656
0
      SizeT destLen2, srcLen2; // destLen2_Orig;
657
0
      const Byte *src2;
658
0
      int srcFinished2;
659
0
      int encodingWasFinished;
660
0
      ECoderStatus status2;
661
      
662
0
      if (i == 0)
663
0
      {
664
0
        src2 = src;
665
0
        srcLen2 = srcLenOrig - *srcLen;
666
0
        srcFinished2 = srcWasFinished;
667
0
      }
668
0
      else
669
0
      {
670
0
        size_t k = i - 1;
671
0
        src2 = p->buf + (CODER_BUF_SIZE * k) + p->pos[k];
672
0
        srcLen2 = p->size[k] - p->pos[k];
673
0
        srcFinished2 = p->finished[k];
674
0
      }
675
      
676
0
      if (i == p->numCoders - 1)
677
0
      {
678
0
        dest2 = dest;
679
0
        destLen2 = destLenOrig - *destLen;
680
0
      }
681
0
      else
682
0
      {
683
0
        if (p->pos[i] != p->size[i])
684
0
          continue;
685
0
        dest2 = p->buf + (CODER_BUF_SIZE * i);
686
0
        destLen2 = CODER_BUF_SIZE;
687
0
      }
688
      
689
      // destLen2_Orig = destLen2;
690
      
691
0
      if (p->results[i] != SZ_OK)
692
0
      {
693
0
        if (resMain == SZ_OK)
694
0
          resMain = p->results[i];
695
0
        continue;
696
0
      }
697
698
0
      res = coder->Code2(coder->p,
699
0
          dest2, &destLen2,
700
0
          src2, &srcLen2, srcFinished2,
701
0
          finishMode,
702
          // &encodingWasFinished,
703
0
          &status2);
704
705
0
      if (res != SZ_OK)
706
0
      {
707
0
        p->results[i] = res;
708
0
        if (resMain == SZ_OK)
709
0
          resMain = res;
710
0
      }
711
712
0
      encodingWasFinished = (status2 == CODER_STATUS_FINISHED_WITH_MARK);
713
      
714
0
      if (!encodingWasFinished)
715
0
      {
716
0
        allFinished = False;
717
0
        if (p->numCoders == 1 && res == SZ_OK)
718
0
          p->status = status2;
719
0
      }
720
721
0
      if (i == 0)
722
0
      {
723
0
        *srcLen += srcLen2;
724
0
        src += srcLen2;
725
0
      }
726
0
      else
727
0
        p->pos[(size_t)i - 1] += srcLen2;
728
729
0
      if (i == p->numCoders - 1)
730
0
      {
731
0
        *destLen += destLen2;
732
0
        dest += destLen2;
733
0
      }
734
0
      else
735
0
      {
736
0
        p->size[i] = destLen2;
737
0
        p->pos[i] = 0;
738
0
        p->finished[i] = encodingWasFinished;
739
0
      }
740
      
741
0
      if (destLen2 != 0 || srcLen2 != 0)
742
0
        processed = True;
743
0
    }
744
    
745
0
    if (!processed)
746
0
    {
747
0
      if (allFinished)
748
0
        p->status = CODER_STATUS_FINISHED_WITH_MARK;
749
0
      return resMain;
750
0
    }
751
0
  }
752
0
}
753
754
755
SRes Xz_ParseHeader(CXzStreamFlags *p, const Byte *buf)
756
0
{
757
0
  *p = (CXzStreamFlags)GetBe16(buf + XZ_SIG_SIZE);
758
0
  if (CrcCalc(buf + XZ_SIG_SIZE, XZ_STREAM_FLAGS_SIZE) !=
759
0
      GetUi32(buf + XZ_SIG_SIZE + XZ_STREAM_FLAGS_SIZE))
760
0
    return SZ_ERROR_NO_ARCHIVE;
761
0
  return XzFlags_IsSupported(*p) ? SZ_OK : SZ_ERROR_UNSUPPORTED;
762
0
}
763
764
static Bool Xz_CheckFooter(CXzStreamFlags flags, UInt64 indexSize, const Byte *buf)
765
0
{
766
0
  return indexSize == (((UInt64)GetUi32(buf + 4) + 1) << 2)
767
0
      && GetUi32(buf) == CrcCalc(buf + 4, 6)
768
0
      && flags == GetBe16(buf + 8)
769
0
      && buf[10] == XZ_FOOTER_SIG_0
770
0
      && buf[11] == XZ_FOOTER_SIG_1;
771
0
}
772
773
#define READ_VARINT_AND_CHECK(buf, pos, size, res) \
774
0
  { unsigned s = Xz_ReadVarInt(buf + pos, size - pos, res); \
775
0
  if (s == 0) return SZ_ERROR_ARCHIVE; pos += s; }
776
777
778
static Bool XzBlock_AreSupportedFilters(const CXzBlock *p)
779
0
{
780
0
  unsigned numFilters = XzBlock_GetNumFilters(p) - 1;
781
0
  unsigned i;
782
0
  {
783
0
    const CXzFilter *f = &p->filters[numFilters];
784
0
    if (f->id != XZ_ID_LZMA2 || f->propsSize != 1 || f->props[0] > 40)
785
0
      return False;
786
0
  }
787
788
0
  for (i = 0; i < numFilters; i++)
789
0
  {
790
0
    const CXzFilter *f = &p->filters[i];
791
0
    if (f->id == XZ_ID_Delta)
792
0
    {
793
0
      if (f->propsSize != 1)
794
0
        return False;
795
0
    }
796
0
    else if (f->id < XZ_ID_Delta
797
0
        || f->id > XZ_ID_SPARC
798
0
        || (f->propsSize != 0 && f->propsSize != 4))
799
0
      return False;
800
0
  }
801
0
  return True;
802
0
}
803
804
805
SRes XzBlock_Parse(CXzBlock *p, const Byte *header)
806
0
{
807
0
  unsigned pos;
808
0
  unsigned numFilters, i;
809
0
  unsigned headerSize = (unsigned)header[0] << 2;
810
811
  /* (headerSize != 0) : another code checks */
812
813
0
  if (CrcCalc(header, headerSize) != GetUi32(header + headerSize))
814
0
    return SZ_ERROR_ARCHIVE;
815
816
0
  pos = 1;
817
0
  p->flags = header[pos++];
818
819
0
  p->packSize = (UInt64)(Int64)-1;
820
0
  if (XzBlock_HasPackSize(p))
821
0
  {
822
0
    READ_VARINT_AND_CHECK(header, pos, headerSize, &p->packSize);
823
0
    if (p->packSize == 0 || p->packSize + headerSize >= (UInt64)1 << 63)
824
0
      return SZ_ERROR_ARCHIVE;
825
0
  }
826
827
0
  p->unpackSize = (UInt64)(Int64)-1;
828
0
  if (XzBlock_HasUnpackSize(p))
829
0
    READ_VARINT_AND_CHECK(header, pos, headerSize, &p->unpackSize);
830
831
0
  numFilters = XzBlock_GetNumFilters(p);
832
0
  for (i = 0; i < numFilters; i++)
833
0
  {
834
0
    CXzFilter *filter = p->filters + i;
835
0
    UInt64 size;
836
0
    READ_VARINT_AND_CHECK(header, pos, headerSize, &filter->id);
837
0
    READ_VARINT_AND_CHECK(header, pos, headerSize, &size);
838
0
    if (size > headerSize - pos || size > XZ_FILTER_PROPS_SIZE_MAX)
839
0
      return SZ_ERROR_ARCHIVE;
840
0
    filter->propsSize = (UInt32)size;
841
0
    memcpy(filter->props, header + pos, (size_t)size);
842
0
    pos += (unsigned)size;
843
844
    #ifdef XZ_DUMP
845
    printf("\nf[%u] = %2X: ", i, (unsigned)filter->id);
846
    {
847
      unsigned i;
848
      for (i = 0; i < size; i++)
849
        printf(" %2X", filter->props[i]);
850
    }
851
    #endif
852
0
  }
853
854
0
  if (XzBlock_HasUnsupportedFlags(p))
855
0
    return SZ_ERROR_UNSUPPORTED;
856
857
0
  while (pos < headerSize)
858
0
    if (header[pos++] != 0)
859
0
      return SZ_ERROR_ARCHIVE;
860
0
  return SZ_OK;
861
0
}
862
863
864
865
866
static SRes XzDecMix_Init(CMixCoder *p, const CXzBlock *block, Byte *outBuf, size_t outBufSize)
867
0
{
868
0
  unsigned i;
869
0
  Bool needReInit = True;
870
0
  unsigned numFilters = XzBlock_GetNumFilters(block);
871
872
0
  if (numFilters == p->numCoders && ((p->outBuf && outBuf) || (!p->outBuf && !outBuf)))
873
0
  {
874
0
    needReInit = False;
875
0
    for (i = 0; i < numFilters; i++)
876
0
      if (p->ids[i] != block->filters[numFilters - 1 - i].id)
877
0
      {
878
0
        needReInit = True;
879
0
        break;
880
0
      }
881
0
  }
882
883
  // p->SingleBufMode = (outBuf != NULL);
884
0
  p->outBuf = outBuf;
885
0
  p->outBufSize = outBufSize;
886
887
  // p->SingleBufMode = False;
888
  // outBuf = NULL;
889
  
890
0
  if (needReInit)
891
0
  {
892
0
    MixCoder_Free(p);
893
0
    for (i = 0; i < numFilters; i++)
894
0
    {
895
0
      RINOK(MixCoder_SetFromMethod(p, i, block->filters[numFilters - 1 - i].id, outBuf, outBufSize));
896
0
    }
897
0
    p->numCoders = numFilters;
898
0
  }
899
0
  else
900
0
  {
901
0
    RINOK(MixCoder_ResetFromMethod(p, 0, block->filters[numFilters - 1].id, outBuf, outBufSize));
902
0
  }
903
904
0
  for (i = 0; i < numFilters; i++)
905
0
  {
906
0
    const CXzFilter *f = &block->filters[numFilters - 1 - i];
907
0
    IStateCoder *sc = &p->coders[i];
908
0
    RINOK(sc->SetProps(sc->p, f->props, f->propsSize, p->alloc));
909
0
  }
910
  
911
0
  MixCoder_Init(p);
912
0
  return SZ_OK;
913
0
}
914
915
916
917
void XzUnpacker_Init(CXzUnpacker *p)
918
0
{
919
0
  p->state = XZ_STATE_STREAM_HEADER;
920
0
  p->pos = 0;
921
0
  p->numStartedStreams = 0;
922
0
  p->numFinishedStreams = 0;
923
0
  p->numTotalBlocks = 0;
924
0
  p->padSize = 0;
925
0
  p->decodeOnlyOneBlock = 0;
926
927
0
  p->parseMode = False;
928
0
  p->decodeToStreamSignature = False;
929
930
  // p->outBuf = NULL;
931
  // p->outBufSize = 0;
932
0
  p->outDataWritten = 0;
933
0
}
934
935
936
void XzUnpacker_SetOutBuf(CXzUnpacker *p, Byte *outBuf, size_t outBufSize)
937
0
{
938
0
  p->outBuf = outBuf;
939
0
  p->outBufSize = outBufSize;
940
0
}
941
942
943
void XzUnpacker_Construct(CXzUnpacker *p, ISzAllocPtr alloc)
944
0
{
945
0
  MixCoder_Construct(&p->decoder, alloc);
946
0
  p->outBuf = NULL;
947
0
  p->outBufSize = 0;
948
0
  XzUnpacker_Init(p);
949
0
}
950
951
952
void XzUnpacker_Free(CXzUnpacker *p)
953
0
{
954
0
  MixCoder_Free(&p->decoder);
955
0
}
956
957
958
void XzUnpacker_PrepareToRandomBlockDecoding(CXzUnpacker *p)
959
0
{
960
0
  p->indexSize = 0;
961
0
  p->numBlocks = 0;
962
0
  Sha256_Init(&p->sha);
963
0
  p->state = XZ_STATE_BLOCK_HEADER;
964
0
  p->pos = 0;
965
0
  p->decodeOnlyOneBlock = 1;
966
0
}
967
968
969
static void XzUnpacker_UpdateIndex(CXzUnpacker *p, UInt64 packSize, UInt64 unpackSize)
970
0
{
971
0
  Byte temp[32];
972
0
  unsigned num = Xz_WriteVarInt(temp, packSize);
973
0
  num += Xz_WriteVarInt(temp + num, unpackSize);
974
0
  Sha256_Update(&p->sha, temp, num);
975
0
  p->indexSize += num;
976
0
  p->numBlocks++;
977
0
}
978
979
980
981
SRes XzUnpacker_Code(CXzUnpacker *p, Byte *dest, SizeT *destLen,
982
    const Byte *src, SizeT *srcLen, int srcFinished,
983
    ECoderFinishMode finishMode, ECoderStatus *status)
984
0
{
985
0
  SizeT destLenOrig = *destLen;
986
0
  SizeT srcLenOrig = *srcLen;
987
0
  *destLen = 0;
988
0
  *srcLen = 0;
989
0
  *status = CODER_STATUS_NOT_SPECIFIED;
990
991
0
  for (;;)
992
0
  {
993
0
    SizeT srcRem;
994
995
0
    if (p->state == XZ_STATE_BLOCK)
996
0
    {
997
0
      SizeT destLen2 = destLenOrig - *destLen;
998
0
      SizeT srcLen2 = srcLenOrig - *srcLen;
999
0
      SRes res;
1000
1001
0
      ECoderFinishMode finishMode2 = finishMode;
1002
0
      Bool srcFinished2 = srcFinished;
1003
0
      Bool destFinish = False;
1004
1005
0
      if (p->block.packSize != (UInt64)(Int64)-1)
1006
0
      {
1007
0
        UInt64 rem = p->block.packSize - p->packSize;
1008
0
        if (srcLen2 >= rem)
1009
0
        {
1010
0
          srcFinished2 = True;
1011
0
          srcLen2 = (SizeT)rem;
1012
0
        }
1013
0
        if (rem == 0 && p->block.unpackSize == p->unpackSize)
1014
0
          return SZ_ERROR_DATA;
1015
0
      }
1016
1017
0
      if (p->block.unpackSize != (UInt64)(Int64)-1)
1018
0
      {
1019
0
        UInt64 rem = p->block.unpackSize - p->unpackSize;
1020
0
        if (destLen2 >= rem)
1021
0
        {
1022
0
          destFinish = True;
1023
0
          finishMode2 = CODER_FINISH_END;
1024
0
          destLen2 = (SizeT)rem;
1025
0
        }
1026
0
      }
1027
1028
      /*
1029
      if (srcLen2 == 0 && destLen2 == 0)
1030
      {
1031
        *status = CODER_STATUS_NOT_FINISHED;
1032
        return SZ_OK;
1033
      }
1034
      */
1035
      
1036
0
      {
1037
0
        res = MixCoder_Code(&p->decoder,
1038
0
            (p->outBuf ? NULL : dest), &destLen2, destFinish,
1039
0
            src, &srcLen2, srcFinished2,
1040
0
            finishMode2);
1041
        
1042
0
        *status = p->decoder.status;
1043
0
        XzCheck_Update(&p->check, (p->outBuf ? p->outBuf + p->outDataWritten : dest), destLen2);
1044
0
        if (!p->outBuf)
1045
0
          dest += destLen2;
1046
0
        p->outDataWritten += destLen2;
1047
0
      }
1048
      
1049
0
      (*srcLen) += srcLen2;
1050
0
      src += srcLen2;
1051
0
      p->packSize += srcLen2;
1052
0
      (*destLen) += destLen2;
1053
0
      p->unpackSize += destLen2;
1054
1055
0
      RINOK(res);
1056
1057
0
      if (*status != CODER_STATUS_FINISHED_WITH_MARK)
1058
0
      {
1059
0
        if (p->block.packSize == p->packSize
1060
0
            && *status == CODER_STATUS_NEEDS_MORE_INPUT)
1061
0
        {
1062
0
          PRF_STR("CODER_STATUS_NEEDS_MORE_INPUT");
1063
0
          *status = CODER_STATUS_NOT_SPECIFIED;
1064
0
          return SZ_ERROR_DATA;
1065
0
        }
1066
        
1067
0
        return SZ_OK;
1068
0
      }
1069
0
      {
1070
0
        XzUnpacker_UpdateIndex(p, XzUnpacker_GetPackSizeForIndex(p), p->unpackSize);
1071
0
        p->state = XZ_STATE_BLOCK_FOOTER;
1072
0
        p->pos = 0;
1073
0
        p->alignPos = 0;
1074
0
        *status = CODER_STATUS_NOT_SPECIFIED;
1075
1076
0
        if ((p->block.packSize != (UInt64)(Int64)-1 && p->block.packSize != p->packSize)
1077
0
           || (p->block.unpackSize != (UInt64)(Int64)-1 && p->block.unpackSize != p->unpackSize))
1078
0
        {
1079
0
          PRF_STR("ERROR: block.size mismatch");
1080
0
          return SZ_ERROR_DATA;
1081
0
        }
1082
0
      }
1083
      // continue;
1084
0
    }
1085
1086
0
    srcRem = srcLenOrig - *srcLen;
1087
1088
    // XZ_STATE_BLOCK_FOOTER can transit to XZ_STATE_BLOCK_HEADER without input bytes
1089
0
    if (srcRem == 0 && p->state != XZ_STATE_BLOCK_FOOTER)
1090
0
    {
1091
0
      *status = CODER_STATUS_NEEDS_MORE_INPUT;
1092
0
      return SZ_OK;
1093
0
    }
1094
1095
0
    switch (p->state)
1096
0
    {
1097
0
      case XZ_STATE_STREAM_HEADER:
1098
0
      {
1099
0
        if (p->pos < XZ_STREAM_HEADER_SIZE)
1100
0
        {
1101
0
          if (p->pos < XZ_SIG_SIZE && *src != XZ_SIG[p->pos])
1102
0
            return SZ_ERROR_NO_ARCHIVE;
1103
0
          if (p->decodeToStreamSignature)
1104
0
            return SZ_OK;
1105
0
          p->buf[p->pos++] = *src++;
1106
0
          (*srcLen)++;
1107
0
        }
1108
0
        else
1109
0
        {
1110
0
          RINOK(Xz_ParseHeader(&p->streamFlags, p->buf));
1111
0
          p->numStartedStreams++;
1112
0
          p->indexSize = 0;
1113
0
          p->numBlocks = 0;
1114
0
          Sha256_Init(&p->sha);
1115
0
          p->state = XZ_STATE_BLOCK_HEADER;
1116
0
          p->pos = 0;
1117
0
        }
1118
0
        break;
1119
0
      }
1120
1121
0
      case XZ_STATE_BLOCK_HEADER:
1122
0
      {
1123
0
        if (p->pos == 0)
1124
0
        {
1125
0
          p->buf[p->pos++] = *src++;
1126
0
          (*srcLen)++;
1127
0
          if (p->buf[0] == 0)
1128
0
          {
1129
0
            if (p->decodeOnlyOneBlock)
1130
0
              return SZ_ERROR_DATA;
1131
0
            p->indexPreSize = 1 + Xz_WriteVarInt(p->buf + 1, p->numBlocks);
1132
0
            p->indexPos = p->indexPreSize;
1133
0
            p->indexSize += p->indexPreSize;
1134
0
            Sha256_Final(&p->sha, p->shaDigest);
1135
0
            Sha256_Init(&p->sha);
1136
0
            p->crc = CrcUpdate(CRC_INIT_VAL, p->buf, p->indexPreSize);
1137
0
            p->state = XZ_STATE_STREAM_INDEX;
1138
0
            break;
1139
0
          }
1140
0
          p->blockHeaderSize = ((UInt32)p->buf[0] << 2) + 4;
1141
0
          break;
1142
0
        }
1143
        
1144
0
        if (p->pos != p->blockHeaderSize)
1145
0
        {
1146
0
          UInt32 cur = p->blockHeaderSize - p->pos;
1147
0
          if (cur > srcRem)
1148
0
            cur = (UInt32)srcRem;
1149
0
          memcpy(p->buf + p->pos, src, cur);
1150
0
          p->pos += cur;
1151
0
          (*srcLen) += cur;
1152
0
          src += cur;
1153
0
        }
1154
0
        else
1155
0
        {
1156
0
          RINOK(XzBlock_Parse(&p->block, p->buf));
1157
0
          if (!XzBlock_AreSupportedFilters(&p->block))
1158
0
            return SZ_ERROR_UNSUPPORTED;
1159
0
          p->numTotalBlocks++;
1160
0
          p->state = XZ_STATE_BLOCK;
1161
0
          p->packSize = 0;
1162
0
          p->unpackSize = 0;
1163
0
          XzCheck_Init(&p->check, XzFlags_GetCheckType(p->streamFlags));
1164
0
          if (p->parseMode)
1165
0
          {
1166
0
            p->headerParsedOk = True;
1167
0
            return SZ_OK;
1168
0
          }
1169
0
          RINOK(XzDecMix_Init(&p->decoder, &p->block, p->outBuf, p->outBufSize));
1170
0
        }
1171
0
        break;
1172
0
      }
1173
1174
0
      case XZ_STATE_BLOCK_FOOTER:
1175
0
      {
1176
0
        if ((((unsigned)p->packSize + p->alignPos) & 3) != 0)
1177
0
        {
1178
0
          if (srcRem == 0)
1179
0
          {
1180
0
            *status = CODER_STATUS_NEEDS_MORE_INPUT;
1181
0
            return SZ_OK;
1182
0
          }
1183
0
          (*srcLen)++;
1184
0
          p->alignPos++;
1185
0
          if (*src++ != 0)
1186
0
            return SZ_ERROR_CRC;
1187
0
        }
1188
0
        else
1189
0
        {
1190
0
          UInt32 checkSize = XzFlags_GetCheckSize(p->streamFlags);
1191
0
          UInt32 cur = checkSize - p->pos;
1192
0
          if (cur != 0)
1193
0
          {
1194
0
            if (srcRem == 0)
1195
0
            {
1196
0
              *status = CODER_STATUS_NEEDS_MORE_INPUT;
1197
0
              return SZ_OK;
1198
0
            }
1199
0
            if (cur > srcRem)
1200
0
              cur = (UInt32)srcRem;
1201
0
            memcpy(p->buf + p->pos, src, cur);
1202
0
            p->pos += cur;
1203
0
            (*srcLen) += cur;
1204
0
            src += cur;
1205
0
            if (checkSize != p->pos)
1206
0
              break;
1207
0
          }
1208
0
          {
1209
0
            Byte digest[XZ_CHECK_SIZE_MAX];
1210
0
            p->state = XZ_STATE_BLOCK_HEADER;
1211
0
            p->pos = 0;
1212
0
            if (XzCheck_Final(&p->check, digest) && memcmp(digest, p->buf, checkSize) != 0)
1213
0
              return SZ_ERROR_CRC;
1214
0
            if (p->decodeOnlyOneBlock)
1215
0
            {
1216
0
              *status = CODER_STATUS_FINISHED_WITH_MARK;
1217
0
              return SZ_OK;
1218
0
            }
1219
0
          }
1220
0
        }
1221
0
        break;
1222
0
      }
1223
1224
0
      case XZ_STATE_STREAM_INDEX:
1225
0
      {
1226
0
        if (p->pos < p->indexPreSize)
1227
0
        {
1228
0
          (*srcLen)++;
1229
0
          if (*src++ != p->buf[p->pos++])
1230
0
            return SZ_ERROR_CRC;
1231
0
        }
1232
0
        else
1233
0
        {
1234
0
          if (p->indexPos < p->indexSize)
1235
0
          {
1236
0
            UInt64 cur = p->indexSize - p->indexPos;
1237
0
            if (srcRem > cur)
1238
0
              srcRem = (SizeT)cur;
1239
0
            p->crc = CrcUpdate(p->crc, src, srcRem);
1240
0
            Sha256_Update(&p->sha, src, srcRem);
1241
0
            (*srcLen) += srcRem;
1242
0
            src += srcRem;
1243
0
            p->indexPos += srcRem;
1244
0
          }
1245
0
          else if ((p->indexPos & 3) != 0)
1246
0
          {
1247
0
            Byte b = *src++;
1248
0
            p->crc = CRC_UPDATE_BYTE(p->crc, b);
1249
0
            (*srcLen)++;
1250
0
            p->indexPos++;
1251
0
            p->indexSize++;
1252
0
            if (b != 0)
1253
0
              return SZ_ERROR_CRC;
1254
0
          }
1255
0
          else
1256
0
          {
1257
0
            Byte digest[SHA256_DIGEST_SIZE];
1258
0
            p->state = XZ_STATE_STREAM_INDEX_CRC;
1259
0
            p->indexSize += 4;
1260
0
            p->pos = 0;
1261
0
            Sha256_Final(&p->sha, digest);
1262
0
            if (memcmp(digest, p->shaDigest, SHA256_DIGEST_SIZE) != 0)
1263
0
              return SZ_ERROR_CRC;
1264
0
          }
1265
0
        }
1266
0
        break;
1267
0
      }
1268
1269
0
      case XZ_STATE_STREAM_INDEX_CRC:
1270
0
      {
1271
0
        if (p->pos < 4)
1272
0
        {
1273
0
          (*srcLen)++;
1274
0
          p->buf[p->pos++] = *src++;
1275
0
        }
1276
0
        else
1277
0
        {
1278
0
          p->state = XZ_STATE_STREAM_FOOTER;
1279
0
          p->pos = 0;
1280
0
          if (CRC_GET_DIGEST(p->crc) != GetUi32(p->buf))
1281
0
            return SZ_ERROR_CRC;
1282
0
        }
1283
0
        break;
1284
0
      }
1285
1286
0
      case XZ_STATE_STREAM_FOOTER:
1287
0
      {
1288
0
        UInt32 cur = XZ_STREAM_FOOTER_SIZE - p->pos;
1289
0
        if (cur > srcRem)
1290
0
          cur = (UInt32)srcRem;
1291
0
        memcpy(p->buf + p->pos, src, cur);
1292
0
        p->pos += cur;
1293
0
        (*srcLen) += cur;
1294
0
        src += cur;
1295
0
        if (p->pos == XZ_STREAM_FOOTER_SIZE)
1296
0
        {
1297
0
          p->state = XZ_STATE_STREAM_PADDING;
1298
0
          p->numFinishedStreams++;
1299
0
          p->padSize = 0;
1300
0
          if (!Xz_CheckFooter(p->streamFlags, p->indexSize, p->buf))
1301
0
            return SZ_ERROR_CRC;
1302
0
        }
1303
0
        break;
1304
0
      }
1305
1306
0
      case XZ_STATE_STREAM_PADDING:
1307
0
      {
1308
0
        if (*src != 0)
1309
0
        {
1310
0
          if (((UInt32)p->padSize & 3) != 0)
1311
0
            return SZ_ERROR_NO_ARCHIVE;
1312
0
          p->pos = 0;
1313
0
          p->state = XZ_STATE_STREAM_HEADER;
1314
0
        }
1315
0
        else
1316
0
        {
1317
0
          (*srcLen)++;
1318
0
          src++;
1319
0
          p->padSize++;
1320
0
        }
1321
0
        break;
1322
0
      }
1323
      
1324
0
      case XZ_STATE_BLOCK: break; /* to disable GCC warning */
1325
0
    }
1326
0
  }
1327
  /*
1328
  if (p->state == XZ_STATE_FINISHED)
1329
    *status = CODER_STATUS_FINISHED_WITH_MARK;
1330
  return SZ_OK;
1331
  */
1332
0
}
1333
1334
1335
SRes XzUnpacker_CodeFull(CXzUnpacker *p, Byte *dest, SizeT *destLen,
1336
    const Byte *src, SizeT *srcLen,
1337
    ECoderFinishMode finishMode, ECoderStatus *status)
1338
0
{
1339
0
  XzUnpacker_Init(p);
1340
0
  XzUnpacker_SetOutBuf(p, dest, *destLen);
1341
1342
0
  return XzUnpacker_Code(p,
1343
0
      NULL, destLen,
1344
0
      src, srcLen, True,
1345
0
      finishMode, status);
1346
0
}
1347
1348
1349
Bool XzUnpacker_IsBlockFinished(const CXzUnpacker *p)
1350
0
{
1351
0
  return (p->state == XZ_STATE_BLOCK_HEADER) && (p->pos == 0);
1352
0
}
1353
1354
Bool XzUnpacker_IsStreamWasFinished(const CXzUnpacker *p)
1355
0
{
1356
0
  return (p->state == XZ_STATE_STREAM_PADDING) && (((UInt32)p->padSize & 3) == 0);
1357
0
}
1358
1359
UInt64 XzUnpacker_GetExtraSize(const CXzUnpacker *p)
1360
0
{
1361
0
  UInt64 num = 0;
1362
0
  if (p->state == XZ_STATE_STREAM_PADDING)
1363
0
    num = p->padSize;
1364
0
  else if (p->state == XZ_STATE_STREAM_HEADER)
1365
0
    num = p->padSize + p->pos;
1366
0
  return num;
1367
0
}
1368
1369
1370
1371
1372
1373
1374
1375
1376
1377
1378
1379
1380
1381
1382
1383
1384
1385
1386
1387
1388
1389
#ifndef _7ZIP_ST
1390
#include "MtDec.h"
1391
#endif
1392
1393
1394
void XzDecMtProps_Init(CXzDecMtProps *p)
1395
0
{
1396
0
  p->inBufSize_ST = 1 << 18;
1397
0
  p->outStep_ST = 1 << 20;
1398
0
  p->ignoreErrors = False;
1399
1400
  #ifndef _7ZIP_ST
1401
  p->numThreads = 1;
1402
  p->inBufSize_MT = 1 << 18;
1403
  p->memUseMax = sizeof(size_t) << 28;
1404
  #endif
1405
0
}
1406
1407
1408
1409
#ifndef _7ZIP_ST
1410
1411
/* ---------- CXzDecMtThread ---------- */
1412
1413
typedef struct
1414
{
1415
  Byte *outBuf;
1416
  size_t outBufSize;
1417
  size_t outPreSize;
1418
  size_t inPreSize;
1419
  size_t inPreHeaderSize;
1420
  size_t blockPackSize_for_Index;  // including block header and checksum.
1421
  size_t blockPackTotal;  // including stream header, block header and checksum.
1422
  size_t inCodeSize;
1423
  size_t outCodeSize;
1424
  ECoderStatus status;
1425
  SRes codeRes;
1426
  Bool skipMode;
1427
  // Bool finishedWithMark;
1428
  EMtDecParseState parseState;
1429
  Bool parsing_Truncated;
1430
  Bool atBlockHeader;
1431
  CXzStreamFlags streamFlags;
1432
  // UInt64 numFinishedStreams
1433
  UInt64 numStreams;
1434
  UInt64 numTotalBlocks;
1435
  UInt64 numBlocks;
1436
1437
  Bool dec_created;
1438
  CXzUnpacker dec;
1439
1440
  Byte mtPad[1 << 7];
1441
} CXzDecMtThread;
1442
1443
#endif
1444
1445
1446
/* ---------- CXzDecMt ---------- */
1447
1448
typedef struct
1449
{
1450
  CAlignOffsetAlloc alignOffsetAlloc;
1451
  ISzAllocPtr allocMid;
1452
1453
  CXzDecMtProps props;
1454
  size_t unpackBlockMaxSize;
1455
  
1456
  ISeqInStream *inStream;
1457
  ISeqOutStream *outStream;
1458
  ICompressProgress *progress;
1459
  // CXzStatInfo *stat;
1460
1461
  Bool finishMode;
1462
  Bool outSize_Defined;
1463
  UInt64 outSize;
1464
1465
  UInt64 outProcessed;
1466
  UInt64 inProcessed;
1467
  UInt64 readProcessed;
1468
  Bool readWasFinished;
1469
  SRes readRes;
1470
  SRes writeRes;
1471
1472
  Byte *outBuf;
1473
  size_t outBufSize;
1474
  Byte *inBuf;
1475
  size_t inBufSize;
1476
  Bool dec_created;
1477
  CXzUnpacker dec;
1478
1479
  ECoderStatus status;
1480
  SRes codeRes;
1481
1482
  #ifndef _7ZIP_ST
1483
  Bool mainDecoderWasCalled;
1484
  // int statErrorDefined;
1485
  int finishedDecoderIndex;
1486
1487
  // global values that are used in Parse stage
1488
  CXzStreamFlags streamFlags;
1489
  // UInt64 numFinishedStreams
1490
  UInt64 numStreams;
1491
  UInt64 numTotalBlocks;
1492
  UInt64 numBlocks;
1493
1494
  // UInt64 numBadBlocks;
1495
  SRes mainErrorCode;
1496
1497
  Bool isBlockHeaderState_Parse;
1498
  Bool isBlockHeaderState_Write;
1499
  UInt64 outProcessed_Parse;
1500
  Bool parsing_Truncated;
1501
1502
  Bool mtc_WasConstructed;
1503
  CMtDec mtc;
1504
  CXzDecMtThread coders[MTDEC__THREADS_MAX];
1505
  #endif
1506
1507
} CXzDecMt;
1508
1509
1510
1511
CXzDecMtHandle XzDecMt_Create(ISzAllocPtr alloc, ISzAllocPtr allocMid)
1512
0
{
1513
0
  CXzDecMt *p = (CXzDecMt *)ISzAlloc_Alloc(alloc, sizeof(CXzDecMt));
1514
0
  if (!p)
1515
0
    return NULL;
1516
  
1517
0
  AlignOffsetAlloc_CreateVTable(&p->alignOffsetAlloc);
1518
0
  p->alignOffsetAlloc.baseAlloc = alloc;
1519
0
  p->alignOffsetAlloc.numAlignBits = 7;
1520
0
  p->alignOffsetAlloc.offset = 0;
1521
1522
0
  p->allocMid = allocMid;
1523
1524
0
  p->outBuf = NULL;
1525
0
  p->outBufSize = 0;
1526
0
  p->inBuf = NULL;
1527
0
  p->inBufSize = 0;
1528
0
  p->dec_created = False;
1529
1530
0
  p->unpackBlockMaxSize = 0;
1531
1532
0
  XzDecMtProps_Init(&p->props);
1533
1534
  #ifndef _7ZIP_ST
1535
  p->mtc_WasConstructed = False;
1536
  {
1537
    unsigned i;
1538
    for (i = 0; i < MTDEC__THREADS_MAX; i++)
1539
    {
1540
      CXzDecMtThread *coder = &p->coders[i];
1541
      coder->dec_created = False;
1542
      coder->outBuf = NULL;
1543
      coder->outBufSize = 0;
1544
    }
1545
  }
1546
  #endif
1547
1548
0
  return p;
1549
0
}
1550
1551
1552
#ifndef _7ZIP_ST
1553
1554
static void XzDecMt_FreeOutBufs(CXzDecMt *p)
1555
{
1556
  unsigned i;
1557
  for (i = 0; i < MTDEC__THREADS_MAX; i++)
1558
  {
1559
    CXzDecMtThread *coder = &p->coders[i];
1560
    if (coder->outBuf)
1561
    {
1562
      ISzAlloc_Free(p->allocMid, coder->outBuf);
1563
      coder->outBuf = NULL;
1564
      coder->outBufSize = 0;
1565
    }
1566
  }
1567
  p->unpackBlockMaxSize = 0;
1568
}
1569
1570
#endif
1571
1572
1573
1574
static void XzDecMt_FreeSt(CXzDecMt *p)
1575
0
{
1576
0
  if (p->dec_created)
1577
0
  {
1578
0
    XzUnpacker_Free(&p->dec);
1579
0
    p->dec_created = False;
1580
0
  }
1581
  
1582
0
  if (p->outBuf)
1583
0
  {
1584
0
    ISzAlloc_Free(p->allocMid, p->outBuf);
1585
0
    p->outBuf = NULL;
1586
0
  }
1587
0
  p->outBufSize = 0;
1588
  
1589
0
  if (p->inBuf)
1590
0
  {
1591
0
    ISzAlloc_Free(p->allocMid, p->inBuf);
1592
0
    p->inBuf = NULL;
1593
0
  }
1594
0
  p->inBufSize = 0;
1595
0
}
1596
1597
1598
void XzDecMt_Destroy(CXzDecMtHandle pp)
1599
0
{
1600
0
  CXzDecMt *p = (CXzDecMt *)pp;
1601
1602
0
  XzDecMt_FreeSt(p);
1603
1604
  #ifndef _7ZIP_ST
1605
1606
  if (p->mtc_WasConstructed)
1607
  {
1608
    MtDec_Destruct(&p->mtc);
1609
    p->mtc_WasConstructed = False;
1610
  }
1611
  {
1612
    unsigned i;
1613
    for (i = 0; i < MTDEC__THREADS_MAX; i++)
1614
    {
1615
      CXzDecMtThread *t = &p->coders[i];
1616
      if (t->dec_created)
1617
      {
1618
        // we don't need to free dict here
1619
        XzUnpacker_Free(&t->dec);
1620
        t->dec_created = False;
1621
      }
1622
    }
1623
  }
1624
  XzDecMt_FreeOutBufs(p);
1625
1626
  #endif
1627
1628
0
  ISzAlloc_Free(p->alignOffsetAlloc.baseAlloc, pp);
1629
0
}
1630
1631
1632
1633
#ifndef _7ZIP_ST
1634
1635
static void XzDecMt_Callback_Parse(void *obj, unsigned coderIndex, CMtDecCallbackInfo *cc)
1636
{
1637
  CXzDecMt *me = (CXzDecMt *)obj;
1638
  CXzDecMtThread *coder = &me->coders[coderIndex];
1639
  size_t srcSize = cc->srcSize;
1640
1641
  cc->srcSize = 0;
1642
  cc->outPos = 0;
1643
  cc->state = MTDEC_PARSE_CONTINUE;
1644
1645
  cc->canCreateNewThread = True;
1646
1647
  if (cc->startCall)
1648
  {
1649
    coder->outPreSize = 0;
1650
    coder->inPreSize = 0;
1651
    coder->inPreHeaderSize = 0;
1652
    coder->parseState = MTDEC_PARSE_CONTINUE;
1653
    coder->parsing_Truncated = False;
1654
    coder->skipMode = False;
1655
    coder->codeRes = SZ_OK;
1656
    coder->status = CODER_STATUS_NOT_SPECIFIED;
1657
    coder->inCodeSize = 0;
1658
    coder->outCodeSize = 0;
1659
1660
    coder->numStreams = me->numStreams;
1661
    coder->numTotalBlocks = me->numTotalBlocks;
1662
    coder->numBlocks = me->numBlocks;
1663
1664
    if (!coder->dec_created)
1665
    {
1666
      XzUnpacker_Construct(&coder->dec, &me->alignOffsetAlloc.vt);
1667
      coder->dec_created = True;
1668
    }
1669
    
1670
    XzUnpacker_Init(&coder->dec);
1671
1672
    if (me->isBlockHeaderState_Parse)
1673
    {
1674
      coder->dec.streamFlags = me->streamFlags;
1675
      coder->atBlockHeader = True;
1676
      XzUnpacker_PrepareToRandomBlockDecoding(&coder->dec);
1677
    }
1678
    else
1679
    {
1680
      coder->atBlockHeader = False;
1681
      me->isBlockHeaderState_Parse = True;
1682
    }
1683
1684
    coder->dec.numStartedStreams = me->numStreams;
1685
    coder->dec.numTotalBlocks = me->numTotalBlocks;
1686
    coder->dec.numBlocks = me->numBlocks;
1687
  }
1688
1689
  while (!coder->skipMode)
1690
  {
1691
    ECoderStatus status;
1692
    SRes res;
1693
    size_t srcSize2 = srcSize;
1694
    size_t destSize = (size_t)0 - 1;
1695
1696
    coder->dec.parseMode = True;
1697
    coder->dec.headerParsedOk = False;
1698
    
1699
    PRF_STR_INT("Parse", srcSize2);
1700
    
1701
    res = XzUnpacker_Code(&coder->dec,
1702
        NULL, &destSize,
1703
        cc->src, &srcSize2, cc->srcFinished,
1704
        CODER_FINISH_END, &status);
1705
    
1706
    // PRF(printf(" res = %d, srcSize2 = %d", res, (unsigned)srcSize2));
1707
    
1708
    coder->codeRes = res;
1709
    coder->status = status;
1710
    cc->srcSize += srcSize2;
1711
    srcSize -= srcSize2;
1712
    coder->inPreHeaderSize += srcSize2;
1713
    coder->inPreSize = coder->inPreHeaderSize;
1714
    
1715
    if (res != SZ_OK)
1716
    {
1717
      cc->state =
1718
      coder->parseState = MTDEC_PARSE_END;
1719
      /*
1720
      if (res == SZ_ERROR_MEM)
1721
        return res;
1722
      return SZ_OK;
1723
      */
1724
      return; // res;
1725
    }
1726
    
1727
    if (coder->dec.headerParsedOk)
1728
    {
1729
      const CXzBlock *block = &coder->dec.block;
1730
      if (XzBlock_HasUnpackSize(block)
1731
          // && block->unpackSize <= me->props.outBlockMax
1732
          && XzBlock_HasPackSize(block))
1733
      {
1734
        {
1735
          if (block->unpackSize * 2 * me->mtc.numStartedThreads > me->props.memUseMax)
1736
          {
1737
            cc->state = MTDEC_PARSE_OVERFLOW;
1738
            return; // SZ_OK;
1739
          }
1740
        }
1741
        {
1742
        UInt64 packSize = block->packSize;
1743
        UInt64 packSizeAligned = packSize + ((0 - (unsigned)packSize) & 3);
1744
        UInt32 checkSize = XzFlags_GetCheckSize(coder->dec.streamFlags);
1745
        UInt64 blockPackSum = coder->inPreSize + packSizeAligned + checkSize;
1746
        // if (blockPackSum <= me->props.inBlockMax)
1747
        // unpackBlockMaxSize
1748
        {
1749
          coder->blockPackSize_for_Index = (size_t)(coder->dec.blockHeaderSize + packSize + checkSize);
1750
          coder->blockPackTotal = (size_t)blockPackSum;
1751
          coder->outPreSize = (size_t)block->unpackSize;
1752
          coder->streamFlags = coder->dec.streamFlags;
1753
          me->streamFlags = coder->dec.streamFlags;
1754
          coder->skipMode = True;
1755
          break;
1756
        }
1757
        }
1758
      }
1759
    }
1760
    else
1761
    // if (coder->inPreSize <= me->props.inBlockMax)
1762
    {
1763
      if (!cc->srcFinished)
1764
        return; // SZ_OK;
1765
      cc->state =
1766
      coder->parseState = MTDEC_PARSE_END;
1767
      return; // SZ_OK;
1768
    }
1769
    cc->state = MTDEC_PARSE_OVERFLOW;
1770
    return; // SZ_OK;
1771
  }
1772
1773
  // ---------- skipMode ----------
1774
  {
1775
    UInt64 rem = coder->blockPackTotal - coder->inPreSize;
1776
    size_t cur = srcSize;
1777
    if (cur > rem)
1778
      cur = (size_t)rem;
1779
    cc->srcSize += cur;
1780
    coder->inPreSize += cur;
1781
    srcSize -= cur;
1782
1783
    if (coder->inPreSize == coder->blockPackTotal)
1784
    {
1785
      if (srcSize == 0)
1786
      {
1787
        if (!cc->srcFinished)
1788
          return; // SZ_OK;
1789
        cc->state = MTDEC_PARSE_END;
1790
      }
1791
      else if ((cc->src)[cc->srcSize] == 0) // we check control byte of next block
1792
        cc->state = MTDEC_PARSE_END;
1793
      else
1794
      {
1795
        cc->state = MTDEC_PARSE_NEW;
1796
1797
        {
1798
          size_t blockMax = me->unpackBlockMaxSize;
1799
          if (blockMax < coder->outPreSize)
1800
            blockMax = coder->outPreSize;
1801
          {
1802
            UInt64 required = (UInt64)blockMax * (me->mtc.numStartedThreads + 1) * 2;
1803
            if (me->props.memUseMax < required)
1804
              cc->canCreateNewThread = False;
1805
          }
1806
        }
1807
1808
        if (me->outSize_Defined)
1809
        {
1810
          // next block can be zero size
1811
          const UInt64 rem2 = me->outSize - me->outProcessed_Parse;
1812
          if (rem2 < coder->outPreSize)
1813
          {
1814
            coder->parsing_Truncated = True;
1815
            cc->state = MTDEC_PARSE_END;
1816
          }
1817
          me->outProcessed_Parse += coder->outPreSize;
1818
        }
1819
      }
1820
    }
1821
    else if (cc->srcFinished)
1822
      cc->state = MTDEC_PARSE_END;
1823
    else
1824
      return; // SZ_OK;
1825
1826
    coder->parseState = cc->state;
1827
    cc->outPos = coder->outPreSize;
1828
    
1829
    me->numStreams = coder->dec.numStartedStreams;
1830
    me->numTotalBlocks = coder->dec.numTotalBlocks;
1831
    me->numBlocks = coder->dec.numBlocks + 1;
1832
    return; // SZ_OK;
1833
  }
1834
}
1835
1836
1837
static SRes XzDecMt_Callback_PreCode(void *pp, unsigned coderIndex)
1838
{
1839
  CXzDecMt *me = (CXzDecMt *)pp;
1840
  CXzDecMtThread *coder = &me->coders[coderIndex];
1841
  Byte *dest;
1842
1843
  if (!coder->dec.headerParsedOk)
1844
    return SZ_OK;
1845
1846
  dest = coder->outBuf;
1847
1848
  if (!dest || coder->outBufSize < coder->outPreSize)
1849
  {
1850
    if (dest)
1851
    {
1852
      ISzAlloc_Free(me->allocMid, dest);
1853
      coder->outBuf = NULL;
1854
      coder->outBufSize = 0;
1855
    }
1856
    {
1857
      size_t outPreSize = coder->outPreSize;
1858
      if (outPreSize == 0)
1859
        outPreSize = 1;
1860
      dest = (Byte *)ISzAlloc_Alloc(me->allocMid, outPreSize);
1861
    }
1862
    if (!dest)
1863
      return SZ_ERROR_MEM;
1864
    coder->outBuf = dest;
1865
    coder->outBufSize = coder->outPreSize;
1866
1867
    if (coder->outBufSize > me->unpackBlockMaxSize)
1868
      me->unpackBlockMaxSize = coder->outBufSize;
1869
  }
1870
1871
  // return SZ_ERROR_MEM;
1872
1873
  XzUnpacker_SetOutBuf(&coder->dec, coder->outBuf, coder->outBufSize);
1874
1875
  {
1876
    SRes res = XzDecMix_Init(&coder->dec.decoder, &coder->dec.block, coder->outBuf, coder->outBufSize);
1877
    // res = SZ_ERROR_UNSUPPORTED; // to test
1878
    coder->codeRes = res;
1879
    if (res != SZ_OK)
1880
    {
1881
      // if (res == SZ_ERROR_MEM) return res;
1882
      if (me->props.ignoreErrors && res != SZ_ERROR_MEM)
1883
        return S_OK;
1884
      return res;
1885
    }
1886
  }
1887
1888
  return SZ_OK;
1889
}
1890
1891
1892
static SRes XzDecMt_Callback_Code(void *pp, unsigned coderIndex,
1893
    const Byte *src, size_t srcSize, int srcFinished,
1894
    // int finished, int blockFinished,
1895
    UInt64 *inCodePos, UInt64 *outCodePos, int *stop)
1896
{
1897
  CXzDecMt *me = (CXzDecMt *)pp;
1898
  CXzDecMtThread *coder = &me->coders[coderIndex];
1899
1900
  *inCodePos = coder->inCodeSize;
1901
  *outCodePos = coder->outCodeSize;
1902
  *stop = True;
1903
1904
  if (coder->inCodeSize < coder->inPreHeaderSize)
1905
  {
1906
    UInt64 rem = coder->inPreHeaderSize - coder->inCodeSize;
1907
    size_t step = srcSize;
1908
    if (step > rem)
1909
      step = (size_t)rem;
1910
    src += step;
1911
    srcSize -= step;
1912
    coder->inCodeSize += step;
1913
    if (coder->inCodeSize < coder->inPreHeaderSize)
1914
    {
1915
      *stop = False;
1916
      return SZ_OK;
1917
    }
1918
  }
1919
1920
  if (!coder->dec.headerParsedOk)
1921
    return SZ_OK;
1922
  if (!coder->outBuf)
1923
    return SZ_OK;
1924
1925
  if (coder->codeRes == SZ_OK)
1926
  {
1927
    ECoderStatus status;
1928
    SRes res;
1929
    size_t srcProcessed = srcSize;
1930
    size_t outSizeCur = coder->outPreSize - coder->dec.outDataWritten;
1931
1932
    // PRF(printf("\nCallback_Code: Code %d %d\n", (unsigned)srcSize, (unsigned)outSizeCur));
1933
1934
    res = XzUnpacker_Code(&coder->dec,
1935
        NULL, &outSizeCur,
1936
        src, &srcProcessed, srcFinished,
1937
        // coder->finishedWithMark ? CODER_FINISH_END : CODER_FINISH_ANY,
1938
        CODER_FINISH_END,
1939
        &status);
1940
1941
    // PRF(printf(" res = %d, srcSize2 = %d, outSizeCur = %d", res, (unsigned)srcProcessed, (unsigned)outSizeCur));
1942
1943
    coder->codeRes = res;
1944
    coder->status = status;
1945
    coder->inCodeSize += srcProcessed;
1946
    coder->outCodeSize = coder->dec.outDataWritten;
1947
    *inCodePos = coder->inCodeSize;
1948
    *outCodePos = coder->outCodeSize;
1949
1950
    if (res == SZ_OK)
1951
    {
1952
      if (srcProcessed == srcSize)
1953
        *stop = False;
1954
      return SZ_OK;
1955
    }
1956
  }
1957
1958
  if (me->props.ignoreErrors && coder->codeRes != SZ_ERROR_MEM)
1959
  {
1960
    *inCodePos = coder->inPreSize;
1961
    *outCodePos = coder->outPreSize;
1962
    return S_OK;
1963
  }
1964
  return coder->codeRes;
1965
}
1966
1967
1968
#define XZDECMT_STREAM_WRITE_STEP (1 << 24)
1969
1970
static SRes XzDecMt_Callback_Write(void *pp, unsigned coderIndex,
1971
    Bool needWriteToStream,
1972
    const Byte *src, size_t srcSize,
1973
    // int srcFinished,
1974
    Bool *needContinue,
1975
    Bool *canRecode)
1976
{
1977
  CXzDecMt *me = (CXzDecMt *)pp;
1978
  const CXzDecMtThread *coder = &me->coders[coderIndex];
1979
1980
  // PRF(printf("\nWrite processed = %d srcSize = %d\n", (unsigned)me->mtc.inProcessed, (unsigned)srcSize));
1981
  
1982
  *needContinue = False;
1983
  *canRecode = True;
1984
  
1985
  if (!needWriteToStream)
1986
    return SZ_OK;
1987
1988
  if (!coder->dec.headerParsedOk || !coder->outBuf)
1989
  {
1990
    if (me->finishedDecoderIndex < 0)
1991
      me->finishedDecoderIndex = coderIndex;
1992
    return SZ_OK;
1993
  }
1994
1995
  if (me->finishedDecoderIndex >= 0)
1996
    return SZ_OK;
1997
1998
  me->mtc.inProcessed += coder->inCodeSize;
1999
2000
  *canRecode = False;
2001
2002
  {
2003
    SRes res;
2004
    size_t size = coder->outCodeSize;
2005
    Byte *data = coder->outBuf;
2006
    
2007
    // we use in me->dec: sha, numBlocks, indexSize
2008
2009
    if (!me->isBlockHeaderState_Write)
2010
    {
2011
      XzUnpacker_PrepareToRandomBlockDecoding(&me->dec);
2012
      me->dec.decodeOnlyOneBlock = False;
2013
      me->dec.numStartedStreams = coder->dec.numStartedStreams;
2014
      me->dec.streamFlags = coder->streamFlags;
2015
2016
      me->isBlockHeaderState_Write = True;
2017
    }
2018
    
2019
    me->dec.numTotalBlocks = coder->dec.numTotalBlocks;
2020
    XzUnpacker_UpdateIndex(&me->dec, coder->blockPackSize_for_Index, coder->outPreSize);
2021
    
2022
    if (coder->outPreSize != size)
2023
    {
2024
      if (me->props.ignoreErrors)
2025
      {
2026
        memset(data + size, 0, coder->outPreSize - size);
2027
        size = coder->outPreSize;
2028
      }
2029
      // me->numBadBlocks++;
2030
      if (me->mainErrorCode == SZ_OK)
2031
      {
2032
        if ((int)coder->status == LZMA_STATUS_NEEDS_MORE_INPUT)
2033
          me->mainErrorCode = SZ_ERROR_INPUT_EOF;
2034
        else
2035
          me->mainErrorCode = SZ_ERROR_DATA;
2036
      }
2037
    }
2038
    
2039
    if (me->writeRes != SZ_OK)
2040
      return me->writeRes;
2041
2042
    res = SZ_OK;
2043
    {
2044
      if (me->outSize_Defined)
2045
      {
2046
        const UInt64 rem = me->outSize - me->outProcessed;
2047
        if (size > rem)
2048
          size = (SizeT)rem;
2049
      }
2050
2051
      for (;;)
2052
      {
2053
        size_t cur = size;
2054
        size_t written;
2055
        if (cur > XZDECMT_STREAM_WRITE_STEP)
2056
          cur = XZDECMT_STREAM_WRITE_STEP;
2057
2058
        written = ISeqOutStream_Write(me->outStream, data, cur);
2059
2060
        // PRF(printf("\nWritten ask = %d written = %d\n", (unsigned)cur, (unsigned)written));
2061
        
2062
        me->outProcessed += written;
2063
        if (written != cur)
2064
        {
2065
          me->writeRes = SZ_ERROR_WRITE;
2066
          res = me->writeRes;
2067
          break;
2068
        }
2069
        data += cur;
2070
        size -= cur;
2071
        // PRF_STR_INT("Written size =", size);
2072
        if (size == 0)
2073
          break;
2074
        res = MtProgress_ProgressAdd(&me->mtc.mtProgress, 0, 0);
2075
        if (res != SZ_OK)
2076
          break;
2077
      }
2078
    }
2079
2080
    if (coder->codeRes != SZ_OK)
2081
      if (!me->props.ignoreErrors)
2082
      {
2083
        me->finishedDecoderIndex = coderIndex;
2084
        return res;
2085
      }
2086
2087
    RINOK(res);
2088
2089
    if (coder->inPreSize != coder->inCodeSize
2090
        || coder->blockPackTotal != coder->inCodeSize)
2091
    {
2092
      me->finishedDecoderIndex = coderIndex;
2093
      return SZ_OK;
2094
    }
2095
2096
    if (coder->parseState != MTDEC_PARSE_END)
2097
    {
2098
      *needContinue = True;
2099
      return SZ_OK;
2100
    }
2101
  }
2102
2103
  // (coder->state == MTDEC_PARSE_END) means that there are no other working threads
2104
  // so we can use mtc variables without lock
2105
2106
  PRF_STR_INT("Write MTDEC_PARSE_END", me->mtc.inProcessed);
2107
2108
  me->mtc.mtProgress.totalInSize = me->mtc.inProcessed;
2109
  {
2110
    CXzUnpacker *dec = &me->dec;
2111
    
2112
    PRF_STR_INT("PostSingle", srcSize);
2113
    
2114
    {
2115
      size_t srcProcessed = srcSize;
2116
      ECoderStatus status;
2117
      size_t outSizeCur = 0;
2118
      SRes res;
2119
      
2120
      // dec->decodeOnlyOneBlock = False;
2121
      dec->decodeToStreamSignature = True;
2122
2123
      me->mainDecoderWasCalled = True;
2124
2125
      if (coder->parsing_Truncated)
2126
      {
2127
        me->parsing_Truncated = True;
2128
        return SZ_OK;
2129
      }
2130
      
2131
      res = XzUnpacker_Code(dec,
2132
          NULL, &outSizeCur,
2133
          src, &srcProcessed,
2134
          me->mtc.readWasFinished, // srcFinished
2135
          CODER_FINISH_END, // CODER_FINISH_ANY,
2136
          &status);
2137
      
2138
      me->status = status;
2139
      me->codeRes = res;
2140
2141
      me->mtc.inProcessed += srcProcessed;
2142
      me->mtc.mtProgress.totalInSize = me->mtc.inProcessed;
2143
2144
      if (res != SZ_OK)
2145
      {
2146
        return S_OK;
2147
        // return res;
2148
      }
2149
      
2150
      if (dec->state == XZ_STATE_STREAM_HEADER)
2151
      {
2152
        *needContinue = True;
2153
        me->isBlockHeaderState_Parse = False;
2154
        me->isBlockHeaderState_Write = False;
2155
        {
2156
          Byte *crossBuf = MtDec_GetCrossBuff(&me->mtc);
2157
          if (!crossBuf)
2158
            return SZ_ERROR_MEM;
2159
          memcpy(crossBuf, src + srcProcessed, srcSize - srcProcessed);
2160
        }
2161
        me->mtc.crossStart = 0;
2162
        me->mtc.crossEnd = srcSize - srcProcessed;
2163
        return SZ_OK;
2164
      }
2165
      
2166
      if (status != CODER_STATUS_NEEDS_MORE_INPUT)
2167
      {
2168
        return E_FAIL;
2169
      }
2170
      
2171
      if (me->mtc.readWasFinished)
2172
      {
2173
        return SZ_OK;
2174
      }
2175
    }
2176
    
2177
    {
2178
      size_t inPos;
2179
      size_t inLim;
2180
      const Byte *inData;
2181
      UInt64 inProgressPrev = me->mtc.inProcessed;
2182
      
2183
      // XzDecMt_Prepare_InBuf_ST(p);
2184
      Byte *crossBuf = MtDec_GetCrossBuff(&me->mtc);
2185
      if (!crossBuf)
2186
        return SZ_ERROR_MEM;
2187
      
2188
      inPos = 0;
2189
      inLim = 0;
2190
      // outProcessed = 0;
2191
      
2192
      inData = crossBuf;
2193
      
2194
      for (;;)
2195
      {
2196
        SizeT inProcessed;
2197
        SizeT outProcessed;
2198
        ECoderStatus status;
2199
        SRes res;
2200
        
2201
        if (inPos == inLim)
2202
        {
2203
          if (!me->mtc.readWasFinished)
2204
          {
2205
            inPos = 0;
2206
            inLim = me->mtc.inBufSize;
2207
            me->mtc.readRes = ISeqInStream_Read(me->inStream, (void *)inData, &inLim);
2208
            me->mtc.readProcessed += inLim;
2209
            if (inLim == 0 || me->mtc.readRes != SZ_OK)
2210
              me->mtc.readWasFinished = True;
2211
          }
2212
        }
2213
        
2214
        inProcessed = inLim - inPos;
2215
        outProcessed = 0;
2216
2217
        res = XzUnpacker_Code(dec,
2218
            NULL, &outProcessed,
2219
            inData + inPos, &inProcessed,
2220
            (inProcessed == 0), // srcFinished
2221
            CODER_FINISH_END, &status);
2222
        
2223
        me->codeRes = res;
2224
        me->status = status;
2225
        inPos += inProcessed;
2226
        me->mtc.inProcessed += inProcessed;
2227
        me->mtc.mtProgress.totalInSize = me->mtc.inProcessed;
2228
2229
        if (res != SZ_OK)
2230
        {
2231
          return S_OK;
2232
          // return res;
2233
        }
2234
2235
        if (dec->state == XZ_STATE_STREAM_HEADER)
2236
        {
2237
          *needContinue = True;
2238
          me->mtc.crossStart = inPos;
2239
          me->mtc.crossEnd = inLim;
2240
          me->isBlockHeaderState_Parse = False;
2241
          me->isBlockHeaderState_Write = False;
2242
          return SZ_OK;
2243
        }
2244
        
2245
        if (status != CODER_STATUS_NEEDS_MORE_INPUT)
2246
          return E_FAIL;
2247
        
2248
        if (me->mtc.progress)
2249
        {
2250
          UInt64 inDelta = me->mtc.inProcessed - inProgressPrev;
2251
          if (inDelta >= (1 << 22))
2252
          {
2253
            RINOK(MtProgress_Progress_ST(&me->mtc.mtProgress));
2254
            inProgressPrev = me->mtc.inProcessed;
2255
          }
2256
        }
2257
        if (me->mtc.readWasFinished)
2258
          return SZ_OK;
2259
      }
2260
    }
2261
  }
2262
}
2263
2264
2265
#endif
2266
2267
2268
2269
void XzStatInfo_Clear(CXzStatInfo *p)
2270
0
{
2271
0
  p->InSize = 0;
2272
0
  p->OutSize = 0;
2273
  
2274
0
  p->NumStreams = 0;
2275
0
  p->NumBlocks = 0;
2276
  
2277
0
  p->UnpackSize_Defined = False;
2278
  
2279
0
  p->NumStreams_Defined = False;
2280
0
  p->NumBlocks_Defined = False;
2281
  
2282
  // p->IsArc = False;
2283
  // p->UnexpectedEnd = False;
2284
  // p->Unsupported = False;
2285
  // p->HeadersError = False;
2286
  // p->DataError = False;
2287
  // p->CrcError = False;
2288
2289
0
  p->DataAfterEnd = False;
2290
0
  p->DecodingTruncated = False;
2291
  
2292
0
  p->DecodeRes = SZ_OK;
2293
0
  p->ReadRes = SZ_OK;
2294
0
  p->ProgressRes = SZ_OK;
2295
2296
0
  p->CombinedRes = SZ_OK;
2297
0
  p->CombinedRes_Type = SZ_OK;
2298
0
}
2299
2300
2301
2302
2303
static SRes XzDecMt_Decode_ST(CXzDecMt *p
2304
    #ifndef _7ZIP_ST
2305
    , Bool tMode
2306
    #endif
2307
    , CXzStatInfo *stat)
2308
0
{
2309
0
  size_t outPos;
2310
0
  size_t inPos, inLim;
2311
0
  const Byte *inData;
2312
0
  UInt64 inPrev, outPrev;
2313
2314
0
  CXzUnpacker *dec;
2315
2316
  #ifndef _7ZIP_ST
2317
  if (tMode)
2318
  {
2319
    XzDecMt_FreeOutBufs(p);
2320
    tMode = MtDec_PrepareRead(&p->mtc);
2321
  }
2322
  #endif
2323
2324
0
  if (!p->outBuf || p->outBufSize != p->props.outStep_ST)
2325
0
  {
2326
0
    ISzAlloc_Free(p->allocMid, p->outBuf);
2327
0
    p->outBufSize = 0;
2328
0
    p->outBuf = (Byte *)ISzAlloc_Alloc(p->allocMid, p->props.outStep_ST);
2329
0
    if (!p->outBuf)
2330
0
      return SZ_ERROR_MEM;
2331
0
    p->outBufSize = p->props.outStep_ST;
2332
0
  }
2333
2334
0
  if (!p->inBuf || p->inBufSize != p->props.inBufSize_ST)
2335
0
  {
2336
0
    ISzAlloc_Free(p->allocMid, p->inBuf);
2337
0
    p->inBufSize = 0;
2338
0
    p->inBuf = (Byte *)ISzAlloc_Alloc(p->allocMid, p->props.inBufSize_ST);
2339
0
    if (!p->inBuf)
2340
0
      return SZ_ERROR_MEM;
2341
0
    p->inBufSize = p->props.inBufSize_ST;
2342
0
  }
2343
2344
0
  dec = &p->dec;
2345
0
  dec->decodeToStreamSignature = False;
2346
  // dec->decodeOnlyOneBlock = False;
2347
2348
0
  XzUnpacker_SetOutBuf(dec, NULL, 0);
2349
2350
0
  inPrev = p->inProcessed;
2351
0
  outPrev = p->outProcessed;
2352
2353
0
  inPos = 0;
2354
0
  inLim = 0;
2355
0
  inData = NULL;
2356
0
  outPos = 0;
2357
2358
0
  for (;;)
2359
0
  {
2360
0
    SizeT outSize;
2361
0
    Bool finished;
2362
0
    ECoderFinishMode finishMode;
2363
0
    SizeT inProcessed;
2364
0
    ECoderStatus status;
2365
0
    SRes res;
2366
2367
0
    SizeT outProcessed;
2368
2369
2370
2371
0
    if (inPos == inLim)
2372
0
    {
2373
      #ifndef _7ZIP_ST
2374
      if (tMode)
2375
      {
2376
        inData = MtDec_Read(&p->mtc, &inLim);
2377
        inPos = 0;
2378
        if (inData)
2379
          continue;
2380
        tMode = False;
2381
        inLim = 0;
2382
      }
2383
      #endif
2384
      
2385
0
      if (!p->readWasFinished)
2386
0
      {
2387
0
        inPos = 0;
2388
0
        inLim = p->inBufSize;
2389
0
        inData = p->inBuf;
2390
0
        p->readRes = ISeqInStream_Read(p->inStream, (void *)inData, &inLim);
2391
0
        p->readProcessed += inLim;
2392
0
        if (inLim == 0 || p->readRes != SZ_OK)
2393
0
          p->readWasFinished = True;
2394
0
      }
2395
0
    }
2396
2397
0
    outSize = p->props.outStep_ST - outPos;
2398
2399
0
    finishMode = CODER_FINISH_ANY;
2400
0
    if (p->outSize_Defined)
2401
0
    {
2402
0
      const UInt64 rem = p->outSize - p->outProcessed;
2403
0
      if (outSize >= rem)
2404
0
      {
2405
0
        outSize = (SizeT)rem;
2406
0
        if (p->finishMode)
2407
0
          finishMode = CODER_FINISH_END;
2408
0
      }
2409
0
    }
2410
2411
0
    inProcessed = inLim - inPos;
2412
0
    outProcessed = outSize;
2413
2414
0
    res = XzUnpacker_Code(dec, p->outBuf + outPos, &outProcessed,
2415
0
        inData + inPos, &inProcessed,
2416
0
        (inPos == inLim), // srcFinished
2417
0
        finishMode, &status);
2418
2419
0
    p->codeRes = res;
2420
0
    p->status = status;
2421
2422
0
    inPos += inProcessed;
2423
0
    outPos += outProcessed;
2424
0
    p->inProcessed += inProcessed;
2425
0
    p->outProcessed += outProcessed;
2426
2427
0
    finished = ((inProcessed == 0 && outProcessed == 0) || res != SZ_OK);
2428
2429
0
    if (finished || outProcessed >= outSize)
2430
0
      if (outPos != 0)
2431
0
      {
2432
0
        size_t written = ISeqOutStream_Write(p->outStream, p->outBuf, outPos);
2433
0
        p->outProcessed += written;
2434
0
        if (written != outPos)
2435
0
        {
2436
0
          stat->CombinedRes_Type = SZ_ERROR_WRITE;
2437
0
          return SZ_ERROR_WRITE;
2438
0
        }
2439
0
        outPos = 0;
2440
0
      }
2441
2442
0
    if (p->progress && res == SZ_OK)
2443
0
    {
2444
0
      UInt64 inDelta = p->inProcessed - inPrev;
2445
0
      UInt64 outDelta = p->outProcessed - outPrev;
2446
0
      if (inDelta >= (1 << 22) || outDelta >= (1 << 22))
2447
0
      {
2448
0
        res = ICompressProgress_Progress(p->progress, p->inProcessed, p->outProcessed);
2449
0
        if (res != SZ_OK)
2450
0
        {
2451
0
          stat->CombinedRes_Type = SZ_ERROR_PROGRESS;
2452
0
          stat->ProgressRes = res;
2453
0
          return res;
2454
0
        }
2455
0
        inPrev = p->inProcessed;
2456
0
        outPrev = p->outProcessed;
2457
0
      }
2458
0
    }
2459
2460
0
    if (finished)
2461
0
      return res;
2462
0
  }
2463
0
}
2464
2465
static SRes XzStatInfo_SetStat(const CXzUnpacker *dec,
2466
    int finishMode,
2467
    UInt64 readProcessed, UInt64 inProcessed,
2468
    SRes res, ECoderStatus status,
2469
    Bool decodingTruncated,
2470
    CXzStatInfo *stat)
2471
0
{
2472
0
  UInt64 extraSize;
2473
  
2474
0
  stat->DecodingTruncated = (Byte)(decodingTruncated ? 1 : 0);
2475
0
  stat->InSize = inProcessed;
2476
0
  stat->NumStreams = dec->numStartedStreams;
2477
0
  stat->NumBlocks = dec->numTotalBlocks;
2478
  
2479
0
  stat->UnpackSize_Defined = True;
2480
0
  stat->NumStreams_Defined = True;
2481
0
  stat->NumBlocks_Defined = True;
2482
  
2483
0
  extraSize = XzUnpacker_GetExtraSize(dec);
2484
  
2485
0
  if (res == SZ_OK)
2486
0
  {
2487
0
    if (status == CODER_STATUS_NEEDS_MORE_INPUT)
2488
0
    {
2489
      // CODER_STATUS_NEEDS_MORE_INPUT is expected status for correct xz streams
2490
0
      extraSize = 0;
2491
0
      if (!XzUnpacker_IsStreamWasFinished(dec))
2492
0
        res = SZ_ERROR_INPUT_EOF;
2493
0
    }
2494
0
    else if (!decodingTruncated || finishMode) // (status == CODER_STATUS_NOT_FINISHED)
2495
0
      res = SZ_ERROR_DATA;
2496
0
  }
2497
0
  else if (res == SZ_ERROR_NO_ARCHIVE)
2498
0
  {
2499
    /*
2500
    SZ_ERROR_NO_ARCHIVE is possible for 2 states:
2501
      XZ_STATE_STREAM_HEADER  - if bad signature or bad CRC
2502
      XZ_STATE_STREAM_PADDING - if non-zero padding data
2503
    extraSize / inProcessed don't include "bad" byte
2504
    */
2505
0
    if (inProcessed != extraSize) // if good streams before error
2506
0
      if (extraSize != 0 || readProcessed != inProcessed)
2507
0
      {
2508
0
        stat->DataAfterEnd = True;
2509
        // there is some good xz stream before. So we set SZ_OK
2510
0
        res = SZ_OK;
2511
0
      }
2512
0
  }
2513
  
2514
0
  stat->DecodeRes = res;
2515
2516
0
  stat->InSize -= extraSize;
2517
0
  return res;
2518
0
}
2519
2520
2521
SRes XzDecMt_Decode(CXzDecMtHandle pp,
2522
    const CXzDecMtProps *props,
2523
    const UInt64 *outDataSize, int finishMode,
2524
    ISeqOutStream *outStream,
2525
    // Byte *outBuf, size_t *outBufSize,
2526
    ISeqInStream *inStream,
2527
    // const Byte *inData, size_t inDataSize,
2528
    CXzStatInfo *stat,
2529
    int *isMT,
2530
    ICompressProgress *progress)
2531
0
{
2532
0
  CXzDecMt *p = (CXzDecMt *)pp;
2533
  #ifndef _7ZIP_ST
2534
  Bool tMode;
2535
  #endif
2536
2537
0
  XzStatInfo_Clear(stat);
2538
2539
0
  p->props = *props;
2540
2541
0
  p->inStream = inStream;
2542
0
  p->outStream = outStream;
2543
0
  p->progress = progress;
2544
  // p->stat = stat;
2545
2546
0
  p->outSize = 0;
2547
0
  p->outSize_Defined = False;
2548
0
  if (outDataSize)
2549
0
  {
2550
0
    p->outSize_Defined = True;
2551
0
    p->outSize = *outDataSize;
2552
0
  }
2553
2554
0
  p->finishMode = finishMode;
2555
2556
  // p->outSize = 457; p->outSize_Defined = True; p->finishMode = False; // for test
2557
2558
0
  p->writeRes = SZ_OK;
2559
0
  p->outProcessed = 0;
2560
0
  p->inProcessed = 0;
2561
0
  p->readProcessed = 0;
2562
0
  p->readWasFinished = False;
2563
2564
0
  p->codeRes = 0;
2565
0
  p->status = CODER_STATUS_NOT_SPECIFIED;
2566
2567
0
  if (!p->dec_created)
2568
0
  {
2569
0
    XzUnpacker_Construct(&p->dec, &p->alignOffsetAlloc.vt);
2570
0
    p->dec_created = True;
2571
0
  }
2572
0
  XzUnpacker_Init(&p->dec);
2573
  
2574
2575
0
  *isMT = False;
2576
2577
    /*
2578
    p->outBuf = NULL;
2579
    p->outBufSize = 0;
2580
    if (!outStream)
2581
    {
2582
      p->outBuf = outBuf;
2583
      p->outBufSize = *outBufSize;
2584
      *outBufSize = 0;
2585
    }
2586
    */
2587
2588
  
2589
  #ifndef _7ZIP_ST
2590
2591
  p->isBlockHeaderState_Parse = False;
2592
  p->isBlockHeaderState_Write = False;
2593
  // p->numBadBlocks = 0;
2594
  p->mainErrorCode = SZ_OK;
2595
  p->mainDecoderWasCalled = False;
2596
2597
  tMode = False;
2598
2599
  if (p->props.numThreads > 1)
2600
  {
2601
    IMtDecCallback vt;
2602
2603
    XzDecMt_FreeSt(p);
2604
2605
    p->outProcessed_Parse = 0;
2606
    p->parsing_Truncated = False;
2607
2608
    p->numStreams = 0;
2609
    p->numTotalBlocks = 0;
2610
    p->numBlocks = 0;
2611
    p->finishedDecoderIndex = -1;
2612
2613
    if (!p->mtc_WasConstructed)
2614
    {
2615
      p->mtc_WasConstructed = True;
2616
      MtDec_Construct(&p->mtc);
2617
    }
2618
    
2619
    p->mtc.mtCallback = &vt;
2620
    p->mtc.mtCallbackObject = p;
2621
2622
    p->mtc.progress = progress;
2623
    p->mtc.inStream = inStream;
2624
    p->mtc.alloc = &p->alignOffsetAlloc.vt;
2625
    // p->mtc.inData = inData;
2626
    // p->mtc.inDataSize = inDataSize;
2627
    p->mtc.inBufSize = p->props.inBufSize_MT;
2628
    // p->mtc.inBlockMax = p->props.inBlockMax;
2629
    p->mtc.numThreadsMax = p->props.numThreads;
2630
2631
    *isMT = True;
2632
2633
    vt.Parse = XzDecMt_Callback_Parse;
2634
    vt.PreCode = XzDecMt_Callback_PreCode;
2635
    vt.Code = XzDecMt_Callback_Code;
2636
    vt.Write = XzDecMt_Callback_Write;
2637
2638
    {
2639
      Bool needContinue;
2640
      
2641
      SRes res = MtDec_Code(&p->mtc);
2642
2643
      stat->InSize = p->mtc.inProcessed;
2644
2645
      p->inProcessed = p->mtc.inProcessed;
2646
      p->readRes = p->mtc.readRes;
2647
      p->readWasFinished = p->mtc.readWasFinished;
2648
      p->readProcessed = p->mtc.readProcessed;
2649
2650
      tMode = True;
2651
      needContinue = False;
2652
2653
      if (res == SZ_OK)
2654
      {
2655
        if (p->mtc.mtProgress.res != SZ_OK)
2656
        {
2657
          res = p->mtc.mtProgress.res;
2658
          stat->ProgressRes = res;
2659
          stat->CombinedRes_Type = SZ_ERROR_PROGRESS;
2660
        }
2661
        else
2662
          needContinue = p->mtc.needContinue;
2663
      }
2664
2665
      if (!needContinue)
2666
      {
2667
        SRes codeRes;
2668
        Bool truncated = False;
2669
        ECoderStatus status;
2670
        CXzUnpacker *dec;
2671
2672
        stat->OutSize = p->outProcessed;
2673
       
2674
        if (p->finishedDecoderIndex >= 0)
2675
        {
2676
          CXzDecMtThread *coder = &p->coders[(unsigned)p->finishedDecoderIndex];
2677
          codeRes = coder->codeRes;
2678
          dec = &coder->dec;
2679
          status = coder->status;
2680
        }
2681
        else if (p->mainDecoderWasCalled)
2682
        {
2683
          codeRes = p->codeRes;
2684
          dec = &p->dec;
2685
          status = p->status;
2686
          truncated = p->parsing_Truncated;
2687
        }
2688
        else
2689
          return E_FAIL;
2690
2691
        XzStatInfo_SetStat(dec, p->finishMode,
2692
            p->mtc.readProcessed, p->mtc.inProcessed,
2693
            codeRes, status,
2694
            truncated,
2695
            stat);
2696
2697
        if (res == SZ_OK)
2698
        {
2699
          if (p->writeRes != SZ_OK)
2700
          {
2701
            res = p->writeRes;
2702
            stat->CombinedRes_Type = SZ_ERROR_WRITE;
2703
          }
2704
          else if (p->mtc.readRes != SZ_OK && p->mtc.inProcessed == p->mtc.readProcessed)
2705
          {
2706
            res = p->mtc.readRes;
2707
            stat->ReadRes = res;
2708
            stat->CombinedRes_Type = SZ_ERROR_READ;
2709
          }
2710
          else if (p->mainErrorCode != SZ_OK)
2711
          {
2712
            res = p->mainErrorCode;
2713
          }
2714
        }
2715
2716
        stat->CombinedRes = res;
2717
        if (stat->CombinedRes_Type == SZ_OK)
2718
          stat->CombinedRes_Type = res;
2719
        return res;
2720
      }
2721
2722
      PRF_STR("----- decoding ST -----");
2723
    }
2724
  }
2725
2726
  #endif
2727
2728
2729
0
  *isMT = False;
2730
2731
0
  {
2732
0
    SRes res = XzDecMt_Decode_ST(p
2733
        #ifndef _7ZIP_ST
2734
        , tMode
2735
        #endif
2736
0
        , stat
2737
0
        );
2738
2739
0
    XzStatInfo_SetStat(&p->dec,
2740
0
        p->finishMode,
2741
0
        p->readProcessed, p->inProcessed,
2742
0
        p->codeRes, p->status,
2743
0
        False, // truncated
2744
0
        stat);
2745
2746
0
    if (res == SZ_OK)
2747
0
    {
2748
      /*
2749
      if (p->writeRes != SZ_OK)
2750
      {
2751
        res = p->writeRes;
2752
        stat->CombinedRes_Type = SZ_ERROR_WRITE;
2753
      }
2754
      else
2755
      */
2756
0
      if (p->readRes != SZ_OK && p->inProcessed == p->readProcessed)
2757
0
      {
2758
0
        res = p->readRes;
2759
0
        stat->ReadRes = res;
2760
0
        stat->CombinedRes_Type = SZ_ERROR_READ;
2761
0
      }
2762
      #ifndef _7ZIP_ST
2763
      else if (p->mainErrorCode != SZ_OK)
2764
        res = p->mainErrorCode;
2765
      #endif
2766
0
    }
2767
2768
0
    stat->CombinedRes = res;
2769
0
    if (stat->CombinedRes_Type == SZ_OK)
2770
0
      stat->CombinedRes_Type = res;
2771
0
    return res;
2772
0
  }
2773
0
}