extzstd 0.1.1 → 0.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (85) hide show
  1. checksums.yaml +5 -5
  2. data/HISTORY.ja.md +18 -0
  3. data/README.md +15 -50
  4. data/contrib/zstd/CONTRIBUTING.md +1 -1
  5. data/contrib/zstd/COPYING +339 -0
  6. data/contrib/zstd/Makefile +82 -51
  7. data/contrib/zstd/NEWS +92 -5
  8. data/contrib/zstd/README.md +50 -41
  9. data/contrib/zstd/appveyor.yml +164 -102
  10. data/contrib/zstd/circle.yml +10 -22
  11. data/contrib/zstd/lib/BUCK +31 -10
  12. data/contrib/zstd/lib/Makefile +57 -31
  13. data/contrib/zstd/lib/README.md +68 -37
  14. data/contrib/zstd/lib/common/bitstream.h +130 -76
  15. data/contrib/zstd/lib/common/compiler.h +86 -0
  16. data/contrib/zstd/lib/common/error_private.c +15 -11
  17. data/contrib/zstd/lib/common/error_private.h +8 -8
  18. data/contrib/zstd/lib/common/fse.h +19 -9
  19. data/contrib/zstd/lib/common/fse_decompress.c +3 -22
  20. data/contrib/zstd/lib/common/huf.h +68 -26
  21. data/contrib/zstd/lib/common/mem.h +23 -35
  22. data/contrib/zstd/lib/common/pool.c +123 -63
  23. data/contrib/zstd/lib/common/pool.h +19 -10
  24. data/contrib/zstd/lib/common/threading.c +11 -16
  25. data/contrib/zstd/lib/common/threading.h +52 -33
  26. data/contrib/zstd/lib/common/xxhash.c +28 -22
  27. data/contrib/zstd/lib/common/zstd_common.c +40 -27
  28. data/contrib/zstd/lib/common/zstd_errors.h +43 -34
  29. data/contrib/zstd/lib/common/zstd_internal.h +131 -123
  30. data/contrib/zstd/lib/compress/fse_compress.c +17 -33
  31. data/contrib/zstd/lib/compress/huf_compress.c +15 -9
  32. data/contrib/zstd/lib/compress/zstd_compress.c +2096 -2363
  33. data/contrib/zstd/lib/compress/zstd_compress_internal.h +462 -0
  34. data/contrib/zstd/lib/compress/zstd_double_fast.c +309 -0
  35. data/contrib/zstd/lib/compress/zstd_double_fast.h +29 -0
  36. data/contrib/zstd/lib/compress/zstd_fast.c +243 -0
  37. data/contrib/zstd/lib/compress/zstd_fast.h +31 -0
  38. data/contrib/zstd/lib/compress/zstd_lazy.c +765 -0
  39. data/contrib/zstd/lib/compress/zstd_lazy.h +39 -0
  40. data/contrib/zstd/lib/compress/zstd_ldm.c +707 -0
  41. data/contrib/zstd/lib/compress/zstd_ldm.h +68 -0
  42. data/contrib/zstd/lib/compress/zstd_opt.c +785 -0
  43. data/contrib/zstd/lib/compress/zstd_opt.h +19 -908
  44. data/contrib/zstd/lib/compress/zstdmt_compress.c +737 -327
  45. data/contrib/zstd/lib/compress/zstdmt_compress.h +88 -26
  46. data/contrib/zstd/lib/decompress/huf_decompress.c +158 -50
  47. data/contrib/zstd/lib/decompress/zstd_decompress.c +884 -699
  48. data/contrib/zstd/lib/deprecated/zbuff.h +5 -4
  49. data/contrib/zstd/lib/deprecated/zbuff_common.c +5 -5
  50. data/contrib/zstd/lib/deprecated/zbuff_compress.c +6 -4
  51. data/contrib/zstd/lib/deprecated/zbuff_decompress.c +5 -4
  52. data/contrib/zstd/lib/dictBuilder/cover.c +93 -77
  53. data/contrib/zstd/lib/dictBuilder/zdict.c +107 -92
  54. data/contrib/zstd/lib/dictBuilder/zdict.h +112 -102
  55. data/contrib/zstd/lib/legacy/zstd_legacy.h +9 -4
  56. data/contrib/zstd/lib/legacy/zstd_v01.c +7 -6
  57. data/contrib/zstd/lib/legacy/zstd_v01.h +5 -4
  58. data/contrib/zstd/lib/legacy/zstd_v02.c +27 -99
  59. data/contrib/zstd/lib/legacy/zstd_v02.h +5 -4
  60. data/contrib/zstd/lib/legacy/zstd_v03.c +26 -98
  61. data/contrib/zstd/lib/legacy/zstd_v03.h +5 -4
  62. data/contrib/zstd/lib/legacy/zstd_v04.c +22 -91
  63. data/contrib/zstd/lib/legacy/zstd_v04.h +5 -4
  64. data/contrib/zstd/lib/legacy/zstd_v05.c +23 -99
  65. data/contrib/zstd/lib/legacy/zstd_v05.h +5 -4
  66. data/contrib/zstd/lib/legacy/zstd_v06.c +22 -96
  67. data/contrib/zstd/lib/legacy/zstd_v06.h +5 -4
  68. data/contrib/zstd/lib/legacy/zstd_v07.c +19 -95
  69. data/contrib/zstd/lib/legacy/zstd_v07.h +5 -4
  70. data/contrib/zstd/lib/zstd.h +895 -271
  71. data/ext/extconf.rb +11 -2
  72. data/ext/extzstd.c +45 -128
  73. data/ext/extzstd.h +74 -31
  74. data/ext/extzstd_stream.c +401 -142
  75. data/ext/zstd_common.c +5 -0
  76. data/ext/zstd_compress.c +8 -0
  77. data/ext/zstd_decompress.c +1 -0
  78. data/ext/zstd_dictbuilder.c +2 -0
  79. data/lib/extzstd/version.rb +1 -1
  80. data/lib/extzstd.rb +48 -1
  81. data/test/test_basic.rb +9 -1
  82. metadata +17 -7
  83. data/HISTORY.ja +0 -10
  84. data/contrib/zstd/LICENSE-examples +0 -11
  85. data/contrib/zstd/PATENTS +0 -33
@@ -1,10 +1,11 @@
1
- /**
1
+ /*
2
2
  * Copyright (c) 2016-present, Yann Collet, Facebook, Inc.
3
3
  * All rights reserved.
4
4
  *
5
- * This source code is licensed under the BSD-style license found in the
6
- * LICENSE file in the root directory of this source tree. An additional grant
7
- * of patent rights can be found in the PATENTS file in the same directory.
5
+ * This source code is licensed under both the BSD-style license (found in the
6
+ * LICENSE file in the root directory of this source tree) and the GPLv2 (found
7
+ * in the COPYING file in the root directory of this source tree).
8
+ * You may select, at your option, one of the above-listed licenses.
8
9
  */
9
10
 
10
11
 
@@ -34,7 +35,7 @@
34
35
  * Frames requiring more memory will be rejected.
35
36
  */
36
37
  #ifndef ZSTD_MAXWINDOWSIZE_DEFAULT
37
- # define ZSTD_MAXWINDOWSIZE_DEFAULT ((1 << ZSTD_WINDOWLOG_MAX) + 1) /* defined within zstd.h */
38
+ # define ZSTD_MAXWINDOWSIZE_DEFAULT (((U32)1 << ZSTD_WINDOWLOG_DEFAULTMAX) + 1)
38
39
  #endif
39
40
 
40
41
 
@@ -54,17 +55,8 @@
54
55
  #endif
55
56
 
56
57
 
57
- #if defined(_MSC_VER)
58
- # include <mmintrin.h> /* https://msdn.microsoft.com/fr-fr/library/84szxsww(v=vs.90).aspx */
59
- # define ZSTD_PREFETCH(ptr) _mm_prefetch((const char*)ptr, _MM_HINT_T0)
60
- #elif defined(__GNUC__)
61
- # define ZSTD_PREFETCH(ptr) __builtin_prefetch(ptr, 0, 0)
62
- #else
63
- # define ZSTD_PREFETCH(ptr) /* disabled */
64
- #endif
65
-
66
58
  /*-*************************************
67
- * Macros
59
+ * Errors
68
60
  ***************************************/
69
61
  #define ZSTD_isError ERR_isError /* for inlining */
70
62
  #define FSE_isError ERR_isError
@@ -85,13 +77,17 @@ typedef enum { ZSTDds_getFrameHeaderSize, ZSTDds_decodeFrameHeader,
85
77
  ZSTDds_decompressLastBlock, ZSTDds_checkChecksum,
86
78
  ZSTDds_decodeSkippableHeader, ZSTDds_skipFrame } ZSTD_dStage;
87
79
 
80
+ typedef enum { zdss_init=0, zdss_loadHeader,
81
+ zdss_read, zdss_load, zdss_flush } ZSTD_dStreamStage;
82
+
88
83
  typedef struct {
89
84
  FSE_DTable LLTable[FSE_DTABLE_SIZE_U32(LLFSELog)];
90
85
  FSE_DTable OFTable[FSE_DTABLE_SIZE_U32(OffFSELog)];
91
86
  FSE_DTable MLTable[FSE_DTABLE_SIZE_U32(MLFSELog)];
92
87
  HUF_DTable hufTable[HUF_DTABLE_SIZE(HufLog)]; /* can accommodate HUF_decompress4X */
88
+ U32 workspace[HUF_DECOMPRESS_WORKSPACE_SIZE_U32];
93
89
  U32 rep[ZSTD_REP_NUM];
94
- } ZSTD_entropyTables_t;
90
+ } ZSTD_entropyDTables_t;
95
91
 
96
92
  struct ZSTD_DCtx_s
97
93
  {
@@ -99,109 +95,142 @@ struct ZSTD_DCtx_s
99
95
  const FSE_DTable* MLTptr;
100
96
  const FSE_DTable* OFTptr;
101
97
  const HUF_DTable* HUFptr;
102
- ZSTD_entropyTables_t entropy;
98
+ ZSTD_entropyDTables_t entropy;
103
99
  const void* previousDstEnd; /* detect continuity */
104
100
  const void* base; /* start of current segment */
105
101
  const void* vBase; /* virtual start of previous segment if it was just before current one */
106
102
  const void* dictEnd; /* end of previous segment */
107
103
  size_t expected;
108
- ZSTD_frameParams fParams;
109
- blockType_e bType; /* used in ZSTD_decompressContinue(), to transfer blockType between header decoding and block decoding stages */
104
+ ZSTD_frameHeader fParams;
105
+ U64 decodedSize;
106
+ blockType_e bType; /* used in ZSTD_decompressContinue(), store blockType between block header decoding and block decompression stages */
110
107
  ZSTD_dStage stage;
111
108
  U32 litEntropy;
112
109
  U32 fseEntropy;
113
110
  XXH64_state_t xxhState;
114
111
  size_t headerSize;
115
112
  U32 dictID;
113
+ ZSTD_format_e format;
116
114
  const BYTE* litPtr;
117
115
  ZSTD_customMem customMem;
118
116
  size_t litSize;
119
117
  size_t rleSize;
120
- BYTE litBuffer[ZSTD_BLOCKSIZE_ABSOLUTEMAX + WILDCOPY_OVERLENGTH];
118
+ size_t staticSize;
119
+
120
+ /* streaming */
121
+ ZSTD_DDict* ddictLocal;
122
+ const ZSTD_DDict* ddict;
123
+ ZSTD_dStreamStage streamStage;
124
+ char* inBuff;
125
+ size_t inBuffSize;
126
+ size_t inPos;
127
+ size_t maxWindowSize;
128
+ char* outBuff;
129
+ size_t outBuffSize;
130
+ size_t outStart;
131
+ size_t outEnd;
132
+ size_t lhSize;
133
+ void* legacyContext;
134
+ U32 previousLegacyVersion;
135
+ U32 legacyVersion;
136
+ U32 hostageByte;
137
+
138
+ /* workspace */
139
+ BYTE litBuffer[ZSTD_BLOCKSIZE_MAX + WILDCOPY_OVERLENGTH];
121
140
  BYTE headerBuffer[ZSTD_FRAMEHEADERSIZE_MAX];
122
141
  }; /* typedef'd to ZSTD_DCtx within "zstd.h" */
123
142
 
124
- size_t ZSTD_sizeof_DCtx (const ZSTD_DCtx* dctx) { return (dctx==NULL) ? 0 : sizeof(ZSTD_DCtx); }
143
+ size_t ZSTD_sizeof_DCtx (const ZSTD_DCtx* dctx)
144
+ {
145
+ if (dctx==NULL) return 0; /* support sizeof NULL */
146
+ return sizeof(*dctx)
147
+ + ZSTD_sizeof_DDict(dctx->ddictLocal)
148
+ + dctx->inBuffSize + dctx->outBuffSize;
149
+ }
125
150
 
126
151
  size_t ZSTD_estimateDCtxSize(void) { return sizeof(ZSTD_DCtx); }
127
152
 
128
- size_t ZSTD_decompressBegin(ZSTD_DCtx* dctx)
153
+
154
+ static size_t ZSTD_startingInputLength(ZSTD_format_e format)
129
155
  {
130
- dctx->expected = ZSTD_frameHeaderSize_prefix;
131
- dctx->stage = ZSTDds_getFrameHeaderSize;
132
- dctx->previousDstEnd = NULL;
133
- dctx->base = NULL;
134
- dctx->vBase = NULL;
135
- dctx->dictEnd = NULL;
136
- dctx->entropy.hufTable[0] = (HUF_DTable)((HufLog)*0x1000001); /* cover both little and big endian */
137
- dctx->litEntropy = dctx->fseEntropy = 0;
138
- dctx->dictID = 0;
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;
145
- return 0;
156
+ size_t const startingInputLength = (format==ZSTD_f_zstd1_magicless) ?
157
+ ZSTD_frameHeaderSize_prefix - ZSTD_frameIdSize :
158
+ ZSTD_frameHeaderSize_prefix;
159
+ ZSTD_STATIC_ASSERT(ZSTD_FRAMEHEADERSIZE_PREFIX >= ZSTD_FRAMEIDSIZE);
160
+ /* only supports formats ZSTD_f_zstd1 and ZSTD_f_zstd1_magicless */
161
+ assert( (format == ZSTD_f_zstd1) || (format == ZSTD_f_zstd1_magicless) );
162
+ return startingInputLength;
146
163
  }
147
164
 
148
- ZSTD_DCtx* ZSTD_createDCtx_advanced(ZSTD_customMem customMem)
165
+ static void ZSTD_initDCtx_internal(ZSTD_DCtx* dctx)
166
+ {
167
+ dctx->format = ZSTD_f_zstd1; /* ZSTD_decompressBegin() invokes ZSTD_startingInputLength() with argument dctx->format */
168
+ dctx->staticSize = 0;
169
+ dctx->maxWindowSize = ZSTD_MAXWINDOWSIZE_DEFAULT;
170
+ dctx->ddict = NULL;
171
+ dctx->ddictLocal = NULL;
172
+ dctx->inBuff = NULL;
173
+ dctx->inBuffSize = 0;
174
+ dctx->outBuffSize = 0;
175
+ dctx->streamStage = zdss_init;
176
+ }
177
+
178
+ ZSTD_DCtx* ZSTD_initStaticDCtx(void *workspace, size_t workspaceSize)
149
179
  {
150
- ZSTD_DCtx* dctx;
180
+ ZSTD_DCtx* const dctx = (ZSTD_DCtx*) workspace;
151
181
 
152
- if (!customMem.customAlloc && !customMem.customFree) customMem = defaultCustomMem;
153
- if (!customMem.customAlloc || !customMem.customFree) return NULL;
182
+ if ((size_t)workspace & 7) return NULL; /* 8-aligned */
183
+ if (workspaceSize < sizeof(ZSTD_DCtx)) return NULL; /* minimum size */
154
184
 
155
- dctx = (ZSTD_DCtx*)ZSTD_malloc(sizeof(ZSTD_DCtx), customMem);
156
- if (!dctx) return NULL;
157
- memcpy(&dctx->customMem, &customMem, sizeof(customMem));
158
- ZSTD_decompressBegin(dctx);
185
+ ZSTD_initDCtx_internal(dctx);
186
+ dctx->staticSize = workspaceSize;
187
+ dctx->inBuff = (char*)(dctx+1);
159
188
  return dctx;
160
189
  }
161
190
 
191
+ ZSTD_DCtx* ZSTD_createDCtx_advanced(ZSTD_customMem customMem)
192
+ {
193
+ if (!customMem.customAlloc ^ !customMem.customFree) return NULL;
194
+
195
+ { ZSTD_DCtx* const dctx = (ZSTD_DCtx*)ZSTD_malloc(sizeof(*dctx), customMem);
196
+ if (!dctx) return NULL;
197
+ dctx->customMem = customMem;
198
+ dctx->legacyContext = NULL;
199
+ dctx->previousLegacyVersion = 0;
200
+ ZSTD_initDCtx_internal(dctx);
201
+ return dctx;
202
+ }
203
+ }
204
+
162
205
  ZSTD_DCtx* ZSTD_createDCtx(void)
163
206
  {
164
- return ZSTD_createDCtx_advanced(defaultCustomMem);
207
+ return ZSTD_createDCtx_advanced(ZSTD_defaultCMem);
165
208
  }
166
209
 
167
210
  size_t ZSTD_freeDCtx(ZSTD_DCtx* dctx)
168
211
  {
169
212
  if (dctx==NULL) return 0; /* support free on NULL */
170
- ZSTD_free(dctx, dctx->customMem);
171
- return 0; /* reserved as a potential error code in the future */
213
+ if (dctx->staticSize) return ERROR(memory_allocation); /* not compatible with static DCtx */
214
+ { ZSTD_customMem const cMem = dctx->customMem;
215
+ ZSTD_freeDDict(dctx->ddictLocal);
216
+ dctx->ddictLocal = NULL;
217
+ ZSTD_free(dctx->inBuff, cMem);
218
+ dctx->inBuff = NULL;
219
+ #if defined(ZSTD_LEGACY_SUPPORT) && (ZSTD_LEGACY_SUPPORT >= 1)
220
+ if (dctx->legacyContext)
221
+ ZSTD_freeLegacyStreamContext(dctx->legacyContext, dctx->previousLegacyVersion);
222
+ #endif
223
+ ZSTD_free(dctx, cMem);
224
+ return 0;
225
+ }
172
226
  }
173
227
 
228
+ /* no longer useful */
174
229
  void ZSTD_copyDCtx(ZSTD_DCtx* dstDCtx, const ZSTD_DCtx* srcDCtx)
175
230
  {
176
- size_t const workSpaceSize = (ZSTD_BLOCKSIZE_ABSOLUTEMAX+WILDCOPY_OVERLENGTH) + ZSTD_frameHeaderSize_max;
177
- memcpy(dstDCtx, srcDCtx, sizeof(ZSTD_DCtx) - workSpaceSize); /* no need to copy workspace */
178
- }
179
-
180
- #if 0
181
- /* deprecated */
182
- static void ZSTD_refDCtx(ZSTD_DCtx* dstDCtx, const ZSTD_DCtx* srcDCtx)
183
- {
184
- ZSTD_decompressBegin(dstDCtx); /* init */
185
- if (srcDCtx) { /* support refDCtx on NULL */
186
- dstDCtx->dictEnd = srcDCtx->dictEnd;
187
- dstDCtx->vBase = srcDCtx->vBase;
188
- dstDCtx->base = srcDCtx->base;
189
- dstDCtx->previousDstEnd = srcDCtx->previousDstEnd;
190
- dstDCtx->dictID = srcDCtx->dictID;
191
- dstDCtx->litEntropy = srcDCtx->litEntropy;
192
- dstDCtx->fseEntropy = srcDCtx->fseEntropy;
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];
200
- }
231
+ size_t const toCopy = (size_t)((char*)(&dstDCtx->inBuff) - (char*)dstDCtx);
232
+ memcpy(dstDCtx, srcDCtx, toCopy); /* no need to copy workspace */
201
233
  }
202
- #endif
203
-
204
- static void ZSTD_refDDict(ZSTD_DCtx* dstDCtx, const ZSTD_DDict* ddict);
205
234
 
206
235
 
207
236
  /*-*************************************************************
@@ -215,7 +244,7 @@ static void ZSTD_refDDict(ZSTD_DCtx* dstDCtx, const ZSTD_DDict* ddict);
215
244
  * Note 3 : Skippable Frame Identifiers are considered valid. */
216
245
  unsigned ZSTD_isFrame(const void* buffer, size_t size)
217
246
  {
218
- if (size < 4) return 0;
247
+ if (size < ZSTD_frameIdSize) return 0;
219
248
  { U32 const magic = MEM_readLE32(buffer);
220
249
  if (magic == ZSTD_MAGICNUMBER) return 1;
221
250
  if ((magic & 0xFFFFFFF0U) == ZSTD_MAGIC_SKIPPABLE_START) return 1;
@@ -226,70 +255,91 @@ unsigned ZSTD_isFrame(const void* buffer, size_t size)
226
255
  return 0;
227
256
  }
228
257
 
229
-
230
- /** ZSTD_frameHeaderSize() :
231
- * srcSize must be >= ZSTD_frameHeaderSize_prefix.
232
- * @return : size of the Frame Header */
233
- static size_t ZSTD_frameHeaderSize(const void* src, size_t srcSize)
258
+ /** ZSTD_frameHeaderSize_internal() :
259
+ * srcSize must be large enough to reach header size fields.
260
+ * note : only works for formats ZSTD_f_zstd1 and ZSTD_f_zstd1_magicless
261
+ * @return : size of the Frame Header
262
+ * or an error code, which can be tested with ZSTD_isError() */
263
+ static size_t ZSTD_frameHeaderSize_internal(const void* src, size_t srcSize, ZSTD_format_e format)
234
264
  {
235
- if (srcSize < ZSTD_frameHeaderSize_prefix) return ERROR(srcSize_wrong);
236
- { BYTE const fhd = ((const BYTE*)src)[4];
265
+ size_t const minInputSize = ZSTD_startingInputLength(format);
266
+ if (srcSize < minInputSize) return ERROR(srcSize_wrong);
267
+
268
+ { BYTE const fhd = ((const BYTE*)src)[minInputSize-1];
237
269
  U32 const dictID= fhd & 3;
238
270
  U32 const singleSegment = (fhd >> 5) & 1;
239
271
  U32 const fcsId = fhd >> 6;
240
- return ZSTD_frameHeaderSize_prefix + !singleSegment + ZSTD_did_fieldSize[dictID] + ZSTD_fcs_fieldSize[fcsId]
241
- + (singleSegment && !fcsId);
272
+ return minInputSize + !singleSegment
273
+ + ZSTD_did_fieldSize[dictID] + ZSTD_fcs_fieldSize[fcsId]
274
+ + (singleSegment && !fcsId);
242
275
  }
243
276
  }
244
277
 
278
+ /** ZSTD_frameHeaderSize() :
279
+ * srcSize must be >= ZSTD_frameHeaderSize_prefix.
280
+ * @return : size of the Frame Header */
281
+ size_t ZSTD_frameHeaderSize(const void* src, size_t srcSize)
282
+ {
283
+ return ZSTD_frameHeaderSize_internal(src, srcSize, ZSTD_f_zstd1);
284
+ }
285
+
245
286
 
246
- /** ZSTD_getFrameParams() :
247
- * decode Frame Header, or require larger `srcSize`.
248
- * @return : 0, `fparamsPtr` is correctly filled,
249
- * >0, `srcSize` is too small, result is expected `srcSize`,
250
- * or an error code, which can be tested using ZSTD_isError() */
251
- size_t ZSTD_getFrameParams(ZSTD_frameParams* fparamsPtr, const void* src, size_t srcSize)
287
+ /** ZSTD_getFrameHeader_internal() :
288
+ * decode Frame Header, or require larger `srcSize`.
289
+ * note : only works for formats ZSTD_f_zstd1 and ZSTD_f_zstd1_magicless
290
+ * @return : 0, `zfhPtr` is correctly filled,
291
+ * >0, `srcSize` is too small, value is wanted `srcSize` amount,
292
+ * or an error code, which can be tested using ZSTD_isError() */
293
+ static size_t ZSTD_getFrameHeader_internal(ZSTD_frameHeader* zfhPtr, const void* src, size_t srcSize, ZSTD_format_e format)
252
294
  {
253
295
  const BYTE* ip = (const BYTE*)src;
296
+ size_t const minInputSize = ZSTD_startingInputLength(format);
254
297
 
255
- if (srcSize < ZSTD_frameHeaderSize_prefix) return ZSTD_frameHeaderSize_prefix;
256
- if (MEM_readLE32(src) != ZSTD_MAGICNUMBER) {
298
+ if (srcSize < minInputSize) return minInputSize;
299
+
300
+ if ( (format != ZSTD_f_zstd1_magicless)
301
+ && (MEM_readLE32(src) != ZSTD_MAGICNUMBER) ) {
257
302
  if ((MEM_readLE32(src) & 0xFFFFFFF0U) == ZSTD_MAGIC_SKIPPABLE_START) {
258
- if (srcSize < ZSTD_skippableHeaderSize) return ZSTD_skippableHeaderSize; /* magic number + skippable frame length */
259
- memset(fparamsPtr, 0, sizeof(*fparamsPtr));
260
- fparamsPtr->frameContentSize = MEM_readLE32((const char *)src + 4);
261
- fparamsPtr->windowSize = 0; /* windowSize==0 means a frame is skippable */
303
+ /* skippable frame */
304
+ if (srcSize < ZSTD_skippableHeaderSize)
305
+ return ZSTD_skippableHeaderSize; /* magic number + frame length */
306
+ memset(zfhPtr, 0, sizeof(*zfhPtr));
307
+ zfhPtr->frameContentSize = MEM_readLE32((const char *)src + ZSTD_frameIdSize);
308
+ zfhPtr->frameType = ZSTD_skippableFrame;
262
309
  return 0;
263
310
  }
264
311
  return ERROR(prefix_unknown);
265
312
  }
266
313
 
267
314
  /* ensure there is enough `srcSize` to fully read/decode frame header */
268
- { size_t const fhsize = ZSTD_frameHeaderSize(src, srcSize);
269
- if (srcSize < fhsize) return fhsize; }
315
+ { size_t const fhsize = ZSTD_frameHeaderSize_internal(src, srcSize, format);
316
+ if (srcSize < fhsize) return fhsize;
317
+ zfhPtr->headerSize = (U32)fhsize;
318
+ }
270
319
 
271
- { BYTE const fhdByte = ip[4];
272
- size_t pos = 5;
320
+ { BYTE const fhdByte = ip[minInputSize-1];
321
+ size_t pos = minInputSize;
273
322
  U32 const dictIDSizeCode = fhdByte&3;
274
323
  U32 const checksumFlag = (fhdByte>>2)&1;
275
324
  U32 const singleSegment = (fhdByte>>5)&1;
276
325
  U32 const fcsID = fhdByte>>6;
277
- U32 const windowSizeMax = 1U << ZSTD_WINDOWLOG_MAX;
278
- U32 windowSize = 0;
326
+ U64 windowSize = 0;
279
327
  U32 dictID = 0;
280
- U64 frameContentSize = 0;
281
- if ((fhdByte & 0x08) != 0) return ERROR(frameParameter_unsupported); /* reserved bits, which must be zero */
328
+ U64 frameContentSize = ZSTD_CONTENTSIZE_UNKNOWN;
329
+ if ((fhdByte & 0x08) != 0)
330
+ return ERROR(frameParameter_unsupported); /* reserved bits, must be zero */
331
+
282
332
  if (!singleSegment) {
283
333
  BYTE const wlByte = ip[pos++];
284
334
  U32 const windowLog = (wlByte >> 3) + ZSTD_WINDOWLOG_ABSOLUTEMIN;
285
- if (windowLog > ZSTD_WINDOWLOG_MAX) return ERROR(frameParameter_windowTooLarge); /* avoids issue with 1 << windowLog */
286
- windowSize = (1U << windowLog);
335
+ if (windowLog > ZSTD_WINDOWLOG_MAX)
336
+ return ERROR(frameParameter_windowTooLarge);
337
+ windowSize = (1ULL << windowLog);
287
338
  windowSize += (windowSize >> 3) * (wlByte&7);
288
339
  }
289
-
290
340
  switch(dictIDSizeCode)
291
341
  {
292
- default: /* impossible */
342
+ default: assert(0); /* impossible */
293
343
  case 0 : break;
294
344
  case 1 : dictID = ip[pos]; pos++; break;
295
345
  case 2 : dictID = MEM_readLE16(ip+pos); pos+=2; break;
@@ -297,27 +347,41 @@ size_t ZSTD_getFrameParams(ZSTD_frameParams* fparamsPtr, const void* src, size_t
297
347
  }
298
348
  switch(fcsID)
299
349
  {
300
- default: /* impossible */
350
+ default: assert(0); /* impossible */
301
351
  case 0 : if (singleSegment) frameContentSize = ip[pos]; break;
302
352
  case 1 : frameContentSize = MEM_readLE16(ip+pos)+256; break;
303
353
  case 2 : frameContentSize = MEM_readLE32(ip+pos); break;
304
354
  case 3 : frameContentSize = MEM_readLE64(ip+pos); break;
305
355
  }
306
- if (!windowSize) windowSize = (U32)frameContentSize;
307
- if (windowSize > windowSizeMax) return ERROR(frameParameter_windowTooLarge);
308
- fparamsPtr->frameContentSize = frameContentSize;
309
- fparamsPtr->windowSize = windowSize;
310
- fparamsPtr->dictID = dictID;
311
- fparamsPtr->checksumFlag = checksumFlag;
356
+ if (singleSegment) windowSize = frameContentSize;
357
+
358
+ zfhPtr->frameType = ZSTD_frame;
359
+ zfhPtr->frameContentSize = frameContentSize;
360
+ zfhPtr->windowSize = windowSize;
361
+ zfhPtr->blockSizeMax = (unsigned) MIN(windowSize, ZSTD_BLOCKSIZE_MAX);
362
+ zfhPtr->dictID = dictID;
363
+ zfhPtr->checksumFlag = checksumFlag;
312
364
  }
313
365
  return 0;
314
366
  }
315
367
 
368
+ /** ZSTD_getFrameHeader() :
369
+ * decode Frame Header, or require larger `srcSize`.
370
+ * note : this function does not consume input, it only reads it.
371
+ * @return : 0, `zfhPtr` is correctly filled,
372
+ * >0, `srcSize` is too small, value is wanted `srcSize` amount,
373
+ * or an error code, which can be tested using ZSTD_isError() */
374
+ size_t ZSTD_getFrameHeader(ZSTD_frameHeader* zfhPtr, const void* src, size_t srcSize)
375
+ {
376
+ return ZSTD_getFrameHeader_internal(zfhPtr, src, srcSize, ZSTD_f_zstd1);
377
+ }
378
+
379
+
316
380
  /** 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) */
381
+ * compatible with legacy mode
382
+ * @return : decompressed size of the single frame pointed to be `src` if known, otherwise
383
+ * - ZSTD_CONTENTSIZE_UNKNOWN if the size cannot be determined
384
+ * - ZSTD_CONTENTSIZE_ERROR if an error occurred (e.g. invalid magic number, srcSize too small) */
321
385
  unsigned long long ZSTD_getFrameContentSize(const void *src, size_t srcSize)
322
386
  {
323
387
  #if defined(ZSTD_LEGACY_SUPPORT) && (ZSTD_LEGACY_SUPPORT >= 1)
@@ -326,18 +390,14 @@ unsigned long long ZSTD_getFrameContentSize(const void *src, size_t srcSize)
326
390
  return ret == 0 ? ZSTD_CONTENTSIZE_UNKNOWN : ret;
327
391
  }
328
392
  #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 */
393
+ { ZSTD_frameHeader zfh;
394
+ if (ZSTD_getFrameHeader(&zfh, src, srcSize) != 0)
395
+ return ZSTD_CONTENTSIZE_ERROR;
396
+ if (zfh.frameType == ZSTD_skippableFrame) {
334
397
  return 0;
335
- } else if (fParams.frameContentSize != 0) {
336
- return fParams.frameContentSize;
337
398
  } else {
338
- return ZSTD_CONTENTSIZE_UNKNOWN;
339
- }
340
- }
399
+ return zfh.frameContentSize;
400
+ } }
341
401
  }
342
402
 
343
403
  /** ZSTD_findDecompressedSize() :
@@ -347,64 +407,61 @@ unsigned long long ZSTD_getFrameContentSize(const void *src, size_t srcSize)
347
407
  * @return : decompressed size of the frames contained */
348
408
  unsigned long long ZSTD_findDecompressedSize(const void* src, size_t srcSize)
349
409
  {
350
- {
351
- unsigned long long totalDstSize = 0;
352
- while (srcSize >= ZSTD_frameHeaderSize_prefix) {
353
- const U32 magicNumber = MEM_readLE32(src);
410
+ unsigned long long totalDstSize = 0;
354
411
 
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;
412
+ while (srcSize >= ZSTD_frameHeaderSize_prefix) {
413
+ U32 const magicNumber = MEM_readLE32(src);
414
+
415
+ if ((magicNumber & 0xFFFFFFF0U) == ZSTD_MAGIC_SKIPPABLE_START) {
416
+ size_t skippableSize;
417
+ if (srcSize < ZSTD_skippableHeaderSize)
418
+ return ERROR(srcSize_wrong);
419
+ skippableSize = MEM_readLE32((const BYTE *)src + ZSTD_frameIdSize)
420
+ + ZSTD_skippableHeaderSize;
421
+ if (srcSize < skippableSize) {
422
+ return ZSTD_CONTENTSIZE_ERROR;
368
423
  }
369
424
 
370
- {
371
- unsigned long long const ret = ZSTD_getFrameContentSize(src, srcSize);
372
- if (ret >= ZSTD_CONTENTSIZE_ERROR) return ret;
425
+ src = (const BYTE *)src + skippableSize;
426
+ srcSize -= skippableSize;
427
+ continue;
428
+ }
373
429
 
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
- }
430
+ { unsigned long long const ret = ZSTD_getFrameContentSize(src, srcSize);
431
+ if (ret >= ZSTD_CONTENTSIZE_ERROR) return ret;
383
432
 
384
- src = (const BYTE *)src + frameSrcSize;
385
- srcSize -= frameSrcSize;
386
- }
433
+ /* check for overflow */
434
+ if (totalDstSize + ret < totalDstSize) return ZSTD_CONTENTSIZE_ERROR;
435
+ totalDstSize += ret;
387
436
  }
437
+ { size_t const frameSrcSize = ZSTD_findFrameCompressedSize(src, srcSize);
438
+ if (ZSTD_isError(frameSrcSize)) {
439
+ return ZSTD_CONTENTSIZE_ERROR;
440
+ }
388
441
 
389
- if (srcSize) {
390
- return ZSTD_CONTENTSIZE_ERROR;
442
+ src = (const BYTE *)src + frameSrcSize;
443
+ srcSize -= frameSrcSize;
391
444
  }
445
+ } /* while (srcSize >= ZSTD_frameHeaderSize_prefix) */
392
446
 
393
- return totalDstSize;
394
- }
447
+ if (srcSize) return ZSTD_CONTENTSIZE_ERROR;
448
+
449
+ return totalDstSize;
395
450
  }
396
451
 
397
452
  /** ZSTD_getDecompressedSize() :
398
453
  * compatible with legacy mode
399
454
  * @return : decompressed size if known, 0 otherwise
400
455
  note : 0 can mean any of the following :
401
- - decompressed size is not present within frame header
456
+ - frame content is empty
457
+ - decompressed size field is not present in frame header
402
458
  - frame header unknown / not supported
403
459
  - frame header not complete (`srcSize` too small) */
404
460
  unsigned long long ZSTD_getDecompressedSize(const void* src, size_t srcSize)
405
461
  {
406
462
  unsigned long long const ret = ZSTD_getFrameContentSize(src, srcSize);
407
- return ret >= ZSTD_CONTENTSIZE_ERROR ? 0 : ret;
463
+ ZSTD_STATIC_ASSERT(ZSTD_CONTENTSIZE_ERROR < ZSTD_CONTENTSIZE_UNKNOWN);
464
+ return (ret >= ZSTD_CONTENTSIZE_ERROR) ? 0 : ret;
408
465
  }
409
466
 
410
467
 
@@ -413,25 +470,20 @@ unsigned long long ZSTD_getDecompressedSize(const void* src, size_t srcSize)
413
470
  * @return : 0 if success, or an error code, which can be tested using ZSTD_isError() */
414
471
  static size_t ZSTD_decodeFrameHeader(ZSTD_DCtx* dctx, const void* src, size_t headerSize)
415
472
  {
416
- size_t const result = ZSTD_getFrameParams(&(dctx->fParams), src, headerSize);
417
- if (ZSTD_isError(result)) return result; /* invalid header */
418
- if (result>0) return ERROR(srcSize_wrong); /* headerSize too small */
419
- if (dctx->fParams.dictID && (dctx->dictID != dctx->fParams.dictID)) return ERROR(dictionary_wrong);
473
+ size_t const result = ZSTD_getFrameHeader_internal(&(dctx->fParams), src, headerSize, dctx->format);
474
+ if (ZSTD_isError(result)) return result; /* invalid header */
475
+ if (result>0) return ERROR(srcSize_wrong); /* headerSize too small */
476
+ if (dctx->fParams.dictID && (dctx->dictID != dctx->fParams.dictID))
477
+ return ERROR(dictionary_wrong);
420
478
  if (dctx->fParams.checksumFlag) XXH64_reset(&dctx->xxhState, 0);
421
479
  return 0;
422
480
  }
423
481
 
424
482
 
425
- typedef struct
426
- {
427
- blockType_e blockType;
428
- U32 lastBlock;
429
- U32 origSize;
430
- } blockProperties_t;
431
-
432
483
  /*! ZSTD_getcBlockSize() :
433
484
  * Provides the size of compressed block from block header `src` */
434
- size_t ZSTD_getcBlockSize(const void* src, size_t srcSize, blockProperties_t* bpPtr)
485
+ size_t ZSTD_getcBlockSize(const void* src, size_t srcSize,
486
+ blockProperties_t* bpPtr)
435
487
  {
436
488
  if (srcSize < ZSTD_blockHeaderSize) return ERROR(srcSize_wrong);
437
489
  { U32 const cBlockHeader = MEM_readLE24(src);
@@ -446,7 +498,8 @@ size_t ZSTD_getcBlockSize(const void* src, size_t srcSize, blockProperties_t* bp
446
498
  }
447
499
 
448
500
 
449
- static size_t ZSTD_copyRawBlock(void* dst, size_t dstCapacity, const void* src, size_t srcSize)
501
+ static size_t ZSTD_copyRawBlock(void* dst, size_t dstCapacity,
502
+ const void* src, size_t srcSize)
450
503
  {
451
504
  if (srcSize > dstCapacity) return ERROR(dstSize_tooSmall);
452
505
  memcpy(dst, src, srcSize);
@@ -454,7 +507,9 @@ static size_t ZSTD_copyRawBlock(void* dst, size_t dstCapacity, const void* src,
454
507
  }
455
508
 
456
509
 
457
- static size_t ZSTD_setRleBlock(void* dst, size_t dstCapacity, const void* src, size_t srcSize, size_t regenSize)
510
+ static size_t ZSTD_setRleBlock(void* dst, size_t dstCapacity,
511
+ const void* src, size_t srcSize,
512
+ size_t regenSize)
458
513
  {
459
514
  if (srcSize != 1) return ERROR(srcSize_wrong);
460
515
  if (regenSize > dstCapacity) return ERROR(dstSize_tooSmall);
@@ -463,7 +518,8 @@ static size_t ZSTD_setRleBlock(void* dst, size_t dstCapacity, const void* src, s
463
518
  }
464
519
 
465
520
  /*! ZSTD_decodeLiteralsBlock() :
466
- @return : nb of bytes read from src (< srcSize ) */
521
+ * @return : nb of bytes read from src (< srcSize )
522
+ * note : symbol not declared but exposed for fullbench */
467
523
  size_t ZSTD_decodeLiteralsBlock(ZSTD_DCtx* dctx,
468
524
  const void* src, size_t srcSize) /* note : srcSize < BLOCKSIZE */
469
525
  {
@@ -505,7 +561,7 @@ size_t ZSTD_decodeLiteralsBlock(ZSTD_DCtx* dctx,
505
561
  litCSize = (lhc >> 22) + (istart[4] << 10);
506
562
  break;
507
563
  }
508
- if (litSize > ZSTD_BLOCKSIZE_ABSOLUTEMAX) return ERROR(corruption_detected);
564
+ if (litSize > ZSTD_BLOCKSIZE_MAX) return ERROR(corruption_detected);
509
565
  if (litCSize + lhSize > srcSize) return ERROR(corruption_detected);
510
566
 
511
567
  if (HUF_isError((litEncType==set_repeat) ?
@@ -513,8 +569,10 @@ size_t ZSTD_decodeLiteralsBlock(ZSTD_DCtx* dctx,
513
569
  HUF_decompress1X_usingDTable(dctx->litBuffer, litSize, istart+lhSize, litCSize, dctx->HUFptr) :
514
570
  HUF_decompress4X_usingDTable(dctx->litBuffer, litSize, istart+lhSize, litCSize, dctx->HUFptr) ) :
515
571
  ( singleStream ?
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)) ))
572
+ HUF_decompress1X2_DCtx_wksp(dctx->entropy.hufTable, dctx->litBuffer, litSize, istart+lhSize, litCSize,
573
+ dctx->entropy.workspace, sizeof(dctx->entropy.workspace)) :
574
+ HUF_decompress4X_hufOnly_wksp(dctx->entropy.hufTable, dctx->litBuffer, litSize, istart+lhSize, litCSize,
575
+ dctx->entropy.workspace, sizeof(dctx->entropy.workspace)))))
518
576
  return ERROR(corruption_detected);
519
577
 
520
578
  dctx->litPtr = dctx->litBuffer;
@@ -577,7 +635,7 @@ size_t ZSTD_decodeLiteralsBlock(ZSTD_DCtx* dctx,
577
635
  if (srcSize<4) return ERROR(corruption_detected); /* srcSize >= MIN_CBLOCK_SIZE == 3; here we need lhSize+1 = 4 */
578
636
  break;
579
637
  }
580
- if (litSize > ZSTD_BLOCKSIZE_ABSOLUTEMAX) return ERROR(corruption_detected);
638
+ if (litSize > ZSTD_BLOCKSIZE_MAX) return ERROR(corruption_detected);
581
639
  memset(dctx->litBuffer, istart[lhSize], litSize + WILDCOPY_OVERLENGTH);
582
640
  dctx->litPtr = dctx->litBuffer;
583
641
  dctx->litSize = litSize;
@@ -595,182 +653,76 @@ typedef union {
595
653
  U32 alignedBy4;
596
654
  } FSE_decode_t4;
597
655
 
656
+ /* Default FSE distribution table for Literal Lengths */
598
657
  static const FSE_decode_t4 LL_defaultDTable[(1<<LL_DEFAULTNORMLOG)+1] = {
599
658
  { { LL_DEFAULTNORMLOG, 1, 1 } }, /* header : tableLog, fastMode, fastMode */
600
- { { 0, 0, 4 } }, /* 0 : base, symbol, bits */
601
- { { 16, 0, 4 } },
602
- { { 32, 1, 5 } },
603
- { { 0, 3, 5 } },
604
- { { 0, 4, 5 } },
605
- { { 0, 6, 5 } },
606
- { { 0, 7, 5 } },
607
- { { 0, 9, 5 } },
608
- { { 0, 10, 5 } },
609
- { { 0, 12, 5 } },
610
- { { 0, 14, 6 } },
611
- { { 0, 16, 5 } },
612
- { { 0, 18, 5 } },
613
- { { 0, 19, 5 } },
614
- { { 0, 21, 5 } },
615
- { { 0, 22, 5 } },
616
- { { 0, 24, 5 } },
617
- { { 32, 25, 5 } },
618
- { { 0, 26, 5 } },
619
- { { 0, 27, 6 } },
620
- { { 0, 29, 6 } },
621
- { { 0, 31, 6 } },
622
- { { 32, 0, 4 } },
623
- { { 0, 1, 4 } },
624
- { { 0, 2, 5 } },
625
- { { 32, 4, 5 } },
626
- { { 0, 5, 5 } },
627
- { { 32, 7, 5 } },
628
- { { 0, 8, 5 } },
629
- { { 32, 10, 5 } },
630
- { { 0, 11, 5 } },
631
- { { 0, 13, 6 } },
632
- { { 32, 16, 5 } },
633
- { { 0, 17, 5 } },
634
- { { 32, 19, 5 } },
635
- { { 0, 20, 5 } },
636
- { { 32, 22, 5 } },
637
- { { 0, 23, 5 } },
638
- { { 0, 25, 4 } },
639
- { { 16, 25, 4 } },
640
- { { 32, 26, 5 } },
641
- { { 0, 28, 6 } },
642
- { { 0, 30, 6 } },
643
- { { 48, 0, 4 } },
644
- { { 16, 1, 4 } },
645
- { { 32, 2, 5 } },
646
- { { 32, 3, 5 } },
647
- { { 32, 5, 5 } },
648
- { { 32, 6, 5 } },
649
- { { 32, 8, 5 } },
650
- { { 32, 9, 5 } },
651
- { { 32, 11, 5 } },
652
- { { 32, 12, 5 } },
653
- { { 0, 15, 6 } },
654
- { { 32, 17, 5 } },
655
- { { 32, 18, 5 } },
656
- { { 32, 20, 5 } },
657
- { { 32, 21, 5 } },
658
- { { 32, 23, 5 } },
659
- { { 32, 24, 5 } },
660
- { { 0, 35, 6 } },
661
- { { 0, 34, 6 } },
662
- { { 0, 33, 6 } },
663
- { { 0, 32, 6 } },
659
+ /* base, symbol, bits */
660
+ { { 0, 0, 4 } }, { { 16, 0, 4 } }, { { 32, 1, 5 } }, { { 0, 3, 5 } },
661
+ { { 0, 4, 5 } }, { { 0, 6, 5 } }, { { 0, 7, 5 } }, { { 0, 9, 5 } },
662
+ { { 0, 10, 5 } }, { { 0, 12, 5 } }, { { 0, 14, 6 } }, { { 0, 16, 5 } },
663
+ { { 0, 18, 5 } }, { { 0, 19, 5 } }, { { 0, 21, 5 } }, { { 0, 22, 5 } },
664
+ { { 0, 24, 5 } }, { { 32, 25, 5 } }, { { 0, 26, 5 } }, { { 0, 27, 6 } },
665
+ { { 0, 29, 6 } }, { { 0, 31, 6 } }, { { 32, 0, 4 } }, { { 0, 1, 4 } },
666
+ { { 0, 2, 5 } }, { { 32, 4, 5 } }, { { 0, 5, 5 } }, { { 32, 7, 5 } },
667
+ { { 0, 8, 5 } }, { { 32, 10, 5 } }, { { 0, 11, 5 } }, { { 0, 13, 6 } },
668
+ { { 32, 16, 5 } }, { { 0, 17, 5 } }, { { 32, 19, 5 } }, { { 0, 20, 5 } },
669
+ { { 32, 22, 5 } }, { { 0, 23, 5 } }, { { 0, 25, 4 } }, { { 16, 25, 4 } },
670
+ { { 32, 26, 5 } }, { { 0, 28, 6 } }, { { 0, 30, 6 } }, { { 48, 0, 4 } },
671
+ { { 16, 1, 4 } }, { { 32, 2, 5 } }, { { 32, 3, 5 } }, { { 32, 5, 5 } },
672
+ { { 32, 6, 5 } }, { { 32, 8, 5 } }, { { 32, 9, 5 } }, { { 32, 11, 5 } },
673
+ { { 32, 12, 5 } }, { { 0, 15, 6 } }, { { 32, 17, 5 } }, { { 32, 18, 5 } },
674
+ { { 32, 20, 5 } }, { { 32, 21, 5 } }, { { 32, 23, 5 } }, { { 32, 24, 5 } },
675
+ { { 0, 35, 6 } }, { { 0, 34, 6 } }, { { 0, 33, 6 } }, { { 0, 32, 6 } },
664
676
  }; /* LL_defaultDTable */
665
677
 
678
+ /* Default FSE distribution table for Match Lengths */
666
679
  static const FSE_decode_t4 ML_defaultDTable[(1<<ML_DEFAULTNORMLOG)+1] = {
667
680
  { { ML_DEFAULTNORMLOG, 1, 1 } }, /* header : tableLog, fastMode, fastMode */
668
- { { 0, 0, 6 } }, /* 0 : base, symbol, bits */
669
- { { 0, 1, 4 } },
670
- { { 32, 2, 5 } },
671
- { { 0, 3, 5 } },
672
- { { 0, 5, 5 } },
673
- { { 0, 6, 5 } },
674
- { { 0, 8, 5 } },
675
- { { 0, 10, 6 } },
676
- { { 0, 13, 6 } },
677
- { { 0, 16, 6 } },
678
- { { 0, 19, 6 } },
679
- { { 0, 22, 6 } },
680
- { { 0, 25, 6 } },
681
- { { 0, 28, 6 } },
682
- { { 0, 31, 6 } },
683
- { { 0, 33, 6 } },
684
- { { 0, 35, 6 } },
685
- { { 0, 37, 6 } },
686
- { { 0, 39, 6 } },
687
- { { 0, 41, 6 } },
688
- { { 0, 43, 6 } },
689
- { { 0, 45, 6 } },
690
- { { 16, 1, 4 } },
691
- { { 0, 2, 4 } },
692
- { { 32, 3, 5 } },
693
- { { 0, 4, 5 } },
694
- { { 32, 6, 5 } },
695
- { { 0, 7, 5 } },
696
- { { 0, 9, 6 } },
697
- { { 0, 12, 6 } },
698
- { { 0, 15, 6 } },
699
- { { 0, 18, 6 } },
700
- { { 0, 21, 6 } },
701
- { { 0, 24, 6 } },
702
- { { 0, 27, 6 } },
703
- { { 0, 30, 6 } },
704
- { { 0, 32, 6 } },
705
- { { 0, 34, 6 } },
706
- { { 0, 36, 6 } },
707
- { { 0, 38, 6 } },
708
- { { 0, 40, 6 } },
709
- { { 0, 42, 6 } },
710
- { { 0, 44, 6 } },
711
- { { 32, 1, 4 } },
712
- { { 48, 1, 4 } },
713
- { { 16, 2, 4 } },
714
- { { 32, 4, 5 } },
715
- { { 32, 5, 5 } },
716
- { { 32, 7, 5 } },
717
- { { 32, 8, 5 } },
718
- { { 0, 11, 6 } },
719
- { { 0, 14, 6 } },
720
- { { 0, 17, 6 } },
721
- { { 0, 20, 6 } },
722
- { { 0, 23, 6 } },
723
- { { 0, 26, 6 } },
724
- { { 0, 29, 6 } },
725
- { { 0, 52, 6 } },
726
- { { 0, 51, 6 } },
727
- { { 0, 50, 6 } },
728
- { { 0, 49, 6 } },
729
- { { 0, 48, 6 } },
730
- { { 0, 47, 6 } },
731
- { { 0, 46, 6 } },
681
+ /* base, symbol, bits */
682
+ { { 0, 0, 6 } }, { { 0, 1, 4 } }, { { 32, 2, 5 } }, { { 0, 3, 5 } },
683
+ { { 0, 5, 5 } }, { { 0, 6, 5 } }, { { 0, 8, 5 } }, { { 0, 10, 6 } },
684
+ { { 0, 13, 6 } }, { { 0, 16, 6 } }, { { 0, 19, 6 } }, { { 0, 22, 6 } },
685
+ { { 0, 25, 6 } }, { { 0, 28, 6 } }, { { 0, 31, 6 } }, { { 0, 33, 6 } },
686
+ { { 0, 35, 6 } }, { { 0, 37, 6 } }, { { 0, 39, 6 } }, { { 0, 41, 6 } },
687
+ { { 0, 43, 6 } }, { { 0, 45, 6 } }, { { 16, 1, 4 } }, { { 0, 2, 4 } },
688
+ { { 32, 3, 5 } }, { { 0, 4, 5 } }, { { 32, 6, 5 } }, { { 0, 7, 5 } },
689
+ { { 0, 9, 6 } }, { { 0, 12, 6 } }, { { 0, 15, 6 } }, { { 0, 18, 6 } },
690
+ { { 0, 21, 6 } }, { { 0, 24, 6 } }, { { 0, 27, 6 } }, { { 0, 30, 6 } },
691
+ { { 0, 32, 6 } }, { { 0, 34, 6 } }, { { 0, 36, 6 } }, { { 0, 38, 6 } },
692
+ { { 0, 40, 6 } }, { { 0, 42, 6 } }, { { 0, 44, 6 } }, { { 32, 1, 4 } },
693
+ { { 48, 1, 4 } }, { { 16, 2, 4 } }, { { 32, 4, 5 } }, { { 32, 5, 5 } },
694
+ { { 32, 7, 5 } }, { { 32, 8, 5 } }, { { 0, 11, 6 } }, { { 0, 14, 6 } },
695
+ { { 0, 17, 6 } }, { { 0, 20, 6 } }, { { 0, 23, 6 } }, { { 0, 26, 6 } },
696
+ { { 0, 29, 6 } }, { { 0, 52, 6 } }, { { 0, 51, 6 } }, { { 0, 50, 6 } },
697
+ { { 0, 49, 6 } }, { { 0, 48, 6 } }, { { 0, 47, 6 } }, { { 0, 46, 6 } },
732
698
  }; /* ML_defaultDTable */
733
699
 
700
+ /* Default FSE distribution table for Offset Codes */
734
701
  static const FSE_decode_t4 OF_defaultDTable[(1<<OF_DEFAULTNORMLOG)+1] = {
735
702
  { { OF_DEFAULTNORMLOG, 1, 1 } }, /* header : tableLog, fastMode, fastMode */
736
- { { 0, 0, 5 } }, /* 0 : base, symbol, bits */
737
- { { 0, 6, 4 } },
738
- { { 0, 9, 5 } },
739
- { { 0, 15, 5 } },
740
- { { 0, 21, 5 } },
741
- { { 0, 3, 5 } },
742
- { { 0, 7, 4 } },
743
- { { 0, 12, 5 } },
744
- { { 0, 18, 5 } },
745
- { { 0, 23, 5 } },
746
- { { 0, 5, 5 } },
747
- { { 0, 8, 4 } },
748
- { { 0, 14, 5 } },
749
- { { 0, 20, 5 } },
750
- { { 0, 2, 5 } },
751
- { { 16, 7, 4 } },
752
- { { 0, 11, 5 } },
753
- { { 0, 17, 5 } },
754
- { { 0, 22, 5 } },
755
- { { 0, 4, 5 } },
756
- { { 16, 8, 4 } },
757
- { { 0, 13, 5 } },
758
- { { 0, 19, 5 } },
759
- { { 0, 1, 5 } },
760
- { { 16, 6, 4 } },
761
- { { 0, 10, 5 } },
762
- { { 0, 16, 5 } },
763
- { { 0, 28, 5 } },
764
- { { 0, 27, 5 } },
765
- { { 0, 26, 5 } },
766
- { { 0, 25, 5 } },
767
- { { 0, 24, 5 } },
703
+ /* base, symbol, bits */
704
+ { { 0, 0, 5 } }, { { 0, 6, 4 } },
705
+ { { 0, 9, 5 } }, { { 0, 15, 5 } },
706
+ { { 0, 21, 5 } }, { { 0, 3, 5 } },
707
+ { { 0, 7, 4 } }, { { 0, 12, 5 } },
708
+ { { 0, 18, 5 } }, { { 0, 23, 5 } },
709
+ { { 0, 5, 5 } }, { { 0, 8, 4 } },
710
+ { { 0, 14, 5 } }, { { 0, 20, 5 } },
711
+ { { 0, 2, 5 } }, { { 16, 7, 4 } },
712
+ { { 0, 11, 5 } }, { { 0, 17, 5 } },
713
+ { { 0, 22, 5 } }, { { 0, 4, 5 } },
714
+ { { 16, 8, 4 } }, { { 0, 13, 5 } },
715
+ { { 0, 19, 5 } }, { { 0, 1, 5 } },
716
+ { { 16, 6, 4 } }, { { 0, 10, 5 } },
717
+ { { 0, 16, 5 } }, { { 0, 28, 5 } },
718
+ { { 0, 27, 5 } }, { { 0, 26, 5 } },
719
+ { { 0, 25, 5 } }, { { 0, 24, 5 } },
768
720
  }; /* OF_defaultDTable */
769
721
 
770
722
  /*! ZSTD_buildSeqTable() :
771
- @return : nb bytes read from src,
772
- or an error code if it fails, testable with ZSTD_isError()
773
- */
723
+ * @return : nb bytes read from src,
724
+ * or an error code if it fails, testable with ZSTD_isError()
725
+ */
774
726
  static size_t ZSTD_buildSeqTable(FSE_DTable* DTableSpace, const FSE_DTable** DTablePtr,
775
727
  symbolEncodingType_e type, U32 max, U32 maxLog,
776
728
  const void* src, size_t srcSize,
@@ -810,6 +762,7 @@ size_t ZSTD_decodeSeqHeaders(ZSTD_DCtx* dctx, int* nbSeqPtr,
810
762
  const BYTE* const istart = (const BYTE* const)src;
811
763
  const BYTE* const iend = istart + srcSize;
812
764
  const BYTE* ip = istart;
765
+ DEBUGLOG(5, "ZSTD_decodeSeqHeaders");
813
766
 
814
767
  /* check */
815
768
  if (srcSize < MIN_SEQUENCES_SIZE) return ERROR(srcSize_wrong);
@@ -874,9 +827,9 @@ typedef struct {
874
827
  FSE_DState_t stateOffb;
875
828
  FSE_DState_t stateML;
876
829
  size_t prevOffset[ZSTD_REP_NUM];
877
- const BYTE* base;
830
+ const BYTE* prefixStart;
831
+ const BYTE* dictEnd;
878
832
  size_t pos;
879
- uPtrDiff gotoDict;
880
833
  } seqState_t;
881
834
 
882
835
 
@@ -927,15 +880,25 @@ size_t ZSTD_execSequenceLast7(BYTE* op,
927
880
  }
928
881
 
929
882
 
883
+ typedef enum { ZSTD_lo_isRegularOffset, ZSTD_lo_isLongOffset=1 } ZSTD_longOffset_e;
930
884
 
885
+ /* We need to add at most (ZSTD_WINDOWLOG_MAX_32 - 1) bits to read the maximum
886
+ * offset bits. But we can only read at most (STREAM_ACCUMULATOR_MIN_32 - 1)
887
+ * bits before reloading. This value is the maximum number of bytes we read
888
+ * after reloading when we are decoding long offets.
889
+ */
890
+ #define LONG_OFFSETS_MAX_EXTRA_BITS_32 \
891
+ (ZSTD_WINDOWLOG_MAX_32 > STREAM_ACCUMULATOR_MIN_32 \
892
+ ? ZSTD_WINDOWLOG_MAX_32 - STREAM_ACCUMULATOR_MIN_32 \
893
+ : 0)
931
894
 
932
- static seq_t ZSTD_decodeSequence(seqState_t* seqState)
895
+ static seq_t ZSTD_decodeSequence(seqState_t* seqState, const ZSTD_longOffset_e longOffsets)
933
896
  {
934
897
  seq_t seq;
935
898
 
936
899
  U32 const llCode = FSE_peekSymbol(&seqState->stateLL);
937
900
  U32 const mlCode = FSE_peekSymbol(&seqState->stateML);
938
- U32 const ofCode = FSE_peekSymbol(&seqState->stateOffb); /* <= maxOff, by table construction */
901
+ U32 const ofCode = FSE_peekSymbol(&seqState->stateOffb); /* <= MaxOff, by table construction */
939
902
 
940
903
  U32 const llBits = LL_bits[llCode];
941
904
  U32 const mlBits = ML_bits[mlCode];
@@ -943,29 +906,44 @@ static seq_t ZSTD_decodeSequence(seqState_t* seqState)
943
906
  U32 const totalBits = llBits+mlBits+ofBits;
944
907
 
945
908
  static const U32 LL_base[MaxLL+1] = {
946
- 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
947
- 16, 18, 20, 22, 24, 28, 32, 40, 48, 64, 0x80, 0x100, 0x200, 0x400, 0x800, 0x1000,
909
+ 0, 1, 2, 3, 4, 5, 6, 7,
910
+ 8, 9, 10, 11, 12, 13, 14, 15,
911
+ 16, 18, 20, 22, 24, 28, 32, 40,
912
+ 48, 64, 0x80, 0x100, 0x200, 0x400, 0x800, 0x1000,
948
913
  0x2000, 0x4000, 0x8000, 0x10000 };
949
914
 
950
915
  static const U32 ML_base[MaxML+1] = {
951
- 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18,
952
- 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34,
953
- 35, 37, 39, 41, 43, 47, 51, 59, 67, 83, 99, 0x83, 0x103, 0x203, 0x403, 0x803,
916
+ 3, 4, 5, 6, 7, 8, 9, 10,
917
+ 11, 12, 13, 14, 15, 16, 17, 18,
918
+ 19, 20, 21, 22, 23, 24, 25, 26,
919
+ 27, 28, 29, 30, 31, 32, 33, 34,
920
+ 35, 37, 39, 41, 43, 47, 51, 59,
921
+ 67, 83, 99, 0x83, 0x103, 0x203, 0x403, 0x803,
954
922
  0x1003, 0x2003, 0x4003, 0x8003, 0x10003 };
955
923
 
956
924
  static const U32 OF_base[MaxOff+1] = {
957
- 0, 1, 1, 5, 0xD, 0x1D, 0x3D, 0x7D,
958
- 0xFD, 0x1FD, 0x3FD, 0x7FD, 0xFFD, 0x1FFD, 0x3FFD, 0x7FFD,
959
- 0xFFFD, 0x1FFFD, 0x3FFFD, 0x7FFFD, 0xFFFFD, 0x1FFFFD, 0x3FFFFD, 0x7FFFFD,
960
- 0xFFFFFD, 0x1FFFFFD, 0x3FFFFFD, 0x7FFFFFD, 0xFFFFFFD };
925
+ 0, 1, 1, 5, 0xD, 0x1D, 0x3D, 0x7D,
926
+ 0xFD, 0x1FD, 0x3FD, 0x7FD, 0xFFD, 0x1FFD, 0x3FFD, 0x7FFD,
927
+ 0xFFFD, 0x1FFFD, 0x3FFFD, 0x7FFFD, 0xFFFFD, 0x1FFFFD, 0x3FFFFD, 0x7FFFFD,
928
+ 0xFFFFFD, 0x1FFFFFD, 0x3FFFFFD, 0x7FFFFFD, 0xFFFFFFD, 0x1FFFFFFD, 0x3FFFFFFD, 0x7FFFFFFD };
961
929
 
962
930
  /* sequence */
963
931
  { size_t offset;
964
932
  if (!ofCode)
965
933
  offset = 0;
966
934
  else {
967
- offset = OF_base[ofCode] + BIT_readBitsFast(&seqState->DStream, ofBits); /* <= (ZSTD_WINDOWLOG_MAX-1) bits */
968
- if (MEM_32bits()) BIT_reloadDStream(&seqState->DStream);
935
+ ZSTD_STATIC_ASSERT(ZSTD_lo_isLongOffset == 1);
936
+ ZSTD_STATIC_ASSERT(LONG_OFFSETS_MAX_EXTRA_BITS_32 == 5);
937
+ assert(ofBits <= MaxOff);
938
+ if (MEM_32bits() && longOffsets) {
939
+ U32 const extraBits = ofBits - MIN(ofBits, STREAM_ACCUMULATOR_MIN_32-1);
940
+ offset = OF_base[ofCode] + (BIT_readBitsFast(&seqState->DStream, ofBits - extraBits) << extraBits);
941
+ if (MEM_32bits() || extraBits) BIT_reloadDStream(&seqState->DStream);
942
+ if (extraBits) offset += BIT_readBitsFast(&seqState->DStream, extraBits);
943
+ } else {
944
+ offset = OF_base[ofCode] + BIT_readBitsFast(&seqState->DStream, ofBits); /* <= (ZSTD_WINDOWLOG_MAX-1) bits */
945
+ if (MEM_32bits()) BIT_reloadDStream(&seqState->DStream);
946
+ }
969
947
  }
970
948
 
971
949
  if (ofCode <= 1) {
@@ -987,12 +965,22 @@ static seq_t ZSTD_decodeSequence(seqState_t* seqState)
987
965
  seq.offset = offset;
988
966
  }
989
967
 
990
- seq.matchLength = ML_base[mlCode] + ((mlCode>31) ? BIT_readBitsFast(&seqState->DStream, mlBits) : 0); /* <= 16 bits */
991
- if (MEM_32bits() && (mlBits+llBits>24)) BIT_reloadDStream(&seqState->DStream);
968
+ seq.matchLength = ML_base[mlCode]
969
+ + ((mlCode>31) ? BIT_readBitsFast(&seqState->DStream, mlBits) : 0); /* <= 16 bits */
970
+ if (MEM_32bits() && (mlBits+llBits >= STREAM_ACCUMULATOR_MIN_32-LONG_OFFSETS_MAX_EXTRA_BITS_32))
971
+ BIT_reloadDStream(&seqState->DStream);
972
+ if (MEM_64bits() && (totalBits >= STREAM_ACCUMULATOR_MIN_64-(LLFSELog+MLFSELog+OffFSELog)))
973
+ BIT_reloadDStream(&seqState->DStream);
974
+ /* Verify that there is enough bits to read the rest of the data in 64-bit mode. */
975
+ ZSTD_STATIC_ASSERT(16+LLFSELog+MLFSELog+OffFSELog < STREAM_ACCUMULATOR_MIN_64);
992
976
 
993
- seq.litLength = LL_base[llCode] + ((llCode>15) ? BIT_readBitsFast(&seqState->DStream, llBits) : 0); /* <= 16 bits */
994
- if (MEM_32bits() ||
995
- (totalBits > 64 - 7 - (LLFSELog+MLFSELog+OffFSELog)) ) BIT_reloadDStream(&seqState->DStream);
977
+ seq.litLength = LL_base[llCode]
978
+ + ((llCode>15) ? BIT_readBitsFast(&seqState->DStream, llBits) : 0); /* <= 16 bits */
979
+ if (MEM_32bits())
980
+ BIT_reloadDStream(&seqState->DStream);
981
+
982
+ DEBUGLOG(6, "seq: litL=%u, matchL=%u, offset=%u",
983
+ (U32)seq.litLength, (U32)seq.matchLength, (U32)seq.offset);
996
984
 
997
985
  /* ANS state update */
998
986
  FSE_updateState(&seqState->stateLL, &seqState->DStream); /* <= 9 bits */
@@ -1004,7 +992,7 @@ static seq_t ZSTD_decodeSequence(seqState_t* seqState)
1004
992
  }
1005
993
 
1006
994
 
1007
- FORCE_INLINE
995
+ HINT_INLINE
1008
996
  size_t ZSTD_execSequence(BYTE* op,
1009
997
  BYTE* const oend, seq_t sequence,
1010
998
  const BYTE** litPtr, const BYTE* const litLimit,
@@ -1031,8 +1019,9 @@ size_t ZSTD_execSequence(BYTE* op,
1031
1019
 
1032
1020
  /* copy Match */
1033
1021
  if (sequence.offset > (size_t)(oLitEnd - base)) {
1034
- /* offset beyond prefix */
1035
- if (sequence.offset > (size_t)(oLitEnd - vBase)) return ERROR(corruption_detected);
1022
+ /* offset beyond prefix -> go into extDict */
1023
+ if (sequence.offset > (size_t)(oLitEnd - vBase))
1024
+ return ERROR(corruption_detected);
1036
1025
  match = dictEnd + (match - base);
1037
1026
  if (match + sequence.matchLength <= dictEnd) {
1038
1027
  memmove(oLitEnd, match, sequence.matchLength);
@@ -1087,7 +1076,8 @@ size_t ZSTD_execSequence(BYTE* op,
1087
1076
  static size_t ZSTD_decompressSequences(
1088
1077
  ZSTD_DCtx* dctx,
1089
1078
  void* dst, size_t maxDstSize,
1090
- const void* seqStart, size_t seqSize)
1079
+ const void* seqStart, size_t seqSize,
1080
+ const ZSTD_longOffset_e isLongOffset)
1091
1081
  {
1092
1082
  const BYTE* ip = (const BYTE*)seqStart;
1093
1083
  const BYTE* const iend = ip + seqSize;
@@ -1100,9 +1090,12 @@ static size_t ZSTD_decompressSequences(
1100
1090
  const BYTE* const vBase = (const BYTE*) (dctx->vBase);
1101
1091
  const BYTE* const dictEnd = (const BYTE*) (dctx->dictEnd);
1102
1092
  int nbSeq;
1093
+ DEBUGLOG(5, "ZSTD_decompressSequences");
1103
1094
 
1104
1095
  /* Build Decoding Tables */
1105
1096
  { size_t const seqHSize = ZSTD_decodeSeqHeaders(dctx, &nbSeq, ip, seqSize);
1097
+ DEBUGLOG(5, "ZSTD_decodeSeqHeaders: size=%u, nbSeq=%i",
1098
+ (U32)seqHSize, nbSeq);
1106
1099
  if (ZSTD_isError(seqHSize)) return seqHSize;
1107
1100
  ip += seqHSize;
1108
1101
  }
@@ -1119,13 +1112,15 @@ static size_t ZSTD_decompressSequences(
1119
1112
 
1120
1113
  for ( ; (BIT_reloadDStream(&(seqState.DStream)) <= BIT_DStream_completed) && nbSeq ; ) {
1121
1114
  nbSeq--;
1122
- { seq_t const sequence = ZSTD_decodeSequence(&seqState);
1115
+ { seq_t const sequence = ZSTD_decodeSequence(&seqState, isLongOffset);
1123
1116
  size_t const oneSeqSize = ZSTD_execSequence(op, oend, sequence, &litPtr, litEnd, base, vBase, dictEnd);
1117
+ DEBUGLOG(6, "regenerated sequence size : %u", (U32)oneSeqSize);
1124
1118
  if (ZSTD_isError(oneSeqSize)) return oneSeqSize;
1125
1119
  op += oneSeqSize;
1126
1120
  } }
1127
1121
 
1128
1122
  /* check if reached exact end */
1123
+ DEBUGLOG(5, "after decode loop, remaining nbSeq : %i", nbSeq);
1129
1124
  if (nbSeq) return ERROR(corruption_detected);
1130
1125
  /* save reps for next block */
1131
1126
  { U32 i; for (i=0; i<ZSTD_REP_NUM; i++) dctx->entropy.rep[i] = (U32)(seqState.prevOffset[i]); }
@@ -1142,13 +1137,14 @@ static size_t ZSTD_decompressSequences(
1142
1137
  }
1143
1138
 
1144
1139
 
1145
- FORCE_INLINE seq_t ZSTD_decodeSequenceLong_generic(seqState_t* seqState, int const longOffsets)
1140
+ HINT_INLINE
1141
+ seq_t ZSTD_decodeSequenceLong(seqState_t* seqState, ZSTD_longOffset_e const longOffsets)
1146
1142
  {
1147
1143
  seq_t seq;
1148
1144
 
1149
1145
  U32 const llCode = FSE_peekSymbol(&seqState->stateLL);
1150
1146
  U32 const mlCode = FSE_peekSymbol(&seqState->stateML);
1151
- U32 const ofCode = FSE_peekSymbol(&seqState->stateOffb); /* <= maxOff, by table construction */
1147
+ U32 const ofCode = FSE_peekSymbol(&seqState->stateOffb); /* <= MaxOff, by table construction */
1152
1148
 
1153
1149
  U32 const llBits = LL_bits[llCode];
1154
1150
  U32 const mlBits = ML_bits[mlCode];
@@ -1156,29 +1152,37 @@ FORCE_INLINE seq_t ZSTD_decodeSequenceLong_generic(seqState_t* seqState, int con
1156
1152
  U32 const totalBits = llBits+mlBits+ofBits;
1157
1153
 
1158
1154
  static const U32 LL_base[MaxLL+1] = {
1159
- 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
1160
- 16, 18, 20, 22, 24, 28, 32, 40, 48, 64, 0x80, 0x100, 0x200, 0x400, 0x800, 0x1000,
1155
+ 0, 1, 2, 3, 4, 5, 6, 7,
1156
+ 8, 9, 10, 11, 12, 13, 14, 15,
1157
+ 16, 18, 20, 22, 24, 28, 32, 40,
1158
+ 48, 64, 0x80, 0x100, 0x200, 0x400, 0x800, 0x1000,
1161
1159
  0x2000, 0x4000, 0x8000, 0x10000 };
1162
1160
 
1163
1161
  static const U32 ML_base[MaxML+1] = {
1164
- 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18,
1165
- 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34,
1166
- 35, 37, 39, 41, 43, 47, 51, 59, 67, 83, 99, 0x83, 0x103, 0x203, 0x403, 0x803,
1162
+ 3, 4, 5, 6, 7, 8, 9, 10,
1163
+ 11, 12, 13, 14, 15, 16, 17, 18,
1164
+ 19, 20, 21, 22, 23, 24, 25, 26,
1165
+ 27, 28, 29, 30, 31, 32, 33, 34,
1166
+ 35, 37, 39, 41, 43, 47, 51, 59,
1167
+ 67, 83, 99, 0x83, 0x103, 0x203, 0x403, 0x803,
1167
1168
  0x1003, 0x2003, 0x4003, 0x8003, 0x10003 };
1168
1169
 
1169
1170
  static const U32 OF_base[MaxOff+1] = {
1170
- 0, 1, 1, 5, 0xD, 0x1D, 0x3D, 0x7D,
1171
- 0xFD, 0x1FD, 0x3FD, 0x7FD, 0xFFD, 0x1FFD, 0x3FFD, 0x7FFD,
1172
- 0xFFFD, 0x1FFFD, 0x3FFFD, 0x7FFFD, 0xFFFFD, 0x1FFFFD, 0x3FFFFD, 0x7FFFFD,
1173
- 0xFFFFFD, 0x1FFFFFD, 0x3FFFFFD, 0x7FFFFFD, 0xFFFFFFD };
1171
+ 0, 1, 1, 5, 0xD, 0x1D, 0x3D, 0x7D,
1172
+ 0xFD, 0x1FD, 0x3FD, 0x7FD, 0xFFD, 0x1FFD, 0x3FFD, 0x7FFD,
1173
+ 0xFFFD, 0x1FFFD, 0x3FFFD, 0x7FFFD, 0xFFFFD, 0x1FFFFD, 0x3FFFFD, 0x7FFFFD,
1174
+ 0xFFFFFD, 0x1FFFFFD, 0x3FFFFFD, 0x7FFFFFD, 0xFFFFFFD, 0x1FFFFFFD, 0x3FFFFFFD, 0x7FFFFFFD };
1174
1175
 
1175
1176
  /* sequence */
1176
1177
  { size_t offset;
1177
1178
  if (!ofCode)
1178
1179
  offset = 0;
1179
1180
  else {
1180
- if (longOffsets) {
1181
- int const extraBits = ofBits - MIN(ofBits, STREAM_ACCUMULATOR_MIN);
1181
+ ZSTD_STATIC_ASSERT(ZSTD_lo_isLongOffset == 1);
1182
+ ZSTD_STATIC_ASSERT(LONG_OFFSETS_MAX_EXTRA_BITS_32 == 5);
1183
+ assert(ofBits <= MaxOff);
1184
+ if (MEM_32bits() && longOffsets) {
1185
+ U32 const extraBits = ofBits - MIN(ofBits, STREAM_ACCUMULATOR_MIN_32-1);
1182
1186
  offset = OF_base[ofCode] + (BIT_readBitsFast(&seqState->DStream, ofBits - extraBits) << extraBits);
1183
1187
  if (MEM_32bits() || extraBits) BIT_reloadDStream(&seqState->DStream);
1184
1188
  if (extraBits) offset += BIT_readBitsFast(&seqState->DStream, extraBits);
@@ -1208,15 +1212,21 @@ FORCE_INLINE seq_t ZSTD_decodeSequenceLong_generic(seqState_t* seqState, int con
1208
1212
  }
1209
1213
 
1210
1214
  seq.matchLength = ML_base[mlCode] + ((mlCode>31) ? BIT_readBitsFast(&seqState->DStream, mlBits) : 0); /* <= 16 bits */
1211
- if (MEM_32bits() && (mlBits+llBits>24)) BIT_reloadDStream(&seqState->DStream);
1215
+ if (MEM_32bits() && (mlBits+llBits >= STREAM_ACCUMULATOR_MIN_32-LONG_OFFSETS_MAX_EXTRA_BITS_32))
1216
+ BIT_reloadDStream(&seqState->DStream);
1217
+ if (MEM_64bits() && (totalBits >= STREAM_ACCUMULATOR_MIN_64-(LLFSELog+MLFSELog+OffFSELog)))
1218
+ BIT_reloadDStream(&seqState->DStream);
1219
+ /* Verify that there is enough bits to read the rest of the data in 64-bit mode. */
1220
+ ZSTD_STATIC_ASSERT(16+LLFSELog+MLFSELog+OffFSELog < STREAM_ACCUMULATOR_MIN_64);
1212
1221
 
1213
1222
  seq.litLength = LL_base[llCode] + ((llCode>15) ? BIT_readBitsFast(&seqState->DStream, llBits) : 0); /* <= 16 bits */
1214
- if (MEM_32bits() ||
1215
- (totalBits > 64 - 7 - (LLFSELog+MLFSELog+OffFSELog)) ) BIT_reloadDStream(&seqState->DStream);
1223
+ if (MEM_32bits())
1224
+ BIT_reloadDStream(&seqState->DStream);
1216
1225
 
1217
1226
  { size_t const pos = seqState->pos + seq.litLength;
1218
- seq.match = seqState->base + pos - seq.offset; /* single memory segment */
1219
- if (seq.offset > pos) seq.match += seqState->gotoDict; /* separate memory segment */
1227
+ const BYTE* const matchBase = (seq.offset > pos) ? seqState->dictEnd : seqState->prefixStart;
1228
+ seq.match = matchBase + pos - seq.offset; /* note : this operation can overflow when seq.offset is really too large, which can only happen when input is corrupted.
1229
+ * No consequence though : no memory access will occur, overly large offset will be detected in ZSTD_execSequenceLong() */
1220
1230
  seqState->pos = pos + seq.matchLength;
1221
1231
  }
1222
1232
 
@@ -1229,19 +1239,12 @@ FORCE_INLINE seq_t ZSTD_decodeSequenceLong_generic(seqState_t* seqState, int con
1229
1239
  return seq;
1230
1240
  }
1231
1241
 
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
1242
 
1240
- FORCE_INLINE
1243
+ HINT_INLINE
1241
1244
  size_t ZSTD_execSequenceLong(BYTE* op,
1242
- BYTE* const oend, seq_t sequence,
1243
- const BYTE** litPtr, const BYTE* const litLimit,
1244
- const BYTE* const base, const BYTE* const vBase, const BYTE* const dictEnd)
1245
+ BYTE* const oend, seq_t sequence,
1246
+ const BYTE** litPtr, const BYTE* const litLimit,
1247
+ const BYTE* const prefixStart, const BYTE* const dictStart, const BYTE* const dictEnd)
1245
1248
  {
1246
1249
  BYTE* const oLitEnd = op + sequence.litLength;
1247
1250
  size_t const sequenceLength = sequence.litLength + sequence.matchLength;
@@ -1251,24 +1254,21 @@ size_t ZSTD_execSequenceLong(BYTE* op,
1251
1254
  const BYTE* match = sequence.match;
1252
1255
 
1253
1256
  /* check */
1254
- #if 1
1255
- if (oMatchEnd>oend) return ERROR(dstSize_tooSmall); /* last match must start at a minimum distance of WILDCOPY_OVERLENGTH from oend */
1257
+ if (oMatchEnd > oend) return ERROR(dstSize_tooSmall); /* last match must start at a minimum distance of WILDCOPY_OVERLENGTH from oend */
1256
1258
  if (iLitEnd > litLimit) return ERROR(corruption_detected); /* over-read beyond lit buffer */
1257
- if (oLitEnd>oend_w) return ZSTD_execSequenceLast7(op, oend, sequence, litPtr, litLimit, base, vBase, dictEnd);
1258
- #endif
1259
+ if (oLitEnd > oend_w) return ZSTD_execSequenceLast7(op, oend, sequence, litPtr, litLimit, prefixStart, dictStart, dictEnd);
1259
1260
 
1260
1261
  /* copy Literals */
1261
- ZSTD_copy8(op, *litPtr);
1262
+ ZSTD_copy8(op, *litPtr); /* note : op <= oLitEnd <= oend_w == oend - 8 */
1262
1263
  if (sequence.litLength > 8)
1263
1264
  ZSTD_wildcopy(op+8, (*litPtr)+8, sequence.litLength - 8); /* note : since oLitEnd <= oend-WILDCOPY_OVERLENGTH, no risk of overwrite beyond oend */
1264
1265
  op = oLitEnd;
1265
1266
  *litPtr = iLitEnd; /* update for next sequence */
1266
1267
 
1267
1268
  /* copy Match */
1268
- #if 1
1269
- if (sequence.offset > (size_t)(oLitEnd - base)) {
1269
+ if (sequence.offset > (size_t)(oLitEnd - prefixStart)) {
1270
1270
  /* offset beyond prefix */
1271
- if (sequence.offset > (size_t)(oLitEnd - vBase)) return ERROR(corruption_detected);
1271
+ if (sequence.offset > (size_t)(oLitEnd - dictStart)) return ERROR(corruption_detected);
1272
1272
  if (match + sequence.matchLength <= dictEnd) {
1273
1273
  memmove(oLitEnd, match, sequence.matchLength);
1274
1274
  return sequenceLength;
@@ -1278,15 +1278,15 @@ size_t ZSTD_execSequenceLong(BYTE* op,
1278
1278
  memmove(oLitEnd, match, length1);
1279
1279
  op = oLitEnd + length1;
1280
1280
  sequence.matchLength -= length1;
1281
- match = base;
1281
+ match = prefixStart;
1282
1282
  if (op > oend_w || sequence.matchLength < MINMATCH) {
1283
1283
  U32 i;
1284
1284
  for (i = 0; i < sequence.matchLength; ++i) op[i] = match[i];
1285
1285
  return sequenceLength;
1286
1286
  }
1287
1287
  } }
1288
- /* Requirement: op <= oend_w && sequence.matchLength >= MINMATCH */
1289
- #endif
1288
+ assert(op <= oend_w);
1289
+ assert(sequence.matchLength >= MINMATCH);
1290
1290
 
1291
1291
  /* match within prefix */
1292
1292
  if (sequence.offset < 8) {
@@ -1322,7 +1322,8 @@ size_t ZSTD_execSequenceLong(BYTE* op,
1322
1322
  static size_t ZSTD_decompressSequencesLong(
1323
1323
  ZSTD_DCtx* dctx,
1324
1324
  void* dst, size_t maxDstSize,
1325
- const void* seqStart, size_t seqSize)
1325
+ const void* seqStart, size_t seqSize,
1326
+ const ZSTD_longOffset_e isLongOffset)
1326
1327
  {
1327
1328
  const BYTE* ip = (const BYTE*)seqStart;
1328
1329
  const BYTE* const iend = ip + seqSize;
@@ -1331,10 +1332,9 @@ static size_t ZSTD_decompressSequencesLong(
1331
1332
  BYTE* op = ostart;
1332
1333
  const BYTE* litPtr = dctx->litPtr;
1333
1334
  const BYTE* const litEnd = litPtr + dctx->litSize;
1334
- const BYTE* const base = (const BYTE*) (dctx->base);
1335
- const BYTE* const vBase = (const BYTE*) (dctx->vBase);
1335
+ const BYTE* const prefixStart = (const BYTE*) (dctx->base);
1336
+ const BYTE* const dictStart = (const BYTE*) (dctx->vBase);
1336
1337
  const BYTE* const dictEnd = (const BYTE*) (dctx->dictEnd);
1337
- unsigned const windowSize = dctx->fParams.windowSize;
1338
1338
  int nbSeq;
1339
1339
 
1340
1340
  /* Build Decoding Tables */
@@ -1354,9 +1354,9 @@ static size_t ZSTD_decompressSequencesLong(
1354
1354
  int seqNb;
1355
1355
  dctx->fseEntropy = 1;
1356
1356
  { U32 i; for (i=0; i<ZSTD_REP_NUM; i++) seqState.prevOffset[i] = dctx->entropy.rep[i]; }
1357
- seqState.base = base;
1358
- seqState.pos = (size_t)(op-base);
1359
- seqState.gotoDict = (uPtrDiff)dictEnd - (uPtrDiff)base; /* cast to avoid undefined behaviour */
1357
+ seqState.prefixStart = prefixStart;
1358
+ seqState.pos = (size_t)(op-prefixStart);
1359
+ seqState.dictEnd = dictEnd;
1360
1360
  CHECK_E(BIT_initDStream(&seqState.DStream, ip, iend-ip), corruption_detected);
1361
1361
  FSE_initDState(&seqState.stateLL, &seqState.DStream, dctx->LLTptr);
1362
1362
  FSE_initDState(&seqState.stateOffb, &seqState.DStream, dctx->OFTptr);
@@ -1364,16 +1364,16 @@ static size_t ZSTD_decompressSequencesLong(
1364
1364
 
1365
1365
  /* prepare in advance */
1366
1366
  for (seqNb=0; (BIT_reloadDStream(&seqState.DStream) <= BIT_DStream_completed) && seqNb<seqAdvance; seqNb++) {
1367
- sequences[seqNb] = ZSTD_decodeSequenceLong(&seqState, windowSize);
1367
+ sequences[seqNb] = ZSTD_decodeSequenceLong(&seqState, isLongOffset);
1368
1368
  }
1369
1369
  if (seqNb<seqAdvance) return ERROR(corruption_detected);
1370
1370
 
1371
1371
  /* decode and decompress */
1372
1372
  for ( ; (BIT_reloadDStream(&(seqState.DStream)) <= BIT_DStream_completed) && seqNb<nbSeq ; seqNb++) {
1373
- seq_t const sequence = ZSTD_decodeSequenceLong(&seqState, windowSize);
1374
- size_t const oneSeqSize = ZSTD_execSequenceLong(op, oend, sequences[(seqNb-ADVANCED_SEQS) & STOSEQ_MASK], &litPtr, litEnd, base, vBase, dictEnd);
1373
+ seq_t const sequence = ZSTD_decodeSequenceLong(&seqState, isLongOffset);
1374
+ size_t const oneSeqSize = ZSTD_execSequenceLong(op, oend, sequences[(seqNb-ADVANCED_SEQS) & STOSEQ_MASK], &litPtr, litEnd, prefixStart, dictStart, dictEnd);
1375
1375
  if (ZSTD_isError(oneSeqSize)) return oneSeqSize;
1376
- ZSTD_PREFETCH(sequence.match);
1376
+ PREFETCH(sequence.match); /* note : it's safe to invoke PREFETCH() on any memory address, including invalid ones */
1377
1377
  sequences[seqNb&STOSEQ_MASK] = sequence;
1378
1378
  op += oneSeqSize;
1379
1379
  }
@@ -1382,7 +1382,7 @@ static size_t ZSTD_decompressSequencesLong(
1382
1382
  /* finish queue */
1383
1383
  seqNb -= seqAdvance;
1384
1384
  for ( ; seqNb<nbSeq ; seqNb++) {
1385
- size_t const oneSeqSize = ZSTD_execSequenceLong(op, oend, sequences[seqNb&STOSEQ_MASK], &litPtr, litEnd, base, vBase, dictEnd);
1385
+ size_t const oneSeqSize = ZSTD_execSequenceLong(op, oend, sequences[seqNb&STOSEQ_MASK], &litPtr, litEnd, prefixStart, dictStart, dictEnd);
1386
1386
  if (ZSTD_isError(oneSeqSize)) return oneSeqSize;
1387
1387
  op += oneSeqSize;
1388
1388
  }
@@ -1404,25 +1404,33 @@ static size_t ZSTD_decompressSequencesLong(
1404
1404
 
1405
1405
  static size_t ZSTD_decompressBlock_internal(ZSTD_DCtx* dctx,
1406
1406
  void* dst, size_t dstCapacity,
1407
- const void* src, size_t srcSize)
1407
+ const void* src, size_t srcSize, const int frame)
1408
1408
  { /* blockType == blockCompressed */
1409
1409
  const BYTE* ip = (const BYTE*)src;
1410
-
1411
- if (srcSize >= ZSTD_BLOCKSIZE_ABSOLUTEMAX) return ERROR(srcSize_wrong);
1410
+ /* isLongOffset must be true if there are long offsets.
1411
+ * Offsets are long if they are larger than 2^STREAM_ACCUMULATOR_MIN.
1412
+ * We don't expect that to be the case in 64-bit mode.
1413
+ * If we are in block mode we don't know the window size, so we have to be
1414
+ * conservative.
1415
+ */
1416
+ ZSTD_longOffset_e const isLongOffset = (ZSTD_longOffset_e)(MEM_32bits() && (!frame || dctx->fParams.windowSize > (1ULL << STREAM_ACCUMULATOR_MIN)));
1417
+ /* windowSize could be any value at this point, since it is only validated
1418
+ * in the streaming API.
1419
+ */
1420
+ DEBUGLOG(5, "ZSTD_decompressBlock_internal (size : %u)", (U32)srcSize);
1421
+
1422
+ if (srcSize >= ZSTD_BLOCKSIZE_MAX) return ERROR(srcSize_wrong);
1412
1423
 
1413
1424
  /* Decode literals section */
1414
1425
  { size_t const litCSize = ZSTD_decodeLiteralsBlock(dctx, src, srcSize);
1426
+ DEBUGLOG(5, "ZSTD_decodeLiteralsBlock : %u", (U32)litCSize);
1415
1427
  if (ZSTD_isError(litCSize)) return litCSize;
1416
1428
  ip += litCSize;
1417
1429
  srcSize -= litCSize;
1418
1430
  }
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);
1425
- return ZSTD_decompressSequences(dctx, dst, dstCapacity, ip, srcSize);
1431
+ if (frame && dctx->fParams.windowSize > (1<<23))
1432
+ return ZSTD_decompressSequencesLong(dctx, dst, dstCapacity, ip, srcSize, isLongOffset);
1433
+ return ZSTD_decompressSequences(dctx, dst, dstCapacity, ip, srcSize, isLongOffset);
1426
1434
  }
1427
1435
 
1428
1436
 
@@ -1442,7 +1450,7 @@ size_t ZSTD_decompressBlock(ZSTD_DCtx* dctx,
1442
1450
  {
1443
1451
  size_t dSize;
1444
1452
  ZSTD_checkContinuity(dctx, dst);
1445
- dSize = ZSTD_decompressBlock_internal(dctx, dst, dstCapacity, src, srcSize);
1453
+ dSize = ZSTD_decompressBlock_internal(dctx, dst, dstCapacity, src, srcSize, /* frame */ 0);
1446
1454
  dctx->previousDstEnd = (char*)dst + dSize;
1447
1455
  return dSize;
1448
1456
  }
@@ -1458,7 +1466,7 @@ ZSTDLIB_API size_t ZSTD_insertBlock(ZSTD_DCtx* dctx, const void* blockStart, siz
1458
1466
  }
1459
1467
 
1460
1468
 
1461
- size_t ZSTD_generateNxBytes(void* dst, size_t dstCapacity, BYTE byte, size_t length)
1469
+ static size_t ZSTD_generateNxBytes(void* dst, size_t dstCapacity, BYTE byte, size_t length)
1462
1470
  {
1463
1471
  if (length > dstCapacity) return ERROR(dstSize_tooSmall);
1464
1472
  memset(dst, byte, length);
@@ -1473,28 +1481,26 @@ size_t ZSTD_generateNxBytes(void* dst, size_t dstCapacity, BYTE byte, size_t len
1473
1481
  size_t ZSTD_findFrameCompressedSize(const void *src, size_t srcSize)
1474
1482
  {
1475
1483
  #if defined(ZSTD_LEGACY_SUPPORT) && (ZSTD_LEGACY_SUPPORT >= 1)
1476
- if (ZSTD_isLegacy(src, srcSize)) return ZSTD_findFrameCompressedSizeLegacy(src, srcSize);
1484
+ if (ZSTD_isLegacy(src, srcSize))
1485
+ return ZSTD_findFrameCompressedSizeLegacy(src, srcSize);
1477
1486
  #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);
1487
+ if ( (srcSize >= ZSTD_skippableHeaderSize)
1488
+ && (MEM_readLE32(src) & 0xFFFFFFF0U) == ZSTD_MAGIC_SKIPPABLE_START ) {
1489
+ return ZSTD_skippableHeaderSize + MEM_readLE32((const BYTE*)src + ZSTD_frameIdSize);
1481
1490
  } else {
1482
1491
  const BYTE* ip = (const BYTE*)src;
1483
1492
  const BYTE* const ipstart = ip;
1484
1493
  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;
1494
+ ZSTD_frameHeader zfh;
1489
1495
 
1490
- /* Frame Header */
1491
- { size_t const ret = ZSTD_getFrameParams(&fParams, ip, remainingSize);
1496
+ /* Extract Frame Header */
1497
+ { size_t const ret = ZSTD_getFrameHeader(&zfh, src, srcSize);
1492
1498
  if (ZSTD_isError(ret)) return ret;
1493
1499
  if (ret > 0) return ERROR(srcSize_wrong);
1494
1500
  }
1495
1501
 
1496
- ip += headerSize;
1497
- remainingSize -= headerSize;
1502
+ ip += zfh.headerSize;
1503
+ remainingSize -= zfh.headerSize;
1498
1504
 
1499
1505
  /* Loop on each block */
1500
1506
  while (1) {
@@ -1502,7 +1508,8 @@ size_t ZSTD_findFrameCompressedSize(const void *src, size_t srcSize)
1502
1508
  size_t const cBlockSize = ZSTD_getcBlockSize(ip, remainingSize, &blockProperties);
1503
1509
  if (ZSTD_isError(cBlockSize)) return cBlockSize;
1504
1510
 
1505
- if (ZSTD_blockHeaderSize + cBlockSize > remainingSize) return ERROR(srcSize_wrong);
1511
+ if (ZSTD_blockHeaderSize + cBlockSize > remainingSize)
1512
+ return ERROR(srcSize_wrong);
1506
1513
 
1507
1514
  ip += ZSTD_blockHeaderSize + cBlockSize;
1508
1515
  remainingSize -= ZSTD_blockHeaderSize + cBlockSize;
@@ -1510,7 +1517,7 @@ size_t ZSTD_findFrameCompressedSize(const void *src, size_t srcSize)
1510
1517
  if (blockProperties.lastBlock) break;
1511
1518
  }
1512
1519
 
1513
- if (fParams.checksumFlag) { /* Frame content checksum */
1520
+ if (zfh.checksumFlag) { /* Final frame content checksum */
1514
1521
  if (remainingSize < 4) return ERROR(srcSize_wrong);
1515
1522
  ip += 4;
1516
1523
  remainingSize -= 4;
@@ -1523,8 +1530,8 @@ size_t ZSTD_findFrameCompressedSize(const void *src, size_t srcSize)
1523
1530
  /*! ZSTD_decompressFrame() :
1524
1531
  * @dctx must be properly initialized */
1525
1532
  static size_t ZSTD_decompressFrame(ZSTD_DCtx* dctx,
1526
- void* dst, size_t dstCapacity,
1527
- const void** srcPtr, size_t *srcSizePtr)
1533
+ void* dst, size_t dstCapacity,
1534
+ const void** srcPtr, size_t *srcSizePtr)
1528
1535
  {
1529
1536
  const BYTE* ip = (const BYTE*)(*srcPtr);
1530
1537
  BYTE* const ostart = (BYTE* const)dst;
@@ -1533,13 +1540,15 @@ static size_t ZSTD_decompressFrame(ZSTD_DCtx* dctx,
1533
1540
  size_t remainingSize = *srcSizePtr;
1534
1541
 
1535
1542
  /* check */
1536
- if (remainingSize < ZSTD_frameHeaderSize_min+ZSTD_blockHeaderSize) return ERROR(srcSize_wrong);
1543
+ if (remainingSize < ZSTD_frameHeaderSize_min+ZSTD_blockHeaderSize)
1544
+ return ERROR(srcSize_wrong);
1537
1545
 
1538
1546
  /* Frame Header */
1539
1547
  { size_t const frameHeaderSize = ZSTD_frameHeaderSize(ip, ZSTD_frameHeaderSize_prefix);
1540
1548
  if (ZSTD_isError(frameHeaderSize)) return frameHeaderSize;
1541
- if (remainingSize < frameHeaderSize+ZSTD_blockHeaderSize) return ERROR(srcSize_wrong);
1542
- CHECK_F(ZSTD_decodeFrameHeader(dctx, ip, frameHeaderSize));
1549
+ if (remainingSize < frameHeaderSize+ZSTD_blockHeaderSize)
1550
+ return ERROR(srcSize_wrong);
1551
+ CHECK_F( ZSTD_decodeFrameHeader(dctx, ip, frameHeaderSize) );
1543
1552
  ip += frameHeaderSize; remainingSize -= frameHeaderSize;
1544
1553
  }
1545
1554
 
@@ -1557,7 +1566,7 @@ static size_t ZSTD_decompressFrame(ZSTD_DCtx* dctx,
1557
1566
  switch(blockProperties.blockType)
1558
1567
  {
1559
1568
  case bt_compressed:
1560
- decodedSize = ZSTD_decompressBlock_internal(dctx, op, oend-op, ip, cBlockSize);
1569
+ decodedSize = ZSTD_decompressBlock_internal(dctx, op, oend-op, ip, cBlockSize, /* frame */ 1);
1561
1570
  break;
1562
1571
  case bt_raw :
1563
1572
  decodedSize = ZSTD_copyRawBlock(op, oend-op, ip, cBlockSize);
@@ -1571,14 +1580,19 @@ static size_t ZSTD_decompressFrame(ZSTD_DCtx* dctx,
1571
1580
  }
1572
1581
 
1573
1582
  if (ZSTD_isError(decodedSize)) return decodedSize;
1574
- if (dctx->fParams.checksumFlag) XXH64_update(&dctx->xxhState, op, decodedSize);
1583
+ if (dctx->fParams.checksumFlag)
1584
+ XXH64_update(&dctx->xxhState, op, decodedSize);
1575
1585
  op += decodedSize;
1576
1586
  ip += cBlockSize;
1577
1587
  remainingSize -= cBlockSize;
1578
1588
  if (blockProperties.lastBlock) break;
1579
1589
  }
1580
1590
 
1581
- if (dctx->fParams.checksumFlag) { /* Frame content checksum verification */
1591
+ if (dctx->fParams.frameContentSize != ZSTD_CONTENTSIZE_UNKNOWN) {
1592
+ if ((U64)(op-ostart) != dctx->fParams.frameContentSize) {
1593
+ return ERROR(corruption_detected);
1594
+ } }
1595
+ if (dctx->fParams.checksumFlag) { /* Frame content checksum verification */
1582
1596
  U32 const checkCalc = (U32)XXH64_digest(&dctx->xxhState);
1583
1597
  U32 checkRead;
1584
1598
  if (remainingSize<4) return ERROR(checksum_wrong);
@@ -1600,17 +1614,13 @@ static size_t ZSTD_DDictDictSize(const ZSTD_DDict* ddict);
1600
1614
  static size_t ZSTD_decompressMultiFrame(ZSTD_DCtx* dctx,
1601
1615
  void* dst, size_t dstCapacity,
1602
1616
  const void* src, size_t srcSize,
1603
- const void *dict, size_t dictSize,
1617
+ const void* dict, size_t dictSize,
1604
1618
  const ZSTD_DDict* ddict)
1605
1619
  {
1606
1620
  void* const dststart = dst;
1621
+ assert(dict==NULL || ddict==NULL); /* either dict or ddict set, not both */
1607
1622
 
1608
1623
  if (ddict) {
1609
- if (dict) {
1610
- /* programmer error, these two cases should be mutually exclusive */
1611
- return ERROR(GENERIC);
1612
- }
1613
-
1614
1624
  dict = ZSTD_DDictDictContent(ddict);
1615
1625
  dictSize = ZSTD_DDictDictSize(ddict);
1616
1626
  }
@@ -1623,6 +1633,8 @@ static size_t ZSTD_decompressMultiFrame(ZSTD_DCtx* dctx,
1623
1633
  size_t decodedSize;
1624
1634
  size_t const frameSize = ZSTD_findFrameCompressedSizeLegacy(src, srcSize);
1625
1635
  if (ZSTD_isError(frameSize)) return frameSize;
1636
+ /* legacy support is not compatible with static dctx */
1637
+ if (dctx->staticSize) return ERROR(memory_allocation);
1626
1638
 
1627
1639
  decodedSize = ZSTD_decompressLegacy(dst, dstCapacity, src, frameSize, dict, dictSize);
1628
1640
 
@@ -1637,28 +1649,27 @@ static size_t ZSTD_decompressMultiFrame(ZSTD_DCtx* dctx,
1637
1649
  #endif
1638
1650
 
1639
1651
  magicNumber = MEM_readLE32(src);
1652
+ DEBUGLOG(4, "reading magic number %08X (expecting %08X)",
1653
+ (U32)magicNumber, (U32)ZSTD_MAGICNUMBER);
1640
1654
  if (magicNumber != ZSTD_MAGICNUMBER) {
1641
1655
  if ((magicNumber & 0xFFFFFFF0U) == ZSTD_MAGIC_SKIPPABLE_START) {
1642
1656
  size_t skippableSize;
1643
1657
  if (srcSize < ZSTD_skippableHeaderSize)
1644
1658
  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
- }
1659
+ skippableSize = MEM_readLE32((const BYTE*)src + ZSTD_frameIdSize)
1660
+ + ZSTD_skippableHeaderSize;
1661
+ if (srcSize < skippableSize) return ERROR(srcSize_wrong);
1650
1662
 
1651
1663
  src = (const BYTE *)src + skippableSize;
1652
1664
  srcSize -= skippableSize;
1653
1665
  continue;
1654
- } else {
1655
- return ERROR(prefix_unknown);
1656
1666
  }
1667
+ return ERROR(prefix_unknown);
1657
1668
  }
1658
1669
 
1659
1670
  if (ddict) {
1660
1671
  /* we were called from ZSTD_decompress_usingDDict */
1661
- ZSTD_refDDict(dctx, ddict);
1672
+ CHECK_F(ZSTD_decompressBegin_usingDDict(dctx, ddict));
1662
1673
  } else {
1663
1674
  /* this will initialize correctly with no dict if dict == NULL, so
1664
1675
  * use this in all cases but ddict */
@@ -1669,12 +1680,11 @@ static size_t ZSTD_decompressMultiFrame(ZSTD_DCtx* dctx,
1669
1680
  { const size_t res = ZSTD_decompressFrame(dctx, dst, dstCapacity,
1670
1681
  &src, &srcSize);
1671
1682
  if (ZSTD_isError(res)) return res;
1672
- /* don't need to bounds check this, ZSTD_decompressFrame will have
1673
- * already */
1683
+ /* no need to bound check, ZSTD_decompressFrame already has */
1674
1684
  dst = (BYTE*)dst + res;
1675
1685
  dstCapacity -= res;
1676
1686
  }
1677
- }
1687
+ } /* while (srcSize >= ZSTD_frameHeaderSize_prefix) */
1678
1688
 
1679
1689
  if (srcSize) return ERROR(srcSize_wrong); /* input not entirely consumed */
1680
1690
 
@@ -1698,7 +1708,7 @@ size_t ZSTD_decompressDCtx(ZSTD_DCtx* dctx, void* dst, size_t dstCapacity, const
1698
1708
 
1699
1709
  size_t ZSTD_decompress(void* dst, size_t dstCapacity, const void* src, size_t srcSize)
1700
1710
  {
1701
- #if defined(ZSTD_HEAPMODE) && (ZSTD_HEAPMODE==1)
1711
+ #if defined(ZSTD_HEAPMODE) && (ZSTD_HEAPMODE>=1)
1702
1712
  size_t regenSize;
1703
1713
  ZSTD_DCtx* const dctx = ZSTD_createDCtx();
1704
1714
  if (dctx==NULL) return ERROR(memory_allocation);
@@ -1722,6 +1732,7 @@ ZSTD_nextInputType_e ZSTD_nextInputType(ZSTD_DCtx* dctx) {
1722
1732
  switch(dctx->stage)
1723
1733
  {
1724
1734
  default: /* should not happen */
1735
+ assert(0);
1725
1736
  case ZSTDds_getFrameHeaderSize:
1726
1737
  case ZSTDds_decodeFrameHeader:
1727
1738
  return ZSTDnit_frameHeader;
@@ -1739,39 +1750,41 @@ ZSTD_nextInputType_e ZSTD_nextInputType(ZSTD_DCtx* dctx) {
1739
1750
  }
1740
1751
  }
1741
1752
 
1742
- int ZSTD_isSkipFrame(ZSTD_DCtx* dctx) { return dctx->stage == ZSTDds_skipFrame; } /* for zbuff */
1753
+ static int ZSTD_isSkipFrame(ZSTD_DCtx* dctx) { return dctx->stage == ZSTDds_skipFrame; }
1743
1754
 
1744
1755
  /** ZSTD_decompressContinue() :
1745
- * @return : nb of bytes generated into `dst` (necessarily <= `dstCapacity)
1746
- * or an error code, which can be tested using ZSTD_isError() */
1756
+ * srcSize : must be the exact nb of bytes expected (see ZSTD_nextSrcSizeToDecompress())
1757
+ * @return : nb of bytes generated into `dst` (necessarily <= `dstCapacity)
1758
+ * or an error code, which can be tested using ZSTD_isError() */
1747
1759
  size_t ZSTD_decompressContinue(ZSTD_DCtx* dctx, void* dst, size_t dstCapacity, const void* src, size_t srcSize)
1748
1760
  {
1761
+ DEBUGLOG(5, "ZSTD_decompressContinue");
1749
1762
  /* Sanity check */
1750
- if (srcSize != dctx->expected) return ERROR(srcSize_wrong);
1763
+ if (srcSize != dctx->expected) return ERROR(srcSize_wrong); /* not allowed */
1751
1764
  if (dstCapacity) ZSTD_checkContinuity(dctx, dst);
1752
1765
 
1753
1766
  switch (dctx->stage)
1754
1767
  {
1755
1768
  case ZSTDds_getFrameHeaderSize :
1756
- if (srcSize != ZSTD_frameHeaderSize_prefix) return ERROR(srcSize_wrong); /* impossible */
1757
- if ((MEM_readLE32(src) & 0xFFFFFFF0U) == ZSTD_MAGIC_SKIPPABLE_START) { /* skippable frame */
1758
- memcpy(dctx->headerBuffer, src, ZSTD_frameHeaderSize_prefix);
1759
- dctx->expected = ZSTD_skippableHeaderSize - ZSTD_frameHeaderSize_prefix; /* magic number + skippable frame length */
1760
- dctx->stage = ZSTDds_decodeSkippableHeader;
1761
- return 0;
1762
- }
1763
- dctx->headerSize = ZSTD_frameHeaderSize(src, ZSTD_frameHeaderSize_prefix);
1769
+ assert(src != NULL);
1770
+ if (dctx->format == ZSTD_f_zstd1) { /* allows header */
1771
+ assert(srcSize >= ZSTD_frameIdSize); /* to read skippable magic number */
1772
+ if ((MEM_readLE32(src) & 0xFFFFFFF0U) == ZSTD_MAGIC_SKIPPABLE_START) { /* skippable frame */
1773
+ memcpy(dctx->headerBuffer, src, srcSize);
1774
+ dctx->expected = ZSTD_skippableHeaderSize - srcSize; /* remaining to load to get full skippable frame header */
1775
+ dctx->stage = ZSTDds_decodeSkippableHeader;
1776
+ return 0;
1777
+ } }
1778
+ dctx->headerSize = ZSTD_frameHeaderSize_internal(src, srcSize, dctx->format);
1764
1779
  if (ZSTD_isError(dctx->headerSize)) return dctx->headerSize;
1765
- memcpy(dctx->headerBuffer, src, ZSTD_frameHeaderSize_prefix);
1766
- if (dctx->headerSize > ZSTD_frameHeaderSize_prefix) {
1767
- dctx->expected = dctx->headerSize - ZSTD_frameHeaderSize_prefix;
1768
- dctx->stage = ZSTDds_decodeFrameHeader;
1769
- return 0;
1770
- }
1771
- dctx->expected = 0; /* not necessary to copy more */
1780
+ memcpy(dctx->headerBuffer, src, srcSize);
1781
+ dctx->expected = dctx->headerSize - srcSize;
1782
+ dctx->stage = ZSTDds_decodeFrameHeader;
1783
+ return 0;
1772
1784
 
1773
1785
  case ZSTDds_decodeFrameHeader:
1774
- memcpy(dctx->headerBuffer + ZSTD_frameHeaderSize_prefix, src, dctx->expected);
1786
+ assert(src != NULL);
1787
+ memcpy(dctx->headerBuffer + (dctx->headerSize - srcSize), src, srcSize);
1775
1788
  CHECK_F(ZSTD_decodeFrameHeader(dctx, dctx->headerBuffer, dctx->headerSize));
1776
1789
  dctx->expected = ZSTD_blockHeaderSize;
1777
1790
  dctx->stage = ZSTDds_decodeBlockHeader;
@@ -1798,18 +1811,21 @@ size_t ZSTD_decompressContinue(ZSTD_DCtx* dctx, void* dst, size_t dstCapacity, c
1798
1811
  dctx->stage = ZSTDds_getFrameHeaderSize;
1799
1812
  }
1800
1813
  } else {
1801
- dctx->expected = 3; /* go directly to next header */
1814
+ dctx->expected = ZSTD_blockHeaderSize; /* jump to next header */
1802
1815
  dctx->stage = ZSTDds_decodeBlockHeader;
1803
1816
  }
1804
1817
  return 0;
1805
1818
  }
1819
+
1806
1820
  case ZSTDds_decompressLastBlock:
1807
1821
  case ZSTDds_decompressBlock:
1822
+ DEBUGLOG(5, "case ZSTDds_decompressBlock");
1808
1823
  { size_t rSize;
1809
1824
  switch(dctx->bType)
1810
1825
  {
1811
1826
  case bt_compressed:
1812
- rSize = ZSTD_decompressBlock_internal(dctx, dst, dstCapacity, src, srcSize);
1827
+ DEBUGLOG(5, "case bt_compressed");
1828
+ rSize = ZSTD_decompressBlock_internal(dctx, dst, dstCapacity, src, srcSize, /* frame */ 1);
1813
1829
  break;
1814
1830
  case bt_raw :
1815
1831
  rSize = ZSTD_copyRawBlock(dst, dstCapacity, src, srcSize);
@@ -1822,9 +1838,16 @@ size_t ZSTD_decompressContinue(ZSTD_DCtx* dctx, void* dst, size_t dstCapacity, c
1822
1838
  return ERROR(corruption_detected);
1823
1839
  }
1824
1840
  if (ZSTD_isError(rSize)) return rSize;
1841
+ DEBUGLOG(5, "decoded size from block : %u", (U32)rSize);
1842
+ dctx->decodedSize += rSize;
1825
1843
  if (dctx->fParams.checksumFlag) XXH64_update(&dctx->xxhState, dst, rSize);
1826
1844
 
1827
1845
  if (dctx->stage == ZSTDds_decompressLastBlock) { /* end of frame */
1846
+ DEBUGLOG(4, "decoded size from frame : %u", (U32)dctx->decodedSize);
1847
+ if (dctx->fParams.frameContentSize != ZSTD_CONTENTSIZE_UNKNOWN) {
1848
+ if (dctx->decodedSize != dctx->fParams.frameContentSize) {
1849
+ return ERROR(corruption_detected);
1850
+ } }
1828
1851
  if (dctx->fParams.checksumFlag) { /* another round for frame checksum */
1829
1852
  dctx->expected = 4;
1830
1853
  dctx->stage = ZSTDds_checkChecksum;
@@ -1839,25 +1862,31 @@ size_t ZSTD_decompressContinue(ZSTD_DCtx* dctx, void* dst, size_t dstCapacity, c
1839
1862
  }
1840
1863
  return rSize;
1841
1864
  }
1865
+
1842
1866
  case ZSTDds_checkChecksum:
1867
+ assert(srcSize == 4); /* guaranteed by dctx->expected */
1843
1868
  { U32 const h32 = (U32)XXH64_digest(&dctx->xxhState);
1844
- U32 const check32 = MEM_readLE32(src); /* srcSize == 4, guaranteed by dctx->expected */
1869
+ U32 const check32 = MEM_readLE32(src);
1870
+ DEBUGLOG(4, "checksum : calculated %08X :: %08X read", h32, check32);
1845
1871
  if (check32 != h32) return ERROR(checksum_wrong);
1846
1872
  dctx->expected = 0;
1847
1873
  dctx->stage = ZSTDds_getFrameHeaderSize;
1848
1874
  return 0;
1849
1875
  }
1876
+
1850
1877
  case ZSTDds_decodeSkippableHeader:
1851
- { memcpy(dctx->headerBuffer + ZSTD_frameHeaderSize_prefix, src, dctx->expected);
1852
- dctx->expected = MEM_readLE32(dctx->headerBuffer + 4);
1853
- dctx->stage = ZSTDds_skipFrame;
1854
- return 0;
1855
- }
1878
+ assert(src != NULL);
1879
+ assert(srcSize <= ZSTD_skippableHeaderSize);
1880
+ memcpy(dctx->headerBuffer + (ZSTD_skippableHeaderSize - srcSize), src, srcSize); /* complete skippable header */
1881
+ dctx->expected = MEM_readLE32(dctx->headerBuffer + ZSTD_frameIdSize); /* note : dctx->expected can grow seriously large, beyond local buffer size */
1882
+ dctx->stage = ZSTDds_skipFrame;
1883
+ return 0;
1884
+
1856
1885
  case ZSTDds_skipFrame:
1857
- { dctx->expected = 0;
1858
- dctx->stage = ZSTDds_getFrameHeaderSize;
1859
- return 0;
1860
- }
1886
+ dctx->expected = 0;
1887
+ dctx->stage = ZSTDds_getFrameHeaderSize;
1888
+ return 0;
1889
+
1861
1890
  default:
1862
1891
  return ERROR(GENERIC); /* impossible */
1863
1892
  }
@@ -1876,7 +1905,7 @@ static size_t ZSTD_refDictContent(ZSTD_DCtx* dctx, const void* dict, size_t dict
1876
1905
  /* ZSTD_loadEntropy() :
1877
1906
  * dict : must point at beginning of a valid zstd dictionary
1878
1907
  * @return : size of entropy tables read */
1879
- static size_t ZSTD_loadEntropy(ZSTD_entropyTables_t* entropy, const void* const dict, size_t const dictSize)
1908
+ static size_t ZSTD_loadEntropy(ZSTD_entropyDTables_t* entropy, const void* const dict, size_t const dictSize)
1880
1909
  {
1881
1910
  const BYTE* dictPtr = (const BYTE*)dict;
1882
1911
  const BYTE* const dictEnd = dictPtr + dictSize;
@@ -1885,7 +1914,9 @@ static size_t ZSTD_loadEntropy(ZSTD_entropyTables_t* entropy, const void* const
1885
1914
  dictPtr += 8; /* skip header = magic + dictID */
1886
1915
 
1887
1916
 
1888
- { size_t const hSize = HUF_readDTableX4(entropy->hufTable, dictPtr, dictEnd-dictPtr);
1917
+ { size_t const hSize = HUF_readDTableX4_wksp(
1918
+ entropy->hufTable, dictPtr, dictEnd - dictPtr,
1919
+ entropy->workspace, sizeof(entropy->workspace));
1889
1920
  if (HUF_isError(hSize)) return ERROR(dictionary_corrupted);
1890
1921
  dictPtr += hSize;
1891
1922
  }
@@ -1933,10 +1964,10 @@ static size_t ZSTD_decompress_insertDictionary(ZSTD_DCtx* dctx, const void* dict
1933
1964
  {
1934
1965
  if (dictSize < 8) return ZSTD_refDictContent(dctx, dict, dictSize);
1935
1966
  { U32 const magic = MEM_readLE32(dict);
1936
- if (magic != ZSTD_DICT_MAGIC) {
1967
+ if (magic != ZSTD_MAGIC_DICTIONARY) {
1937
1968
  return ZSTD_refDictContent(dctx, dict, dictSize); /* pure content mode */
1938
1969
  } }
1939
- dctx->dictID = MEM_readLE32((const char*)dict + 4);
1970
+ dctx->dictID = MEM_readLE32((const char*)dict + ZSTD_frameIdSize);
1940
1971
 
1941
1972
  /* load entropy tables */
1942
1973
  { size_t const eSize = ZSTD_loadEntropy(&dctx->entropy, dict, dictSize);
@@ -1950,10 +1981,34 @@ static size_t ZSTD_decompress_insertDictionary(ZSTD_DCtx* dctx, const void* dict
1950
1981
  return ZSTD_refDictContent(dctx, dict, dictSize);
1951
1982
  }
1952
1983
 
1984
+ /* Note : this function cannot fail */
1985
+ size_t ZSTD_decompressBegin(ZSTD_DCtx* dctx)
1986
+ {
1987
+ assert(dctx != NULL);
1988
+ dctx->expected = ZSTD_startingInputLength(dctx->format); /* dctx->format must be properly set */
1989
+ dctx->stage = ZSTDds_getFrameHeaderSize;
1990
+ dctx->decodedSize = 0;
1991
+ dctx->previousDstEnd = NULL;
1992
+ dctx->base = NULL;
1993
+ dctx->vBase = NULL;
1994
+ dctx->dictEnd = NULL;
1995
+ dctx->entropy.hufTable[0] = (HUF_DTable)((HufLog)*0x1000001); /* cover both little and big endian */
1996
+ dctx->litEntropy = dctx->fseEntropy = 0;
1997
+ dctx->dictID = 0;
1998
+ ZSTD_STATIC_ASSERT(sizeof(dctx->entropy.rep) == sizeof(repStartValue));
1999
+ memcpy(dctx->entropy.rep, repStartValue, sizeof(repStartValue)); /* initial repcodes */
2000
+ dctx->LLTptr = dctx->entropy.LLTable;
2001
+ dctx->MLTptr = dctx->entropy.MLTable;
2002
+ dctx->OFTptr = dctx->entropy.OFTable;
2003
+ dctx->HUFptr = dctx->entropy.hufTable;
2004
+ return 0;
2005
+ }
2006
+
1953
2007
  size_t ZSTD_decompressBegin_usingDict(ZSTD_DCtx* dctx, const void* dict, size_t dictSize)
1954
2008
  {
1955
- CHECK_F(ZSTD_decompressBegin(dctx));
1956
- if (dict && dictSize) CHECK_E(ZSTD_decompress_insertDictionary(dctx, dict, dictSize), dictionary_corrupted);
2009
+ CHECK_F( ZSTD_decompressBegin(dctx) );
2010
+ if (dict && dictSize)
2011
+ CHECK_E(ZSTD_decompress_insertDictionary(dctx, dict, dictSize), dictionary_corrupted);
1957
2012
  return 0;
1958
2013
  }
1959
2014
 
@@ -1964,7 +2019,7 @@ struct ZSTD_DDict_s {
1964
2019
  void* dictBuffer;
1965
2020
  const void* dictContent;
1966
2021
  size_t dictSize;
1967
- ZSTD_entropyTables_t entropy;
2022
+ ZSTD_entropyDTables_t entropy;
1968
2023
  U32 dictID;
1969
2024
  U32 entropyPresent;
1970
2025
  ZSTD_customMem cMem;
@@ -1980,10 +2035,10 @@ static size_t ZSTD_DDictDictSize(const ZSTD_DDict* ddict)
1980
2035
  return ddict->dictSize;
1981
2036
  }
1982
2037
 
1983
- static void ZSTD_refDDict(ZSTD_DCtx* dstDCtx, const ZSTD_DDict* ddict)
2038
+ size_t ZSTD_decompressBegin_usingDDict(ZSTD_DCtx* dstDCtx, const ZSTD_DDict* ddict)
1984
2039
  {
1985
- ZSTD_decompressBegin(dstDCtx); /* init */
1986
- if (ddict) { /* support refDDict on NULL */
2040
+ CHECK_F( ZSTD_decompressBegin(dstDCtx) );
2041
+ if (ddict) { /* support begin on NULL */
1987
2042
  dstDCtx->dictID = ddict->dictID;
1988
2043
  dstDCtx->base = ddict->dictContent;
1989
2044
  dstDCtx->vBase = ddict->dictContent;
@@ -2004,6 +2059,7 @@ static void ZSTD_refDDict(ZSTD_DCtx* dstDCtx, const ZSTD_DDict* ddict)
2004
2059
  dstDCtx->fseEntropy = 0;
2005
2060
  }
2006
2061
  }
2062
+ return 0;
2007
2063
  }
2008
2064
 
2009
2065
  static size_t ZSTD_loadEntropy_inDDict(ZSTD_DDict* ddict)
@@ -2012,9 +2068,9 @@ static size_t ZSTD_loadEntropy_inDDict(ZSTD_DDict* ddict)
2012
2068
  ddict->entropyPresent = 0;
2013
2069
  if (ddict->dictSize < 8) return 0;
2014
2070
  { U32 const magic = MEM_readLE32(ddict->dictContent);
2015
- if (magic != ZSTD_DICT_MAGIC) return 0; /* pure content mode */
2071
+ if (magic != ZSTD_MAGIC_DICTIONARY) return 0; /* pure content mode */
2016
2072
  }
2017
- ddict->dictID = MEM_readLE32((const char*)ddict->dictContent + 4);
2073
+ ddict->dictID = MEM_readLE32((const char*)ddict->dictContent + ZSTD_frameIdSize);
2018
2074
 
2019
2075
  /* load entropy tables */
2020
2076
  CHECK_E( ZSTD_loadEntropy(&ddict->entropy, ddict->dictContent, ddict->dictSize), dictionary_corrupted );
@@ -2023,33 +2079,39 @@ static size_t ZSTD_loadEntropy_inDDict(ZSTD_DDict* ddict)
2023
2079
  }
2024
2080
 
2025
2081
 
2026
- ZSTD_DDict* ZSTD_createDDict_advanced(const void* dict, size_t dictSize, unsigned byReference, ZSTD_customMem customMem)
2082
+ static size_t ZSTD_initDDict_internal(ZSTD_DDict* ddict, const void* dict, size_t dictSize, ZSTD_dictLoadMethod_e dictLoadMethod)
2083
+ {
2084
+ if ((dictLoadMethod == ZSTD_dlm_byRef) || (!dict) || (!dictSize)) {
2085
+ ddict->dictBuffer = NULL;
2086
+ ddict->dictContent = dict;
2087
+ } else {
2088
+ void* const internalBuffer = ZSTD_malloc(dictSize, ddict->cMem);
2089
+ ddict->dictBuffer = internalBuffer;
2090
+ ddict->dictContent = internalBuffer;
2091
+ if (!internalBuffer) return ERROR(memory_allocation);
2092
+ memcpy(internalBuffer, dict, dictSize);
2093
+ }
2094
+ ddict->dictSize = dictSize;
2095
+ ddict->entropy.hufTable[0] = (HUF_DTable)((HufLog)*0x1000001); /* cover both little and big endian */
2096
+
2097
+ /* parse dictionary content */
2098
+ CHECK_F( ZSTD_loadEntropy_inDDict(ddict) );
2099
+
2100
+ return 0;
2101
+ }
2102
+
2103
+ ZSTD_DDict* ZSTD_createDDict_advanced(const void* dict, size_t dictSize, ZSTD_dictLoadMethod_e dictLoadMethod, ZSTD_customMem customMem)
2027
2104
  {
2028
- if (!customMem.customAlloc && !customMem.customFree) customMem = defaultCustomMem;
2029
- if (!customMem.customAlloc || !customMem.customFree) return NULL;
2105
+ if (!customMem.customAlloc ^ !customMem.customFree) return NULL;
2030
2106
 
2031
2107
  { ZSTD_DDict* const ddict = (ZSTD_DDict*) ZSTD_malloc(sizeof(ZSTD_DDict), customMem);
2032
2108
  if (!ddict) return NULL;
2033
2109
  ddict->cMem = customMem;
2034
2110
 
2035
- if ((byReference) || (!dict) || (!dictSize)) {
2036
- ddict->dictBuffer = NULL;
2037
- ddict->dictContent = dict;
2038
- } else {
2039
- void* const internalBuffer = ZSTD_malloc(dictSize, customMem);
2040
- if (!internalBuffer) { ZSTD_freeDDict(ddict); return NULL; }
2041
- memcpy(internalBuffer, dict, dictSize);
2042
- ddict->dictBuffer = internalBuffer;
2043
- ddict->dictContent = internalBuffer;
2111
+ if (ZSTD_isError( ZSTD_initDDict_internal(ddict, dict, dictSize, dictLoadMethod) )) {
2112
+ ZSTD_freeDDict(ddict);
2113
+ return NULL;
2044
2114
  }
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);
2049
- if (ZSTD_isError(errorCode)) {
2050
- ZSTD_freeDDict(ddict);
2051
- return NULL;
2052
- } }
2053
2115
 
2054
2116
  return ddict;
2055
2117
  }
@@ -2062,10 +2124,9 @@ ZSTD_DDict* ZSTD_createDDict_advanced(const void* dict, size_t dictSize, unsigne
2062
2124
  ZSTD_DDict* ZSTD_createDDict(const void* dict, size_t dictSize)
2063
2125
  {
2064
2126
  ZSTD_customMem const allocator = { NULL, NULL, NULL };
2065
- return ZSTD_createDDict_advanced(dict, dictSize, 0, allocator);
2127
+ return ZSTD_createDDict_advanced(dict, dictSize, ZSTD_dlm_byCopy, allocator);
2066
2128
  }
2067
2129
 
2068
-
2069
2130
  /*! ZSTD_createDDict_byReference() :
2070
2131
  * Create a digested dictionary, to start decompression without startup delay.
2071
2132
  * Dictionary content is simply referenced, it will be accessed during decompression.
@@ -2073,7 +2134,28 @@ ZSTD_DDict* ZSTD_createDDict(const void* dict, size_t dictSize)
2073
2134
  ZSTD_DDict* ZSTD_createDDict_byReference(const void* dictBuffer, size_t dictSize)
2074
2135
  {
2075
2136
  ZSTD_customMem const allocator = { NULL, NULL, NULL };
2076
- return ZSTD_createDDict_advanced(dictBuffer, dictSize, 1, allocator);
2137
+ return ZSTD_createDDict_advanced(dictBuffer, dictSize, ZSTD_dlm_byRef, allocator);
2138
+ }
2139
+
2140
+
2141
+ ZSTD_DDict* ZSTD_initStaticDDict(void* workspace, size_t workspaceSize,
2142
+ const void* dict, size_t dictSize,
2143
+ ZSTD_dictLoadMethod_e dictLoadMethod)
2144
+ {
2145
+ size_t const neededSpace =
2146
+ sizeof(ZSTD_DDict) + (dictLoadMethod == ZSTD_dlm_byRef ? 0 : dictSize);
2147
+ ZSTD_DDict* const ddict = (ZSTD_DDict*)workspace;
2148
+ assert(workspace != NULL);
2149
+ assert(dict != NULL);
2150
+ if ((size_t)workspace & 7) return NULL; /* 8-aligned */
2151
+ if (workspaceSize < neededSpace) return NULL;
2152
+ if (dictLoadMethod == ZSTD_dlm_byCopy) {
2153
+ memcpy(ddict+1, dict, dictSize); /* local copy */
2154
+ dict = ddict+1;
2155
+ }
2156
+ if (ZSTD_isError( ZSTD_initDDict_internal(ddict, dict, dictSize, ZSTD_dlm_byRef) ))
2157
+ return NULL;
2158
+ return ddict;
2077
2159
  }
2078
2160
 
2079
2161
 
@@ -2087,6 +2169,14 @@ size_t ZSTD_freeDDict(ZSTD_DDict* ddict)
2087
2169
  }
2088
2170
  }
2089
2171
 
2172
+ /*! ZSTD_estimateDDictSize() :
2173
+ * Estimate amount of memory that will be needed to create a dictionary for decompression.
2174
+ * Note : dictionary created by reference using ZSTD_dlm_byRef are smaller */
2175
+ size_t ZSTD_estimateDDictSize(size_t dictSize, ZSTD_dictLoadMethod_e dictLoadMethod)
2176
+ {
2177
+ return sizeof(ZSTD_DDict) + (dictLoadMethod == ZSTD_dlm_byRef ? 0 : dictSize);
2178
+ }
2179
+
2090
2180
  size_t ZSTD_sizeof_DDict(const ZSTD_DDict* ddict)
2091
2181
  {
2092
2182
  if (ddict==NULL) return 0; /* support sizeof on NULL */
@@ -2100,8 +2190,8 @@ size_t ZSTD_sizeof_DDict(const ZSTD_DDict* ddict)
2100
2190
  unsigned ZSTD_getDictID_fromDict(const void* dict, size_t dictSize)
2101
2191
  {
2102
2192
  if (dictSize < 8) return 0;
2103
- if (MEM_readLE32(dict) != ZSTD_DICT_MAGIC) return 0;
2104
- return MEM_readLE32((const char*)dict + 4);
2193
+ if (MEM_readLE32(dict) != ZSTD_MAGIC_DICTIONARY) return 0;
2194
+ return MEM_readLE32((const char*)dict + ZSTD_frameIdSize);
2105
2195
  }
2106
2196
 
2107
2197
  /*! ZSTD_getDictID_fromDDict() :
@@ -2115,19 +2205,22 @@ unsigned ZSTD_getDictID_fromDDict(const ZSTD_DDict* ddict)
2115
2205
  }
2116
2206
 
2117
2207
  /*! ZSTD_getDictID_fromFrame() :
2118
- * Provides the dictID required to decompressed the frame stored within `src`.
2208
+ * Provides the dictID required to decompresse frame stored within `src`.
2119
2209
  * If @return == 0, the dictID could not be decoded.
2120
2210
  * This could for one of the following reasons :
2121
- * - The frame does not require a dictionary to be decoded (most common case).
2122
- * - The frame was built with dictID intentionally removed. Whatever dictionary is necessary is a hidden information.
2211
+ * - The frame does not require a dictionary (most common case).
2212
+ * - The frame was built with dictID intentionally removed.
2213
+ * Needed dictionary is a hidden information.
2123
2214
  * Note : this use case also happens when using a non-conformant dictionary.
2124
- * - `srcSize` is too small, and as a result, the frame header could not be decoded (only possible if `srcSize < ZSTD_FRAMEHEADERSIZE_MAX`).
2215
+ * - `srcSize` is too small, and as a result, frame header could not be decoded.
2216
+ * Note : possible if `srcSize < ZSTD_FRAMEHEADERSIZE_MAX`.
2125
2217
  * - This is not a Zstandard frame.
2126
- * When identifying the exact failure cause, it's possible to used ZSTD_getFrameParams(), which will provide a more precise error code. */
2218
+ * When identifying the exact failure cause, it's possible to use
2219
+ * ZSTD_getFrameHeader(), which will provide a more precise error code. */
2127
2220
  unsigned ZSTD_getDictID_fromFrame(const void* src, size_t srcSize)
2128
2221
  {
2129
- ZSTD_frameParams zfp = { 0 , 0 , 0 , 0 };
2130
- size_t const hError = ZSTD_getFrameParams(&zfp, src, srcSize);
2222
+ ZSTD_frameHeader zfp = { 0, 0, 0, ZSTD_frame, 0, 0, 0 };
2223
+ size_t const hError = ZSTD_getFrameHeader(&zfp, src, srcSize);
2131
2224
  if (ZSTD_isError(hError)) return 0;
2132
2225
  return zfp.dictID;
2133
2226
  }
@@ -2152,84 +2245,35 @@ size_t ZSTD_decompress_usingDDict(ZSTD_DCtx* dctx,
2152
2245
  * Streaming decompression
2153
2246
  *====================================*/
2154
2247
 
2155
- typedef enum { zdss_init, zdss_loadHeader,
2156
- zdss_read, zdss_load, zdss_flush } ZSTD_dStreamStage;
2157
-
2158
- /* *** Resource management *** */
2159
- struct ZSTD_DStream_s {
2160
- ZSTD_DCtx* dctx;
2161
- ZSTD_DDict* ddictLocal;
2162
- const ZSTD_DDict* ddict;
2163
- ZSTD_frameParams fParams;
2164
- ZSTD_dStreamStage stage;
2165
- char* inBuff;
2166
- size_t inBuffSize;
2167
- size_t inPos;
2168
- size_t maxWindowSize;
2169
- char* outBuff;
2170
- size_t outBuffSize;
2171
- size_t outStart;
2172
- size_t outEnd;
2173
- size_t blockSize;
2174
- BYTE headerBuffer[ZSTD_FRAMEHEADERSIZE_MAX]; /* tmp buffer to store frame header */
2175
- size_t lhSize;
2176
- ZSTD_customMem customMem;
2177
- void* legacyContext;
2178
- U32 previousLegacyVersion;
2179
- U32 legacyVersion;
2180
- U32 hostageByte;
2181
- }; /* typedef'd to ZSTD_DStream within "zstd.h" */
2182
-
2183
-
2184
2248
  ZSTD_DStream* ZSTD_createDStream(void)
2185
2249
  {
2186
- return ZSTD_createDStream_advanced(defaultCustomMem);
2250
+ return ZSTD_createDStream_advanced(ZSTD_defaultCMem);
2187
2251
  }
2188
2252
 
2189
- ZSTD_DStream* ZSTD_createDStream_advanced(ZSTD_customMem customMem)
2253
+ ZSTD_DStream* ZSTD_initStaticDStream(void *workspace, size_t workspaceSize)
2190
2254
  {
2191
- ZSTD_DStream* zds;
2192
-
2193
- if (!customMem.customAlloc && !customMem.customFree) customMem = defaultCustomMem;
2194
- if (!customMem.customAlloc || !customMem.customFree) return NULL;
2255
+ return ZSTD_initStaticDCtx(workspace, workspaceSize);
2256
+ }
2195
2257
 
2196
- zds = (ZSTD_DStream*) ZSTD_malloc(sizeof(ZSTD_DStream), customMem);
2197
- if (zds==NULL) return NULL;
2198
- memset(zds, 0, sizeof(ZSTD_DStream));
2199
- memcpy(&zds->customMem, &customMem, sizeof(ZSTD_customMem));
2200
- zds->dctx = ZSTD_createDCtx_advanced(customMem);
2201
- if (zds->dctx == NULL) { ZSTD_freeDStream(zds); return NULL; }
2202
- zds->stage = zdss_init;
2203
- zds->maxWindowSize = ZSTD_MAXWINDOWSIZE_DEFAULT;
2204
- return zds;
2258
+ ZSTD_DStream* ZSTD_createDStream_advanced(ZSTD_customMem customMem)
2259
+ {
2260
+ return ZSTD_createDCtx_advanced(customMem);
2205
2261
  }
2206
2262
 
2207
2263
  size_t ZSTD_freeDStream(ZSTD_DStream* zds)
2208
2264
  {
2209
- if (zds==NULL) return 0; /* support free on null */
2210
- { ZSTD_customMem const cMem = zds->customMem;
2211
- ZSTD_freeDCtx(zds->dctx);
2212
- ZSTD_freeDDict(zds->ddictLocal);
2213
- ZSTD_free(zds->inBuff, cMem);
2214
- ZSTD_free(zds->outBuff, cMem);
2215
- #if defined(ZSTD_LEGACY_SUPPORT) && (ZSTD_LEGACY_SUPPORT >= 1)
2216
- if (zds->legacyContext)
2217
- ZSTD_freeLegacyStreamContext(zds->legacyContext, zds->previousLegacyVersion);
2218
- #endif
2219
- ZSTD_free(zds, cMem);
2220
- return 0;
2221
- }
2265
+ return ZSTD_freeDCtx(zds);
2222
2266
  }
2223
2267
 
2224
2268
 
2225
2269
  /* *** Initialization *** */
2226
2270
 
2227
- size_t ZSTD_DStreamInSize(void) { return ZSTD_BLOCKSIZE_ABSOLUTEMAX + ZSTD_blockHeaderSize; }
2228
- size_t ZSTD_DStreamOutSize(void) { return ZSTD_BLOCKSIZE_ABSOLUTEMAX; }
2271
+ size_t ZSTD_DStreamInSize(void) { return ZSTD_BLOCKSIZE_MAX + ZSTD_blockHeaderSize; }
2272
+ size_t ZSTD_DStreamOutSize(void) { return ZSTD_BLOCKSIZE_MAX; }
2229
2273
 
2230
2274
  size_t ZSTD_initDStream_usingDict(ZSTD_DStream* zds, const void* dict, size_t dictSize)
2231
2275
  {
2232
- zds->stage = zdss_loadHeader;
2276
+ zds->streamStage = zdss_loadHeader;
2233
2277
  zds->lhSize = zds->inPos = zds->outStart = zds->outEnd = 0;
2234
2278
  ZSTD_freeDDict(zds->ddictLocal);
2235
2279
  if (dict && dictSize >= 8) {
@@ -2242,12 +2286,16 @@ size_t ZSTD_initDStream_usingDict(ZSTD_DStream* zds, const void* dict, size_t di
2242
2286
  return ZSTD_frameHeaderSize_prefix;
2243
2287
  }
2244
2288
 
2289
+ /* note : this variant can't fail */
2245
2290
  size_t ZSTD_initDStream(ZSTD_DStream* zds)
2246
2291
  {
2247
2292
  return ZSTD_initDStream_usingDict(zds, NULL, 0);
2248
2293
  }
2249
2294
 
2250
- size_t ZSTD_initDStream_usingDDict(ZSTD_DStream* zds, const ZSTD_DDict* ddict) /**< note : ddict will just be referenced, and must outlive decompression session */
2295
+ /* ZSTD_initDStream_usingDDict() :
2296
+ * ddict will just be referenced, and must outlive decompression session
2297
+ * this function cannot fail */
2298
+ size_t ZSTD_initDStream_usingDDict(ZSTD_DStream* zds, const ZSTD_DDict* ddict)
2251
2299
  {
2252
2300
  size_t const initResult = ZSTD_initDStream(zds);
2253
2301
  zds->ddict = ddict;
@@ -2256,7 +2304,7 @@ size_t ZSTD_initDStream_usingDDict(ZSTD_DStream* zds, const ZSTD_DDict* ddict)
2256
2304
 
2257
2305
  size_t ZSTD_resetDStream(ZSTD_DStream* zds)
2258
2306
  {
2259
- zds->stage = zdss_loadHeader;
2307
+ zds->streamStage = zdss_loadHeader;
2260
2308
  zds->lhSize = zds->inPos = zds->outStart = zds->outEnd = 0;
2261
2309
  zds->legacyVersion = 0;
2262
2310
  zds->hostageByte = 0;
@@ -2266,19 +2314,73 @@ size_t ZSTD_resetDStream(ZSTD_DStream* zds)
2266
2314
  size_t ZSTD_setDStreamParameter(ZSTD_DStream* zds,
2267
2315
  ZSTD_DStreamParameter_e paramType, unsigned paramValue)
2268
2316
  {
2317
+ ZSTD_STATIC_ASSERT((unsigned)zdss_loadHeader >= (unsigned)zdss_init);
2318
+ if ((unsigned)zds->streamStage > (unsigned)zdss_loadHeader)
2319
+ return ERROR(stage_wrong);
2269
2320
  switch(paramType)
2270
2321
  {
2271
- default : return ERROR(parameter_unknown);
2272
- case DStream_p_maxWindowSize : zds->maxWindowSize = paramValue ? paramValue : (U32)(-1); break;
2322
+ default : return ERROR(parameter_unsupported);
2323
+ case DStream_p_maxWindowSize :
2324
+ DEBUGLOG(4, "setting maxWindowSize = %u KB", paramValue >> 10);
2325
+ zds->maxWindowSize = paramValue ? paramValue : (U32)(-1);
2326
+ break;
2273
2327
  }
2274
2328
  return 0;
2275
2329
  }
2276
2330
 
2331
+ size_t ZSTD_DCtx_setMaxWindowSize(ZSTD_DCtx* dctx, size_t maxWindowSize)
2332
+ {
2333
+ ZSTD_STATIC_ASSERT((unsigned)zdss_loadHeader >= (unsigned)zdss_init);
2334
+ if ((unsigned)dctx->streamStage > (unsigned)zdss_loadHeader)
2335
+ return ERROR(stage_wrong);
2336
+ dctx->maxWindowSize = maxWindowSize;
2337
+ return 0;
2338
+ }
2339
+
2340
+ size_t ZSTD_DCtx_setFormat(ZSTD_DCtx* dctx, ZSTD_format_e format)
2341
+ {
2342
+ DEBUGLOG(4, "ZSTD_DCtx_setFormat : %u", (unsigned)format);
2343
+ ZSTD_STATIC_ASSERT((unsigned)zdss_loadHeader >= (unsigned)zdss_init);
2344
+ if ((unsigned)dctx->streamStage > (unsigned)zdss_loadHeader)
2345
+ return ERROR(stage_wrong);
2346
+ dctx->format = format;
2347
+ return 0;
2348
+ }
2349
+
2277
2350
 
2278
2351
  size_t ZSTD_sizeof_DStream(const ZSTD_DStream* zds)
2279
2352
  {
2280
- if (zds==NULL) return 0; /* support sizeof on NULL */
2281
- return sizeof(*zds) + ZSTD_sizeof_DCtx(zds->dctx) + ZSTD_sizeof_DDict(zds->ddictLocal) + zds->inBuffSize + zds->outBuffSize;
2353
+ return ZSTD_sizeof_DCtx(zds);
2354
+ }
2355
+
2356
+ size_t ZSTD_decodingBufferSize_min(unsigned long long windowSize, unsigned long long frameContentSize)
2357
+ {
2358
+ size_t const blockSize = (size_t) MIN(windowSize, ZSTD_BLOCKSIZE_MAX);
2359
+ unsigned long long const neededRBSize = windowSize + blockSize + (WILDCOPY_OVERLENGTH * 2);
2360
+ unsigned long long const neededSize = MIN(frameContentSize, neededRBSize);
2361
+ size_t const minRBSize = (size_t) neededSize;
2362
+ if ((unsigned long long)minRBSize != neededSize) return ERROR(frameParameter_windowTooLarge);
2363
+ return minRBSize;
2364
+ }
2365
+
2366
+ size_t ZSTD_estimateDStreamSize(size_t windowSize)
2367
+ {
2368
+ size_t const blockSize = MIN(windowSize, ZSTD_BLOCKSIZE_MAX);
2369
+ size_t const inBuffSize = blockSize; /* no block can be larger */
2370
+ size_t const outBuffSize = ZSTD_decodingBufferSize_min(windowSize, ZSTD_CONTENTSIZE_UNKNOWN);
2371
+ return ZSTD_estimateDCtxSize() + inBuffSize + outBuffSize;
2372
+ }
2373
+
2374
+ size_t ZSTD_estimateDStreamSize_fromFrame(const void* src, size_t srcSize)
2375
+ {
2376
+ U32 const windowSizeMax = 1U << ZSTD_WINDOWLOG_MAX; /* note : should be user-selectable */
2377
+ ZSTD_frameHeader zfh;
2378
+ size_t const err = ZSTD_getFrameHeader(&zfh, src, srcSize);
2379
+ if (ZSTD_isError(err)) return err;
2380
+ if (err>0) return ERROR(srcSize_wrong);
2381
+ if (zfh.windowSize > windowSizeMax)
2382
+ return ERROR(frameParameter_windowTooLarge);
2383
+ return ZSTD_estimateDStreamSize((size_t)zfh.windowSize);
2282
2384
  }
2283
2385
 
2284
2386
 
@@ -2302,44 +2404,68 @@ size_t ZSTD_decompressStream(ZSTD_DStream* zds, ZSTD_outBuffer* output, ZSTD_inB
2302
2404
  char* op = ostart;
2303
2405
  U32 someMoreWork = 1;
2304
2406
 
2407
+ DEBUGLOG(5, "ZSTD_decompressStream");
2408
+ if (input->pos > input->size) { /* forbidden */
2409
+ DEBUGLOG(5, "in: pos: %u vs size: %u",
2410
+ (U32)input->pos, (U32)input->size);
2411
+ return ERROR(srcSize_wrong);
2412
+ }
2413
+ if (output->pos > output->size) { /* forbidden */
2414
+ DEBUGLOG(5, "out: pos: %u vs size: %u",
2415
+ (U32)output->pos, (U32)output->size);
2416
+ return ERROR(dstSize_tooSmall);
2417
+ }
2418
+ DEBUGLOG(5, "input size : %u", (U32)(input->size - input->pos));
2419
+
2305
2420
  #if defined(ZSTD_LEGACY_SUPPORT) && (ZSTD_LEGACY_SUPPORT>=1)
2306
- if (zds->legacyVersion)
2421
+ if (zds->legacyVersion) {
2422
+ /* legacy support is incompatible with static dctx */
2423
+ if (zds->staticSize) return ERROR(memory_allocation);
2307
2424
  return ZSTD_decompressLegacyStream(zds->legacyContext, zds->legacyVersion, output, input);
2425
+ }
2308
2426
  #endif
2309
2427
 
2310
2428
  while (someMoreWork) {
2311
- switch(zds->stage)
2429
+ switch(zds->streamStage)
2312
2430
  {
2313
2431
  case zdss_init :
2314
2432
  ZSTD_resetDStream(zds); /* transparent reset on starting decoding a new frame */
2315
2433
  /* fall-through */
2316
2434
 
2317
2435
  case zdss_loadHeader :
2318
- { size_t const hSize = ZSTD_getFrameParams(&zds->fParams, zds->headerBuffer, zds->lhSize);
2319
- if (ZSTD_isError(hSize))
2436
+ DEBUGLOG(5, "stage zdss_loadHeader (srcSize : %u)", (U32)(iend - ip));
2437
+ { size_t const hSize = ZSTD_getFrameHeader_internal(&zds->fParams, zds->headerBuffer, zds->lhSize, zds->format);
2438
+ DEBUGLOG(5, "header size : %u", (U32)hSize);
2439
+ if (ZSTD_isError(hSize)) {
2320
2440
  #if defined(ZSTD_LEGACY_SUPPORT) && (ZSTD_LEGACY_SUPPORT>=1)
2321
- { U32 const legacyVersion = ZSTD_isLegacy(istart, iend-istart);
2441
+ U32 const legacyVersion = ZSTD_isLegacy(istart, iend-istart);
2322
2442
  if (legacyVersion) {
2323
2443
  const void* const dict = zds->ddict ? zds->ddict->dictContent : NULL;
2324
2444
  size_t const dictSize = zds->ddict ? zds->ddict->dictSize : 0;
2325
- CHECK_F(ZSTD_initLegacyStream(&zds->legacyContext, zds->previousLegacyVersion, legacyVersion,
2326
- dict, dictSize));
2445
+ /* legacy support is incompatible with static dctx */
2446
+ if (zds->staticSize) return ERROR(memory_allocation);
2447
+ CHECK_F(ZSTD_initLegacyStream(&zds->legacyContext,
2448
+ zds->previousLegacyVersion, legacyVersion,
2449
+ dict, dictSize));
2327
2450
  zds->legacyVersion = zds->previousLegacyVersion = legacyVersion;
2328
- return ZSTD_decompressLegacyStream(zds->legacyContext, zds->legacyVersion, output, input);
2329
- } else {
2330
- return hSize; /* error */
2331
- } }
2332
- #else
2333
- return hSize;
2451
+ return ZSTD_decompressLegacyStream(zds->legacyContext, legacyVersion, output, input);
2452
+ }
2334
2453
  #endif
2454
+ return hSize; /* error */
2455
+ }
2335
2456
  if (hSize != 0) { /* need more input */
2336
2457
  size_t const toLoad = hSize - zds->lhSize; /* if hSize!=0, hSize > zds->lhSize */
2337
- if (toLoad > (size_t)(iend-ip)) { /* not enough input to load full header */
2338
- memcpy(zds->headerBuffer + zds->lhSize, ip, iend-ip);
2339
- zds->lhSize += iend-ip;
2458
+ size_t const remainingInput = (size_t)(iend-ip);
2459
+ assert(iend >= ip);
2460
+ if (toLoad > remainingInput) { /* not enough input to load full header */
2461
+ if (remainingInput > 0) {
2462
+ memcpy(zds->headerBuffer + zds->lhSize, ip, remainingInput);
2463
+ zds->lhSize += remainingInput;
2464
+ }
2340
2465
  input->pos = input->size;
2341
2466
  return (MAX(ZSTD_frameHeaderSize_min, hSize) - zds->lhSize) + ZSTD_blockHeaderSize; /* remaining header bytes + next block header */
2342
2467
  }
2468
+ assert(ip != NULL);
2343
2469
  memcpy(zds->headerBuffer + zds->lhSize, ip, toLoad); zds->lhSize = hSize; ip += toLoad;
2344
2470
  break;
2345
2471
  } }
@@ -2349,132 +2475,191 @@ size_t ZSTD_decompressStream(ZSTD_DStream* zds, ZSTD_outBuffer* output, ZSTD_inB
2349
2475
  && (U64)(size_t)(oend-op) >= zds->fParams.frameContentSize) {
2350
2476
  size_t const cSize = ZSTD_findFrameCompressedSize(istart, iend-istart);
2351
2477
  if (cSize <= (size_t)(iend-istart)) {
2352
- size_t const decompressedSize = ZSTD_decompress_usingDDict(zds->dctx, op, oend-op, istart, cSize, zds->ddict);
2478
+ /* shortcut : using single-pass mode */
2479
+ size_t const decompressedSize = ZSTD_decompress_usingDDict(zds, op, oend-op, istart, cSize, zds->ddict);
2353
2480
  if (ZSTD_isError(decompressedSize)) return decompressedSize;
2481
+ DEBUGLOG(4, "shortcut to single-pass ZSTD_decompress_usingDDict()")
2354
2482
  ip = istart + cSize;
2355
2483
  op += decompressedSize;
2356
- zds->dctx->expected = 0;
2357
- zds->stage = zdss_init;
2484
+ zds->expected = 0;
2485
+ zds->streamStage = zdss_init;
2358
2486
  someMoreWork = 0;
2359
2487
  break;
2360
2488
  } }
2361
2489
 
2362
- /* Consume header */
2363
- ZSTD_refDDict(zds->dctx, zds->ddict);
2364
- { size_t const h1Size = ZSTD_nextSrcSizeToDecompress(zds->dctx); /* == ZSTD_frameHeaderSize_prefix */
2365
- CHECK_F(ZSTD_decompressContinue(zds->dctx, NULL, 0, zds->headerBuffer, h1Size));
2366
- { size_t const h2Size = ZSTD_nextSrcSizeToDecompress(zds->dctx);
2367
- CHECK_F(ZSTD_decompressContinue(zds->dctx, NULL, 0, zds->headerBuffer+h1Size, h2Size));
2368
- } }
2490
+ /* Consume header (see ZSTDds_decodeFrameHeader) */
2491
+ DEBUGLOG(4, "Consume header");
2492
+ CHECK_F(ZSTD_decompressBegin_usingDDict(zds, zds->ddict));
2369
2493
 
2494
+ if ((MEM_readLE32(zds->headerBuffer) & 0xFFFFFFF0U) == ZSTD_MAGIC_SKIPPABLE_START) { /* skippable frame */
2495
+ zds->expected = MEM_readLE32(zds->headerBuffer + ZSTD_frameIdSize);
2496
+ zds->stage = ZSTDds_skipFrame;
2497
+ } else {
2498
+ CHECK_F(ZSTD_decodeFrameHeader(zds, zds->headerBuffer, zds->lhSize));
2499
+ zds->expected = ZSTD_blockHeaderSize;
2500
+ zds->stage = ZSTDds_decodeBlockHeader;
2501
+ }
2502
+
2503
+ /* control buffer memory usage */
2504
+ DEBUGLOG(4, "Control max memory usage (%u KB <= max %u KB)",
2505
+ (U32)(zds->fParams.windowSize >>10),
2506
+ (U32)(zds->maxWindowSize >> 10) );
2370
2507
  zds->fParams.windowSize = MAX(zds->fParams.windowSize, 1U << ZSTD_WINDOWLOG_ABSOLUTEMIN);
2371
2508
  if (zds->fParams.windowSize > zds->maxWindowSize) return ERROR(frameParameter_windowTooLarge);
2372
2509
 
2373
2510
  /* Adapt buffer sizes to frame header instructions */
2374
- { size_t const blockSize = MIN(zds->fParams.windowSize, ZSTD_BLOCKSIZE_ABSOLUTEMAX);
2375
- size_t const neededOutSize = zds->fParams.windowSize + blockSize + WILDCOPY_OVERLENGTH * 2;
2376
- zds->blockSize = blockSize;
2377
- if (zds->inBuffSize < blockSize) {
2378
- ZSTD_free(zds->inBuff, zds->customMem);
2379
- zds->inBuffSize = blockSize;
2380
- zds->inBuff = (char*)ZSTD_malloc(blockSize, zds->customMem);
2381
- if (zds->inBuff == NULL) return ERROR(memory_allocation);
2382
- }
2383
- if (zds->outBuffSize < neededOutSize) {
2384
- ZSTD_free(zds->outBuff, zds->customMem);
2385
- zds->outBuffSize = neededOutSize;
2386
- zds->outBuff = (char*)ZSTD_malloc(neededOutSize, zds->customMem);
2387
- if (zds->outBuff == NULL) return ERROR(memory_allocation);
2511
+ { size_t const neededInBuffSize = MAX(zds->fParams.blockSizeMax, 4 /* frame checksum */);
2512
+ size_t const neededOutBuffSize = ZSTD_decodingBufferSize_min(zds->fParams.windowSize, zds->fParams.frameContentSize);
2513
+ if ((zds->inBuffSize < neededInBuffSize) || (zds->outBuffSize < neededOutBuffSize)) {
2514
+ size_t const bufferSize = neededInBuffSize + neededOutBuffSize;
2515
+ DEBUGLOG(4, "inBuff : from %u to %u",
2516
+ (U32)zds->inBuffSize, (U32)neededInBuffSize);
2517
+ DEBUGLOG(4, "outBuff : from %u to %u",
2518
+ (U32)zds->outBuffSize, (U32)neededOutBuffSize);
2519
+ if (zds->staticSize) { /* static DCtx */
2520
+ DEBUGLOG(4, "staticSize : %u", (U32)zds->staticSize);
2521
+ assert(zds->staticSize >= sizeof(ZSTD_DCtx)); /* controlled at init */
2522
+ if (bufferSize > zds->staticSize - sizeof(ZSTD_DCtx))
2523
+ return ERROR(memory_allocation);
2524
+ } else {
2525
+ ZSTD_free(zds->inBuff, zds->customMem);
2526
+ zds->inBuffSize = 0;
2527
+ zds->outBuffSize = 0;
2528
+ zds->inBuff = (char*)ZSTD_malloc(bufferSize, zds->customMem);
2529
+ if (zds->inBuff == NULL) return ERROR(memory_allocation);
2530
+ }
2531
+ zds->inBuffSize = neededInBuffSize;
2532
+ zds->outBuff = zds->inBuff + zds->inBuffSize;
2533
+ zds->outBuffSize = neededOutBuffSize;
2388
2534
  } }
2389
- zds->stage = zdss_read;
2390
- /* pass-through */
2535
+ zds->streamStage = zdss_read;
2536
+ /* fall-through */
2391
2537
 
2392
2538
  case zdss_read:
2393
- { size_t const neededInSize = ZSTD_nextSrcSizeToDecompress(zds->dctx);
2539
+ DEBUGLOG(5, "stage zdss_read");
2540
+ { size_t const neededInSize = ZSTD_nextSrcSizeToDecompress(zds);
2541
+ DEBUGLOG(5, "neededInSize = %u", (U32)neededInSize);
2394
2542
  if (neededInSize==0) { /* end of frame */
2395
- zds->stage = zdss_init;
2543
+ zds->streamStage = zdss_init;
2396
2544
  someMoreWork = 0;
2397
2545
  break;
2398
2546
  }
2399
2547
  if ((size_t)(iend-ip) >= neededInSize) { /* decode directly from src */
2400
- const int isSkipFrame = ZSTD_isSkipFrame(zds->dctx);
2401
- size_t const decodedSize = ZSTD_decompressContinue(zds->dctx,
2548
+ int const isSkipFrame = ZSTD_isSkipFrame(zds);
2549
+ size_t const decodedSize = ZSTD_decompressContinue(zds,
2402
2550
  zds->outBuff + zds->outStart, (isSkipFrame ? 0 : zds->outBuffSize - zds->outStart),
2403
2551
  ip, neededInSize);
2404
2552
  if (ZSTD_isError(decodedSize)) return decodedSize;
2405
2553
  ip += neededInSize;
2406
2554
  if (!decodedSize && !isSkipFrame) break; /* this was just a header */
2407
2555
  zds->outEnd = zds->outStart + decodedSize;
2408
- zds->stage = zdss_flush;
2556
+ zds->streamStage = zdss_flush;
2409
2557
  break;
2410
- }
2411
- if (ip==iend) { someMoreWork = 0; break; } /* no more input */
2412
- zds->stage = zdss_load;
2413
- /* pass-through */
2414
- }
2415
-
2558
+ } }
2559
+ if (ip==iend) { someMoreWork = 0; break; } /* no more input */
2560
+ zds->streamStage = zdss_load;
2561
+ /* fall-through */
2416
2562
  case zdss_load:
2417
- { size_t const neededInSize = ZSTD_nextSrcSizeToDecompress(zds->dctx);
2418
- size_t const toLoad = neededInSize - zds->inPos; /* should always be <= remaining space within inBuff */
2563
+ { size_t const neededInSize = ZSTD_nextSrcSizeToDecompress(zds);
2564
+ size_t const toLoad = neededInSize - zds->inPos;
2565
+ int const isSkipFrame = ZSTD_isSkipFrame(zds);
2419
2566
  size_t loadedSize;
2420
- if (toLoad > zds->inBuffSize - zds->inPos) return ERROR(corruption_detected); /* should never happen */
2421
- loadedSize = ZSTD_limitCopy(zds->inBuff + zds->inPos, toLoad, ip, iend-ip);
2567
+ if (isSkipFrame) {
2568
+ loadedSize = MIN(toLoad, (size_t)(iend-ip));
2569
+ } else {
2570
+ if (toLoad > zds->inBuffSize - zds->inPos) return ERROR(corruption_detected); /* should never happen */
2571
+ loadedSize = ZSTD_limitCopy(zds->inBuff + zds->inPos, toLoad, ip, iend-ip);
2572
+ }
2422
2573
  ip += loadedSize;
2423
2574
  zds->inPos += loadedSize;
2424
2575
  if (loadedSize < toLoad) { someMoreWork = 0; break; } /* not enough input, wait for more */
2425
2576
 
2426
2577
  /* decode loaded input */
2427
- { const int isSkipFrame = ZSTD_isSkipFrame(zds->dctx);
2428
- size_t const decodedSize = ZSTD_decompressContinue(zds->dctx,
2578
+ { size_t const decodedSize = ZSTD_decompressContinue(zds,
2429
2579
  zds->outBuff + zds->outStart, zds->outBuffSize - zds->outStart,
2430
2580
  zds->inBuff, neededInSize);
2431
2581
  if (ZSTD_isError(decodedSize)) return decodedSize;
2432
2582
  zds->inPos = 0; /* input is consumed */
2433
- if (!decodedSize && !isSkipFrame) { zds->stage = zdss_read; break; } /* this was just a header */
2583
+ if (!decodedSize && !isSkipFrame) { zds->streamStage = zdss_read; break; } /* this was just a header */
2434
2584
  zds->outEnd = zds->outStart + decodedSize;
2435
- zds->stage = zdss_flush;
2436
- /* pass-through */
2437
2585
  } }
2438
-
2586
+ zds->streamStage = zdss_flush;
2587
+ /* fall-through */
2439
2588
  case zdss_flush:
2440
2589
  { size_t const toFlushSize = zds->outEnd - zds->outStart;
2441
2590
  size_t const flushedSize = ZSTD_limitCopy(op, oend-op, zds->outBuff + zds->outStart, toFlushSize);
2442
2591
  op += flushedSize;
2443
2592
  zds->outStart += flushedSize;
2444
2593
  if (flushedSize == toFlushSize) { /* flush completed */
2445
- zds->stage = zdss_read;
2446
- if (zds->outStart + zds->blockSize > zds->outBuffSize)
2594
+ zds->streamStage = zdss_read;
2595
+ if ( (zds->outBuffSize < zds->fParams.frameContentSize)
2596
+ && (zds->outStart + zds->fParams.blockSizeMax > zds->outBuffSize) ) {
2597
+ DEBUGLOG(5, "restart filling outBuff from beginning (left:%i, needed:%u)",
2598
+ (int)(zds->outBuffSize - zds->outStart),
2599
+ (U32)zds->fParams.blockSizeMax);
2447
2600
  zds->outStart = zds->outEnd = 0;
2601
+ }
2448
2602
  break;
2449
- }
2450
- /* cannot complete flush */
2451
- someMoreWork = 0;
2452
- break;
2453
- }
2603
+ } }
2604
+ /* cannot complete flush */
2605
+ someMoreWork = 0;
2606
+ break;
2607
+
2454
2608
  default: return ERROR(GENERIC); /* impossible */
2455
2609
  } }
2456
2610
 
2457
2611
  /* result */
2458
2612
  input->pos += (size_t)(ip-istart);
2459
2613
  output->pos += (size_t)(op-ostart);
2460
- { size_t nextSrcSizeHint = ZSTD_nextSrcSizeToDecompress(zds->dctx);
2614
+ { size_t nextSrcSizeHint = ZSTD_nextSrcSizeToDecompress(zds);
2461
2615
  if (!nextSrcSizeHint) { /* frame fully decoded */
2462
2616
  if (zds->outEnd == zds->outStart) { /* output fully flushed */
2463
2617
  if (zds->hostageByte) {
2464
- if (input->pos >= input->size) { zds->stage = zdss_read; return 1; } /* can't release hostage (not present) */
2618
+ if (input->pos >= input->size) {
2619
+ /* can't release hostage (not present) */
2620
+ zds->streamStage = zdss_read;
2621
+ return 1;
2622
+ }
2465
2623
  input->pos++; /* release hostage */
2466
- }
2624
+ } /* zds->hostageByte */
2467
2625
  return 0;
2468
- }
2626
+ } /* zds->outEnd == zds->outStart */
2469
2627
  if (!zds->hostageByte) { /* output not fully flushed; keep last byte as hostage; will be released when all output is flushed */
2470
2628
  input->pos--; /* note : pos > 0, otherwise, impossible to finish reading last block */
2471
2629
  zds->hostageByte=1;
2472
2630
  }
2473
2631
  return 1;
2474
- }
2475
- nextSrcSizeHint += ZSTD_blockHeaderSize * (ZSTD_nextInputType(zds->dctx) == ZSTDnit_block); /* preload header of next block */
2632
+ } /* nextSrcSizeHint==0 */
2633
+ nextSrcSizeHint += ZSTD_blockHeaderSize * (ZSTD_nextInputType(zds) == ZSTDnit_block); /* preload header of next block */
2476
2634
  if (zds->inPos > nextSrcSizeHint) return ERROR(GENERIC); /* should never happen */
2477
2635
  nextSrcSizeHint -= zds->inPos; /* already loaded*/
2478
2636
  return nextSrcSizeHint;
2479
2637
  }
2480
2638
  }
2639
+
2640
+
2641
+ size_t ZSTD_decompress_generic(ZSTD_DCtx* dctx, ZSTD_outBuffer* output, ZSTD_inBuffer* input)
2642
+ {
2643
+ return ZSTD_decompressStream(dctx, output, input);
2644
+ }
2645
+
2646
+ size_t ZSTD_decompress_generic_simpleArgs (
2647
+ ZSTD_DCtx* dctx,
2648
+ void* dst, size_t dstCapacity, size_t* dstPos,
2649
+ const void* src, size_t srcSize, size_t* srcPos)
2650
+ {
2651
+ ZSTD_outBuffer output = { dst, dstCapacity, *dstPos };
2652
+ ZSTD_inBuffer input = { src, srcSize, *srcPos };
2653
+ /* ZSTD_compress_generic() will check validity of dstPos and srcPos */
2654
+ size_t const cErr = ZSTD_decompress_generic(dctx, &output, &input);
2655
+ *dstPos = output.pos;
2656
+ *srcPos = input.pos;
2657
+ return cErr;
2658
+ }
2659
+
2660
+ void ZSTD_DCtx_reset(ZSTD_DCtx* dctx)
2661
+ {
2662
+ (void)ZSTD_initDStream(dctx);
2663
+ dctx->format = ZSTD_f_zstd1;
2664
+ dctx->maxWindowSize = ZSTD_MAXWINDOWSIZE_DEFAULT;
2665
+ }