extzstd 0.1.1 → 0.2

Sign up to get free protection for your applications and to get access to all the features.
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
+ }