zstd-ruby 1.1.3.0 → 1.1.4.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (45) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +1 -1
  3. data/ext/zstdruby/libzstd/Makefile +9 -6
  4. data/ext/zstdruby/libzstd/common/bitstream.h +3 -0
  5. data/ext/zstdruby/libzstd/common/entropy_common.c +13 -19
  6. data/ext/zstdruby/libzstd/common/fse.h +48 -22
  7. data/ext/zstdruby/libzstd/common/fse_decompress.c +0 -1
  8. data/ext/zstdruby/libzstd/common/huf.h +27 -5
  9. data/ext/zstdruby/libzstd/common/mem.h +14 -12
  10. data/ext/zstdruby/libzstd/common/threading.c +5 -4
  11. data/ext/zstdruby/libzstd/common/threading.h +1 -1
  12. data/ext/zstdruby/libzstd/common/xxhash.c +3 -1
  13. data/ext/zstdruby/libzstd/common/xxhash.h +11 -15
  14. data/ext/zstdruby/libzstd/common/zstd_common.c +1 -1
  15. data/ext/zstdruby/libzstd/common/zstd_internal.h +4 -0
  16. data/ext/zstdruby/libzstd/compress/fse_compress.c +16 -9
  17. data/ext/zstdruby/libzstd/compress/huf_compress.c +103 -28
  18. data/ext/zstdruby/libzstd/compress/zstd_compress.c +90 -37
  19. data/ext/zstdruby/libzstd/compress/zstd_opt.h +1 -1
  20. data/ext/zstdruby/libzstd/compress/zstdmt_compress.c +7 -8
  21. data/ext/zstdruby/libzstd/decompress/huf_decompress.c +20 -17
  22. data/ext/zstdruby/libzstd/decompress/zstd_decompress.c +429 -120
  23. data/ext/zstdruby/libzstd/deprecated/zbuff.h +3 -1
  24. data/ext/zstdruby/libzstd/dictBuilder/cover.c +16 -8
  25. data/ext/zstdruby/libzstd/dictBuilder/zdict.h +1 -1
  26. data/ext/zstdruby/libzstd/dll/example/build_package.bat +1 -0
  27. data/ext/zstdruby/libzstd/dll/libzstd.def +2 -0
  28. data/ext/zstdruby/libzstd/legacy/zstd_legacy.h +122 -7
  29. data/ext/zstdruby/libzstd/legacy/zstd_v01.c +31 -0
  30. data/ext/zstdruby/libzstd/legacy/zstd_v01.h +8 -0
  31. data/ext/zstdruby/libzstd/legacy/zstd_v02.c +37 -0
  32. data/ext/zstdruby/libzstd/legacy/zstd_v02.h +8 -0
  33. data/ext/zstdruby/libzstd/legacy/zstd_v03.c +37 -0
  34. data/ext/zstdruby/libzstd/legacy/zstd_v03.h +8 -0
  35. data/ext/zstdruby/libzstd/legacy/zstd_v04.c +33 -0
  36. data/ext/zstdruby/libzstd/legacy/zstd_v04.h +8 -0
  37. data/ext/zstdruby/libzstd/legacy/zstd_v05.c +29 -0
  38. data/ext/zstdruby/libzstd/legacy/zstd_v05.h +7 -0
  39. data/ext/zstdruby/libzstd/legacy/zstd_v06.c +32 -1
  40. data/ext/zstdruby/libzstd/legacy/zstd_v06.h +7 -0
  41. data/ext/zstdruby/libzstd/legacy/zstd_v07.c +44 -6
  42. data/ext/zstdruby/libzstd/legacy/zstd_v07.h +8 -0
  43. data/ext/zstdruby/libzstd/zstd.h +87 -13
  44. data/lib/zstd-ruby/version.rb +1 -1
  45. metadata +2 -2
@@ -43,8 +43,6 @@
43
43
  *********************************************************/
44
44
  #include <string.h> /* memcpy, memmove, memset */
45
45
  #include "mem.h" /* low level memory routines */
46
- #define XXH_STATIC_LINKING_ONLY /* XXH64_state_t */
47
- #include "xxhash.h" /* XXH64_* */
48
46
  #define FSE_STATIC_LINKING_ONLY
49
47
  #include "fse.h"
50
48
  #define HUF_STATIC_LINKING_ONLY
@@ -87,22 +85,26 @@ typedef enum { ZSTDds_getFrameHeaderSize, ZSTDds_decodeFrameHeader,
87
85
  ZSTDds_decompressLastBlock, ZSTDds_checkChecksum,
88
86
  ZSTDds_decodeSkippableHeader, ZSTDds_skipFrame } ZSTD_dStage;
89
87
 
88
+ typedef struct {
89
+ FSE_DTable LLTable[FSE_DTABLE_SIZE_U32(LLFSELog)];
90
+ FSE_DTable OFTable[FSE_DTABLE_SIZE_U32(OffFSELog)];
91
+ FSE_DTable MLTable[FSE_DTABLE_SIZE_U32(MLFSELog)];
92
+ HUF_DTable hufTable[HUF_DTABLE_SIZE(HufLog)]; /* can accommodate HUF_decompress4X */
93
+ U32 rep[ZSTD_REP_NUM];
94
+ } ZSTD_entropyTables_t;
95
+
90
96
  struct ZSTD_DCtx_s
91
97
  {
92
98
  const FSE_DTable* LLTptr;
93
99
  const FSE_DTable* MLTptr;
94
100
  const FSE_DTable* OFTptr;
95
101
  const HUF_DTable* HUFptr;
96
- FSE_DTable LLTable[FSE_DTABLE_SIZE_U32(LLFSELog)];
97
- FSE_DTable OFTable[FSE_DTABLE_SIZE_U32(OffFSELog)];
98
- FSE_DTable MLTable[FSE_DTABLE_SIZE_U32(MLFSELog)];
99
- HUF_DTable hufTable[HUF_DTABLE_SIZE(HufLog)]; /* can accommodate HUF_decompress4X */
100
- const void* previousDstEnd;
101
- const void* base;
102
- const void* vBase;
103
- const void* dictEnd;
102
+ ZSTD_entropyTables_t entropy;
103
+ const void* previousDstEnd; /* detect continuity */
104
+ const void* base; /* start of current segment */
105
+ const void* vBase; /* virtual start of previous segment if it was just before current one */
106
+ const void* dictEnd; /* end of previous segment */
104
107
  size_t expected;
105
- U32 rep[ZSTD_REP_NUM];
106
108
  ZSTD_frameParams fParams;
107
109
  blockType_e bType; /* used in ZSTD_decompressContinue(), to transfer blockType between header decoding and block decoding stages */
108
110
  ZSTD_dStage stage;
@@ -131,15 +133,15 @@ size_t ZSTD_decompressBegin(ZSTD_DCtx* dctx)
131
133
  dctx->base = NULL;
132
134
  dctx->vBase = NULL;
133
135
  dctx->dictEnd = NULL;
134
- dctx->hufTable[0] = (HUF_DTable)((HufLog)*0x1000001); /* cover both little and big endian */
136
+ dctx->entropy.hufTable[0] = (HUF_DTable)((HufLog)*0x1000001); /* cover both little and big endian */
135
137
  dctx->litEntropy = dctx->fseEntropy = 0;
136
138
  dctx->dictID = 0;
137
- MEM_STATIC_ASSERT(sizeof(dctx->rep) == sizeof(repStartValue));
138
- memcpy(dctx->rep, repStartValue, sizeof(repStartValue)); /* initial repcodes */
139
- dctx->LLTptr = dctx->LLTable;
140
- dctx->MLTptr = dctx->MLTable;
141
- dctx->OFTptr = dctx->OFTable;
142
- dctx->HUFptr = dctx->hufTable;
139
+ MEM_STATIC_ASSERT(sizeof(dctx->entropy.rep) == sizeof(repStartValue));
140
+ memcpy(dctx->entropy.rep, repStartValue, sizeof(repStartValue)); /* initial repcodes */
141
+ dctx->LLTptr = dctx->entropy.LLTable;
142
+ dctx->MLTptr = dctx->entropy.MLTable;
143
+ dctx->OFTptr = dctx->entropy.OFTable;
144
+ dctx->HUFptr = dctx->entropy.hufTable;
143
145
  return 0;
144
146
  }
145
147
 
@@ -175,6 +177,8 @@ void ZSTD_copyDCtx(ZSTD_DCtx* dstDCtx, const ZSTD_DCtx* srcDCtx)
175
177
  memcpy(dstDCtx, srcDCtx, sizeof(ZSTD_DCtx) - workSpaceSize); /* no need to copy workspace */
176
178
  }
177
179
 
180
+ #if 0
181
+ /* deprecated */
178
182
  static void ZSTD_refDCtx(ZSTD_DCtx* dstDCtx, const ZSTD_DCtx* srcDCtx)
179
183
  {
180
184
  ZSTD_decompressBegin(dstDCtx); /* init */
@@ -186,15 +190,18 @@ static void ZSTD_refDCtx(ZSTD_DCtx* dstDCtx, const ZSTD_DCtx* srcDCtx)
186
190
  dstDCtx->dictID = srcDCtx->dictID;
187
191
  dstDCtx->litEntropy = srcDCtx->litEntropy;
188
192
  dstDCtx->fseEntropy = srcDCtx->fseEntropy;
189
- dstDCtx->LLTptr = srcDCtx->LLTable;
190
- dstDCtx->MLTptr = srcDCtx->MLTable;
191
- dstDCtx->OFTptr = srcDCtx->OFTable;
192
- dstDCtx->HUFptr = srcDCtx->hufTable;
193
- dstDCtx->rep[0] = srcDCtx->rep[0];
194
- dstDCtx->rep[1] = srcDCtx->rep[1];
195
- dstDCtx->rep[2] = srcDCtx->rep[2];
193
+ dstDCtx->LLTptr = srcDCtx->entropy.LLTable;
194
+ dstDCtx->MLTptr = srcDCtx->entropy.MLTable;
195
+ dstDCtx->OFTptr = srcDCtx->entropy.OFTable;
196
+ dstDCtx->HUFptr = srcDCtx->entropy.hufTable;
197
+ dstDCtx->entropy.rep[0] = srcDCtx->entropy.rep[0];
198
+ dstDCtx->entropy.rep[1] = srcDCtx->entropy.rep[1];
199
+ dstDCtx->entropy.rep[2] = srcDCtx->entropy.rep[2];
196
200
  }
197
201
  }
202
+ #endif
203
+
204
+ static void ZSTD_refDDict(ZSTD_DCtx* dstDCtx, const ZSTD_DDict* ddict);
198
205
 
199
206
 
200
207
  /*-*************************************************************
@@ -306,6 +313,86 @@ size_t ZSTD_getFrameParams(ZSTD_frameParams* fparamsPtr, const void* src, size_t
306
313
  return 0;
307
314
  }
308
315
 
316
+ /** ZSTD_getFrameContentSize() :
317
+ * compatible with legacy mode
318
+ * @return : decompressed size of the single frame pointed to be `src` if known, otherwise
319
+ * - ZSTD_CONTENTSIZE_UNKNOWN if the size cannot be determined
320
+ * - ZSTD_CONTENTSIZE_ERROR if an error occurred (e.g. invalid magic number, srcSize too small) */
321
+ unsigned long long ZSTD_getFrameContentSize(const void *src, size_t srcSize)
322
+ {
323
+ #if defined(ZSTD_LEGACY_SUPPORT) && (ZSTD_LEGACY_SUPPORT >= 1)
324
+ if (ZSTD_isLegacy(src, srcSize)) {
325
+ unsigned long long const ret = ZSTD_getDecompressedSize_legacy(src, srcSize);
326
+ return ret == 0 ? ZSTD_CONTENTSIZE_UNKNOWN : ret;
327
+ }
328
+ #endif
329
+ {
330
+ ZSTD_frameParams fParams;
331
+ if (ZSTD_getFrameParams(&fParams, src, srcSize) != 0) return ZSTD_CONTENTSIZE_ERROR;
332
+ if (fParams.windowSize == 0) {
333
+ /* Either skippable or empty frame, size == 0 either way */
334
+ return 0;
335
+ } else if (fParams.frameContentSize != 0) {
336
+ return fParams.frameContentSize;
337
+ } else {
338
+ return ZSTD_CONTENTSIZE_UNKNOWN;
339
+ }
340
+ }
341
+ }
342
+
343
+ /** ZSTD_findDecompressedSize() :
344
+ * compatible with legacy mode
345
+ * `srcSize` must be the exact length of some number of ZSTD compressed and/or
346
+ * skippable frames
347
+ * @return : decompressed size of the frames contained */
348
+ unsigned long long ZSTD_findDecompressedSize(const void* src, size_t srcSize)
349
+ {
350
+ {
351
+ unsigned long long totalDstSize = 0;
352
+ while (srcSize >= ZSTD_frameHeaderSize_prefix) {
353
+ const U32 magicNumber = MEM_readLE32(src);
354
+
355
+ if ((magicNumber & 0xFFFFFFF0U) == ZSTD_MAGIC_SKIPPABLE_START) {
356
+ size_t skippableSize;
357
+ if (srcSize < ZSTD_skippableHeaderSize)
358
+ return ERROR(srcSize_wrong);
359
+ skippableSize = MEM_readLE32((const BYTE *)src + 4) +
360
+ ZSTD_skippableHeaderSize;
361
+ if (srcSize < skippableSize) {
362
+ return ZSTD_CONTENTSIZE_ERROR;
363
+ }
364
+
365
+ src = (const BYTE *)src + skippableSize;
366
+ srcSize -= skippableSize;
367
+ continue;
368
+ }
369
+
370
+ {
371
+ unsigned long long const ret = ZSTD_getFrameContentSize(src, srcSize);
372
+ if (ret >= ZSTD_CONTENTSIZE_ERROR) return ret;
373
+
374
+ /* check for overflow */
375
+ if (totalDstSize + ret < totalDstSize) return ZSTD_CONTENTSIZE_ERROR;
376
+ totalDstSize += ret;
377
+ }
378
+ {
379
+ size_t const frameSrcSize = ZSTD_findFrameCompressedSize(src, srcSize);
380
+ if (ZSTD_isError(frameSrcSize)) {
381
+ return ZSTD_CONTENTSIZE_ERROR;
382
+ }
383
+
384
+ src = (const BYTE *)src + frameSrcSize;
385
+ srcSize -= frameSrcSize;
386
+ }
387
+ }
388
+
389
+ if (srcSize) {
390
+ return ZSTD_CONTENTSIZE_ERROR;
391
+ }
392
+
393
+ return totalDstSize;
394
+ }
395
+ }
309
396
 
310
397
  /** ZSTD_getDecompressedSize() :
311
398
  * compatible with legacy mode
@@ -316,14 +403,8 @@ size_t ZSTD_getFrameParams(ZSTD_frameParams* fparamsPtr, const void* src, size_t
316
403
  - frame header not complete (`srcSize` too small) */
317
404
  unsigned long long ZSTD_getDecompressedSize(const void* src, size_t srcSize)
318
405
  {
319
- #if defined(ZSTD_LEGACY_SUPPORT) && (ZSTD_LEGACY_SUPPORT==1)
320
- if (ZSTD_isLegacy(src, srcSize)) return ZSTD_getDecompressedSize_legacy(src, srcSize);
321
- #endif
322
- { ZSTD_frameParams fparams;
323
- size_t const frResult = ZSTD_getFrameParams(&fparams, src, srcSize);
324
- if (frResult!=0) return 0;
325
- return fparams.frameContentSize;
326
- }
406
+ unsigned long long const ret = ZSTD_getFrameContentSize(src, srcSize);
407
+ return ret >= ZSTD_CONTENTSIZE_ERROR ? 0 : ret;
327
408
  }
328
409
 
329
410
 
@@ -432,14 +513,14 @@ size_t ZSTD_decodeLiteralsBlock(ZSTD_DCtx* dctx,
432
513
  HUF_decompress1X_usingDTable(dctx->litBuffer, litSize, istart+lhSize, litCSize, dctx->HUFptr) :
433
514
  HUF_decompress4X_usingDTable(dctx->litBuffer, litSize, istart+lhSize, litCSize, dctx->HUFptr) ) :
434
515
  ( singleStream ?
435
- HUF_decompress1X2_DCtx(dctx->hufTable, dctx->litBuffer, litSize, istart+lhSize, litCSize) :
436
- HUF_decompress4X_hufOnly (dctx->hufTable, dctx->litBuffer, litSize, istart+lhSize, litCSize)) ))
516
+ HUF_decompress1X2_DCtx(dctx->entropy.hufTable, dctx->litBuffer, litSize, istart+lhSize, litCSize) :
517
+ HUF_decompress4X_hufOnly (dctx->entropy.hufTable, dctx->litBuffer, litSize, istart+lhSize, litCSize)) ))
437
518
  return ERROR(corruption_detected);
438
519
 
439
520
  dctx->litPtr = dctx->litBuffer;
440
521
  dctx->litSize = litSize;
441
522
  dctx->litEntropy = 1;
442
- if (litEncType==set_compressed) dctx->HUFptr = dctx->hufTable;
523
+ if (litEncType==set_compressed) dctx->HUFptr = dctx->entropy.hufTable;
443
524
  memset(dctx->litBuffer + dctx->litSize, 0, WILDCOPY_OVERLENGTH);
444
525
  return litCSize + lhSize;
445
526
  }
@@ -756,19 +837,19 @@ size_t ZSTD_decodeSeqHeaders(ZSTD_DCtx* dctx, int* nbSeqPtr,
756
837
  ip++;
757
838
 
758
839
  /* Build DTables */
759
- { size_t const llhSize = ZSTD_buildSeqTable(dctx->LLTable, &dctx->LLTptr,
840
+ { size_t const llhSize = ZSTD_buildSeqTable(dctx->entropy.LLTable, &dctx->LLTptr,
760
841
  LLtype, MaxLL, LLFSELog,
761
842
  ip, iend-ip, LL_defaultDTable, dctx->fseEntropy);
762
843
  if (ZSTD_isError(llhSize)) return ERROR(corruption_detected);
763
844
  ip += llhSize;
764
845
  }
765
- { size_t const ofhSize = ZSTD_buildSeqTable(dctx->OFTable, &dctx->OFTptr,
846
+ { size_t const ofhSize = ZSTD_buildSeqTable(dctx->entropy.OFTable, &dctx->OFTptr,
766
847
  OFtype, MaxOff, OffFSELog,
767
848
  ip, iend-ip, OF_defaultDTable, dctx->fseEntropy);
768
849
  if (ZSTD_isError(ofhSize)) return ERROR(corruption_detected);
769
850
  ip += ofhSize;
770
851
  }
771
- { size_t const mlhSize = ZSTD_buildSeqTable(dctx->MLTable, &dctx->MLTptr,
852
+ { size_t const mlhSize = ZSTD_buildSeqTable(dctx->entropy.MLTable, &dctx->MLTptr,
772
853
  MLtype, MaxML, MLFSELog,
773
854
  ip, iend-ip, ML_defaultDTable, dctx->fseEntropy);
774
855
  if (ZSTD_isError(mlhSize)) return ERROR(corruption_detected);
@@ -795,7 +876,7 @@ typedef struct {
795
876
  size_t prevOffset[ZSTD_REP_NUM];
796
877
  const BYTE* base;
797
878
  size_t pos;
798
- iPtrDiff gotoDict;
879
+ uPtrDiff gotoDict;
799
880
  } seqState_t;
800
881
 
801
882
 
@@ -925,9 +1006,9 @@ static seq_t ZSTD_decodeSequence(seqState_t* seqState)
925
1006
 
926
1007
  FORCE_INLINE
927
1008
  size_t ZSTD_execSequence(BYTE* op,
928
- BYTE* const oend, seq_t sequence,
929
- const BYTE** litPtr, const BYTE* const litLimit,
930
- const BYTE* const base, const BYTE* const vBase, const BYTE* const dictEnd)
1009
+ BYTE* const oend, seq_t sequence,
1010
+ const BYTE** litPtr, const BYTE* const litLimit,
1011
+ const BYTE* const base, const BYTE* const vBase, const BYTE* const dictEnd)
931
1012
  {
932
1013
  BYTE* const oLitEnd = op + sequence.litLength;
933
1014
  size_t const sequenceLength = sequence.litLength + sequence.matchLength;
@@ -952,7 +1033,7 @@ size_t ZSTD_execSequence(BYTE* op,
952
1033
  if (sequence.offset > (size_t)(oLitEnd - base)) {
953
1034
  /* offset beyond prefix */
954
1035
  if (sequence.offset > (size_t)(oLitEnd - vBase)) return ERROR(corruption_detected);
955
- match += (dictEnd-base);
1036
+ match = dictEnd + (match - base);
956
1037
  if (match + sequence.matchLength <= dictEnd) {
957
1038
  memmove(oLitEnd, match, sequence.matchLength);
958
1039
  return sequenceLength;
@@ -975,7 +1056,7 @@ size_t ZSTD_execSequence(BYTE* op,
975
1056
  if (sequence.offset < 8) {
976
1057
  /* close range match, overlap */
977
1058
  static const U32 dec32table[] = { 0, 1, 2, 1, 4, 4, 4, 4 }; /* added */
978
- static const int dec64table[] = { 8, 8, 8, 7, 8, 9,10,11 }; /* substracted */
1059
+ static const int dec64table[] = { 8, 8, 8, 7, 8, 9,10,11 }; /* subtracted */
979
1060
  int const sub2 = dec64table[sequence.offset];
980
1061
  op[0] = match[0];
981
1062
  op[1] = match[1];
@@ -1030,7 +1111,7 @@ static size_t ZSTD_decompressSequences(
1030
1111
  if (nbSeq) {
1031
1112
  seqState_t seqState;
1032
1113
  dctx->fseEntropy = 1;
1033
- { U32 i; for (i=0; i<ZSTD_REP_NUM; i++) seqState.prevOffset[i] = dctx->rep[i]; }
1114
+ { U32 i; for (i=0; i<ZSTD_REP_NUM; i++) seqState.prevOffset[i] = dctx->entropy.rep[i]; }
1034
1115
  CHECK_E(BIT_initDStream(&seqState.DStream, ip, iend-ip), corruption_detected);
1035
1116
  FSE_initDState(&seqState.stateLL, &seqState.DStream, dctx->LLTptr);
1036
1117
  FSE_initDState(&seqState.stateOffb, &seqState.DStream, dctx->OFTptr);
@@ -1047,7 +1128,7 @@ static size_t ZSTD_decompressSequences(
1047
1128
  /* check if reached exact end */
1048
1129
  if (nbSeq) return ERROR(corruption_detected);
1049
1130
  /* save reps for next block */
1050
- { U32 i; for (i=0; i<ZSTD_REP_NUM; i++) dctx->rep[i] = (U32)(seqState.prevOffset[i]); }
1131
+ { U32 i; for (i=0; i<ZSTD_REP_NUM; i++) dctx->entropy.rep[i] = (U32)(seqState.prevOffset[i]); }
1051
1132
  }
1052
1133
 
1053
1134
  /* last literal segment */
@@ -1061,7 +1142,7 @@ static size_t ZSTD_decompressSequences(
1061
1142
  }
1062
1143
 
1063
1144
 
1064
- static seq_t ZSTD_decodeSequenceLong(seqState_t* seqState)
1145
+ FORCE_INLINE seq_t ZSTD_decodeSequenceLong_generic(seqState_t* seqState, int const longOffsets)
1065
1146
  {
1066
1147
  seq_t seq;
1067
1148
 
@@ -1096,8 +1177,15 @@ static seq_t ZSTD_decodeSequenceLong(seqState_t* seqState)
1096
1177
  if (!ofCode)
1097
1178
  offset = 0;
1098
1179
  else {
1099
- offset = OF_base[ofCode] + BIT_readBitsFast(&seqState->DStream, ofBits); /* <= (ZSTD_WINDOWLOG_MAX-1) bits */
1100
- if (MEM_32bits()) BIT_reloadDStream(&seqState->DStream);
1180
+ if (longOffsets) {
1181
+ int const extraBits = ofBits - MIN(ofBits, STREAM_ACCUMULATOR_MIN);
1182
+ offset = OF_base[ofCode] + (BIT_readBitsFast(&seqState->DStream, ofBits - extraBits) << extraBits);
1183
+ if (MEM_32bits() || extraBits) BIT_reloadDStream(&seqState->DStream);
1184
+ if (extraBits) offset += BIT_readBitsFast(&seqState->DStream, extraBits);
1185
+ } else {
1186
+ offset = OF_base[ofCode] + BIT_readBitsFast(&seqState->DStream, ofBits); /* <= (ZSTD_WINDOWLOG_MAX-1) bits */
1187
+ if (MEM_32bits()) BIT_reloadDStream(&seqState->DStream);
1188
+ }
1101
1189
  }
1102
1190
 
1103
1191
  if (ofCode <= 1) {
@@ -1141,6 +1229,14 @@ static seq_t ZSTD_decodeSequenceLong(seqState_t* seqState)
1141
1229
  return seq;
1142
1230
  }
1143
1231
 
1232
+ static seq_t ZSTD_decodeSequenceLong(seqState_t* seqState, unsigned const windowSize) {
1233
+ if (ZSTD_highbit32(windowSize) > STREAM_ACCUMULATOR_MIN) {
1234
+ return ZSTD_decodeSequenceLong_generic(seqState, 1);
1235
+ } else {
1236
+ return ZSTD_decodeSequenceLong_generic(seqState, 0);
1237
+ }
1238
+ }
1239
+
1144
1240
  FORCE_INLINE
1145
1241
  size_t ZSTD_execSequenceLong(BYTE* op,
1146
1242
  BYTE* const oend, seq_t sequence,
@@ -1196,7 +1292,7 @@ size_t ZSTD_execSequenceLong(BYTE* op,
1196
1292
  if (sequence.offset < 8) {
1197
1293
  /* close range match, overlap */
1198
1294
  static const U32 dec32table[] = { 0, 1, 2, 1, 4, 4, 4, 4 }; /* added */
1199
- static const int dec64table[] = { 8, 8, 8, 7, 8, 9,10,11 }; /* substracted */
1295
+ static const int dec64table[] = { 8, 8, 8, 7, 8, 9,10,11 }; /* subtracted */
1200
1296
  int const sub2 = dec64table[sequence.offset];
1201
1297
  op[0] = match[0];
1202
1298
  op[1] = match[1];
@@ -1238,6 +1334,7 @@ static size_t ZSTD_decompressSequencesLong(
1238
1334
  const BYTE* const base = (const BYTE*) (dctx->base);
1239
1335
  const BYTE* const vBase = (const BYTE*) (dctx->vBase);
1240
1336
  const BYTE* const dictEnd = (const BYTE*) (dctx->dictEnd);
1337
+ unsigned const windowSize = dctx->fParams.windowSize;
1241
1338
  int nbSeq;
1242
1339
 
1243
1340
  /* Build Decoding Tables */
@@ -1256,10 +1353,10 @@ static size_t ZSTD_decompressSequencesLong(
1256
1353
  seqState_t seqState;
1257
1354
  int seqNb;
1258
1355
  dctx->fseEntropy = 1;
1259
- { U32 i; for (i=0; i<ZSTD_REP_NUM; i++) seqState.prevOffset[i] = dctx->rep[i]; }
1356
+ { U32 i; for (i=0; i<ZSTD_REP_NUM; i++) seqState.prevOffset[i] = dctx->entropy.rep[i]; }
1260
1357
  seqState.base = base;
1261
1358
  seqState.pos = (size_t)(op-base);
1262
- seqState.gotoDict = (iPtrDiff)(dictEnd - base);
1359
+ seqState.gotoDict = (uPtrDiff)dictEnd - (uPtrDiff)base; /* cast to avoid undefined behaviour */
1263
1360
  CHECK_E(BIT_initDStream(&seqState.DStream, ip, iend-ip), corruption_detected);
1264
1361
  FSE_initDState(&seqState.stateLL, &seqState.DStream, dctx->LLTptr);
1265
1362
  FSE_initDState(&seqState.stateOffb, &seqState.DStream, dctx->OFTptr);
@@ -1267,13 +1364,13 @@ static size_t ZSTD_decompressSequencesLong(
1267
1364
 
1268
1365
  /* prepare in advance */
1269
1366
  for (seqNb=0; (BIT_reloadDStream(&seqState.DStream) <= BIT_DStream_completed) && seqNb<seqAdvance; seqNb++) {
1270
- sequences[seqNb] = ZSTD_decodeSequenceLong(&seqState);
1367
+ sequences[seqNb] = ZSTD_decodeSequenceLong(&seqState, windowSize);
1271
1368
  }
1272
1369
  if (seqNb<seqAdvance) return ERROR(corruption_detected);
1273
1370
 
1274
1371
  /* decode and decompress */
1275
1372
  for ( ; (BIT_reloadDStream(&(seqState.DStream)) <= BIT_DStream_completed) && seqNb<nbSeq ; seqNb++) {
1276
- seq_t const sequence = ZSTD_decodeSequenceLong(&seqState);
1373
+ seq_t const sequence = ZSTD_decodeSequenceLong(&seqState, windowSize);
1277
1374
  size_t const oneSeqSize = ZSTD_execSequenceLong(op, oend, sequences[(seqNb-ADVANCED_SEQS) & STOSEQ_MASK], &litPtr, litEnd, base, vBase, dictEnd);
1278
1375
  if (ZSTD_isError(oneSeqSize)) return oneSeqSize;
1279
1376
  ZSTD_PREFETCH(sequence.match);
@@ -1291,7 +1388,7 @@ static size_t ZSTD_decompressSequencesLong(
1291
1388
  }
1292
1389
 
1293
1390
  /* save reps for next block */
1294
- { U32 i; for (i=0; i<ZSTD_REP_NUM; i++) dctx->rep[i] = (U32)(seqState.prevOffset[i]); }
1391
+ { U32 i; for (i=0; i<ZSTD_REP_NUM; i++) dctx->entropy.rep[i] = (U32)(seqState.prevOffset[i]); }
1295
1392
  }
1296
1393
 
1297
1394
  /* last literal segment */
@@ -1313,13 +1410,18 @@ static size_t ZSTD_decompressBlock_internal(ZSTD_DCtx* dctx,
1313
1410
 
1314
1411
  if (srcSize >= ZSTD_BLOCKSIZE_ABSOLUTEMAX) return ERROR(srcSize_wrong);
1315
1412
 
1316
- /* Decode literals sub-block */
1413
+ /* Decode literals section */
1317
1414
  { size_t const litCSize = ZSTD_decodeLiteralsBlock(dctx, src, srcSize);
1318
1415
  if (ZSTD_isError(litCSize)) return litCSize;
1319
1416
  ip += litCSize;
1320
1417
  srcSize -= litCSize;
1321
1418
  }
1322
- if (dctx->fParams.windowSize > (1<<23)) return ZSTD_decompressSequencesLong(dctx, dst, dstCapacity, ip, srcSize);
1419
+ if (sizeof(size_t) > 4) /* do not enable prefetching on 32-bits x86, as it's performance detrimental */
1420
+ /* likely because of register pressure */
1421
+ /* if that's the correct cause, then 32-bits ARM should be affected differently */
1422
+ /* it would be good to test this on ARM real hardware, to see if prefetch version improves speed */
1423
+ if (dctx->fParams.windowSize > (1<<23))
1424
+ return ZSTD_decompressSequencesLong(dctx, dst, dstCapacity, ip, srcSize);
1323
1425
  return ZSTD_decompressSequences(dctx, dst, dstCapacity, ip, srcSize);
1324
1426
  }
1325
1427
 
@@ -1363,27 +1465,81 @@ size_t ZSTD_generateNxBytes(void* dst, size_t dstCapacity, BYTE byte, size_t len
1363
1465
  return length;
1364
1466
  }
1365
1467
 
1468
+ /** ZSTD_findFrameCompressedSize() :
1469
+ * compatible with legacy mode
1470
+ * `src` must point to the start of a ZSTD frame, ZSTD legacy frame, or skippable frame
1471
+ * `srcSize` must be at least as large as the frame contained
1472
+ * @return : the compressed size of the frame starting at `src` */
1473
+ size_t ZSTD_findFrameCompressedSize(const void *src, size_t srcSize)
1474
+ {
1475
+ #if defined(ZSTD_LEGACY_SUPPORT) && (ZSTD_LEGACY_SUPPORT >= 1)
1476
+ if (ZSTD_isLegacy(src, srcSize)) return ZSTD_findFrameCompressedSizeLegacy(src, srcSize);
1477
+ #endif
1478
+ if (srcSize >= ZSTD_skippableHeaderSize &&
1479
+ (MEM_readLE32(src) & 0xFFFFFFFF0U) == ZSTD_MAGIC_SKIPPABLE_START) {
1480
+ return ZSTD_skippableHeaderSize + MEM_readLE32((const BYTE*)src + 4);
1481
+ } else {
1482
+ const BYTE* ip = (const BYTE*)src;
1483
+ const BYTE* const ipstart = ip;
1484
+ size_t remainingSize = srcSize;
1485
+ ZSTD_frameParams fParams;
1486
+
1487
+ size_t const headerSize = ZSTD_frameHeaderSize(ip, remainingSize);
1488
+ if (ZSTD_isError(headerSize)) return headerSize;
1489
+
1490
+ /* Frame Header */
1491
+ { size_t const ret = ZSTD_getFrameParams(&fParams, ip, remainingSize);
1492
+ if (ZSTD_isError(ret)) return ret;
1493
+ if (ret > 0) return ERROR(srcSize_wrong);
1494
+ }
1495
+
1496
+ ip += headerSize;
1497
+ remainingSize -= headerSize;
1498
+
1499
+ /* Loop on each block */
1500
+ while (1) {
1501
+ blockProperties_t blockProperties;
1502
+ size_t const cBlockSize = ZSTD_getcBlockSize(ip, remainingSize, &blockProperties);
1503
+ if (ZSTD_isError(cBlockSize)) return cBlockSize;
1504
+
1505
+ if (ZSTD_blockHeaderSize + cBlockSize > remainingSize) return ERROR(srcSize_wrong);
1506
+
1507
+ ip += ZSTD_blockHeaderSize + cBlockSize;
1508
+ remainingSize -= ZSTD_blockHeaderSize + cBlockSize;
1509
+
1510
+ if (blockProperties.lastBlock) break;
1511
+ }
1512
+
1513
+ if (fParams.checksumFlag) { /* Frame content checksum */
1514
+ if (remainingSize < 4) return ERROR(srcSize_wrong);
1515
+ ip += 4;
1516
+ remainingSize -= 4;
1517
+ }
1518
+
1519
+ return ip - ipstart;
1520
+ }
1521
+ }
1366
1522
 
1367
1523
  /*! ZSTD_decompressFrame() :
1368
- * `dctx` must be properly initialized */
1524
+ * @dctx must be properly initialized */
1369
1525
  static size_t ZSTD_decompressFrame(ZSTD_DCtx* dctx,
1370
1526
  void* dst, size_t dstCapacity,
1371
- const void* src, size_t srcSize)
1527
+ const void** srcPtr, size_t *srcSizePtr)
1372
1528
  {
1373
- const BYTE* ip = (const BYTE*)src;
1529
+ const BYTE* ip = (const BYTE*)(*srcPtr);
1374
1530
  BYTE* const ostart = (BYTE* const)dst;
1375
1531
  BYTE* const oend = ostart + dstCapacity;
1376
1532
  BYTE* op = ostart;
1377
- size_t remainingSize = srcSize;
1533
+ size_t remainingSize = *srcSizePtr;
1378
1534
 
1379
1535
  /* check */
1380
- if (srcSize < ZSTD_frameHeaderSize_min+ZSTD_blockHeaderSize) return ERROR(srcSize_wrong);
1536
+ if (remainingSize < ZSTD_frameHeaderSize_min+ZSTD_blockHeaderSize) return ERROR(srcSize_wrong);
1381
1537
 
1382
1538
  /* Frame Header */
1383
- { size_t const frameHeaderSize = ZSTD_frameHeaderSize(src, ZSTD_frameHeaderSize_prefix);
1539
+ { size_t const frameHeaderSize = ZSTD_frameHeaderSize(ip, ZSTD_frameHeaderSize_prefix);
1384
1540
  if (ZSTD_isError(frameHeaderSize)) return frameHeaderSize;
1385
- if (srcSize < frameHeaderSize+ZSTD_blockHeaderSize) return ERROR(srcSize_wrong);
1386
- CHECK_F(ZSTD_decodeFrameHeader(dctx, src, frameHeaderSize));
1541
+ if (remainingSize < frameHeaderSize+ZSTD_blockHeaderSize) return ERROR(srcSize_wrong);
1542
+ CHECK_F(ZSTD_decodeFrameHeader(dctx, ip, frameHeaderSize));
1387
1543
  ip += frameHeaderSize; remainingSize -= frameHeaderSize;
1388
1544
  }
1389
1545
 
@@ -1428,25 +1584,109 @@ static size_t ZSTD_decompressFrame(ZSTD_DCtx* dctx,
1428
1584
  if (remainingSize<4) return ERROR(checksum_wrong);
1429
1585
  checkRead = MEM_readLE32(ip);
1430
1586
  if (checkRead != checkCalc) return ERROR(checksum_wrong);
1587
+ ip += 4;
1431
1588
  remainingSize -= 4;
1432
1589
  }
1433
1590
 
1434
- if (remainingSize) return ERROR(srcSize_wrong);
1591
+ /* Allow caller to get size read */
1592
+ *srcPtr = ip;
1593
+ *srcSizePtr = remainingSize;
1435
1594
  return op-ostart;
1436
1595
  }
1437
1596
 
1597
+ static const void* ZSTD_DDictDictContent(const ZSTD_DDict* ddict);
1598
+ static size_t ZSTD_DDictDictSize(const ZSTD_DDict* ddict);
1599
+
1600
+ static size_t ZSTD_decompressMultiFrame(ZSTD_DCtx* dctx,
1601
+ void* dst, size_t dstCapacity,
1602
+ const void* src, size_t srcSize,
1603
+ const void *dict, size_t dictSize,
1604
+ const ZSTD_DDict* ddict)
1605
+ {
1606
+ void* const dststart = dst;
1607
+
1608
+ if (ddict) {
1609
+ if (dict) {
1610
+ /* programmer error, these two cases should be mutually exclusive */
1611
+ return ERROR(GENERIC);
1612
+ }
1613
+
1614
+ dict = ZSTD_DDictDictContent(ddict);
1615
+ dictSize = ZSTD_DDictDictSize(ddict);
1616
+ }
1617
+
1618
+ while (srcSize >= ZSTD_frameHeaderSize_prefix) {
1619
+ U32 magicNumber;
1620
+
1621
+ #if defined(ZSTD_LEGACY_SUPPORT) && (ZSTD_LEGACY_SUPPORT >= 1)
1622
+ if (ZSTD_isLegacy(src, srcSize)) {
1623
+ size_t decodedSize;
1624
+ size_t const frameSize = ZSTD_findFrameCompressedSizeLegacy(src, srcSize);
1625
+ if (ZSTD_isError(frameSize)) return frameSize;
1626
+
1627
+ decodedSize = ZSTD_decompressLegacy(dst, dstCapacity, src, frameSize, dict, dictSize);
1628
+
1629
+ dst = (BYTE*)dst + decodedSize;
1630
+ dstCapacity -= decodedSize;
1631
+
1632
+ src = (const BYTE*)src + frameSize;
1633
+ srcSize -= frameSize;
1634
+
1635
+ continue;
1636
+ }
1637
+ #endif
1638
+
1639
+ magicNumber = MEM_readLE32(src);
1640
+ if (magicNumber != ZSTD_MAGICNUMBER) {
1641
+ if ((magicNumber & 0xFFFFFFF0U) == ZSTD_MAGIC_SKIPPABLE_START) {
1642
+ size_t skippableSize;
1643
+ if (srcSize < ZSTD_skippableHeaderSize)
1644
+ return ERROR(srcSize_wrong);
1645
+ skippableSize = MEM_readLE32((const BYTE *)src + 4) +
1646
+ ZSTD_skippableHeaderSize;
1647
+ if (srcSize < skippableSize) {
1648
+ return ERROR(srcSize_wrong);
1649
+ }
1650
+
1651
+ src = (const BYTE *)src + skippableSize;
1652
+ srcSize -= skippableSize;
1653
+ continue;
1654
+ } else {
1655
+ return ERROR(prefix_unknown);
1656
+ }
1657
+ }
1658
+
1659
+ if (ddict) {
1660
+ /* we were called from ZSTD_decompress_usingDDict */
1661
+ ZSTD_refDDict(dctx, ddict);
1662
+ } else {
1663
+ /* this will initialize correctly with no dict if dict == NULL, so
1664
+ * use this in all cases but ddict */
1665
+ CHECK_F(ZSTD_decompressBegin_usingDict(dctx, dict, dictSize));
1666
+ }
1667
+ ZSTD_checkContinuity(dctx, dst);
1668
+
1669
+ { const size_t res = ZSTD_decompressFrame(dctx, dst, dstCapacity,
1670
+ &src, &srcSize);
1671
+ if (ZSTD_isError(res)) return res;
1672
+ /* don't need to bounds check this, ZSTD_decompressFrame will have
1673
+ * already */
1674
+ dst = (BYTE*)dst + res;
1675
+ dstCapacity -= res;
1676
+ }
1677
+ }
1678
+
1679
+ if (srcSize) return ERROR(srcSize_wrong); /* input not entirely consumed */
1680
+
1681
+ return (BYTE*)dst - (BYTE*)dststart;
1682
+ }
1438
1683
 
1439
1684
  size_t ZSTD_decompress_usingDict(ZSTD_DCtx* dctx,
1440
1685
  void* dst, size_t dstCapacity,
1441
1686
  const void* src, size_t srcSize,
1442
1687
  const void* dict, size_t dictSize)
1443
1688
  {
1444
- #if defined(ZSTD_LEGACY_SUPPORT) && (ZSTD_LEGACY_SUPPORT==1)
1445
- if (ZSTD_isLegacy(src, srcSize)) return ZSTD_decompressLegacy(dst, dstCapacity, src, srcSize, dict, dictSize);
1446
- #endif
1447
- CHECK_F(ZSTD_decompressBegin_usingDict(dctx, dict, dictSize));
1448
- ZSTD_checkContinuity(dctx, dst);
1449
- return ZSTD_decompressFrame(dctx, dst, dstCapacity, src, srcSize);
1689
+ return ZSTD_decompressMultiFrame(dctx, dst, dstCapacity, src, srcSize, dict, dictSize, NULL);
1450
1690
  }
1451
1691
 
1452
1692
 
@@ -1633,22 +1873,29 @@ static size_t ZSTD_refDictContent(ZSTD_DCtx* dctx, const void* dict, size_t dict
1633
1873
  return 0;
1634
1874
  }
1635
1875
 
1636
- static size_t ZSTD_loadEntropy(ZSTD_DCtx* dctx, const void* const dict, size_t const dictSize)
1876
+ /* ZSTD_loadEntropy() :
1877
+ * dict : must point at beginning of a valid zstd dictionary
1878
+ * @return : size of entropy tables read */
1879
+ static size_t ZSTD_loadEntropy(ZSTD_entropyTables_t* entropy, const void* const dict, size_t const dictSize)
1637
1880
  {
1638
1881
  const BYTE* dictPtr = (const BYTE*)dict;
1639
1882
  const BYTE* const dictEnd = dictPtr + dictSize;
1640
1883
 
1641
- { size_t const hSize = HUF_readDTableX4(dctx->hufTable, dict, dictSize);
1884
+ if (dictSize <= 8) return ERROR(dictionary_corrupted);
1885
+ dictPtr += 8; /* skip header = magic + dictID */
1886
+
1887
+
1888
+ { size_t const hSize = HUF_readDTableX4(entropy->hufTable, dictPtr, dictEnd-dictPtr);
1642
1889
  if (HUF_isError(hSize)) return ERROR(dictionary_corrupted);
1643
1890
  dictPtr += hSize;
1644
1891
  }
1645
1892
 
1646
1893
  { short offcodeNCount[MaxOff+1];
1647
- U32 offcodeMaxValue=MaxOff, offcodeLog;
1894
+ U32 offcodeMaxValue = MaxOff, offcodeLog;
1648
1895
  size_t const offcodeHeaderSize = FSE_readNCount(offcodeNCount, &offcodeMaxValue, &offcodeLog, dictPtr, dictEnd-dictPtr);
1649
1896
  if (FSE_isError(offcodeHeaderSize)) return ERROR(dictionary_corrupted);
1650
1897
  if (offcodeLog > OffFSELog) return ERROR(dictionary_corrupted);
1651
- CHECK_E(FSE_buildDTable(dctx->OFTable, offcodeNCount, offcodeMaxValue, offcodeLog), dictionary_corrupted);
1898
+ CHECK_E(FSE_buildDTable(entropy->OFTable, offcodeNCount, offcodeMaxValue, offcodeLog), dictionary_corrupted);
1652
1899
  dictPtr += offcodeHeaderSize;
1653
1900
  }
1654
1901
 
@@ -1657,7 +1904,7 @@ static size_t ZSTD_loadEntropy(ZSTD_DCtx* dctx, const void* const dict, size_t c
1657
1904
  size_t const matchlengthHeaderSize = FSE_readNCount(matchlengthNCount, &matchlengthMaxValue, &matchlengthLog, dictPtr, dictEnd-dictPtr);
1658
1905
  if (FSE_isError(matchlengthHeaderSize)) return ERROR(dictionary_corrupted);
1659
1906
  if (matchlengthLog > MLFSELog) return ERROR(dictionary_corrupted);
1660
- CHECK_E(FSE_buildDTable(dctx->MLTable, matchlengthNCount, matchlengthMaxValue, matchlengthLog), dictionary_corrupted);
1907
+ CHECK_E(FSE_buildDTable(entropy->MLTable, matchlengthNCount, matchlengthMaxValue, matchlengthLog), dictionary_corrupted);
1661
1908
  dictPtr += matchlengthHeaderSize;
1662
1909
  }
1663
1910
 
@@ -1666,17 +1913,19 @@ static size_t ZSTD_loadEntropy(ZSTD_DCtx* dctx, const void* const dict, size_t c
1666
1913
  size_t const litlengthHeaderSize = FSE_readNCount(litlengthNCount, &litlengthMaxValue, &litlengthLog, dictPtr, dictEnd-dictPtr);
1667
1914
  if (FSE_isError(litlengthHeaderSize)) return ERROR(dictionary_corrupted);
1668
1915
  if (litlengthLog > LLFSELog) return ERROR(dictionary_corrupted);
1669
- CHECK_E(FSE_buildDTable(dctx->LLTable, litlengthNCount, litlengthMaxValue, litlengthLog), dictionary_corrupted);
1916
+ CHECK_E(FSE_buildDTable(entropy->LLTable, litlengthNCount, litlengthMaxValue, litlengthLog), dictionary_corrupted);
1670
1917
  dictPtr += litlengthHeaderSize;
1671
1918
  }
1672
1919
 
1673
1920
  if (dictPtr+12 > dictEnd) return ERROR(dictionary_corrupted);
1674
- dctx->rep[0] = MEM_readLE32(dictPtr+0); if (dctx->rep[0] == 0 || dctx->rep[0] >= dictSize) return ERROR(dictionary_corrupted);
1675
- dctx->rep[1] = MEM_readLE32(dictPtr+4); if (dctx->rep[1] == 0 || dctx->rep[1] >= dictSize) return ERROR(dictionary_corrupted);
1676
- dctx->rep[2] = MEM_readLE32(dictPtr+8); if (dctx->rep[2] == 0 || dctx->rep[2] >= dictSize) return ERROR(dictionary_corrupted);
1677
- dictPtr += 12;
1921
+ { int i;
1922
+ size_t const dictContentSize = (size_t)(dictEnd - (dictPtr+12));
1923
+ for (i=0; i<3; i++) {
1924
+ U32 const rep = MEM_readLE32(dictPtr); dictPtr += 4;
1925
+ if (rep==0 || rep >= dictContentSize) return ERROR(dictionary_corrupted);
1926
+ entropy->rep[i] = rep;
1927
+ } }
1678
1928
 
1679
- dctx->litEntropy = dctx->fseEntropy = 1;
1680
1929
  return dictPtr - (const BYTE*)dict;
1681
1930
  }
1682
1931
 
@@ -1690,13 +1939,12 @@ static size_t ZSTD_decompress_insertDictionary(ZSTD_DCtx* dctx, const void* dict
1690
1939
  dctx->dictID = MEM_readLE32((const char*)dict + 4);
1691
1940
 
1692
1941
  /* load entropy tables */
1693
- dict = (const char*)dict + 8;
1694
- dictSize -= 8;
1695
- { size_t const eSize = ZSTD_loadEntropy(dctx, dict, dictSize);
1942
+ { size_t const eSize = ZSTD_loadEntropy(&dctx->entropy, dict, dictSize);
1696
1943
  if (ZSTD_isError(eSize)) return ERROR(dictionary_corrupted);
1697
1944
  dict = (const char*)dict + eSize;
1698
1945
  dictSize -= eSize;
1699
1946
  }
1947
+ dctx->litEntropy = dctx->fseEntropy = 1;
1700
1948
 
1701
1949
  /* reference dictionary content */
1702
1950
  return ZSTD_refDictContent(dctx, dict, dictSize);
@@ -1716,50 +1964,101 @@ struct ZSTD_DDict_s {
1716
1964
  void* dictBuffer;
1717
1965
  const void* dictContent;
1718
1966
  size_t dictSize;
1719
- ZSTD_DCtx* refContext;
1967
+ ZSTD_entropyTables_t entropy;
1968
+ U32 dictID;
1969
+ U32 entropyPresent;
1970
+ ZSTD_customMem cMem;
1720
1971
  }; /* typedef'd to ZSTD_DDict within "zstd.h" */
1721
1972
 
1973
+ static const void* ZSTD_DDictDictContent(const ZSTD_DDict* ddict)
1974
+ {
1975
+ return ddict->dictContent;
1976
+ }
1977
+
1978
+ static size_t ZSTD_DDictDictSize(const ZSTD_DDict* ddict)
1979
+ {
1980
+ return ddict->dictSize;
1981
+ }
1982
+
1983
+ static void ZSTD_refDDict(ZSTD_DCtx* dstDCtx, const ZSTD_DDict* ddict)
1984
+ {
1985
+ ZSTD_decompressBegin(dstDCtx); /* init */
1986
+ if (ddict) { /* support refDDict on NULL */
1987
+ dstDCtx->dictID = ddict->dictID;
1988
+ dstDCtx->base = ddict->dictContent;
1989
+ dstDCtx->vBase = ddict->dictContent;
1990
+ dstDCtx->dictEnd = (const BYTE*)ddict->dictContent + ddict->dictSize;
1991
+ dstDCtx->previousDstEnd = dstDCtx->dictEnd;
1992
+ if (ddict->entropyPresent) {
1993
+ dstDCtx->litEntropy = 1;
1994
+ dstDCtx->fseEntropy = 1;
1995
+ dstDCtx->LLTptr = ddict->entropy.LLTable;
1996
+ dstDCtx->MLTptr = ddict->entropy.MLTable;
1997
+ dstDCtx->OFTptr = ddict->entropy.OFTable;
1998
+ dstDCtx->HUFptr = ddict->entropy.hufTable;
1999
+ dstDCtx->entropy.rep[0] = ddict->entropy.rep[0];
2000
+ dstDCtx->entropy.rep[1] = ddict->entropy.rep[1];
2001
+ dstDCtx->entropy.rep[2] = ddict->entropy.rep[2];
2002
+ } else {
2003
+ dstDCtx->litEntropy = 0;
2004
+ dstDCtx->fseEntropy = 0;
2005
+ }
2006
+ }
2007
+ }
2008
+
2009
+ static size_t ZSTD_loadEntropy_inDDict(ZSTD_DDict* ddict)
2010
+ {
2011
+ ddict->dictID = 0;
2012
+ ddict->entropyPresent = 0;
2013
+ if (ddict->dictSize < 8) return 0;
2014
+ { U32 const magic = MEM_readLE32(ddict->dictContent);
2015
+ if (magic != ZSTD_DICT_MAGIC) return 0; /* pure content mode */
2016
+ }
2017
+ ddict->dictID = MEM_readLE32((const char*)ddict->dictContent + 4);
2018
+
2019
+ /* load entropy tables */
2020
+ CHECK_E( ZSTD_loadEntropy(&ddict->entropy, ddict->dictContent, ddict->dictSize), dictionary_corrupted );
2021
+ ddict->entropyPresent = 1;
2022
+ return 0;
2023
+ }
2024
+
2025
+
1722
2026
  ZSTD_DDict* ZSTD_createDDict_advanced(const void* dict, size_t dictSize, unsigned byReference, ZSTD_customMem customMem)
1723
2027
  {
1724
2028
  if (!customMem.customAlloc && !customMem.customFree) customMem = defaultCustomMem;
1725
2029
  if (!customMem.customAlloc || !customMem.customFree) return NULL;
1726
2030
 
1727
2031
  { ZSTD_DDict* const ddict = (ZSTD_DDict*) ZSTD_malloc(sizeof(ZSTD_DDict), customMem);
1728
- ZSTD_DCtx* const dctx = ZSTD_createDCtx_advanced(customMem);
1729
-
1730
- if (!ddict || !dctx) {
1731
- ZSTD_free(ddict, customMem);
1732
- ZSTD_free(dctx, customMem);
1733
- return NULL;
1734
- }
2032
+ if (!ddict) return NULL;
2033
+ ddict->cMem = customMem;
1735
2034
 
1736
2035
  if ((byReference) || (!dict) || (!dictSize)) {
1737
2036
  ddict->dictBuffer = NULL;
1738
2037
  ddict->dictContent = dict;
1739
2038
  } else {
1740
2039
  void* const internalBuffer = ZSTD_malloc(dictSize, customMem);
1741
- if (!internalBuffer) { ZSTD_free(dctx, customMem); ZSTD_free(ddict, customMem); return NULL; }
2040
+ if (!internalBuffer) { ZSTD_freeDDict(ddict); return NULL; }
1742
2041
  memcpy(internalBuffer, dict, dictSize);
1743
2042
  ddict->dictBuffer = internalBuffer;
1744
2043
  ddict->dictContent = internalBuffer;
1745
2044
  }
1746
- { size_t const errorCode = ZSTD_decompressBegin_usingDict(dctx, ddict->dictContent, dictSize);
2045
+ ddict->dictSize = dictSize;
2046
+ ddict->entropy.hufTable[0] = (HUF_DTable)((HufLog)*0x1000001); /* cover both little and big endian */
2047
+ /* parse dictionary content */
2048
+ { size_t const errorCode = ZSTD_loadEntropy_inDDict(ddict);
1747
2049
  if (ZSTD_isError(errorCode)) {
1748
- ZSTD_free(ddict->dictBuffer, customMem);
1749
- ZSTD_free(ddict, customMem);
1750
- ZSTD_free(dctx, customMem);
2050
+ ZSTD_freeDDict(ddict);
1751
2051
  return NULL;
1752
2052
  } }
1753
2053
 
1754
- ddict->dictSize = dictSize;
1755
- ddict->refContext = dctx;
1756
2054
  return ddict;
1757
2055
  }
1758
2056
  }
1759
2057
 
1760
2058
  /*! ZSTD_createDDict() :
1761
- * Create a digested dictionary, ready to start decompression without startup delay.
1762
- * `dict` can be released after `ZSTD_DDict` creation */
2059
+ * Create a digested dictionary, to start decompression without startup delay.
2060
+ * `dict` content is copied inside DDict.
2061
+ * Consequently, `dict` can be released after `ZSTD_DDict` creation */
1763
2062
  ZSTD_DDict* ZSTD_createDDict(const void* dict, size_t dictSize)
1764
2063
  {
1765
2064
  ZSTD_customMem const allocator = { NULL, NULL, NULL };
@@ -1768,9 +2067,9 @@ ZSTD_DDict* ZSTD_createDDict(const void* dict, size_t dictSize)
1768
2067
 
1769
2068
 
1770
2069
  /*! ZSTD_createDDict_byReference() :
1771
- * Create a digested dictionary, ready to start decompression operation without startup delay.
1772
- * Dictionary content is simply referenced, and therefore stays in dictBuffer.
1773
- * It is important that dictBuffer outlives DDict, it must remain read accessible throughout the lifetime of DDict */
2070
+ * Create a digested dictionary, to start decompression without startup delay.
2071
+ * Dictionary content is simply referenced, it will be accessed during decompression.
2072
+ * Warning : dictBuffer must outlive DDict (DDict must be freed before dictBuffer) */
1774
2073
  ZSTD_DDict* ZSTD_createDDict_byReference(const void* dictBuffer, size_t dictSize)
1775
2074
  {
1776
2075
  ZSTD_customMem const allocator = { NULL, NULL, NULL };
@@ -1781,8 +2080,7 @@ ZSTD_DDict* ZSTD_createDDict_byReference(const void* dictBuffer, size_t dictSize
1781
2080
  size_t ZSTD_freeDDict(ZSTD_DDict* ddict)
1782
2081
  {
1783
2082
  if (ddict==NULL) return 0; /* support free on NULL */
1784
- { ZSTD_customMem const cMem = ddict->refContext->customMem;
1785
- ZSTD_freeDCtx(ddict->refContext);
2083
+ { ZSTD_customMem const cMem = ddict->cMem;
1786
2084
  ZSTD_free(ddict->dictBuffer, cMem);
1787
2085
  ZSTD_free(ddict, cMem);
1788
2086
  return 0;
@@ -1792,7 +2090,7 @@ size_t ZSTD_freeDDict(ZSTD_DDict* ddict)
1792
2090
  size_t ZSTD_sizeof_DDict(const ZSTD_DDict* ddict)
1793
2091
  {
1794
2092
  if (ddict==NULL) return 0; /* support sizeof on NULL */
1795
- return sizeof(*ddict) + ZSTD_sizeof_DCtx(ddict->refContext) + (ddict->dictBuffer ? ddict->dictSize : 0) ;
2093
+ return sizeof(*ddict) + (ddict->dictBuffer ? ddict->dictSize : 0) ;
1796
2094
  }
1797
2095
 
1798
2096
  /*! ZSTD_getDictID_fromDict() :
@@ -1843,12 +2141,10 @@ size_t ZSTD_decompress_usingDDict(ZSTD_DCtx* dctx,
1843
2141
  const void* src, size_t srcSize,
1844
2142
  const ZSTD_DDict* ddict)
1845
2143
  {
1846
- #if defined(ZSTD_LEGACY_SUPPORT) && (ZSTD_LEGACY_SUPPORT==1)
1847
- if (ZSTD_isLegacy(src, srcSize)) return ZSTD_decompressLegacy(dst, dstCapacity, src, srcSize, ddict->dictContent, ddict->dictSize);
1848
- #endif
1849
- ZSTD_refDCtx(dctx, ddict->refContext);
1850
- ZSTD_checkContinuity(dctx, dst);
1851
- return ZSTD_decompressFrame(dctx, dst, dstCapacity, src, srcSize);
2144
+ /* pass content and size in case legacy frames are encountered */
2145
+ return ZSTD_decompressMultiFrame(dctx, dst, dstCapacity, src, srcSize,
2146
+ NULL, 0,
2147
+ ddict);
1852
2148
  }
1853
2149
 
1854
2150
 
@@ -2048,10 +2344,23 @@ size_t ZSTD_decompressStream(ZSTD_DStream* zds, ZSTD_outBuffer* output, ZSTD_inB
2048
2344
  break;
2049
2345
  } }
2050
2346
 
2347
+ /* check for single-pass mode opportunity */
2348
+ if (zds->fParams.frameContentSize && zds->fParams.windowSize /* skippable frame if == 0 */
2349
+ && (U64)(size_t)(oend-op) >= zds->fParams.frameContentSize) {
2350
+ size_t const cSize = ZSTD_findFrameCompressedSize(istart, iend-istart);
2351
+ if (cSize <= (size_t)(iend-istart)) {
2352
+ size_t const decompressedSize = ZSTD_decompress_usingDDict(zds->dctx, op, oend-op, istart, cSize, zds->ddict);
2353
+ if (ZSTD_isError(decompressedSize)) return decompressedSize;
2354
+ ip = istart + cSize;
2355
+ op += decompressedSize;
2356
+ zds->dctx->expected = 0;
2357
+ zds->stage = zdss_init;
2358
+ someMoreWork = 0;
2359
+ break;
2360
+ } }
2361
+
2051
2362
  /* Consume header */
2052
- { const ZSTD_DCtx* refContext = zds->ddict ? zds->ddict->refContext : NULL;
2053
- ZSTD_refDCtx(zds->dctx, refContext);
2054
- }
2363
+ ZSTD_refDDict(zds->dctx, zds->ddict);
2055
2364
  { size_t const h1Size = ZSTD_nextSrcSizeToDecompress(zds->dctx); /* == ZSTD_frameHeaderSize_prefix */
2056
2365
  CHECK_F(ZSTD_decompressContinue(zds->dctx, NULL, 0, zds->headerBuffer, h1Size));
2057
2366
  { size_t const h2Size = ZSTD_nextSrcSizeToDecompress(zds->dctx);
@@ -2063,7 +2372,7 @@ size_t ZSTD_decompressStream(ZSTD_DStream* zds, ZSTD_outBuffer* output, ZSTD_inB
2063
2372
 
2064
2373
  /* Adapt buffer sizes to frame header instructions */
2065
2374
  { size_t const blockSize = MIN(zds->fParams.windowSize, ZSTD_BLOCKSIZE_ABSOLUTEMAX);
2066
- size_t const neededOutSize = zds->fParams.windowSize + blockSize;
2375
+ size_t const neededOutSize = zds->fParams.windowSize + blockSize + WILDCOPY_OVERLENGTH * 2;
2067
2376
  zds->blockSize = blockSize;
2068
2377
  if (zds->inBuffSize < blockSize) {
2069
2378
  ZSTD_free(zds->inBuff, zds->customMem);