Coverage Report

Created: 2024-07-27 06:13

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