Coverage Report

Created: 2024-07-27 06:17

/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
154k
#define CODER_BUF_SIZE ((size_t)1 << 17)
53
54
unsigned Xz_ReadVarInt(const Byte *p, size_t maxSize, UInt64 *value)
55
199k
{
56
199k
  unsigned i, limit;
57
199k
  *value = 0;
58
199k
  limit = (maxSize > 9) ? 9 : (unsigned)maxSize;
59
60
200k
  for (i = 0; i < limit;)
61
200k
  {
62
200k
    Byte b = p[i];
63
200k
    *value |= (UInt64)(b & 0x7F) << (7 * i++);
64
200k
    if ((b & 0x80) == 0)
65
199k
      return (b == 0 && i != 1) ? 0 : i;
66
200k
  }
67
73
  return 0;
68
199k
}
69
70
/* ---------- BraState ---------- */
71
72
123k
#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
14.5k
{
93
14.5k
  ISzAlloc_Free(alloc, pp);
94
14.5k
}
95
96
static SRes BraState_SetProps(void *pp, const Byte *props, size_t propSize, ISzAllocPtr alloc)
97
25.0k
{
98
25.0k
  CBraState *p = ((CBraState *)pp);
99
25.0k
  UNUSED_VAR(alloc);
100
25.0k
  p->ip = 0;
101
25.0k
  if (p->methodId == XZ_ID_Delta)
102
8.31k
  {
103
8.31k
    if (propSize != 1)
104
0
      return SZ_ERROR_UNSUPPORTED;
105
8.31k
    p->delta = (unsigned)props[0] + 1;
106
8.31k
  }
107
16.7k
  else
108
16.7k
  {
109
16.7k
    if (propSize == 4)
110
5.07k
    {
111
5.07k
      UInt32 v = GetUi32(props);
112
5.07k
      switch (p->methodId)
113
5.07k
      {
114
1.04k
        case XZ_ID_PPC:
115
1.69k
        case XZ_ID_ARM:
116
2.73k
        case XZ_ID_SPARC:
117
2.73k
          if ((v & 3) != 0)
118
0
            return SZ_ERROR_UNSUPPORTED;
119
2.73k
          break;
120
2.73k
        case XZ_ID_ARMT:
121
392
          if ((v & 1) != 0)
122
0
            return SZ_ERROR_UNSUPPORTED;
123
392
          break;
124
652
        case XZ_ID_IA64:
125
652
          if ((v & 0xF) != 0)
126
0
            return SZ_ERROR_UNSUPPORTED;
127
652
          break;
128
5.07k
      }
129
5.07k
      p->ip = v;
130
5.07k
    }
131
11.6k
    else if (propSize != 0)
132
0
      return SZ_ERROR_UNSUPPORTED;
133
16.7k
  }
134
25.0k
  return SZ_OK;
135
25.0k
}
136
137
static void BraState_Init(void *pp)
138
25.0k
{
139
25.0k
  CBraState *p = ((CBraState *)pp);
140
25.0k
  p->bufPos = p->bufConv = p->bufTotal = 0;
141
25.0k
  x86_Convert_Init(p->x86State);
142
25.0k
  if (p->methodId == XZ_ID_Delta)
143
8.31k
    Delta_Init(p->deltaState);
144
25.0k
}
145
146
147
34.7k
#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
75.8k
{
151
75.8k
  CBraState *p = ((CBraState *)pp);
152
75.8k
  switch (p->methodId)
153
75.8k
  {
154
20.6k
    case XZ_ID_Delta:
155
20.6k
      if (p->encodeMode)
156
4.01k
        Delta_Encode(p->deltaState, p->delta, data, size);
157
16.6k
      else
158
16.6k
        Delta_Decode(p->deltaState, p->delta, data, size);
159
20.6k
      break;
160
20.4k
    case XZ_ID_X86:
161
20.4k
      size = x86_Convert(data, size, p->ip, &p->x86State, p->encodeMode);
162
20.4k
      break;
163
10.1k
    CASE_BRA_CONV(PPC)
164
7.68k
    CASE_BRA_CONV(IA64)
165
3.69k
    CASE_BRA_CONV(ARM)
166
4.75k
    CASE_BRA_CONV(ARMT)
167
75.8k
    CASE_BRA_CONV(SPARC)
168
75.8k
  }
169
75.8k
  p->ip += (UInt32)size;
170
75.8k
  return size;
171
75.8k
}
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
60.3k
{
181
60.3k
  CBraState *p = ((CBraState *)pp);
182
60.3k
  SizeT destRem = *destLen;
183
60.3k
  SizeT srcRem = *srcLen;
184
60.3k
  UNUSED_VAR(finishMode);
185
186
60.3k
  *destLen = 0;
187
60.3k
  *srcLen = 0;
188
  // *wasFinished = False;
189
60.3k
  *status = CODER_STATUS_NOT_FINISHED;
190
  
191
193k
  while (destRem > 0)
192
190k
  {
193
190k
    if (p->bufPos != p->bufConv)
194
66.7k
    {
195
66.7k
      size_t size = p->bufConv - p->bufPos;
196
66.7k
      if (size > destRem)
197
151
        size = destRem;
198
66.7k
      memcpy(dest, p->buf + p->bufPos, size);
199
66.7k
      p->bufPos += size;
200
66.7k
      *destLen += size;
201
66.7k
      dest += size;
202
66.7k
      destRem -= size;
203
66.7k
      continue;
204
66.7k
    }
205
    
206
123k
    p->bufTotal -= p->bufPos;
207
123k
    memmove(p->buf, p->buf + p->bufPos, p->bufTotal);
208
123k
    p->bufPos = 0;
209
123k
    p->bufConv = 0;
210
123k
    {
211
123k
      size_t size = BRA_BUF_SIZE - p->bufTotal;
212
123k
      if (size > srcRem)
213
73.9k
        size = srcRem;
214
123k
      memcpy(p->buf + p->bufTotal, src, size);
215
123k
      *srcLen += size;
216
123k
      src += size;
217
123k
      srcRem -= size;
218
123k
      p->bufTotal += size;
219
123k
    }
220
123k
    if (p->bufTotal == 0)
221
47.8k
      break;
222
    
223
75.8k
    p->bufConv = BraState_Filter(pp, p->buf, p->bufTotal);
224
225
75.8k
    if (p->bufConv == 0)
226
14.7k
    {
227
14.7k
      if (!srcWasFinished)
228
9.23k
        break;
229
5.55k
      p->bufConv = p->bufTotal;
230
5.55k
    }
231
75.8k
  }
232
233
60.3k
  if (p->bufTotal == p->bufPos && srcRem == 0 && srcWasFinished)
234
40.5k
  {
235
40.5k
    *status = CODER_STATUS_FINISHED_WITH_MARK;
236
    // *wasFinished = 1;
237
40.5k
  }
238
239
60.3k
  return SZ_OK;
240
60.3k
}
241
242
243
SRes BraState_SetFromMethod(IStateCoder *p, UInt64 id, int encodeMode, ISzAllocPtr alloc)
244
14.5k
{
245
14.5k
  CBraState *decoder;
246
14.5k
  if (id < XZ_ID_Delta || id > XZ_ID_SPARC)
247
0
    return SZ_ERROR_UNSUPPORTED;
248
14.5k
  decoder = (CBraState *)p->p;
249
14.5k
  if (!decoder)
250
14.5k
  {
251
14.5k
    decoder = (CBraState *)ISzAlloc_Alloc(alloc, sizeof(CBraState));
252
14.5k
    if (!decoder)
253
0
      return SZ_ERROR_MEM;
254
14.5k
    p->p = decoder;
255
14.5k
    p->Free = BraState_Free;
256
14.5k
    p->SetProps = BraState_SetProps;
257
14.5k
    p->Init = BraState_Init;
258
14.5k
    p->Code2 = BraState_Code2;
259
14.5k
    p->Filter = BraState_Filter;
260
14.5k
  }
261
14.5k
  decoder->methodId = (UInt32)id;
262
14.5k
  decoder->encodeMode = encodeMode;
263
14.5k
  return SZ_OK;
264
14.5k
}
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
19.2k
{
350
19.2k
  CLzma2Dec_Spec *p = (CLzma2Dec_Spec *)pp;
351
19.2k
  if (p->outBufMode)
352
0
    Lzma2Dec_FreeProbs(&p->decoder, alloc);
353
19.2k
  else
354
19.2k
    Lzma2Dec_Free(&p->decoder, alloc);
355
19.2k
  ISzAlloc_Free(alloc, pp);
356
19.2k
}
357
358
static SRes Lzma2State_SetProps(void *pp, const Byte *props, size_t propSize, ISzAllocPtr alloc)
359
73.8k
{
360
73.8k
  if (propSize != 1)
361
0
    return SZ_ERROR_UNSUPPORTED;
362
73.8k
  {
363
73.8k
    CLzma2Dec_Spec *p = (CLzma2Dec_Spec *)pp;
364
73.8k
    if (p->outBufMode)
365
0
      return Lzma2Dec_AllocateProbs(&p->decoder, props[0], alloc);
366
73.8k
    else
367
73.8k
      return Lzma2Dec_Allocate(&p->decoder, props[0], alloc);
368
73.8k
  }
369
73.8k
}
370
371
static void Lzma2State_Init(void *pp)
372
73.7k
{
373
73.7k
  Lzma2Dec_Init(&((CLzma2Dec_Spec *)pp)->decoder);
374
73.7k
}
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
155k
{
387
155k
  CLzma2Dec_Spec *spec = (CLzma2Dec_Spec *)pp;
388
155k
  ELzmaStatus status2;
389
  /* ELzmaFinishMode fm = (finishMode == LZMA_FINISH_ANY) ? LZMA_FINISH_ANY : LZMA_FINISH_END; */
390
155k
  SRes res;
391
155k
  UNUSED_VAR(srcWasFinished);
392
155k
  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
155k
  else
400
155k
    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
155k
  *status = (ECoderStatus)status2;
404
155k
  return res;
405
155k
}
406
407
408
static SRes Lzma2State_SetFromMethod(IStateCoder *p, Byte *outBuf, size_t outBufSize, ISzAllocPtr alloc)
409
19.2k
{
410
19.2k
  CLzma2Dec_Spec *spec = (CLzma2Dec_Spec *)p->p;
411
19.2k
  if (!spec)
412
19.2k
  {
413
19.2k
    spec = (CLzma2Dec_Spec *)ISzAlloc_Alloc(alloc, sizeof(CLzma2Dec_Spec));
414
19.2k
    if (!spec)
415
0
      return SZ_ERROR_MEM;
416
19.2k
    p->p = spec;
417
19.2k
    p->Free = Lzma2State_Free;
418
19.2k
    p->SetProps = Lzma2State_SetProps;
419
19.2k
    p->Init = Lzma2State_Init;
420
19.2k
    p->Code2 = Lzma2State_Code2;
421
19.2k
    p->Filter = NULL;
422
19.2k
    Lzma2Dec_Construct(&spec->decoder);
423
19.2k
  }
424
19.2k
  spec->outBufMode = False;
425
19.2k
  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
19.2k
  return SZ_OK;
432
19.2k
}
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
15.0k
{
452
15.0k
  unsigned i;
453
15.0k
  p->alloc = alloc;
454
15.0k
  p->buf = NULL;
455
15.0k
  p->numCoders = 0;
456
  
457
15.0k
  p->outBufSize = 0;
458
15.0k
  p->outBuf = NULL;
459
  // p->SingleBufMode = False;
460
461
75.1k
  for (i = 0; i < MIXCODER_NUM_FILTERS_MAX; i++)
462
60.1k
    p->coders[i].p = NULL;
463
15.0k
}
464
465
466
static void MixCoder_Free(CMixCoder *p)
467
34.2k
{
468
34.2k
  unsigned i;
469
34.2k
  p->numCoders = 0;
470
171k
  for (i = 0; i < MIXCODER_NUM_FILTERS_MAX; i++)
471
137k
  {
472
137k
    IStateCoder *sc = &p->coders[i];
473
137k
    if (sc->p)
474
30.6k
    {
475
30.6k
      sc->Free(sc->p, p->alloc);
476
30.6k
      sc->p = NULL;
477
30.6k
    }
478
137k
  }
479
34.2k
  if (p->buf)
480
10.8k
  {
481
10.8k
    ISzAlloc_Free(p->alloc, p->buf);
482
10.8k
    p->buf = NULL; /* 9.31: the BUG was fixed */
483
10.8k
  }
484
34.2k
}
485
486
static void MixCoder_Init(CMixCoder *p)
487
73.7k
{
488
73.7k
  unsigned i;
489
295k
  for (i = 0; i < MIXCODER_NUM_FILTERS_MAX - 1; i++)
490
221k
  {
491
221k
    p->size[i] = 0;
492
221k
    p->pos[i] = 0;
493
221k
    p->finished[i] = 0;
494
221k
  }
495
169k
  for (i = 0; i < p->numCoders; i++)
496
95.6k
  {
497
95.6k
    IStateCoder *coder = &p->coders[i];
498
95.6k
    coder->Init(coder->p);
499
95.6k
    p->results[i] = SZ_OK;
500
95.6k
  }
501
73.7k
  p->outWritten = 0;
502
73.7k
  p->wasFinished = False;
503
73.7k
  p->res = SZ_OK;
504
73.7k
  p->status = CODER_STATUS_NOT_SPECIFIED;
505
73.7k
}
506
507
508
static SRes MixCoder_SetFromMethod(CMixCoder *p, unsigned coderIndex, UInt64 methodId, Byte *outBuf, size_t outBufSize)
509
30.6k
{
510
30.6k
  IStateCoder *sc = &p->coders[coderIndex];
511
30.6k
  p->ids[coderIndex] = methodId;
512
30.6k
  switch (methodId)
513
30.6k
  {
514
19.2k
    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
30.6k
  }
519
11.3k
  if (coderIndex == 0)
520
0
    return SZ_ERROR_UNSUPPORTED;
521
11.3k
  return BraState_SetFromMethod(sc, methodId, 0, p->alloc);
522
11.3k
}
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
79.8k
{
552
79.8k
  SizeT destLenOrig = *destLen;
553
79.8k
  SizeT srcLenOrig = *srcLen;
554
555
79.8k
  *destLen = 0;
556
79.8k
  *srcLen = 0;
557
558
79.8k
  if (p->wasFinished)
559
0
    return p->res;
560
  
561
79.8k
  p->status = CODER_STATUS_NOT_FINISHED;
562
563
  // if (p->SingleBufMode)
564
79.8k
  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
79.8k
  PRF_STR("standard mix");
625
626
79.8k
  if (p->numCoders != 1)
627
23.1k
  {
628
23.1k
    if (!p->buf)
629
10.8k
    {
630
10.8k
      p->buf = (Byte *)ISzAlloc_Alloc(p->alloc, CODER_BUF_SIZE * (MIXCODER_NUM_FILTERS_MAX - 1));
631
10.8k
      if (!p->buf)
632
0
        return SZ_ERROR_MEM;
633
10.8k
    }
634
    
635
23.1k
    finishMode = CODER_FINISH_ANY;
636
23.1k
  }
637
638
79.8k
  for (;;)
639
157k
  {
640
157k
    BoolInt processed = False;
641
157k
    BoolInt allFinished = True;
642
157k
    SRes resMain = SZ_OK;
643
157k
    unsigned i;
644
645
157k
    p->status = CODER_STATUS_NOT_FINISHED;
646
    /*
647
    if (p->numCoders == 1 && *destLen == destLenOrig && finishMode == LZMA_FINISH_ANY)
648
      break;
649
    */
650
651
367k
    for (i = 0; i < p->numCoders; i++)
652
210k
    {
653
210k
      SRes res;
654
210k
      IStateCoder *coder = &p->coders[i];
655
210k
      Byte *dest2;
656
210k
      SizeT destLen2, srcLen2; // destLen2_Orig;
657
210k
      const Byte *src2;
658
210k
      int srcFinished2;
659
210k
      int encodingWasFinished;
660
210k
      ECoderStatus status2;
661
      
662
210k
      if (i == 0)
663
157k
      {
664
157k
        src2 = src;
665
157k
        srcLen2 = srcLenOrig - *srcLen;
666
157k
        srcFinished2 = srcWasFinished;
667
157k
      }
668
52.1k
      else
669
52.1k
      {
670
52.1k
        size_t k = i - 1;
671
52.1k
        src2 = p->buf + (CODER_BUF_SIZE * k) + p->pos[k];
672
52.1k
        srcLen2 = p->size[k] - p->pos[k];
673
52.1k
        srcFinished2 = p->finished[k];
674
52.1k
      }
675
      
676
210k
      if (i == p->numCoders - 1)
677
157k
      {
678
157k
        dest2 = dest;
679
157k
        destLen2 = destLenOrig - *destLen;
680
157k
      }
681
52.1k
      else
682
52.1k
      {
683
52.1k
        if (p->pos[i] != p->size[i])
684
915
          continue;
685
51.2k
        dest2 = p->buf + (CODER_BUF_SIZE * i);
686
51.2k
        destLen2 = CODER_BUF_SIZE;
687
51.2k
      }
688
      
689
      // destLen2_Orig = destLen2;
690
      
691
209k
      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
207k
      res = coder->Code2(coder->p,
699
207k
          dest2, &destLen2,
700
207k
          src2, &srcLen2, srcFinished2,
701
207k
          finishMode,
702
          // &encodingWasFinished,
703
207k
          &status2);
704
705
207k
      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
207k
      encodingWasFinished = (status2 == CODER_STATUS_FINISHED_WITH_MARK);
713
      
714
207k
      if (!encodingWasFinished)
715
36.6k
      {
716
36.6k
        allFinished = False;
717
36.6k
        if (p->numCoders == 1 && res == SZ_OK)
718
5.82k
          p->status = status2;
719
36.6k
      }
720
721
207k
      if (i == 0)
722
155k
      {
723
155k
        *srcLen += srcLen2;
724
155k
        src += srcLen2;
725
155k
      }
726
52.0k
      else
727
52.0k
        p->pos[(size_t)i - 1] += srcLen2;
728
729
207k
      if (i == p->numCoders - 1)
730
157k
      {
731
157k
        *destLen += destLen2;
732
157k
        dest += destLen2;
733
157k
      }
734
50.4k
      else
735
50.4k
      {
736
50.4k
        p->size[i] = destLen2;
737
50.4k
        p->pos[i] = 0;
738
50.4k
        p->finished[i] = encodingWasFinished;
739
50.4k
      }
740
      
741
207k
      if (destLen2 != 0 || srcLen2 != 0)
742
90.3k
        processed = True;
743
207k
    }
744
    
745
157k
    if (!processed)
746
79.8k
    {
747
79.8k
      if (allFinished)
748
68.3k
        p->status = CODER_STATUS_FINISHED_WITH_MARK;
749
79.8k
      return resMain;
750
79.8k
    }
751
157k
  }
752
79.8k
}
753
754
755
SRes Xz_ParseHeader(CXzStreamFlags *p, const Byte *buf)
756
17.4k
{
757
17.4k
  *p = (CXzStreamFlags)GetBe16(buf + XZ_SIG_SIZE);
758
17.4k
  if (CrcCalc(buf + XZ_SIG_SIZE, XZ_STREAM_FLAGS_SIZE) !=
759
17.4k
      GetUi32(buf + XZ_SIG_SIZE + XZ_STREAM_FLAGS_SIZE))
760
51
    return SZ_ERROR_NO_ARCHIVE;
761
17.4k
  return XzFlags_IsSupported(*p) ? SZ_OK : SZ_ERROR_UNSUPPORTED;
762
17.4k
}
763
764
static BoolInt Xz_CheckFooter(CXzStreamFlags flags, UInt64 indexSize, const Byte *buf)
765
10.4k
{
766
10.4k
  return indexSize == (((UInt64)GetUi32(buf + 4) + 1) << 2)
767
10.4k
      && GetUi32(buf) == CrcCalc(buf + 4, 6)
768
10.4k
      && flags == GetBe16(buf + 8)
769
10.4k
      && buf[10] == XZ_FOOTER_SIG_0
770
10.4k
      && buf[11] == XZ_FOOTER_SIG_1;
771
10.4k
}
772
773
#define READ_VARINT_AND_CHECK(buf, pos, size, res) \
774
199k
  { unsigned s = Xz_ReadVarInt(buf + pos, size - pos, res); \
775
199k
  if (s == 0) return SZ_ERROR_ARCHIVE; pos += s; }
776
777
778
static BoolInt XzBlock_AreSupportedFilters(const CXzBlock *p)
779
73.8k
{
780
73.8k
  unsigned numFilters = XzBlock_GetNumFilters(p) - 1;
781
73.8k
  unsigned i;
782
73.8k
  {
783
73.8k
    const CXzFilter *f = &p->filters[numFilters];
784
73.8k
    if (f->id != XZ_ID_LZMA2 || f->propsSize != 1 || f->props[0] > 40)
785
44
      return False;
786
73.8k
  }
787
788
95.7k
  for (i = 0; i < numFilters; i++)
789
21.9k
  {
790
21.9k
    const CXzFilter *f = &p->filters[i];
791
21.9k
    if (f->id == XZ_ID_Delta)
792
7.67k
    {
793
7.67k
      if (f->propsSize != 1)
794
2
        return False;
795
7.67k
    }
796
14.2k
    else if (f->id < XZ_ID_Delta
797
14.2k
        || f->id > XZ_ID_SPARC
798
14.2k
        || (f->propsSize != 0 && f->propsSize != 4))
799
13
      return False;
800
21.9k
  }
801
73.8k
  return True;
802
73.8k
}
803
804
805
SRes XzBlock_Parse(CXzBlock *p, const Byte *header)
806
74.1k
{
807
74.1k
  unsigned pos;
808
74.1k
  unsigned numFilters, i;
809
74.1k
  unsigned headerSize = (unsigned)header[0] << 2;
810
811
  /* (headerSize != 0) : another code checks */
812
813
74.1k
  if (CrcCalc(header, headerSize) != GetUi32(header + headerSize))
814
79
    return SZ_ERROR_ARCHIVE;
815
816
74.0k
  pos = 1;
817
74.0k
  p->flags = header[pos++];
818
819
74.0k
  p->packSize = (UInt64)(Int64)-1;
820
74.0k
  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
74.0k
  p->unpackSize = (UInt64)(Int64)-1;
828
74.0k
  if (XzBlock_HasUnpackSize(p))
829
74.0k
    READ_VARINT_AND_CHECK(header, pos, headerSize, &p->unpackSize);
830
831
74.0k
  numFilters = XzBlock_GetNumFilters(p);
832
169k
  for (i = 0; i < numFilters; i++)
833
96.0k
  {
834
96.0k
    CXzFilter *filter = p->filters + i;
835
96.0k
    UInt64 size;
836
96.0k
    READ_VARINT_AND_CHECK(header, pos, headerSize, &filter->id);
837
95.9k
    READ_VARINT_AND_CHECK(header, pos, headerSize, &size);
838
95.9k
    if (size > headerSize - pos || size > XZ_FILTER_PROPS_SIZE_MAX)
839
107
      return SZ_ERROR_ARCHIVE;
840
95.8k
    filter->propsSize = (UInt32)size;
841
95.8k
    memcpy(filter->props, header + pos, (size_t)size);
842
95.8k
    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
95.8k
  }
853
854
73.8k
  if (XzBlock_HasUnsupportedFlags(p))
855
8
    return SZ_ERROR_UNSUPPORTED;
856
857
246k
  while (pos < headerSize)
858
173k
    if (header[pos++] != 0)
859
7
      return SZ_ERROR_ARCHIVE;
860
73.8k
  return SZ_OK;
861
73.8k
}
862
863
864
865
866
static SRes XzDecMix_Init(CMixCoder *p, const CXzBlock *block, Byte *outBuf, size_t outBufSize)
867
73.8k
{
868
73.8k
  unsigned i;
869
73.8k
  BoolInt needReInit = True;
870
73.8k
  unsigned numFilters = XzBlock_GetNumFilters(block);
871
872
73.8k
  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
73.8k
  p->outBuf = outBuf;
885
73.8k
  p->outBufSize = outBufSize;
886
887
  // p->SingleBufMode = False;
888
  // outBuf = NULL;
889
  
890
73.8k
  if (needReInit)
891
19.2k
  {
892
19.2k
    MixCoder_Free(p);
893
49.8k
    for (i = 0; i < numFilters; i++)
894
30.6k
    {
895
30.6k
      RINOK(MixCoder_SetFromMethod(p, i, block->filters[numFilters - 1 - i].id, outBuf, outBufSize));
896
30.6k
    }
897
19.2k
    p->numCoders = numFilters;
898
19.2k
  }
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
169k
  for (i = 0; i < numFilters; i++)
905
95.6k
  {
906
95.6k
    const CXzFilter *f = &block->filters[numFilters - 1 - i];
907
95.6k
    IStateCoder *sc = &p->coders[i];
908
95.6k
    RINOK(sc->SetProps(sc->p, f->props, f->propsSize, p->alloc));
909
95.6k
  }
910
  
911
73.7k
  MixCoder_Init(p);
912
73.7k
  return SZ_OK;
913
73.8k
}
914
915
916
917
void XzUnpacker_Init(CXzUnpacker *p)
918
30.0k
{
919
30.0k
  p->state = XZ_STATE_STREAM_HEADER;
920
30.0k
  p->pos = 0;
921
30.0k
  p->numStartedStreams = 0;
922
30.0k
  p->numFinishedStreams = 0;
923
30.0k
  p->numTotalBlocks = 0;
924
30.0k
  p->padSize = 0;
925
30.0k
  p->decodeOnlyOneBlock = 0;
926
927
30.0k
  p->parseMode = False;
928
30.0k
  p->decodeToStreamSignature = False;
929
930
  // p->outBuf = NULL;
931
  // p->outBufSize = 0;
932
30.0k
  p->outDataWritten = 0;
933
30.0k
}
934
935
936
void XzUnpacker_SetOutBuf(CXzUnpacker *p, Byte *outBuf, size_t outBufSize)
937
15.0k
{
938
15.0k
  p->outBuf = outBuf;
939
15.0k
  p->outBufSize = outBufSize;
940
15.0k
}
941
942
943
void XzUnpacker_Construct(CXzUnpacker *p, ISzAllocPtr alloc)
944
15.0k
{
945
15.0k
  MixCoder_Construct(&p->decoder, alloc);
946
15.0k
  p->outBuf = NULL;
947
15.0k
  p->outBufSize = 0;
948
15.0k
  XzUnpacker_Init(p);
949
15.0k
}
950
951
952
void XzUnpacker_Free(CXzUnpacker *p)
953
15.0k
{
954
15.0k
  MixCoder_Free(&p->decoder);
955
15.0k
}
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
67.9k
{
971
67.9k
  Byte temp[32];
972
67.9k
  unsigned num = Xz_WriteVarInt(temp, packSize);
973
67.9k
  num += Xz_WriteVarInt(temp + num, unpackSize);
974
67.9k
  Sha256_Update(&p->sha, temp, num);
975
67.9k
  p->indexSize += num;
976
67.9k
  p->numBlocks++;
977
67.9k
}
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
29.2k
{
985
29.2k
  SizeT destLenOrig = *destLen;
986
29.2k
  SizeT srcLenOrig = *srcLen;
987
29.2k
  *destLen = 0;
988
29.2k
  *srcLen = 0;
989
29.2k
  *status = CODER_STATUS_NOT_SPECIFIED;
990
991
29.2k
  for (;;)
992
5.90M
  {
993
5.90M
    SizeT srcRem;
994
995
5.90M
    if (p->state == XZ_STATE_BLOCK)
996
79.8k
    {
997
79.8k
      SizeT destLen2 = destLenOrig - *destLen;
998
79.8k
      SizeT srcLen2 = srcLenOrig - *srcLen;
999
79.8k
      SRes res;
1000
1001
79.8k
      ECoderFinishMode finishMode2 = finishMode;
1002
79.8k
      BoolInt srcFinished2 = srcFinished;
1003
79.8k
      BoolInt destFinish = False;
1004
1005
79.8k
      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
79.8k
      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
79.8k
      {
1037
79.8k
        res = MixCoder_Code(&p->decoder,
1038
79.8k
            (p->outBuf ? NULL : dest), &destLen2, destFinish,
1039
79.8k
            src, &srcLen2, srcFinished2,
1040
79.8k
            finishMode2);
1041
        
1042
79.8k
        *status = p->decoder.status;
1043
79.8k
        XzCheck_Update(&p->check, (p->outBuf ? p->outBuf + p->outDataWritten : dest), destLen2);
1044
79.8k
        if (!p->outBuf)
1045
79.8k
          dest += destLen2;
1046
79.8k
        p->outDataWritten += destLen2;
1047
79.8k
      }
1048
      
1049
79.8k
      (*srcLen) += srcLen2;
1050
79.8k
      src += srcLen2;
1051
79.8k
      p->packSize += srcLen2;
1052
79.8k
      (*destLen) += destLen2;
1053
79.8k
      p->unpackSize += destLen2;
1054
1055
79.8k
      RINOK(res);
1056
1057
78.6k
      if (*status != CODER_STATUS_FINISHED_WITH_MARK)
1058
10.6k
      {
1059
10.6k
        if (p->block.packSize == p->packSize
1060
10.6k
            && *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
10.6k
        return SZ_OK;
1068
10.6k
      }
1069
67.9k
      {
1070
67.9k
        XzUnpacker_UpdateIndex(p, XzUnpacker_GetPackSizeForIndex(p), p->unpackSize);
1071
67.9k
        p->state = XZ_STATE_BLOCK_FOOTER;
1072
67.9k
        p->pos = 0;
1073
67.9k
        p->alignPos = 0;
1074
67.9k
        *status = CODER_STATUS_NOT_SPECIFIED;
1075
1076
67.9k
        if ((p->block.packSize != (UInt64)(Int64)-1 && p->block.packSize != p->packSize)
1077
67.9k
           || (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
67.9k
      }
1083
      // continue;
1084
67.9k
    }
1085
1086
5.89M
    srcRem = srcLenOrig - *srcLen;
1087
1088
    // XZ_STATE_BLOCK_FOOTER can transit to XZ_STATE_BLOCK_HEADER without input bytes
1089
5.89M
    if (srcRem == 0 && p->state != XZ_STATE_BLOCK_FOOTER)
1090
15.9k
    {
1091
15.9k
      *status = CODER_STATUS_NEEDS_MORE_INPUT;
1092
15.9k
      return SZ_OK;
1093
15.9k
    }
1094
1095
5.87M
    switch (p->state)
1096
5.87M
    {
1097
227k
      case XZ_STATE_STREAM_HEADER:
1098
227k
      {
1099
227k
        if (p->pos < XZ_STREAM_HEADER_SIZE)
1100
209k
        {
1101
209k
          if (p->pos < XZ_SIG_SIZE && *src != XZ_SIG[p->pos])
1102
77
            return SZ_ERROR_NO_ARCHIVE;
1103
209k
          if (p->decodeToStreamSignature)
1104
0
            return SZ_OK;
1105
209k
          p->buf[p->pos++] = *src++;
1106
209k
          (*srcLen)++;
1107
209k
        }
1108
17.4k
        else
1109
17.4k
        {
1110
17.4k
          RINOK(Xz_ParseHeader(&p->streamFlags, p->buf));
1111
17.4k
          p->numStartedStreams++;
1112
17.4k
          p->indexSize = 0;
1113
17.4k
          p->numBlocks = 0;
1114
17.4k
          Sha256_Init(&p->sha);
1115
17.4k
          p->state = XZ_STATE_BLOCK_HEADER;
1116
17.4k
          p->pos = 0;
1117
17.4k
        }
1118
227k
        break;
1119
227k
      }
1120
1121
233k
      case XZ_STATE_BLOCK_HEADER:
1122
233k
      {
1123
233k
        if (p->pos == 0)
1124
84.8k
        {
1125
84.8k
          p->buf[p->pos++] = *src++;
1126
84.8k
          (*srcLen)++;
1127
84.8k
          if (p->buf[0] == 0)
1128
10.7k
          {
1129
10.7k
            if (p->decodeOnlyOneBlock)
1130
0
              return SZ_ERROR_DATA;
1131
10.7k
            p->indexPreSize = 1 + Xz_WriteVarInt(p->buf + 1, p->numBlocks);
1132
10.7k
            p->indexPos = p->indexPreSize;
1133
10.7k
            p->indexSize += p->indexPreSize;
1134
10.7k
            Sha256_Final(&p->sha, p->shaDigest);
1135
10.7k
            Sha256_Init(&p->sha);
1136
10.7k
            p->crc = CrcUpdate(CRC_INIT_VAL, p->buf, p->indexPreSize);
1137
10.7k
            p->state = XZ_STATE_STREAM_INDEX;
1138
10.7k
            break;
1139
10.7k
          }
1140
74.1k
          p->blockHeaderSize = ((UInt32)p->buf[0] << 2) + 4;
1141
74.1k
          break;
1142
84.8k
        }
1143
        
1144
148k
        if (p->pos != p->blockHeaderSize)
1145
74.1k
        {
1146
74.1k
          UInt32 cur = p->blockHeaderSize - p->pos;
1147
74.1k
          if (cur > srcRem)
1148
16
            cur = (UInt32)srcRem;
1149
74.1k
          memcpy(p->buf + p->pos, src, cur);
1150
74.1k
          p->pos += cur;
1151
74.1k
          (*srcLen) += cur;
1152
74.1k
          src += cur;
1153
74.1k
        }
1154
74.1k
        else
1155
74.1k
        {
1156
74.1k
          RINOK(XzBlock_Parse(&p->block, p->buf));
1157
73.8k
          if (!XzBlock_AreSupportedFilters(&p->block))
1158
59
            return SZ_ERROR_UNSUPPORTED;
1159
73.8k
          p->numTotalBlocks++;
1160
73.8k
          p->state = XZ_STATE_BLOCK;
1161
73.8k
          p->packSize = 0;
1162
73.8k
          p->unpackSize = 0;
1163
73.8k
          XzCheck_Init(&p->check, XzFlags_GetCheckType(p->streamFlags));
1164
73.8k
          if (p->parseMode)
1165
0
          {
1166
0
            p->headerParsedOk = True;
1167
0
            return SZ_OK;
1168
0
          }
1169
73.8k
          RINOK(XzDecMix_Init(&p->decoder, &p->block, p->outBuf, p->outBufSize));
1170
73.7k
        }
1171
147k
        break;
1172
148k
      }
1173
1174
147k
      case XZ_STATE_BLOCK_FOOTER:
1175
129k
      {
1176
129k
        if ((((unsigned)p->packSize + p->alignPos) & 3) != 0)
1177
61.3k
        {
1178
61.3k
          if (srcRem == 0)
1179
260
          {
1180
260
            *status = CODER_STATUS_NEEDS_MORE_INPUT;
1181
260
            return SZ_OK;
1182
260
          }
1183
61.0k
          (*srcLen)++;
1184
61.0k
          p->alignPos++;
1185
61.0k
          if (*src++ != 0)
1186
22
            return SZ_ERROR_CRC;
1187
61.0k
        }
1188
67.7k
        else
1189
67.7k
        {
1190
67.7k
          UInt32 checkSize = XzFlags_GetCheckSize(p->streamFlags);
1191
67.7k
          UInt32 cur = checkSize - p->pos;
1192
67.7k
          if (cur != 0)
1193
9.89k
          {
1194
9.89k
            if (srcRem == 0)
1195
72
            {
1196
72
              *status = CODER_STATUS_NEEDS_MORE_INPUT;
1197
72
              return SZ_OK;
1198
72
            }
1199
9.81k
            if (cur > srcRem)
1200
29
              cur = (UInt32)srcRem;
1201
9.81k
            memcpy(p->buf + p->pos, src, cur);
1202
9.81k
            p->pos += cur;
1203
9.81k
            (*srcLen) += cur;
1204
9.81k
            src += cur;
1205
9.81k
            if (checkSize != p->pos)
1206
29
              break;
1207
9.81k
          }
1208
67.6k
          {
1209
67.6k
            Byte digest[XZ_CHECK_SIZE_MAX];
1210
67.6k
            p->state = XZ_STATE_BLOCK_HEADER;
1211
67.6k
            p->pos = 0;
1212
67.6k
            if (XzCheck_Final(&p->check, digest) && memcmp(digest, p->buf, checkSize) != 0)
1213
173
              return SZ_ERROR_CRC;
1214
67.5k
            if (p->decodeOnlyOneBlock)
1215
0
            {
1216
0
              *status = CODER_STATUS_FINISHED_WITH_MARK;
1217
0
              return SZ_OK;
1218
0
            }
1219
67.5k
          }
1220
67.5k
        }
1221
128k
        break;
1222
129k
      }
1223
1224
128k
      case XZ_STATE_STREAM_INDEX:
1225
39.5k
      {
1226
39.5k
        if (p->pos < p->indexPreSize)
1227
10.6k
        {
1228
10.6k
          (*srcLen)++;
1229
10.6k
          if (*src++ != p->buf[p->pos++])
1230
26
            return SZ_ERROR_CRC;
1231
10.6k
        }
1232
28.8k
        else
1233
28.8k
        {
1234
28.8k
          if (p->indexPos < p->indexSize)
1235
8.23k
          {
1236
8.23k
            UInt64 cur = p->indexSize - p->indexPos;
1237
8.23k
            if (srcRem > cur)
1238
8.21k
              srcRem = (SizeT)cur;
1239
8.23k
            p->crc = CrcUpdate(p->crc, src, srcRem);
1240
8.23k
            Sha256_Update(&p->sha, src, srcRem);
1241
8.23k
            (*srcLen) += srcRem;
1242
8.23k
            src += srcRem;
1243
8.23k
            p->indexPos += srcRem;
1244
8.23k
          }
1245
20.6k
          else if ((p->indexPos & 3) != 0)
1246
10.0k
          {
1247
10.0k
            Byte b = *src++;
1248
10.0k
            p->crc = CRC_UPDATE_BYTE(p->crc, b);
1249
10.0k
            (*srcLen)++;
1250
10.0k
            p->indexPos++;
1251
10.0k
            p->indexSize++;
1252
10.0k
            if (b != 0)
1253
8
              return SZ_ERROR_CRC;
1254
10.0k
          }
1255
10.6k
          else
1256
10.6k
          {
1257
10.6k
            Byte digest[SHA256_DIGEST_SIZE];
1258
10.6k
            p->state = XZ_STATE_STREAM_INDEX_CRC;
1259
10.6k
            p->indexSize += 4;
1260
10.6k
            p->pos = 0;
1261
10.6k
            Sha256_Final(&p->sha, digest);
1262
10.6k
            if (memcmp(digest, p->shaDigest, SHA256_DIGEST_SIZE) != 0)
1263
59
              return SZ_ERROR_CRC;
1264
10.6k
          }
1265
28.8k
        }
1266
39.4k
        break;
1267
39.5k
      }
1268
1269
52.7k
      case XZ_STATE_STREAM_INDEX_CRC:
1270
52.7k
      {
1271
52.7k
        if (p->pos < 4)
1272
42.2k
        {
1273
42.2k
          (*srcLen)++;
1274
42.2k
          p->buf[p->pos++] = *src++;
1275
42.2k
        }
1276
10.5k
        else
1277
10.5k
        {
1278
10.5k
          p->state = XZ_STATE_STREAM_FOOTER;
1279
10.5k
          p->pos = 0;
1280
10.5k
          if (CRC_GET_DIGEST(p->crc) != GetUi32(p->buf))
1281
48
            return SZ_ERROR_CRC;
1282
10.5k
        }
1283
52.7k
        break;
1284
52.7k
      }
1285
1286
52.7k
      case XZ_STATE_STREAM_FOOTER:
1287
10.5k
      {
1288
10.5k
        UInt32 cur = XZ_STREAM_FOOTER_SIZE - p->pos;
1289
10.5k
        if (cur > srcRem)
1290
20
          cur = (UInt32)srcRem;
1291
10.5k
        memcpy(p->buf + p->pos, src, cur);
1292
10.5k
        p->pos += cur;
1293
10.5k
        (*srcLen) += cur;
1294
10.5k
        src += cur;
1295
10.5k
        if (p->pos == XZ_STREAM_FOOTER_SIZE)
1296
10.4k
        {
1297
10.4k
          p->state = XZ_STATE_STREAM_PADDING;
1298
10.4k
          p->numFinishedStreams++;
1299
10.4k
          p->padSize = 0;
1300
10.4k
          if (!Xz_CheckFooter(p->streamFlags, p->indexSize, p->buf))
1301
154
            return SZ_ERROR_CRC;
1302
10.4k
        }
1303
10.3k
        break;
1304
10.5k
      }
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.87M
    }
1326
5.87M
  }
1327
  /*
1328
  if (p->state == XZ_STATE_FINISHED)
1329
    *status = CODER_STATUS_FINISHED_WITH_MARK;
1330
  return SZ_OK;
1331
  */
1332
29.2k
}
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
9.49k
{
1356
9.49k
  return (p->state == XZ_STATE_STREAM_PADDING) && (((UInt32)p->padSize & 3) == 0);
1357
9.49k
}
1358
1359
UInt64 XzUnpacker_GetExtraSize(const CXzUnpacker *p)
1360
15.0k
{
1361
15.0k
  UInt64 num = 0;
1362
15.0k
  if (p->state == XZ_STATE_STREAM_PADDING)
1363
7.95k
    num = p->padSize;
1364
7.07k
  else if (p->state == XZ_STATE_STREAM_HEADER)
1365
162
    num = p->padSize + p->pos;
1366
15.0k
  return num;
1367
15.0k
}
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
30.0k
{
1396
30.0k
  p->inBufSize_ST = 1 << 18;
1397
30.0k
  p->outStep_ST = 1 << 20;
1398
30.0k
  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
30.0k
}
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
15.0k
{
1513
15.0k
  CXzDecMt *p = (CXzDecMt *)ISzAlloc_Alloc(alloc, sizeof(CXzDecMt));
1514
15.0k
  if (!p)
1515
0
    return NULL;
1516
  
1517
15.0k
  AlignOffsetAlloc_CreateVTable(&p->alignOffsetAlloc);
1518
15.0k
  p->alignOffsetAlloc.baseAlloc = alloc;
1519
15.0k
  p->alignOffsetAlloc.numAlignBits = 7;
1520
15.0k
  p->alignOffsetAlloc.offset = 0;
1521
1522
15.0k
  p->allocMid = allocMid;
1523
1524
15.0k
  p->outBuf = NULL;
1525
15.0k
  p->outBufSize = 0;
1526
15.0k
  p->inBuf = NULL;
1527
15.0k
  p->inBufSize = 0;
1528
1529
15.0k
  XzUnpacker_Construct(&p->dec, &p->alignOffsetAlloc.vt);
1530
1531
15.0k
  p->unpackBlockMaxSize = 0;
1532
1533
15.0k
  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
15.0k
  return p;
1550
15.0k
}
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
15.0k
{
1577
15.0k
  XzUnpacker_Free(&p->dec);
1578
  
1579
15.0k
  if (p->outBuf)
1580
15.0k
  {
1581
15.0k
    ISzAlloc_Free(p->allocMid, p->outBuf);
1582
15.0k
    p->outBuf = NULL;
1583
15.0k
  }
1584
15.0k
  p->outBufSize = 0;
1585
  
1586
15.0k
  if (p->inBuf)
1587
15.0k
  {
1588
15.0k
    ISzAlloc_Free(p->allocMid, p->inBuf);
1589
15.0k
    p->inBuf = NULL;
1590
15.0k
  }
1591
15.0k
  p->inBufSize = 0;
1592
15.0k
}
1593
1594
1595
void XzDecMt_Destroy(CXzDecMtHandle pp)
1596
15.0k
{
1597
15.0k
  CXzDecMt *p = (CXzDecMt *)pp;
1598
1599
15.0k
  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
15.0k
  ISzAlloc_Free(p->alignOffsetAlloc.baseAlloc, pp);
1626
15.0k
}
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
15.0k
{
2268
15.0k
  p->InSize = 0;
2269
15.0k
  p->OutSize = 0;
2270
  
2271
15.0k
  p->NumStreams = 0;
2272
15.0k
  p->NumBlocks = 0;
2273
  
2274
15.0k
  p->UnpackSize_Defined = False;
2275
  
2276
15.0k
  p->NumStreams_Defined = False;
2277
15.0k
  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
15.0k
  p->DataAfterEnd = False;
2287
15.0k
  p->DecodingTruncated = False;
2288
  
2289
15.0k
  p->DecodeRes = SZ_OK;
2290
15.0k
  p->ReadRes = SZ_OK;
2291
15.0k
  p->ProgressRes = SZ_OK;
2292
2293
15.0k
  p->CombinedRes = SZ_OK;
2294
15.0k
  p->CombinedRes_Type = SZ_OK;
2295
15.0k
}
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
15.0k
{
2306
15.0k
  size_t outPos;
2307
15.0k
  size_t inPos, inLim;
2308
15.0k
  const Byte *inData;
2309
15.0k
  UInt64 inPrev, outPrev;
2310
2311
15.0k
  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
15.0k
  if (!p->outBuf || p->outBufSize != p->props.outStep_ST)
2322
15.0k
  {
2323
15.0k
    ISzAlloc_Free(p->allocMid, p->outBuf);
2324
15.0k
    p->outBufSize = 0;
2325
15.0k
    p->outBuf = (Byte *)ISzAlloc_Alloc(p->allocMid, p->props.outStep_ST);
2326
15.0k
    if (!p->outBuf)
2327
0
      return SZ_ERROR_MEM;
2328
15.0k
    p->outBufSize = p->props.outStep_ST;
2329
15.0k
  }
2330
2331
15.0k
  if (!p->inBuf || p->inBufSize != p->props.inBufSize_ST)
2332
15.0k
  {
2333
15.0k
    ISzAlloc_Free(p->allocMid, p->inBuf);
2334
15.0k
    p->inBufSize = 0;
2335
15.0k
    p->inBuf = (Byte *)ISzAlloc_Alloc(p->allocMid, p->props.inBufSize_ST);
2336
15.0k
    if (!p->inBuf)
2337
0
      return SZ_ERROR_MEM;
2338
15.0k
    p->inBufSize = p->props.inBufSize_ST;
2339
15.0k
  }
2340
2341
15.0k
  dec = &p->dec;
2342
15.0k
  dec->decodeToStreamSignature = False;
2343
  // dec->decodeOnlyOneBlock = False;
2344
2345
15.0k
  XzUnpacker_SetOutBuf(dec, NULL, 0);
2346
2347
15.0k
  inPrev = p->inProcessed;
2348
15.0k
  outPrev = p->outProcessed;
2349
2350
15.0k
  inPos = 0;
2351
15.0k
  inLim = 0;
2352
15.0k
  inData = NULL;
2353
15.0k
  outPos = 0;
2354
2355
15.0k
  for (;;)
2356
29.2k
  {
2357
29.2k
    SizeT outSize;
2358
29.2k
    BoolInt finished;
2359
29.2k
    ECoderFinishMode finishMode;
2360
29.2k
    SizeT inProcessed;
2361
29.2k
    ECoderStatus status;
2362
29.2k
    SRes res;
2363
2364
29.2k
    SizeT outProcessed;
2365
2366
2367
2368
29.2k
    if (inPos == inLim)
2369
28.6k
    {
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
28.6k
      if (!p->readWasFinished)
2383
28.6k
      {
2384
28.6k
        inPos = 0;
2385
28.6k
        inLim = p->inBufSize;
2386
28.6k
        inData = p->inBuf;
2387
28.6k
        p->readRes = ISeqInStream_Read(p->inStream, (void *)inData, &inLim);
2388
28.6k
        p->readProcessed += inLim;
2389
28.6k
        if (inLim == 0 || p->readRes != SZ_OK)
2390
12.6k
          p->readWasFinished = True;
2391
28.6k
      }
2392
28.6k
    }
2393
2394
29.2k
    outSize = p->props.outStep_ST - outPos;
2395
2396
29.2k
    finishMode = CODER_FINISH_ANY;
2397
29.2k
    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
29.2k
    inProcessed = inLim - inPos;
2409
29.2k
    outProcessed = outSize;
2410
2411
29.2k
    res = XzUnpacker_Code(dec, p->outBuf + outPos, &outProcessed,
2412
29.2k
        inData + inPos, &inProcessed,
2413
29.2k
        (inPos == inLim), // srcFinished
2414
29.2k
        finishMode, &status);
2415
2416
29.2k
    p->codeRes = res;
2417
29.2k
    p->status = status;
2418
2419
29.2k
    inPos += inProcessed;
2420
29.2k
    outPos += outProcessed;
2421
29.2k
    p->inProcessed += inProcessed;
2422
29.2k
    p->outProcessed += outProcessed;
2423
2424
29.2k
    finished = ((inProcessed == 0 && outProcessed == 0) || res != SZ_OK);
2425
2426
29.2k
    if (finished || outProcessed >= outSize)
2427
15.6k
      if (outPos != 0)
2428
12.5k
      {
2429
12.5k
        size_t written = ISeqOutStream_Write(p->outStream, p->outBuf, outPos);
2430
12.5k
        p->outProcessed += written;
2431
12.5k
        if (written != outPos)
2432
0
        {
2433
0
          stat->CombinedRes_Type = SZ_ERROR_WRITE;
2434
0
          return SZ_ERROR_WRITE;
2435
0
        }
2436
12.5k
        outPos = 0;
2437
12.5k
      }
2438
2439
29.2k
    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
29.2k
    if (finished)
2458
15.0k
      return res;
2459
29.2k
  }
2460
15.0k
}
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
15.0k
{
2469
15.0k
  UInt64 extraSize;
2470
  
2471
15.0k
  stat->DecodingTruncated = (Byte)(decodingTruncated ? 1 : 0);
2472
15.0k
  stat->InSize = inProcessed;
2473
15.0k
  stat->NumStreams = dec->numStartedStreams;
2474
15.0k
  stat->NumBlocks = dec->numTotalBlocks;
2475
  
2476
15.0k
  stat->UnpackSize_Defined = True;
2477
15.0k
  stat->NumStreams_Defined = True;
2478
15.0k
  stat->NumBlocks_Defined = True;
2479
  
2480
15.0k
  extraSize = XzUnpacker_GetExtraSize(dec);
2481
  
2482
15.0k
  if (res == SZ_OK)
2483
12.7k
  {
2484
12.7k
    if (status == CODER_STATUS_NEEDS_MORE_INPUT)
2485
9.49k
    {
2486
      // CODER_STATUS_NEEDS_MORE_INPUT is expected status for correct xz streams
2487
9.49k
      extraSize = 0;
2488
9.49k
      if (!XzUnpacker_IsStreamWasFinished(dec))
2489
1.70k
        res = SZ_ERROR_INPUT_EOF;
2490
9.49k
    }
2491
3.22k
    else if (!decodingTruncated || finishMode) // (status == CODER_STATUS_NOT_FINISHED)
2492
3.22k
      res = SZ_ERROR_DATA;
2493
12.7k
  }
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
15.0k
  stat->DecodeRes = res;
2512
2513
15.0k
  stat->InSize -= extraSize;
2514
15.0k
  return res;
2515
15.0k
}
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
15.0k
{
2529
15.0k
  CXzDecMt *p = (CXzDecMt *)pp;
2530
  #ifndef _7ZIP_ST
2531
  BoolInt tMode;
2532
  #endif
2533
2534
15.0k
  XzStatInfo_Clear(stat);
2535
2536
15.0k
  p->props = *props;
2537
2538
15.0k
  p->inStream = inStream;
2539
15.0k
  p->outStream = outStream;
2540
15.0k
  p->progress = progress;
2541
  // p->stat = stat;
2542
2543
15.0k
  p->outSize = 0;
2544
15.0k
  p->outSize_Defined = False;
2545
15.0k
  if (outDataSize)
2546
0
  {
2547
0
    p->outSize_Defined = True;
2548
0
    p->outSize = *outDataSize;
2549
0
  }
2550
2551
15.0k
  p->finishMode = finishMode;
2552
2553
  // p->outSize = 457; p->outSize_Defined = True; p->finishMode = False; // for test
2554
2555
15.0k
  p->writeRes = SZ_OK;
2556
15.0k
  p->outProcessed = 0;
2557
15.0k
  p->inProcessed = 0;
2558
15.0k
  p->readProcessed = 0;
2559
15.0k
  p->readWasFinished = False;
2560
2561
15.0k
  p->codeRes = 0;
2562
15.0k
  p->status = CODER_STATUS_NOT_SPECIFIED;
2563
2564
15.0k
  XzUnpacker_Init(&p->dec);
2565
2566
15.0k
  *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
15.0k
  *isMT = False;
2723
2724
15.0k
  {
2725
15.0k
    SRes res = XzDecMt_Decode_ST(p
2726
        #ifndef _7ZIP_ST
2727
        , tMode
2728
        #endif
2729
15.0k
        , stat
2730
15.0k
        );
2731
2732
15.0k
    XzStatInfo_SetStat(&p->dec,
2733
15.0k
        p->finishMode,
2734
15.0k
        p->readProcessed, p->inProcessed,
2735
15.0k
        p->codeRes, p->status,
2736
15.0k
        False, // truncated
2737
15.0k
        stat);
2738
2739
15.0k
    if (res == SZ_OK)
2740
12.7k
    {
2741
      /*
2742
      if (p->writeRes != SZ_OK)
2743
      {
2744
        res = p->writeRes;
2745
        stat->CombinedRes_Type = SZ_ERROR_WRITE;
2746
      }
2747
      else
2748
      */
2749
12.7k
      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
12.7k
    }
2760
2761
15.0k
    stat->CombinedRes = res;
2762
15.0k
    if (stat->CombinedRes_Type == SZ_OK)
2763
15.0k
      stat->CombinedRes_Type = res;
2764
15.0k
    return res;
2765
15.0k
  }
2766
15.0k
}