extzstd 0.3.2 → 0.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (112) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +4 -3
  3. data/contrib/zstd/CHANGELOG +225 -1
  4. data/contrib/zstd/CONTRIBUTING.md +158 -75
  5. data/contrib/zstd/LICENSE +4 -4
  6. data/contrib/zstd/Makefile +106 -69
  7. data/contrib/zstd/Package.swift +36 -0
  8. data/contrib/zstd/README.md +64 -36
  9. data/contrib/zstd/SECURITY.md +15 -0
  10. data/contrib/zstd/TESTING.md +2 -3
  11. data/contrib/zstd/lib/BUCK +5 -7
  12. data/contrib/zstd/lib/Makefile +117 -199
  13. data/contrib/zstd/lib/README.md +37 -7
  14. data/contrib/zstd/lib/common/allocations.h +55 -0
  15. data/contrib/zstd/lib/common/bits.h +200 -0
  16. data/contrib/zstd/lib/common/bitstream.h +80 -86
  17. data/contrib/zstd/lib/common/compiler.h +225 -63
  18. data/contrib/zstd/lib/common/cpu.h +37 -1
  19. data/contrib/zstd/lib/common/debug.c +7 -1
  20. data/contrib/zstd/lib/common/debug.h +21 -12
  21. data/contrib/zstd/lib/common/entropy_common.c +15 -37
  22. data/contrib/zstd/lib/common/error_private.c +9 -2
  23. data/contrib/zstd/lib/common/error_private.h +93 -5
  24. data/contrib/zstd/lib/common/fse.h +12 -87
  25. data/contrib/zstd/lib/common/fse_decompress.c +37 -117
  26. data/contrib/zstd/lib/common/huf.h +97 -172
  27. data/contrib/zstd/lib/common/mem.h +58 -58
  28. data/contrib/zstd/lib/common/pool.c +38 -17
  29. data/contrib/zstd/lib/common/pool.h +10 -4
  30. data/contrib/zstd/lib/common/portability_macros.h +158 -0
  31. data/contrib/zstd/lib/common/threading.c +74 -14
  32. data/contrib/zstd/lib/common/threading.h +5 -10
  33. data/contrib/zstd/lib/common/xxhash.c +6 -814
  34. data/contrib/zstd/lib/common/xxhash.h +6930 -195
  35. data/contrib/zstd/lib/common/zstd_common.c +1 -36
  36. data/contrib/zstd/lib/common/zstd_deps.h +1 -1
  37. data/contrib/zstd/lib/common/zstd_internal.h +68 -154
  38. data/contrib/zstd/lib/common/zstd_trace.h +163 -0
  39. data/contrib/zstd/lib/compress/clevels.h +134 -0
  40. data/contrib/zstd/lib/compress/fse_compress.c +75 -155
  41. data/contrib/zstd/lib/compress/hist.c +1 -1
  42. data/contrib/zstd/lib/compress/hist.h +1 -1
  43. data/contrib/zstd/lib/compress/huf_compress.c +810 -259
  44. data/contrib/zstd/lib/compress/zstd_compress.c +2864 -919
  45. data/contrib/zstd/lib/compress/zstd_compress_internal.h +523 -192
  46. data/contrib/zstd/lib/compress/zstd_compress_literals.c +117 -40
  47. data/contrib/zstd/lib/compress/zstd_compress_literals.h +16 -6
  48. data/contrib/zstd/lib/compress/zstd_compress_sequences.c +28 -19
  49. data/contrib/zstd/lib/compress/zstd_compress_sequences.h +1 -1
  50. data/contrib/zstd/lib/compress/zstd_compress_superblock.c +251 -412
  51. data/contrib/zstd/lib/compress/zstd_compress_superblock.h +1 -1
  52. data/contrib/zstd/lib/compress/zstd_cwksp.h +284 -97
  53. data/contrib/zstd/lib/compress/zstd_double_fast.c +382 -133
  54. data/contrib/zstd/lib/compress/zstd_double_fast.h +14 -2
  55. data/contrib/zstd/lib/compress/zstd_fast.c +732 -260
  56. data/contrib/zstd/lib/compress/zstd_fast.h +3 -2
  57. data/contrib/zstd/lib/compress/zstd_lazy.c +1177 -390
  58. data/contrib/zstd/lib/compress/zstd_lazy.h +129 -14
  59. data/contrib/zstd/lib/compress/zstd_ldm.c +280 -210
  60. data/contrib/zstd/lib/compress/zstd_ldm.h +3 -2
  61. data/contrib/zstd/lib/compress/zstd_ldm_geartab.h +106 -0
  62. data/contrib/zstd/lib/compress/zstd_opt.c +516 -285
  63. data/contrib/zstd/lib/compress/zstd_opt.h +32 -8
  64. data/contrib/zstd/lib/compress/zstdmt_compress.c +202 -131
  65. data/contrib/zstd/lib/compress/zstdmt_compress.h +9 -6
  66. data/contrib/zstd/lib/decompress/huf_decompress.c +1149 -555
  67. data/contrib/zstd/lib/decompress/huf_decompress_amd64.S +595 -0
  68. data/contrib/zstd/lib/decompress/zstd_ddict.c +4 -4
  69. data/contrib/zstd/lib/decompress/zstd_ddict.h +1 -1
  70. data/contrib/zstd/lib/decompress/zstd_decompress.c +583 -106
  71. data/contrib/zstd/lib/decompress/zstd_decompress_block.c +1054 -379
  72. data/contrib/zstd/lib/decompress/zstd_decompress_block.h +14 -3
  73. data/contrib/zstd/lib/decompress/zstd_decompress_internal.h +56 -6
  74. data/contrib/zstd/lib/deprecated/zbuff.h +1 -1
  75. data/contrib/zstd/lib/deprecated/zbuff_common.c +1 -1
  76. data/contrib/zstd/lib/deprecated/zbuff_compress.c +24 -4
  77. data/contrib/zstd/lib/deprecated/zbuff_decompress.c +3 -1
  78. data/contrib/zstd/lib/dictBuilder/cover.c +60 -44
  79. data/contrib/zstd/lib/dictBuilder/cover.h +6 -11
  80. data/contrib/zstd/lib/dictBuilder/divsufsort.c +1 -1
  81. data/contrib/zstd/lib/dictBuilder/fastcover.c +26 -18
  82. data/contrib/zstd/lib/dictBuilder/zdict.c +100 -101
  83. data/contrib/zstd/lib/legacy/zstd_legacy.h +38 -1
  84. data/contrib/zstd/lib/legacy/zstd_v01.c +18 -53
  85. data/contrib/zstd/lib/legacy/zstd_v01.h +1 -1
  86. data/contrib/zstd/lib/legacy/zstd_v02.c +28 -85
  87. data/contrib/zstd/lib/legacy/zstd_v02.h +1 -1
  88. data/contrib/zstd/lib/legacy/zstd_v03.c +29 -88
  89. data/contrib/zstd/lib/legacy/zstd_v03.h +1 -1
  90. data/contrib/zstd/lib/legacy/zstd_v04.c +27 -80
  91. data/contrib/zstd/lib/legacy/zstd_v04.h +1 -1
  92. data/contrib/zstd/lib/legacy/zstd_v05.c +36 -85
  93. data/contrib/zstd/lib/legacy/zstd_v05.h +1 -1
  94. data/contrib/zstd/lib/legacy/zstd_v06.c +44 -96
  95. data/contrib/zstd/lib/legacy/zstd_v06.h +1 -1
  96. data/contrib/zstd/lib/legacy/zstd_v07.c +37 -92
  97. data/contrib/zstd/lib/legacy/zstd_v07.h +1 -1
  98. data/contrib/zstd/lib/libzstd.mk +237 -0
  99. data/contrib/zstd/lib/libzstd.pc.in +4 -3
  100. data/contrib/zstd/lib/module.modulemap +35 -0
  101. data/contrib/zstd/lib/{dictBuilder/zdict.h → zdict.h} +202 -33
  102. data/contrib/zstd/lib/zstd.h +1030 -332
  103. data/contrib/zstd/lib/{common/zstd_errors.h → zstd_errors.h} +27 -8
  104. data/ext/extconf.rb +26 -7
  105. data/ext/extzstd.c +51 -24
  106. data/ext/extzstd.h +33 -6
  107. data/ext/extzstd_stream.c +74 -31
  108. data/ext/libzstd_conf.h +0 -1
  109. data/ext/zstd_decompress_asm.S +1 -0
  110. metadata +17 -7
  111. data/contrib/zstd/appveyor.yml +0 -292
  112. data/ext/depend +0 -2
@@ -1,5 +1,5 @@
1
1
  /*
2
- * Copyright (c) 2016-2020, Yann Collet, Facebook, Inc.
2
+ * Copyright (c) Meta Platforms, Inc. and affiliates.
3
3
  * All rights reserved.
4
4
  *
5
5
  * This source code is licensed under both the BSD-style license (found in the
@@ -56,13 +56,15 @@
56
56
  * Dependencies
57
57
  *********************************************************/
58
58
  #include "../common/zstd_deps.h" /* ZSTD_memcpy, ZSTD_memmove, ZSTD_memset */
59
- #include "../common/cpu.h" /* bmi2 */
59
+ #include "../common/allocations.h" /* ZSTD_customMalloc, ZSTD_customCalloc, ZSTD_customFree */
60
+ #include "../common/error_private.h"
61
+ #include "../common/zstd_internal.h" /* blockProperties_t */
60
62
  #include "../common/mem.h" /* low level memory routines */
63
+ #include "../common/bits.h" /* ZSTD_highbit32 */
61
64
  #define FSE_STATIC_LINKING_ONLY
62
65
  #include "../common/fse.h"
63
- #define HUF_STATIC_LINKING_ONLY
64
66
  #include "../common/huf.h"
65
- #include "../common/zstd_internal.h" /* blockProperties_t */
67
+ #include "../common/xxhash.h" /* XXH64_reset, XXH64_update, XXH64_digest, XXH64 */
66
68
  #include "zstd_decompress_internal.h" /* ZSTD_DCtx */
67
69
  #include "zstd_ddict.h" /* ZSTD_DDictDictContent */
68
70
  #include "zstd_decompress_block.h" /* ZSTD_decompressBlock_internal */
@@ -72,6 +74,147 @@
72
74
  #endif
73
75
 
74
76
 
77
+
78
+ /*************************************
79
+ * Multiple DDicts Hashset internals *
80
+ *************************************/
81
+
82
+ #define DDICT_HASHSET_MAX_LOAD_FACTOR_COUNT_MULT 4
83
+ #define DDICT_HASHSET_MAX_LOAD_FACTOR_SIZE_MULT 3 /* These two constants represent SIZE_MULT/COUNT_MULT load factor without using a float.
84
+ * Currently, that means a 0.75 load factor.
85
+ * So, if count * COUNT_MULT / size * SIZE_MULT != 0, then we've exceeded
86
+ * the load factor of the ddict hash set.
87
+ */
88
+
89
+ #define DDICT_HASHSET_TABLE_BASE_SIZE 64
90
+ #define DDICT_HASHSET_RESIZE_FACTOR 2
91
+
92
+ /* Hash function to determine starting position of dict insertion within the table
93
+ * Returns an index between [0, hashSet->ddictPtrTableSize]
94
+ */
95
+ static size_t ZSTD_DDictHashSet_getIndex(const ZSTD_DDictHashSet* hashSet, U32 dictID) {
96
+ const U64 hash = XXH64(&dictID, sizeof(U32), 0);
97
+ /* DDict ptr table size is a multiple of 2, use size - 1 as mask to get index within [0, hashSet->ddictPtrTableSize) */
98
+ return hash & (hashSet->ddictPtrTableSize - 1);
99
+ }
100
+
101
+ /* Adds DDict to a hashset without resizing it.
102
+ * If inserting a DDict with a dictID that already exists in the set, replaces the one in the set.
103
+ * Returns 0 if successful, or a zstd error code if something went wrong.
104
+ */
105
+ static size_t ZSTD_DDictHashSet_emplaceDDict(ZSTD_DDictHashSet* hashSet, const ZSTD_DDict* ddict) {
106
+ const U32 dictID = ZSTD_getDictID_fromDDict(ddict);
107
+ size_t idx = ZSTD_DDictHashSet_getIndex(hashSet, dictID);
108
+ const size_t idxRangeMask = hashSet->ddictPtrTableSize - 1;
109
+ RETURN_ERROR_IF(hashSet->ddictPtrCount == hashSet->ddictPtrTableSize, GENERIC, "Hash set is full!");
110
+ DEBUGLOG(4, "Hashed index: for dictID: %u is %zu", dictID, idx);
111
+ while (hashSet->ddictPtrTable[idx] != NULL) {
112
+ /* Replace existing ddict if inserting ddict with same dictID */
113
+ if (ZSTD_getDictID_fromDDict(hashSet->ddictPtrTable[idx]) == dictID) {
114
+ DEBUGLOG(4, "DictID already exists, replacing rather than adding");
115
+ hashSet->ddictPtrTable[idx] = ddict;
116
+ return 0;
117
+ }
118
+ idx &= idxRangeMask;
119
+ idx++;
120
+ }
121
+ DEBUGLOG(4, "Final idx after probing for dictID %u is: %zu", dictID, idx);
122
+ hashSet->ddictPtrTable[idx] = ddict;
123
+ hashSet->ddictPtrCount++;
124
+ return 0;
125
+ }
126
+
127
+ /* Expands hash table by factor of DDICT_HASHSET_RESIZE_FACTOR and
128
+ * rehashes all values, allocates new table, frees old table.
129
+ * Returns 0 on success, otherwise a zstd error code.
130
+ */
131
+ static size_t ZSTD_DDictHashSet_expand(ZSTD_DDictHashSet* hashSet, ZSTD_customMem customMem) {
132
+ size_t newTableSize = hashSet->ddictPtrTableSize * DDICT_HASHSET_RESIZE_FACTOR;
133
+ const ZSTD_DDict** newTable = (const ZSTD_DDict**)ZSTD_customCalloc(sizeof(ZSTD_DDict*) * newTableSize, customMem);
134
+ const ZSTD_DDict** oldTable = hashSet->ddictPtrTable;
135
+ size_t oldTableSize = hashSet->ddictPtrTableSize;
136
+ size_t i;
137
+
138
+ DEBUGLOG(4, "Expanding DDict hash table! Old size: %zu new size: %zu", oldTableSize, newTableSize);
139
+ RETURN_ERROR_IF(!newTable, memory_allocation, "Expanded hashset allocation failed!");
140
+ hashSet->ddictPtrTable = newTable;
141
+ hashSet->ddictPtrTableSize = newTableSize;
142
+ hashSet->ddictPtrCount = 0;
143
+ for (i = 0; i < oldTableSize; ++i) {
144
+ if (oldTable[i] != NULL) {
145
+ FORWARD_IF_ERROR(ZSTD_DDictHashSet_emplaceDDict(hashSet, oldTable[i]), "");
146
+ }
147
+ }
148
+ ZSTD_customFree((void*)oldTable, customMem);
149
+ DEBUGLOG(4, "Finished re-hash");
150
+ return 0;
151
+ }
152
+
153
+ /* Fetches a DDict with the given dictID
154
+ * Returns the ZSTD_DDict* with the requested dictID. If it doesn't exist, then returns NULL.
155
+ */
156
+ static const ZSTD_DDict* ZSTD_DDictHashSet_getDDict(ZSTD_DDictHashSet* hashSet, U32 dictID) {
157
+ size_t idx = ZSTD_DDictHashSet_getIndex(hashSet, dictID);
158
+ const size_t idxRangeMask = hashSet->ddictPtrTableSize - 1;
159
+ DEBUGLOG(4, "Hashed index: for dictID: %u is %zu", dictID, idx);
160
+ for (;;) {
161
+ size_t currDictID = ZSTD_getDictID_fromDDict(hashSet->ddictPtrTable[idx]);
162
+ if (currDictID == dictID || currDictID == 0) {
163
+ /* currDictID == 0 implies a NULL ddict entry */
164
+ break;
165
+ } else {
166
+ idx &= idxRangeMask; /* Goes to start of table when we reach the end */
167
+ idx++;
168
+ }
169
+ }
170
+ DEBUGLOG(4, "Final idx after probing for dictID %u is: %zu", dictID, idx);
171
+ return hashSet->ddictPtrTable[idx];
172
+ }
173
+
174
+ /* Allocates space for and returns a ddict hash set
175
+ * The hash set's ZSTD_DDict* table has all values automatically set to NULL to begin with.
176
+ * Returns NULL if allocation failed.
177
+ */
178
+ static ZSTD_DDictHashSet* ZSTD_createDDictHashSet(ZSTD_customMem customMem) {
179
+ ZSTD_DDictHashSet* ret = (ZSTD_DDictHashSet*)ZSTD_customMalloc(sizeof(ZSTD_DDictHashSet), customMem);
180
+ DEBUGLOG(4, "Allocating new hash set");
181
+ if (!ret)
182
+ return NULL;
183
+ ret->ddictPtrTable = (const ZSTD_DDict**)ZSTD_customCalloc(DDICT_HASHSET_TABLE_BASE_SIZE * sizeof(ZSTD_DDict*), customMem);
184
+ if (!ret->ddictPtrTable) {
185
+ ZSTD_customFree(ret, customMem);
186
+ return NULL;
187
+ }
188
+ ret->ddictPtrTableSize = DDICT_HASHSET_TABLE_BASE_SIZE;
189
+ ret->ddictPtrCount = 0;
190
+ return ret;
191
+ }
192
+
193
+ /* Frees the table of ZSTD_DDict* within a hashset, then frees the hashset itself.
194
+ * Note: The ZSTD_DDict* within the table are NOT freed.
195
+ */
196
+ static void ZSTD_freeDDictHashSet(ZSTD_DDictHashSet* hashSet, ZSTD_customMem customMem) {
197
+ DEBUGLOG(4, "Freeing ddict hash set");
198
+ if (hashSet && hashSet->ddictPtrTable) {
199
+ ZSTD_customFree((void*)hashSet->ddictPtrTable, customMem);
200
+ }
201
+ if (hashSet) {
202
+ ZSTD_customFree(hashSet, customMem);
203
+ }
204
+ }
205
+
206
+ /* Public function: Adds a DDict into the ZSTD_DDictHashSet, possibly triggering a resize of the hash set.
207
+ * Returns 0 on success, or a ZSTD error.
208
+ */
209
+ static size_t ZSTD_DDictHashSet_addDDict(ZSTD_DDictHashSet* hashSet, const ZSTD_DDict* ddict, ZSTD_customMem customMem) {
210
+ DEBUGLOG(4, "Adding dict ID: %u to hashset with - Count: %zu Tablesize: %zu", ZSTD_getDictID_fromDDict(ddict), hashSet->ddictPtrCount, hashSet->ddictPtrTableSize);
211
+ if (hashSet->ddictPtrCount * DDICT_HASHSET_MAX_LOAD_FACTOR_COUNT_MULT / hashSet->ddictPtrTableSize * DDICT_HASHSET_MAX_LOAD_FACTOR_SIZE_MULT != 0) {
212
+ FORWARD_IF_ERROR(ZSTD_DDictHashSet_expand(hashSet, customMem), "");
213
+ }
214
+ FORWARD_IF_ERROR(ZSTD_DDictHashSet_emplaceDDict(hashSet, ddict), "");
215
+ return 0;
216
+ }
217
+
75
218
  /*-*************************************************************
76
219
  * Context management
77
220
  ***************************************************************/
@@ -101,6 +244,9 @@ static void ZSTD_DCtx_resetParameters(ZSTD_DCtx* dctx)
101
244
  dctx->maxWindowSize = ZSTD_MAXWINDOWSIZE_DEFAULT;
102
245
  dctx->outBufferMode = ZSTD_bm_buffered;
103
246
  dctx->forceIgnoreChecksum = ZSTD_d_validateChecksum;
247
+ dctx->refMultipleDDicts = ZSTD_rmd_refSingleDDict;
248
+ dctx->disableHufAsm = 0;
249
+ dctx->maxBlockSizeParam = 0;
104
250
  }
105
251
 
106
252
  static void ZSTD_initDCtx_internal(ZSTD_DCtx* dctx)
@@ -115,13 +261,18 @@ static void ZSTD_initDCtx_internal(ZSTD_DCtx* dctx)
115
261
  dctx->inBuffSize = 0;
116
262
  dctx->outBuffSize = 0;
117
263
  dctx->streamStage = zdss_init;
264
+ #if defined(ZSTD_LEGACY_SUPPORT) && (ZSTD_LEGACY_SUPPORT>=1)
118
265
  dctx->legacyContext = NULL;
119
266
  dctx->previousLegacyVersion = 0;
267
+ #endif
120
268
  dctx->noForwardProgress = 0;
121
269
  dctx->oversizedDuration = 0;
122
- dctx->bmi2 = ZSTD_cpuid_bmi2(ZSTD_cpuid());
270
+ dctx->isFrameDecompression = 1;
271
+ #if DYNAMIC_BMI2
272
+ dctx->bmi2 = ZSTD_cpuSupportsBmi2();
273
+ #endif
274
+ dctx->ddictSet = NULL;
123
275
  ZSTD_DCtx_resetParameters(dctx);
124
- dctx->validateChecksum = 1;
125
276
  #ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
126
277
  dctx->dictContentEndForFuzzing = NULL;
127
278
  #endif
@@ -140,8 +291,7 @@ ZSTD_DCtx* ZSTD_initStaticDCtx(void *workspace, size_t workspaceSize)
140
291
  return dctx;
141
292
  }
142
293
 
143
- ZSTD_DCtx* ZSTD_createDCtx_advanced(ZSTD_customMem customMem)
144
- {
294
+ static ZSTD_DCtx* ZSTD_createDCtx_internal(ZSTD_customMem customMem) {
145
295
  if ((!customMem.customAlloc) ^ (!customMem.customFree)) return NULL;
146
296
 
147
297
  { ZSTD_DCtx* const dctx = (ZSTD_DCtx*)ZSTD_customMalloc(sizeof(*dctx), customMem);
@@ -152,10 +302,15 @@ ZSTD_DCtx* ZSTD_createDCtx_advanced(ZSTD_customMem customMem)
152
302
  }
153
303
  }
154
304
 
305
+ ZSTD_DCtx* ZSTD_createDCtx_advanced(ZSTD_customMem customMem)
306
+ {
307
+ return ZSTD_createDCtx_internal(customMem);
308
+ }
309
+
155
310
  ZSTD_DCtx* ZSTD_createDCtx(void)
156
311
  {
157
312
  DEBUGLOG(3, "ZSTD_createDCtx");
158
- return ZSTD_createDCtx_advanced(ZSTD_defaultCMem);
313
+ return ZSTD_createDCtx_internal(ZSTD_defaultCMem);
159
314
  }
160
315
 
161
316
  static void ZSTD_clearDict(ZSTD_DCtx* dctx)
@@ -178,6 +333,10 @@ size_t ZSTD_freeDCtx(ZSTD_DCtx* dctx)
178
333
  if (dctx->legacyContext)
179
334
  ZSTD_freeLegacyStreamContext(dctx->legacyContext, dctx->previousLegacyVersion);
180
335
  #endif
336
+ if (dctx->ddictSet) {
337
+ ZSTD_freeDDictHashSet(dctx->ddictSet, cMem);
338
+ dctx->ddictSet = NULL;
339
+ }
181
340
  ZSTD_customFree(dctx, cMem);
182
341
  return 0;
183
342
  }
@@ -190,6 +349,29 @@ void ZSTD_copyDCtx(ZSTD_DCtx* dstDCtx, const ZSTD_DCtx* srcDCtx)
190
349
  ZSTD_memcpy(dstDCtx, srcDCtx, toCopy); /* no need to copy workspace */
191
350
  }
192
351
 
352
+ /* Given a dctx with a digested frame params, re-selects the correct ZSTD_DDict based on
353
+ * the requested dict ID from the frame. If there exists a reference to the correct ZSTD_DDict, then
354
+ * accordingly sets the ddict to be used to decompress the frame.
355
+ *
356
+ * If no DDict is found, then no action is taken, and the ZSTD_DCtx::ddict remains as-is.
357
+ *
358
+ * ZSTD_d_refMultipleDDicts must be enabled for this function to be called.
359
+ */
360
+ static void ZSTD_DCtx_selectFrameDDict(ZSTD_DCtx* dctx) {
361
+ assert(dctx->refMultipleDDicts && dctx->ddictSet);
362
+ DEBUGLOG(4, "Adjusting DDict based on requested dict ID from frame");
363
+ if (dctx->ddict) {
364
+ const ZSTD_DDict* frameDDict = ZSTD_DDictHashSet_getDDict(dctx->ddictSet, dctx->fParams.dictID);
365
+ if (frameDDict) {
366
+ DEBUGLOG(4, "DDict found!");
367
+ ZSTD_clearDict(dctx);
368
+ dctx->dictID = dctx->fParams.dictID;
369
+ dctx->ddict = frameDDict;
370
+ dctx->dictUses = ZSTD_use_indefinitely;
371
+ }
372
+ }
373
+ }
374
+
193
375
 
194
376
  /*-*************************************************************
195
377
  * Frame header decoding
@@ -213,6 +395,19 @@ unsigned ZSTD_isFrame(const void* buffer, size_t size)
213
395
  return 0;
214
396
  }
215
397
 
398
+ /*! ZSTD_isSkippableFrame() :
399
+ * Tells if the content of `buffer` starts with a valid Frame Identifier for a skippable frame.
400
+ * Note : Frame Identifier is 4 bytes. If `size < 4`, @return will always be 0.
401
+ */
402
+ unsigned ZSTD_isSkippableFrame(const void* buffer, size_t size)
403
+ {
404
+ if (size < ZSTD_FRAMEIDSIZE) return 0;
405
+ { U32 const magic = MEM_readLE32(buffer);
406
+ if ((magic & ZSTD_MAGIC_SKIPPABLE_MASK) == ZSTD_MAGIC_SKIPPABLE_START) return 1;
407
+ }
408
+ return 0;
409
+ }
410
+
216
411
  /** ZSTD_frameHeaderSize_internal() :
217
412
  * srcSize must be large enough to reach header size fields.
218
413
  * note : only works for formats ZSTD_f_zstd1 and ZSTD_f_zstd1_magicless.
@@ -248,16 +443,40 @@ size_t ZSTD_frameHeaderSize(const void* src, size_t srcSize)
248
443
  * note : only works for formats ZSTD_f_zstd1 and ZSTD_f_zstd1_magicless
249
444
  * @return : 0, `zfhPtr` is correctly filled,
250
445
  * >0, `srcSize` is too small, value is wanted `srcSize` amount,
251
- * or an error code, which can be tested using ZSTD_isError() */
446
+ ** or an error code, which can be tested using ZSTD_isError() */
252
447
  size_t ZSTD_getFrameHeader_advanced(ZSTD_frameHeader* zfhPtr, const void* src, size_t srcSize, ZSTD_format_e format)
253
448
  {
254
449
  const BYTE* ip = (const BYTE*)src;
255
450
  size_t const minInputSize = ZSTD_startingInputLength(format);
256
451
 
257
- ZSTD_memset(zfhPtr, 0, sizeof(*zfhPtr)); /* not strictly necessary, but static analyzer do not understand that zfhPtr is only going to be read only if return value is zero, since they are 2 different signals */
258
- if (srcSize < minInputSize) return minInputSize;
259
- RETURN_ERROR_IF(src==NULL, GENERIC, "invalid parameter");
452
+ DEBUGLOG(5, "ZSTD_getFrameHeader_advanced: minInputSize = %zu, srcSize = %zu", minInputSize, srcSize);
453
+
454
+ if (srcSize > 0) {
455
+ /* note : technically could be considered an assert(), since it's an invalid entry */
456
+ RETURN_ERROR_IF(src==NULL, GENERIC, "invalid parameter : src==NULL, but srcSize>0");
457
+ }
458
+ if (srcSize < minInputSize) {
459
+ if (srcSize > 0 && format != ZSTD_f_zstd1_magicless) {
460
+ /* when receiving less than @minInputSize bytes,
461
+ * control these bytes at least correspond to a supported magic number
462
+ * in order to error out early if they don't.
463
+ **/
464
+ size_t const toCopy = MIN(4, srcSize);
465
+ unsigned char hbuf[4]; MEM_writeLE32(hbuf, ZSTD_MAGICNUMBER);
466
+ assert(src != NULL);
467
+ ZSTD_memcpy(hbuf, src, toCopy);
468
+ if ( MEM_readLE32(hbuf) != ZSTD_MAGICNUMBER ) {
469
+ /* not a zstd frame : let's check if it's a skippable frame */
470
+ MEM_writeLE32(hbuf, ZSTD_MAGIC_SKIPPABLE_START);
471
+ ZSTD_memcpy(hbuf, src, toCopy);
472
+ if ((MEM_readLE32(hbuf) & ZSTD_MAGIC_SKIPPABLE_MASK) != ZSTD_MAGIC_SKIPPABLE_START) {
473
+ RETURN_ERROR(prefix_unknown,
474
+ "first bytes don't correspond to any supported magic number");
475
+ } } }
476
+ return minInputSize;
477
+ }
260
478
 
479
+ ZSTD_memset(zfhPtr, 0, sizeof(*zfhPtr)); /* not strictly necessary, but static analyzers may not understand that zfhPtr will be read only if return value is zero, since they are 2 different signals */
261
480
  if ( (format != ZSTD_f_zstd1_magicless)
262
481
  && (MEM_readLE32(src) != ZSTD_MAGICNUMBER) ) {
263
482
  if ((MEM_readLE32(src) & ZSTD_MAGIC_SKIPPABLE_MASK) == ZSTD_MAGIC_SKIPPABLE_START) {
@@ -299,7 +518,9 @@ size_t ZSTD_getFrameHeader_advanced(ZSTD_frameHeader* zfhPtr, const void* src, s
299
518
  }
300
519
  switch(dictIDSizeCode)
301
520
  {
302
- default: assert(0); /* impossible */
521
+ default:
522
+ assert(0); /* impossible */
523
+ ZSTD_FALLTHROUGH;
303
524
  case 0 : break;
304
525
  case 1 : dictID = ip[pos]; pos++; break;
305
526
  case 2 : dictID = MEM_readLE16(ip+pos); pos+=2; break;
@@ -307,7 +528,9 @@ size_t ZSTD_getFrameHeader_advanced(ZSTD_frameHeader* zfhPtr, const void* src, s
307
528
  }
308
529
  switch(fcsID)
309
530
  {
310
- default: assert(0); /* impossible */
531
+ default:
532
+ assert(0); /* impossible */
533
+ ZSTD_FALLTHROUGH;
311
534
  case 0 : if (singleSegment) frameContentSize = ip[pos]; break;
312
535
  case 1 : frameContentSize = MEM_readLE16(ip+pos)+256; break;
313
536
  case 2 : frameContentSize = MEM_readLE32(ip+pos); break;
@@ -336,7 +559,6 @@ size_t ZSTD_getFrameHeader(ZSTD_frameHeader* zfhPtr, const void* src, size_t src
336
559
  return ZSTD_getFrameHeader_advanced(zfhPtr, src, srcSize, ZSTD_f_zstd1);
337
560
  }
338
561
 
339
-
340
562
  /** ZSTD_getFrameContentSize() :
341
563
  * compatible with legacy mode
342
564
  * @return : decompressed size of the single frame pointed to be `src` if known, otherwise
@@ -370,18 +592,52 @@ static size_t readSkippableFrameSize(void const* src, size_t srcSize)
370
592
  sizeU32 = MEM_readLE32((BYTE const*)src + ZSTD_FRAMEIDSIZE);
371
593
  RETURN_ERROR_IF((U32)(sizeU32 + ZSTD_SKIPPABLEHEADERSIZE) < sizeU32,
372
594
  frameParameter_unsupported, "");
373
- {
374
- size_t const skippableSize = skippableHeaderSize + sizeU32;
595
+ { size_t const skippableSize = skippableHeaderSize + sizeU32;
375
596
  RETURN_ERROR_IF(skippableSize > srcSize, srcSize_wrong, "");
376
597
  return skippableSize;
377
598
  }
378
599
  }
379
600
 
601
+ /*! ZSTD_readSkippableFrame() :
602
+ * Retrieves content of a skippable frame, and writes it to dst buffer.
603
+ *
604
+ * The parameter magicVariant will receive the magicVariant that was supplied when the frame was written,
605
+ * i.e. magicNumber - ZSTD_MAGIC_SKIPPABLE_START. This can be NULL if the caller is not interested
606
+ * in the magicVariant.
607
+ *
608
+ * Returns an error if destination buffer is not large enough, or if this is not a valid skippable frame.
609
+ *
610
+ * @return : number of bytes written or a ZSTD error.
611
+ */
612
+ size_t ZSTD_readSkippableFrame(void* dst, size_t dstCapacity,
613
+ unsigned* magicVariant, /* optional, can be NULL */
614
+ const void* src, size_t srcSize)
615
+ {
616
+ RETURN_ERROR_IF(srcSize < ZSTD_SKIPPABLEHEADERSIZE, srcSize_wrong, "");
617
+
618
+ { U32 const magicNumber = MEM_readLE32(src);
619
+ size_t skippableFrameSize = readSkippableFrameSize(src, srcSize);
620
+ size_t skippableContentSize = skippableFrameSize - ZSTD_SKIPPABLEHEADERSIZE;
621
+
622
+ /* check input validity */
623
+ RETURN_ERROR_IF(!ZSTD_isSkippableFrame(src, srcSize), frameParameter_unsupported, "");
624
+ RETURN_ERROR_IF(skippableFrameSize < ZSTD_SKIPPABLEHEADERSIZE || skippableFrameSize > srcSize, srcSize_wrong, "");
625
+ RETURN_ERROR_IF(skippableContentSize > dstCapacity, dstSize_tooSmall, "");
626
+
627
+ /* deliver payload */
628
+ if (skippableContentSize > 0 && dst != NULL)
629
+ ZSTD_memcpy(dst, (const BYTE *)src + ZSTD_SKIPPABLEHEADERSIZE, skippableContentSize);
630
+ if (magicVariant != NULL)
631
+ *magicVariant = magicNumber - ZSTD_MAGIC_SKIPPABLE_START;
632
+ return skippableContentSize;
633
+ }
634
+ }
635
+
380
636
  /** ZSTD_findDecompressedSize() :
381
- * compatible with legacy mode
382
637
  * `srcSize` must be the exact length of some number of ZSTD compressed and/or
383
638
  * skippable frames
384
- * @return : decompressed size of the frames contained */
639
+ * note: compatible with legacy mode
640
+ * @return : decompressed size of the frames contained */
385
641
  unsigned long long ZSTD_findDecompressedSize(const void* src, size_t srcSize)
386
642
  {
387
643
  unsigned long long totalDstSize = 0;
@@ -391,9 +647,7 @@ unsigned long long ZSTD_findDecompressedSize(const void* src, size_t srcSize)
391
647
 
392
648
  if ((magicNumber & ZSTD_MAGIC_SKIPPABLE_MASK) == ZSTD_MAGIC_SKIPPABLE_START) {
393
649
  size_t const skippableSize = readSkippableFrameSize(src, srcSize);
394
- if (ZSTD_isError(skippableSize)) {
395
- return ZSTD_CONTENTSIZE_ERROR;
396
- }
650
+ if (ZSTD_isError(skippableSize)) return ZSTD_CONTENTSIZE_ERROR;
397
651
  assert(skippableSize <= srcSize);
398
652
 
399
653
  src = (const BYTE *)src + skippableSize;
@@ -401,17 +655,17 @@ unsigned long long ZSTD_findDecompressedSize(const void* src, size_t srcSize)
401
655
  continue;
402
656
  }
403
657
 
404
- { unsigned long long const ret = ZSTD_getFrameContentSize(src, srcSize);
405
- if (ret >= ZSTD_CONTENTSIZE_ERROR) return ret;
658
+ { unsigned long long const fcs = ZSTD_getFrameContentSize(src, srcSize);
659
+ if (fcs >= ZSTD_CONTENTSIZE_ERROR) return fcs;
406
660
 
407
- /* check for overflow */
408
- if (totalDstSize + ret < totalDstSize) return ZSTD_CONTENTSIZE_ERROR;
409
- totalDstSize += ret;
661
+ if (totalDstSize + fcs < totalDstSize)
662
+ return ZSTD_CONTENTSIZE_ERROR; /* check for overflow */
663
+ totalDstSize += fcs;
410
664
  }
665
+ /* skip to next frame */
411
666
  { size_t const frameSrcSize = ZSTD_findFrameCompressedSize(src, srcSize);
412
- if (ZSTD_isError(frameSrcSize)) {
413
- return ZSTD_CONTENTSIZE_ERROR;
414
- }
667
+ if (ZSTD_isError(frameSrcSize)) return ZSTD_CONTENTSIZE_ERROR;
668
+ assert(frameSrcSize <= srcSize);
415
669
 
416
670
  src = (const BYTE *)src + frameSrcSize;
417
671
  srcSize -= frameSrcSize;
@@ -441,12 +695,19 @@ unsigned long long ZSTD_getDecompressedSize(const void* src, size_t srcSize)
441
695
 
442
696
  /** ZSTD_decodeFrameHeader() :
443
697
  * `headerSize` must be the size provided by ZSTD_frameHeaderSize().
698
+ * If multiple DDict references are enabled, also will choose the correct DDict to use.
444
699
  * @return : 0 if success, or an error code, which can be tested using ZSTD_isError() */
445
700
  static size_t ZSTD_decodeFrameHeader(ZSTD_DCtx* dctx, const void* src, size_t headerSize)
446
701
  {
447
702
  size_t const result = ZSTD_getFrameHeader_advanced(&(dctx->fParams), src, headerSize, dctx->format);
448
703
  if (ZSTD_isError(result)) return result; /* invalid header */
449
704
  RETURN_ERROR_IF(result>0, srcSize_wrong, "headerSize too small");
705
+
706
+ /* Reference DDict requested by frame if dctx references multiple ddicts */
707
+ if (dctx->refMultipleDDicts == ZSTD_rmd_refMultipleDDicts && dctx->ddictSet) {
708
+ ZSTD_DCtx_selectFrameDDict(dctx);
709
+ }
710
+
450
711
  #ifndef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
451
712
  /* Skip the dictID check in fuzzing mode, because it makes the search
452
713
  * harder.
@@ -456,6 +717,7 @@ static size_t ZSTD_decodeFrameHeader(ZSTD_DCtx* dctx, const void* src, size_t he
456
717
  #endif
457
718
  dctx->validateChecksum = (dctx->fParams.checksumFlag && !dctx->forceIgnoreChecksum) ? 1 : 0;
458
719
  if (dctx->validateChecksum) XXH64_reset(&dctx->xxhState, 0);
720
+ dctx->processedCSize += headerSize;
459
721
  return 0;
460
722
  }
461
723
 
@@ -467,17 +729,17 @@ static ZSTD_frameSizeInfo ZSTD_errorFrameSizeInfo(size_t ret)
467
729
  return frameSizeInfo;
468
730
  }
469
731
 
470
- static ZSTD_frameSizeInfo ZSTD_findFrameSizeInfo(const void* src, size_t srcSize)
732
+ static ZSTD_frameSizeInfo ZSTD_findFrameSizeInfo(const void* src, size_t srcSize, ZSTD_format_e format)
471
733
  {
472
734
  ZSTD_frameSizeInfo frameSizeInfo;
473
735
  ZSTD_memset(&frameSizeInfo, 0, sizeof(ZSTD_frameSizeInfo));
474
736
 
475
737
  #if defined(ZSTD_LEGACY_SUPPORT) && (ZSTD_LEGACY_SUPPORT >= 1)
476
- if (ZSTD_isLegacy(src, srcSize))
738
+ if (format == ZSTD_f_zstd1 && ZSTD_isLegacy(src, srcSize))
477
739
  return ZSTD_findFrameSizeInfoLegacy(src, srcSize);
478
740
  #endif
479
741
 
480
- if ((srcSize >= ZSTD_SKIPPABLEHEADERSIZE)
742
+ if (format == ZSTD_f_zstd1 && (srcSize >= ZSTD_SKIPPABLEHEADERSIZE)
481
743
  && (MEM_readLE32(src) & ZSTD_MAGIC_SKIPPABLE_MASK) == ZSTD_MAGIC_SKIPPABLE_START) {
482
744
  frameSizeInfo.compressedSize = readSkippableFrameSize(src, srcSize);
483
745
  assert(ZSTD_isError(frameSizeInfo.compressedSize) ||
@@ -491,7 +753,7 @@ static ZSTD_frameSizeInfo ZSTD_findFrameSizeInfo(const void* src, size_t srcSize
491
753
  ZSTD_frameHeader zfh;
492
754
 
493
755
  /* Extract Frame Header */
494
- { size_t const ret = ZSTD_getFrameHeader(&zfh, src, srcSize);
756
+ { size_t const ret = ZSTD_getFrameHeader_advanced(&zfh, src, srcSize, format);
495
757
  if (ZSTD_isError(ret))
496
758
  return ZSTD_errorFrameSizeInfo(ret);
497
759
  if (ret > 0)
@@ -525,23 +787,26 @@ static ZSTD_frameSizeInfo ZSTD_findFrameSizeInfo(const void* src, size_t srcSize
525
787
  ip += 4;
526
788
  }
527
789
 
790
+ frameSizeInfo.nbBlocks = nbBlocks;
528
791
  frameSizeInfo.compressedSize = (size_t)(ip - ipstart);
529
792
  frameSizeInfo.decompressedBound = (zfh.frameContentSize != ZSTD_CONTENTSIZE_UNKNOWN)
530
793
  ? zfh.frameContentSize
531
- : nbBlocks * zfh.blockSizeMax;
794
+ : (unsigned long long)nbBlocks * zfh.blockSizeMax;
532
795
  return frameSizeInfo;
533
796
  }
534
797
  }
535
798
 
799
+ static size_t ZSTD_findFrameCompressedSize_advanced(const void *src, size_t srcSize, ZSTD_format_e format) {
800
+ ZSTD_frameSizeInfo const frameSizeInfo = ZSTD_findFrameSizeInfo(src, srcSize, format);
801
+ return frameSizeInfo.compressedSize;
802
+ }
803
+
536
804
  /** ZSTD_findFrameCompressedSize() :
537
- * compatible with legacy mode
538
- * `src` must point to the start of a ZSTD frame, ZSTD legacy frame, or skippable frame
539
- * `srcSize` must be at least as large as the frame contained
540
- * @return : the compressed size of the frame starting at `src` */
805
+ * See docs in zstd.h
806
+ * Note: compatible with legacy mode */
541
807
  size_t ZSTD_findFrameCompressedSize(const void *src, size_t srcSize)
542
808
  {
543
- ZSTD_frameSizeInfo const frameSizeInfo = ZSTD_findFrameSizeInfo(src, srcSize);
544
- return frameSizeInfo.compressedSize;
809
+ return ZSTD_findFrameCompressedSize_advanced(src, srcSize, ZSTD_f_zstd1);
545
810
  }
546
811
 
547
812
  /** ZSTD_decompressBound() :
@@ -555,7 +820,7 @@ unsigned long long ZSTD_decompressBound(const void* src, size_t srcSize)
555
820
  unsigned long long bound = 0;
556
821
  /* Iterate over each frame */
557
822
  while (srcSize > 0) {
558
- ZSTD_frameSizeInfo const frameSizeInfo = ZSTD_findFrameSizeInfo(src, srcSize);
823
+ ZSTD_frameSizeInfo const frameSizeInfo = ZSTD_findFrameSizeInfo(src, srcSize, ZSTD_f_zstd1);
559
824
  size_t const compressedSize = frameSizeInfo.compressedSize;
560
825
  unsigned long long const decompressedBound = frameSizeInfo.decompressedBound;
561
826
  if (ZSTD_isError(compressedSize) || decompressedBound == ZSTD_CONTENTSIZE_ERROR)
@@ -568,6 +833,48 @@ unsigned long long ZSTD_decompressBound(const void* src, size_t srcSize)
568
833
  return bound;
569
834
  }
570
835
 
836
+ size_t ZSTD_decompressionMargin(void const* src, size_t srcSize)
837
+ {
838
+ size_t margin = 0;
839
+ unsigned maxBlockSize = 0;
840
+
841
+ /* Iterate over each frame */
842
+ while (srcSize > 0) {
843
+ ZSTD_frameSizeInfo const frameSizeInfo = ZSTD_findFrameSizeInfo(src, srcSize, ZSTD_f_zstd1);
844
+ size_t const compressedSize = frameSizeInfo.compressedSize;
845
+ unsigned long long const decompressedBound = frameSizeInfo.decompressedBound;
846
+ ZSTD_frameHeader zfh;
847
+
848
+ FORWARD_IF_ERROR(ZSTD_getFrameHeader(&zfh, src, srcSize), "");
849
+ if (ZSTD_isError(compressedSize) || decompressedBound == ZSTD_CONTENTSIZE_ERROR)
850
+ return ERROR(corruption_detected);
851
+
852
+ if (zfh.frameType == ZSTD_frame) {
853
+ /* Add the frame header to our margin */
854
+ margin += zfh.headerSize;
855
+ /* Add the checksum to our margin */
856
+ margin += zfh.checksumFlag ? 4 : 0;
857
+ /* Add 3 bytes per block */
858
+ margin += 3 * frameSizeInfo.nbBlocks;
859
+
860
+ /* Compute the max block size */
861
+ maxBlockSize = MAX(maxBlockSize, zfh.blockSizeMax);
862
+ } else {
863
+ assert(zfh.frameType == ZSTD_skippableFrame);
864
+ /* Add the entire skippable frame size to our margin. */
865
+ margin += compressedSize;
866
+ }
867
+
868
+ assert(srcSize >= compressedSize);
869
+ src = (const BYTE*)src + compressedSize;
870
+ srcSize -= compressedSize;
871
+ }
872
+
873
+ /* Add the max block size back to the margin. */
874
+ margin += maxBlockSize;
875
+
876
+ return margin;
877
+ }
571
878
 
572
879
  /*-*************************************************************
573
880
  * Frame decoding
@@ -578,7 +885,7 @@ unsigned long long ZSTD_decompressBound(const void* src, size_t srcSize)
578
885
  size_t ZSTD_insertBlock(ZSTD_DCtx* dctx, const void* blockStart, size_t blockSize)
579
886
  {
580
887
  DEBUGLOG(5, "ZSTD_insertBlock: %u bytes", (unsigned)blockSize);
581
- ZSTD_checkContinuity(dctx, blockStart);
888
+ ZSTD_checkContinuity(dctx, blockStart, blockSize);
582
889
  dctx->previousDstEnd = (const char*)blockStart + blockSize;
583
890
  return blockSize;
584
891
  }
@@ -593,7 +900,7 @@ static size_t ZSTD_copyRawBlock(void* dst, size_t dstCapacity,
593
900
  if (srcSize == 0) return 0;
594
901
  RETURN_ERROR(dstBuffer_null, "");
595
902
  }
596
- ZSTD_memcpy(dst, src, srcSize);
903
+ ZSTD_memmove(dst, src, srcSize);
597
904
  return srcSize;
598
905
  }
599
906
 
@@ -610,6 +917,32 @@ static size_t ZSTD_setRleBlock(void* dst, size_t dstCapacity,
610
917
  return regenSize;
611
918
  }
612
919
 
920
+ static void ZSTD_DCtx_trace_end(ZSTD_DCtx const* dctx, U64 uncompressedSize, U64 compressedSize, unsigned streaming)
921
+ {
922
+ #if ZSTD_TRACE
923
+ if (dctx->traceCtx && ZSTD_trace_decompress_end != NULL) {
924
+ ZSTD_Trace trace;
925
+ ZSTD_memset(&trace, 0, sizeof(trace));
926
+ trace.version = ZSTD_VERSION_NUMBER;
927
+ trace.streaming = streaming;
928
+ if (dctx->ddict) {
929
+ trace.dictionaryID = ZSTD_getDictID_fromDDict(dctx->ddict);
930
+ trace.dictionarySize = ZSTD_DDict_dictSize(dctx->ddict);
931
+ trace.dictionaryIsCold = dctx->ddictIsCold;
932
+ }
933
+ trace.uncompressedSize = (size_t)uncompressedSize;
934
+ trace.compressedSize = (size_t)compressedSize;
935
+ trace.dctx = dctx;
936
+ ZSTD_trace_decompress_end(dctx->traceCtx, &trace);
937
+ }
938
+ #else
939
+ (void)dctx;
940
+ (void)uncompressedSize;
941
+ (void)compressedSize;
942
+ (void)streaming;
943
+ #endif
944
+ }
945
+
613
946
 
614
947
  /*! ZSTD_decompressFrame() :
615
948
  * @dctx must be properly initialized
@@ -619,8 +952,9 @@ static size_t ZSTD_decompressFrame(ZSTD_DCtx* dctx,
619
952
  void* dst, size_t dstCapacity,
620
953
  const void** srcPtr, size_t *srcSizePtr)
621
954
  {
622
- const BYTE* ip = (const BYTE*)(*srcPtr);
623
- BYTE* const ostart = (BYTE* const)dst;
955
+ const BYTE* const istart = (const BYTE*)(*srcPtr);
956
+ const BYTE* ip = istart;
957
+ BYTE* const ostart = (BYTE*)dst;
624
958
  BYTE* const oend = dstCapacity != 0 ? ostart + dstCapacity : ostart;
625
959
  BYTE* op = ostart;
626
960
  size_t remainingSrcSize = *srcSizePtr;
@@ -642,8 +976,13 @@ static size_t ZSTD_decompressFrame(ZSTD_DCtx* dctx,
642
976
  ip += frameHeaderSize; remainingSrcSize -= frameHeaderSize;
643
977
  }
644
978
 
979
+ /* Shrink the blockSizeMax if enabled */
980
+ if (dctx->maxBlockSizeParam != 0)
981
+ dctx->fParams.blockSizeMax = MIN(dctx->fParams.blockSizeMax, (unsigned)dctx->maxBlockSizeParam);
982
+
645
983
  /* Loop on each block */
646
984
  while (1) {
985
+ BYTE* oBlockEnd = oend;
647
986
  size_t decodedSize;
648
987
  blockProperties_t blockProperties;
649
988
  size_t const cBlockSize = ZSTD_getcBlockSize(ip, remainingSrcSize, &blockProperties);
@@ -653,27 +992,48 @@ static size_t ZSTD_decompressFrame(ZSTD_DCtx* dctx,
653
992
  remainingSrcSize -= ZSTD_blockHeaderSize;
654
993
  RETURN_ERROR_IF(cBlockSize > remainingSrcSize, srcSize_wrong, "");
655
994
 
995
+ if (ip >= op && ip < oBlockEnd) {
996
+ /* We are decompressing in-place. Limit the output pointer so that we
997
+ * don't overwrite the block that we are currently reading. This will
998
+ * fail decompression if the input & output pointers aren't spaced
999
+ * far enough apart.
1000
+ *
1001
+ * This is important to set, even when the pointers are far enough
1002
+ * apart, because ZSTD_decompressBlock_internal() can decide to store
1003
+ * literals in the output buffer, after the block it is decompressing.
1004
+ * Since we don't want anything to overwrite our input, we have to tell
1005
+ * ZSTD_decompressBlock_internal to never write past ip.
1006
+ *
1007
+ * See ZSTD_allocateLiteralsBuffer() for reference.
1008
+ */
1009
+ oBlockEnd = op + (ip - op);
1010
+ }
1011
+
656
1012
  switch(blockProperties.blockType)
657
1013
  {
658
1014
  case bt_compressed:
659
- decodedSize = ZSTD_decompressBlock_internal(dctx, op, (size_t)(oend-op), ip, cBlockSize, /* frame */ 1);
1015
+ assert(dctx->isFrameDecompression == 1);
1016
+ decodedSize = ZSTD_decompressBlock_internal(dctx, op, (size_t)(oBlockEnd-op), ip, cBlockSize, not_streaming);
660
1017
  break;
661
1018
  case bt_raw :
1019
+ /* Use oend instead of oBlockEnd because this function is safe to overlap. It uses memmove. */
662
1020
  decodedSize = ZSTD_copyRawBlock(op, (size_t)(oend-op), ip, cBlockSize);
663
1021
  break;
664
1022
  case bt_rle :
665
- decodedSize = ZSTD_setRleBlock(op, (size_t)(oend-op), *ip, blockProperties.origSize);
1023
+ decodedSize = ZSTD_setRleBlock(op, (size_t)(oBlockEnd-op), *ip, blockProperties.origSize);
666
1024
  break;
667
1025
  case bt_reserved :
668
1026
  default:
669
1027
  RETURN_ERROR(corruption_detected, "invalid block type");
670
1028
  }
671
-
672
- if (ZSTD_isError(decodedSize)) return decodedSize;
673
- if (dctx->validateChecksum)
1029
+ FORWARD_IF_ERROR(decodedSize, "Block decompression failure");
1030
+ DEBUGLOG(5, "Decompressed block of dSize = %u", (unsigned)decodedSize);
1031
+ if (dctx->validateChecksum) {
674
1032
  XXH64_update(&dctx->xxhState, op, decodedSize);
675
- if (decodedSize != 0)
1033
+ }
1034
+ if (decodedSize) /* support dst = NULL,0 */ {
676
1035
  op += decodedSize;
1036
+ }
677
1037
  assert(ip != NULL);
678
1038
  ip += cBlockSize;
679
1039
  remainingSrcSize -= cBlockSize;
@@ -695,14 +1055,17 @@ static size_t ZSTD_decompressFrame(ZSTD_DCtx* dctx,
695
1055
  ip += 4;
696
1056
  remainingSrcSize -= 4;
697
1057
  }
698
-
1058
+ ZSTD_DCtx_trace_end(dctx, (U64)(op-ostart), (U64)(ip-istart), /* streaming */ 0);
699
1059
  /* Allow caller to get size read */
1060
+ DEBUGLOG(4, "ZSTD_decompressFrame: decompressed frame of size %zi, consuming %zi bytes of input", op-ostart, ip - (const BYTE*)*srcPtr);
700
1061
  *srcPtr = ip;
701
1062
  *srcSizePtr = remainingSrcSize;
702
1063
  return (size_t)(op-ostart);
703
1064
  }
704
1065
 
705
- static size_t ZSTD_decompressMultiFrame(ZSTD_DCtx* dctx,
1066
+ static
1067
+ ZSTD_ALLOW_POINTER_OVERFLOW_ATTR
1068
+ size_t ZSTD_decompressMultiFrame(ZSTD_DCtx* dctx,
706
1069
  void* dst, size_t dstCapacity,
707
1070
  const void* src, size_t srcSize,
708
1071
  const void* dict, size_t dictSize,
@@ -722,7 +1085,7 @@ static size_t ZSTD_decompressMultiFrame(ZSTD_DCtx* dctx,
722
1085
  while (srcSize >= ZSTD_startingInputLength(dctx->format)) {
723
1086
 
724
1087
  #if defined(ZSTD_LEGACY_SUPPORT) && (ZSTD_LEGACY_SUPPORT >= 1)
725
- if (ZSTD_isLegacy(src, srcSize)) {
1088
+ if (dctx->format == ZSTD_f_zstd1 && ZSTD_isLegacy(src, srcSize)) {
726
1089
  size_t decodedSize;
727
1090
  size_t const frameSize = ZSTD_findFrameCompressedSizeLegacy(src, srcSize);
728
1091
  if (ZSTD_isError(frameSize)) return frameSize;
@@ -732,6 +1095,15 @@ static size_t ZSTD_decompressMultiFrame(ZSTD_DCtx* dctx,
732
1095
  decodedSize = ZSTD_decompressLegacy(dst, dstCapacity, src, frameSize, dict, dictSize);
733
1096
  if (ZSTD_isError(decodedSize)) return decodedSize;
734
1097
 
1098
+ {
1099
+ unsigned long long const expectedSize = ZSTD_getFrameContentSize(src, srcSize);
1100
+ RETURN_ERROR_IF(expectedSize == ZSTD_CONTENTSIZE_ERROR, corruption_detected, "Corrupted frame header!");
1101
+ if (expectedSize != ZSTD_CONTENTSIZE_UNKNOWN) {
1102
+ RETURN_ERROR_IF(expectedSize != decodedSize, corruption_detected,
1103
+ "Frame header size does not match decoded size!");
1104
+ }
1105
+ }
1106
+
735
1107
  assert(decodedSize <= dstCapacity);
736
1108
  dst = (BYTE*)dst + decodedSize;
737
1109
  dstCapacity -= decodedSize;
@@ -743,17 +1115,18 @@ static size_t ZSTD_decompressMultiFrame(ZSTD_DCtx* dctx,
743
1115
  }
744
1116
  #endif
745
1117
 
746
- { U32 const magicNumber = MEM_readLE32(src);
747
- DEBUGLOG(4, "reading magic number %08X (expecting %08X)",
748
- (unsigned)magicNumber, ZSTD_MAGICNUMBER);
1118
+ if (dctx->format == ZSTD_f_zstd1 && srcSize >= 4) {
1119
+ U32 const magicNumber = MEM_readLE32(src);
1120
+ DEBUGLOG(5, "reading magic number %08X", (unsigned)magicNumber);
749
1121
  if ((magicNumber & ZSTD_MAGIC_SKIPPABLE_MASK) == ZSTD_MAGIC_SKIPPABLE_START) {
1122
+ /* skippable frame detected : skip it */
750
1123
  size_t const skippableSize = readSkippableFrameSize(src, srcSize);
751
- FORWARD_IF_ERROR(skippableSize, "readSkippableFrameSize failed");
1124
+ FORWARD_IF_ERROR(skippableSize, "invalid skippable frame");
752
1125
  assert(skippableSize <= srcSize);
753
1126
 
754
1127
  src = (const BYTE *)src + skippableSize;
755
1128
  srcSize -= skippableSize;
756
- continue;
1129
+ continue; /* check next frame */
757
1130
  } }
758
1131
 
759
1132
  if (ddict) {
@@ -764,7 +1137,7 @@ static size_t ZSTD_decompressMultiFrame(ZSTD_DCtx* dctx,
764
1137
  * use this in all cases but ddict */
765
1138
  FORWARD_IF_ERROR(ZSTD_decompressBegin_usingDict(dctx, dict, dictSize), "");
766
1139
  }
767
- ZSTD_checkContinuity(dctx, dst);
1140
+ ZSTD_checkContinuity(dctx, dst, dstCapacity);
768
1141
 
769
1142
  { const size_t res = ZSTD_decompressFrame(dctx, dst, dstCapacity,
770
1143
  &src, &srcSize);
@@ -807,7 +1180,7 @@ static ZSTD_DDict const* ZSTD_getDDict(ZSTD_DCtx* dctx)
807
1180
  switch (dctx->dictUses) {
808
1181
  default:
809
1182
  assert(0 /* Impossible */);
810
- /* fall-through */
1183
+ ZSTD_FALLTHROUGH;
811
1184
  case ZSTD_dont_use:
812
1185
  ZSTD_clearDict(dctx);
813
1186
  return NULL;
@@ -829,7 +1202,7 @@ size_t ZSTD_decompress(void* dst, size_t dstCapacity, const void* src, size_t sr
829
1202
  {
830
1203
  #if defined(ZSTD_HEAPMODE) && (ZSTD_HEAPMODE>=1)
831
1204
  size_t regenSize;
832
- ZSTD_DCtx* const dctx = ZSTD_createDCtx();
1205
+ ZSTD_DCtx* const dctx = ZSTD_createDCtx_internal(ZSTD_defaultCMem);
833
1206
  RETURN_ERROR_IF(dctx==NULL, memory_allocation, "NULL pointer!");
834
1207
  regenSize = ZSTD_decompressDCtx(dctx, dst, dstCapacity, src, srcSize);
835
1208
  ZSTD_freeDCtx(dctx);
@@ -849,8 +1222,8 @@ size_t ZSTD_decompress(void* dst, size_t dstCapacity, const void* src, size_t sr
849
1222
  size_t ZSTD_nextSrcSizeToDecompress(ZSTD_DCtx* dctx) { return dctx->expected; }
850
1223
 
851
1224
  /**
852
- * Similar to ZSTD_nextSrcSizeToDecompress(), but when when a block input can be streamed,
853
- * we allow taking a partial block as the input. Currently only raw uncompressed blocks can
1225
+ * Similar to ZSTD_nextSrcSizeToDecompress(), but when a block input can be streamed, we
1226
+ * allow taking a partial block as the input. Currently only raw uncompressed blocks can
854
1227
  * be streamed.
855
1228
  *
856
1229
  * For blocks that can be streamed, this allows us to reduce the latency until we produce
@@ -863,7 +1236,7 @@ static size_t ZSTD_nextSrcSizeToDecompressWithInputSize(ZSTD_DCtx* dctx, size_t
863
1236
  return dctx->expected;
864
1237
  if (dctx->bType != bt_raw)
865
1238
  return dctx->expected;
866
- return MIN(MAX(inputSize, 1), dctx->expected);
1239
+ return BOUNDED(1, inputSize, dctx->expected);
867
1240
  }
868
1241
 
869
1242
  ZSTD_nextInputType_e ZSTD_nextInputType(ZSTD_DCtx* dctx) {
@@ -871,7 +1244,9 @@ ZSTD_nextInputType_e ZSTD_nextInputType(ZSTD_DCtx* dctx) {
871
1244
  {
872
1245
  default: /* should not happen */
873
1246
  assert(0);
1247
+ ZSTD_FALLTHROUGH;
874
1248
  case ZSTDds_getFrameHeaderSize:
1249
+ ZSTD_FALLTHROUGH;
875
1250
  case ZSTDds_decodeFrameHeader:
876
1251
  return ZSTDnit_frameHeader;
877
1252
  case ZSTDds_decodeBlockHeader:
@@ -883,6 +1258,7 @@ ZSTD_nextInputType_e ZSTD_nextInputType(ZSTD_DCtx* dctx) {
883
1258
  case ZSTDds_checkChecksum:
884
1259
  return ZSTDnit_checksum;
885
1260
  case ZSTDds_decodeSkippableHeader:
1261
+ ZSTD_FALLTHROUGH;
886
1262
  case ZSTDds_skipFrame:
887
1263
  return ZSTDnit_skippableFrame;
888
1264
  }
@@ -899,7 +1275,9 @@ size_t ZSTD_decompressContinue(ZSTD_DCtx* dctx, void* dst, size_t dstCapacity, c
899
1275
  DEBUGLOG(5, "ZSTD_decompressContinue (srcSize:%u)", (unsigned)srcSize);
900
1276
  /* Sanity check */
901
1277
  RETURN_ERROR_IF(srcSize != ZSTD_nextSrcSizeToDecompressWithInputSize(dctx, srcSize), srcSize_wrong, "not allowed");
902
- if (dstCapacity) ZSTD_checkContinuity(dctx, dst);
1278
+ ZSTD_checkContinuity(dctx, dst, dstCapacity);
1279
+
1280
+ dctx->processedCSize += srcSize;
903
1281
 
904
1282
  switch (dctx->stage)
905
1283
  {
@@ -964,7 +1342,8 @@ size_t ZSTD_decompressContinue(ZSTD_DCtx* dctx, void* dst, size_t dstCapacity, c
964
1342
  {
965
1343
  case bt_compressed:
966
1344
  DEBUGLOG(5, "ZSTD_decompressContinue: case bt_compressed");
967
- rSize = ZSTD_decompressBlock_internal(dctx, dst, dstCapacity, src, srcSize, /* frame */ 1);
1345
+ assert(dctx->isFrameDecompression == 1);
1346
+ rSize = ZSTD_decompressBlock_internal(dctx, dst, dstCapacity, src, srcSize, is_streaming);
968
1347
  dctx->expected = 0; /* Streaming not supported */
969
1348
  break;
970
1349
  case bt_raw :
@@ -1004,6 +1383,7 @@ size_t ZSTD_decompressContinue(ZSTD_DCtx* dctx, void* dst, size_t dstCapacity, c
1004
1383
  dctx->expected = 4;
1005
1384
  dctx->stage = ZSTDds_checkChecksum;
1006
1385
  } else {
1386
+ ZSTD_DCtx_trace_end(dctx, dctx->decodedSize, dctx->processedCSize, /* streaming */ 1);
1007
1387
  dctx->expected = 0; /* ends here */
1008
1388
  dctx->stage = ZSTDds_getFrameHeaderSize;
1009
1389
  }
@@ -1023,6 +1403,7 @@ size_t ZSTD_decompressContinue(ZSTD_DCtx* dctx, void* dst, size_t dstCapacity, c
1023
1403
  DEBUGLOG(4, "ZSTD_decompressContinue: checksum : calculated %08X :: %08X read", (unsigned)h32, (unsigned)check32);
1024
1404
  RETURN_ERROR_IF(check32 != h32, checksum_wrong, "");
1025
1405
  }
1406
+ ZSTD_DCtx_trace_end(dctx, dctx->decodedSize, dctx->processedCSize, /* streaming */ 1);
1026
1407
  dctx->expected = 0;
1027
1408
  dctx->stage = ZSTDds_getFrameHeaderSize;
1028
1409
  return 0;
@@ -1031,6 +1412,7 @@ size_t ZSTD_decompressContinue(ZSTD_DCtx* dctx, void* dst, size_t dstCapacity, c
1031
1412
  case ZSTDds_decodeSkippableHeader:
1032
1413
  assert(src != NULL);
1033
1414
  assert(srcSize <= ZSTD_SKIPPABLEHEADERSIZE);
1415
+ assert(dctx->format != ZSTD_f_zstd1_magicless);
1034
1416
  ZSTD_memcpy(dctx->headerBuffer + (ZSTD_SKIPPABLEHEADERSIZE - srcSize), src, srcSize); /* complete skippable header */
1035
1417
  dctx->expected = MEM_readLE32(dctx->headerBuffer + ZSTD_FRAMEIDSIZE); /* note : dctx->expected can grow seriously large, beyond local buffer size */
1036
1418
  dctx->stage = ZSTDds_skipFrame;
@@ -1043,7 +1425,7 @@ size_t ZSTD_decompressContinue(ZSTD_DCtx* dctx, void* dst, size_t dstCapacity, c
1043
1425
 
1044
1426
  default:
1045
1427
  assert(0); /* impossible */
1046
- RETURN_ERROR(GENERIC, "impossible to reach"); /* some compiler require default to do something */
1428
+ RETURN_ERROR(GENERIC, "impossible to reach"); /* some compilers require default to do something */
1047
1429
  }
1048
1430
  }
1049
1431
 
@@ -1084,11 +1466,11 @@ ZSTD_loadDEntropy(ZSTD_entropyDTables_t* entropy,
1084
1466
  /* in minimal huffman, we always use X1 variants */
1085
1467
  size_t const hSize = HUF_readDTableX1_wksp(entropy->hufTable,
1086
1468
  dictPtr, dictEnd - dictPtr,
1087
- workspace, workspaceSize);
1469
+ workspace, workspaceSize, /* flags */ 0);
1088
1470
  #else
1089
1471
  size_t const hSize = HUF_readDTableX2_wksp(entropy->hufTable,
1090
1472
  dictPtr, (size_t)(dictEnd - dictPtr),
1091
- workspace, workspaceSize);
1473
+ workspace, workspaceSize, /* flags */ 0);
1092
1474
  #endif
1093
1475
  RETURN_ERROR_IF(HUF_isError(hSize), dictionary_corrupted, "");
1094
1476
  dictPtr += hSize;
@@ -1176,17 +1558,22 @@ static size_t ZSTD_decompress_insertDictionary(ZSTD_DCtx* dctx, const void* dict
1176
1558
  size_t ZSTD_decompressBegin(ZSTD_DCtx* dctx)
1177
1559
  {
1178
1560
  assert(dctx != NULL);
1561
+ #if ZSTD_TRACE
1562
+ dctx->traceCtx = (ZSTD_trace_decompress_begin != NULL) ? ZSTD_trace_decompress_begin(dctx) : 0;
1563
+ #endif
1179
1564
  dctx->expected = ZSTD_startingInputLength(dctx->format); /* dctx->format must be properly set */
1180
1565
  dctx->stage = ZSTDds_getFrameHeaderSize;
1566
+ dctx->processedCSize = 0;
1181
1567
  dctx->decodedSize = 0;
1182
1568
  dctx->previousDstEnd = NULL;
1183
1569
  dctx->prefixStart = NULL;
1184
1570
  dctx->virtualStart = NULL;
1185
1571
  dctx->dictEnd = NULL;
1186
- dctx->entropy.hufTable[0] = (HUF_DTable)((HufLog)*0x1000001); /* cover both little and big endian */
1572
+ dctx->entropy.hufTable[0] = (HUF_DTable)((ZSTD_HUFFDTABLE_CAPACITY_LOG)*0x1000001); /* cover both little and big endian */
1187
1573
  dctx->litEntropy = dctx->fseEntropy = 0;
1188
1574
  dctx->dictID = 0;
1189
1575
  dctx->bType = bt_reserved;
1576
+ dctx->isFrameDecompression = 1;
1190
1577
  ZSTD_STATIC_ASSERT(sizeof(dctx->entropy.rep) == sizeof(repStartValue));
1191
1578
  ZSTD_memcpy(dctx->entropy.rep, repStartValue, sizeof(repStartValue)); /* initial repcodes */
1192
1579
  dctx->LLTptr = dctx->entropy.LLTable;
@@ -1245,7 +1632,7 @@ unsigned ZSTD_getDictID_fromDict(const void* dict, size_t dictSize)
1245
1632
  * This could for one of the following reasons :
1246
1633
  * - The frame does not require a dictionary (most common case).
1247
1634
  * - The frame was built with dictID intentionally removed.
1248
- * Needed dictionary is a hidden information.
1635
+ * Needed dictionary is a hidden piece of information.
1249
1636
  * Note : this use case also happens when using a non-conformant dictionary.
1250
1637
  * - `srcSize` is too small, and as a result, frame header could not be decoded.
1251
1638
  * Note : possible if `srcSize < ZSTD_FRAMEHEADERSIZE_MAX`.
@@ -1254,7 +1641,7 @@ unsigned ZSTD_getDictID_fromDict(const void* dict, size_t dictSize)
1254
1641
  * ZSTD_getFrameHeader(), which will provide a more precise error code. */
1255
1642
  unsigned ZSTD_getDictID_fromFrame(const void* src, size_t srcSize)
1256
1643
  {
1257
- ZSTD_frameHeader zfp = { 0, 0, 0, ZSTD_frame, 0, 0, 0 };
1644
+ ZSTD_frameHeader zfp = { 0, 0, 0, ZSTD_frame, 0, 0, 0, 0, 0 };
1258
1645
  size_t const hError = ZSTD_getFrameHeader(&zfp, src, srcSize);
1259
1646
  if (ZSTD_isError(hError)) return 0;
1260
1647
  return zfp.dictID;
@@ -1283,7 +1670,7 @@ size_t ZSTD_decompress_usingDDict(ZSTD_DCtx* dctx,
1283
1670
  ZSTD_DStream* ZSTD_createDStream(void)
1284
1671
  {
1285
1672
  DEBUGLOG(3, "ZSTD_createDStream");
1286
- return ZSTD_createDStream_advanced(ZSTD_defaultCMem);
1673
+ return ZSTD_createDCtx_internal(ZSTD_defaultCMem);
1287
1674
  }
1288
1675
 
1289
1676
  ZSTD_DStream* ZSTD_initStaticDStream(void *workspace, size_t workspaceSize)
@@ -1293,7 +1680,7 @@ ZSTD_DStream* ZSTD_initStaticDStream(void *workspace, size_t workspaceSize)
1293
1680
 
1294
1681
  ZSTD_DStream* ZSTD_createDStream_advanced(ZSTD_customMem customMem)
1295
1682
  {
1296
- return ZSTD_createDCtx_advanced(customMem);
1683
+ return ZSTD_createDCtx_internal(customMem);
1297
1684
  }
1298
1685
 
1299
1686
  size_t ZSTD_freeDStream(ZSTD_DStream* zds)
@@ -1361,7 +1748,9 @@ size_t ZSTD_initDStream_usingDict(ZSTD_DStream* zds, const void* dict, size_t di
1361
1748
  size_t ZSTD_initDStream(ZSTD_DStream* zds)
1362
1749
  {
1363
1750
  DEBUGLOG(4, "ZSTD_initDStream");
1364
- return ZSTD_initDStream_usingDDict(zds, NULL);
1751
+ FORWARD_IF_ERROR(ZSTD_DCtx_reset(zds, ZSTD_reset_session_only), "");
1752
+ FORWARD_IF_ERROR(ZSTD_DCtx_refDDict(zds, NULL), "");
1753
+ return ZSTD_startingInputLength(zds->format);
1365
1754
  }
1366
1755
 
1367
1756
  /* ZSTD_initDStream_usingDDict() :
@@ -1369,6 +1758,7 @@ size_t ZSTD_initDStream(ZSTD_DStream* zds)
1369
1758
  * this function cannot fail */
1370
1759
  size_t ZSTD_initDStream_usingDDict(ZSTD_DStream* dctx, const ZSTD_DDict* ddict)
1371
1760
  {
1761
+ DEBUGLOG(4, "ZSTD_initDStream_usingDDict");
1372
1762
  FORWARD_IF_ERROR( ZSTD_DCtx_reset(dctx, ZSTD_reset_session_only) , "");
1373
1763
  FORWARD_IF_ERROR( ZSTD_DCtx_refDDict(dctx, ddict) , "");
1374
1764
  return ZSTD_startingInputLength(dctx->format);
@@ -1379,6 +1769,7 @@ size_t ZSTD_initDStream_usingDDict(ZSTD_DStream* dctx, const ZSTD_DDict* ddict)
1379
1769
  * this function cannot fail */
1380
1770
  size_t ZSTD_resetDStream(ZSTD_DStream* dctx)
1381
1771
  {
1772
+ DEBUGLOG(4, "ZSTD_resetDStream");
1382
1773
  FORWARD_IF_ERROR(ZSTD_DCtx_reset(dctx, ZSTD_reset_session_only), "");
1383
1774
  return ZSTD_startingInputLength(dctx->format);
1384
1775
  }
@@ -1391,6 +1782,16 @@ size_t ZSTD_DCtx_refDDict(ZSTD_DCtx* dctx, const ZSTD_DDict* ddict)
1391
1782
  if (ddict) {
1392
1783
  dctx->ddict = ddict;
1393
1784
  dctx->dictUses = ZSTD_use_indefinitely;
1785
+ if (dctx->refMultipleDDicts == ZSTD_rmd_refMultipleDDicts) {
1786
+ if (dctx->ddictSet == NULL) {
1787
+ dctx->ddictSet = ZSTD_createDDictHashSet(dctx->customMem);
1788
+ if (!dctx->ddictSet) {
1789
+ RETURN_ERROR(memory_allocation, "Failed to allocate memory for hash set!");
1790
+ }
1791
+ }
1792
+ assert(!dctx->staticSize); /* Impossible: ddictSet cannot have been allocated if static dctx */
1793
+ FORWARD_IF_ERROR(ZSTD_DDictHashSet_addDDict(dctx->ddictSet, ddict, dctx->customMem), "");
1794
+ }
1394
1795
  }
1395
1796
  return 0;
1396
1797
  }
@@ -1436,6 +1837,19 @@ ZSTD_bounds ZSTD_dParam_getBounds(ZSTD_dParameter dParam)
1436
1837
  bounds.lowerBound = (int)ZSTD_d_validateChecksum;
1437
1838
  bounds.upperBound = (int)ZSTD_d_ignoreChecksum;
1438
1839
  return bounds;
1840
+ case ZSTD_d_refMultipleDDicts:
1841
+ bounds.lowerBound = (int)ZSTD_rmd_refSingleDDict;
1842
+ bounds.upperBound = (int)ZSTD_rmd_refMultipleDDicts;
1843
+ return bounds;
1844
+ case ZSTD_d_disableHuffmanAssembly:
1845
+ bounds.lowerBound = 0;
1846
+ bounds.upperBound = 1;
1847
+ return bounds;
1848
+ case ZSTD_d_maxBlockSize:
1849
+ bounds.lowerBound = ZSTD_BLOCKSIZE_MAX_MIN;
1850
+ bounds.upperBound = ZSTD_BLOCKSIZE_MAX;
1851
+ return bounds;
1852
+
1439
1853
  default:;
1440
1854
  }
1441
1855
  bounds.error = ERROR(parameter_unsupported);
@@ -1473,6 +1887,15 @@ size_t ZSTD_DCtx_getParameter(ZSTD_DCtx* dctx, ZSTD_dParameter param, int* value
1473
1887
  case ZSTD_d_forceIgnoreChecksum:
1474
1888
  *value = (int)dctx->forceIgnoreChecksum;
1475
1889
  return 0;
1890
+ case ZSTD_d_refMultipleDDicts:
1891
+ *value = (int)dctx->refMultipleDDicts;
1892
+ return 0;
1893
+ case ZSTD_d_disableHuffmanAssembly:
1894
+ *value = (int)dctx->disableHufAsm;
1895
+ return 0;
1896
+ case ZSTD_d_maxBlockSize:
1897
+ *value = dctx->maxBlockSizeParam;
1898
+ return 0;
1476
1899
  default:;
1477
1900
  }
1478
1901
  RETURN_ERROR(parameter_unsupported, "");
@@ -1499,6 +1922,21 @@ size_t ZSTD_DCtx_setParameter(ZSTD_DCtx* dctx, ZSTD_dParameter dParam, int value
1499
1922
  CHECK_DBOUNDS(ZSTD_d_forceIgnoreChecksum, value);
1500
1923
  dctx->forceIgnoreChecksum = (ZSTD_forceIgnoreChecksum_e)value;
1501
1924
  return 0;
1925
+ case ZSTD_d_refMultipleDDicts:
1926
+ CHECK_DBOUNDS(ZSTD_d_refMultipleDDicts, value);
1927
+ if (dctx->staticSize != 0) {
1928
+ RETURN_ERROR(parameter_unsupported, "Static dctx does not support multiple DDicts!");
1929
+ }
1930
+ dctx->refMultipleDDicts = (ZSTD_refMultipleDDicts_e)value;
1931
+ return 0;
1932
+ case ZSTD_d_disableHuffmanAssembly:
1933
+ CHECK_DBOUNDS(ZSTD_d_disableHuffmanAssembly, value);
1934
+ dctx->disableHufAsm = value != 0;
1935
+ return 0;
1936
+ case ZSTD_d_maxBlockSize:
1937
+ if (value != 0) CHECK_DBOUNDS(ZSTD_d_maxBlockSize, value);
1938
+ dctx->maxBlockSizeParam = value;
1939
+ return 0;
1502
1940
  default:;
1503
1941
  }
1504
1942
  RETURN_ERROR(parameter_unsupported, "");
@@ -1510,6 +1948,7 @@ size_t ZSTD_DCtx_reset(ZSTD_DCtx* dctx, ZSTD_ResetDirective reset)
1510
1948
  || (reset == ZSTD_reset_session_and_parameters) ) {
1511
1949
  dctx->streamStage = zdss_init;
1512
1950
  dctx->noForwardProgress = 0;
1951
+ dctx->isFrameDecompression = 1;
1513
1952
  }
1514
1953
  if ( (reset == ZSTD_reset_parameters)
1515
1954
  || (reset == ZSTD_reset_session_and_parameters) ) {
@@ -1526,10 +1965,17 @@ size_t ZSTD_sizeof_DStream(const ZSTD_DStream* dctx)
1526
1965
  return ZSTD_sizeof_DCtx(dctx);
1527
1966
  }
1528
1967
 
1529
- size_t ZSTD_decodingBufferSize_min(unsigned long long windowSize, unsigned long long frameContentSize)
1968
+ static size_t ZSTD_decodingBufferSize_internal(unsigned long long windowSize, unsigned long long frameContentSize, size_t blockSizeMax)
1530
1969
  {
1531
- size_t const blockSize = (size_t) MIN(windowSize, ZSTD_BLOCKSIZE_MAX);
1532
- unsigned long long const neededRBSize = windowSize + blockSize + (WILDCOPY_OVERLENGTH * 2);
1970
+ size_t const blockSize = MIN((size_t)MIN(windowSize, ZSTD_BLOCKSIZE_MAX), blockSizeMax);
1971
+ /* We need blockSize + WILDCOPY_OVERLENGTH worth of buffer so that if a block
1972
+ * ends at windowSize + WILDCOPY_OVERLENGTH + 1 bytes, we can start writing
1973
+ * the block at the beginning of the output buffer, and maintain a full window.
1974
+ *
1975
+ * We need another blockSize worth of buffer so that we can store split
1976
+ * literals at the end of the block without overwriting the extDict window.
1977
+ */
1978
+ unsigned long long const neededRBSize = windowSize + (blockSize * 2) + (WILDCOPY_OVERLENGTH * 2);
1533
1979
  unsigned long long const neededSize = MIN(frameContentSize, neededRBSize);
1534
1980
  size_t const minRBSize = (size_t) neededSize;
1535
1981
  RETURN_ERROR_IF((unsigned long long)minRBSize != neededSize,
@@ -1537,6 +1983,11 @@ size_t ZSTD_decodingBufferSize_min(unsigned long long windowSize, unsigned long
1537
1983
  return minRBSize;
1538
1984
  }
1539
1985
 
1986
+ size_t ZSTD_decodingBufferSize_min(unsigned long long windowSize, unsigned long long frameContentSize)
1987
+ {
1988
+ return ZSTD_decodingBufferSize_internal(windowSize, frameContentSize, ZSTD_BLOCKSIZE_MAX);
1989
+ }
1990
+
1540
1991
  size_t ZSTD_estimateDStreamSize(size_t windowSize)
1541
1992
  {
1542
1993
  size_t const blockSize = MIN(windowSize, ZSTD_BLOCKSIZE_MAX);
@@ -1663,10 +2114,12 @@ size_t ZSTD_decompressStream(ZSTD_DStream* zds, ZSTD_outBuffer* output, ZSTD_inB
1663
2114
  DEBUGLOG(5, "stage zdss_init => transparent reset ");
1664
2115
  zds->streamStage = zdss_loadHeader;
1665
2116
  zds->lhSize = zds->inPos = zds->outStart = zds->outEnd = 0;
2117
+ #if defined(ZSTD_LEGACY_SUPPORT) && (ZSTD_LEGACY_SUPPORT>=1)
1666
2118
  zds->legacyVersion = 0;
2119
+ #endif
1667
2120
  zds->hostageByte = 0;
1668
2121
  zds->expectedOutBuffer = *output;
1669
- /* fall-through */
2122
+ ZSTD_FALLTHROUGH;
1670
2123
 
1671
2124
  case zdss_loadHeader :
1672
2125
  DEBUGLOG(5, "stage zdss_loadHeader (srcSize : %u)", (U32)(iend - ip));
@@ -1680,7 +2133,9 @@ size_t ZSTD_decompressStream(ZSTD_DStream* zds, ZSTD_outBuffer* output, ZSTD_inB
1680
2133
  } }
1681
2134
  #endif
1682
2135
  { size_t const hSize = ZSTD_getFrameHeader_advanced(&zds->fParams, zds->headerBuffer, zds->lhSize, zds->format);
1683
- DEBUGLOG(5, "header size : %u", (U32)hSize);
2136
+ if (zds->refMultipleDDicts && zds->ddictSet) {
2137
+ ZSTD_DCtx_selectFrameDDict(zds);
2138
+ }
1684
2139
  if (ZSTD_isError(hSize)) {
1685
2140
  #if defined(ZSTD_LEGACY_SUPPORT) && (ZSTD_LEGACY_SUPPORT>=1)
1686
2141
  U32 const legacyVersion = ZSTD_isLegacy(istart, iend-istart);
@@ -1712,6 +2167,11 @@ size_t ZSTD_decompressStream(ZSTD_DStream* zds, ZSTD_outBuffer* output, ZSTD_inB
1712
2167
  zds->lhSize += remainingInput;
1713
2168
  }
1714
2169
  input->pos = input->size;
2170
+ /* check first few bytes */
2171
+ FORWARD_IF_ERROR(
2172
+ ZSTD_getFrameHeader_advanced(&zds->fParams, zds->headerBuffer, zds->lhSize, zds->format),
2173
+ "First few bytes detected incorrect" );
2174
+ /* return hint input size */
1715
2175
  return (MAX((size_t)ZSTD_FRAMEHEADERSIZE_MIN(zds->format), hSize) - zds->lhSize) + ZSTD_blockHeaderSize; /* remaining header bytes + next block header */
1716
2176
  }
1717
2177
  assert(ip != NULL);
@@ -1723,14 +2183,15 @@ size_t ZSTD_decompressStream(ZSTD_DStream* zds, ZSTD_outBuffer* output, ZSTD_inB
1723
2183
  if (zds->fParams.frameContentSize != ZSTD_CONTENTSIZE_UNKNOWN
1724
2184
  && zds->fParams.frameType != ZSTD_skippableFrame
1725
2185
  && (U64)(size_t)(oend-op) >= zds->fParams.frameContentSize) {
1726
- size_t const cSize = ZSTD_findFrameCompressedSize(istart, (size_t)(iend-istart));
2186
+ size_t const cSize = ZSTD_findFrameCompressedSize_advanced(istart, (size_t)(iend-istart), zds->format);
1727
2187
  if (cSize <= (size_t)(iend-istart)) {
1728
2188
  /* shortcut : using single-pass mode */
1729
2189
  size_t const decompressedSize = ZSTD_decompress_usingDDict(zds, op, (size_t)(oend-op), istart, cSize, ZSTD_getDDict(zds));
1730
2190
  if (ZSTD_isError(decompressedSize)) return decompressedSize;
1731
- DEBUGLOG(4, "shortcut to single-pass ZSTD_decompress_usingDDict()")
2191
+ DEBUGLOG(4, "shortcut to single-pass ZSTD_decompress_usingDDict()");
2192
+ assert(istart != NULL);
1732
2193
  ip = istart + cSize;
1733
- op += decompressedSize;
2194
+ op = op ? op + decompressedSize : op; /* can occur if frameContentSize = 0 (empty frame) */
1734
2195
  zds->expected = 0;
1735
2196
  zds->streamStage = zdss_init;
1736
2197
  someMoreWork = 0;
@@ -1749,7 +2210,8 @@ size_t ZSTD_decompressStream(ZSTD_DStream* zds, ZSTD_outBuffer* output, ZSTD_inB
1749
2210
  DEBUGLOG(4, "Consume header");
1750
2211
  FORWARD_IF_ERROR(ZSTD_decompressBegin_usingDDict(zds, ZSTD_getDDict(zds)), "");
1751
2212
 
1752
- if ((MEM_readLE32(zds->headerBuffer) & ZSTD_MAGIC_SKIPPABLE_MASK) == ZSTD_MAGIC_SKIPPABLE_START) { /* skippable frame */
2213
+ if (zds->format == ZSTD_f_zstd1
2214
+ && (MEM_readLE32(zds->headerBuffer) & ZSTD_MAGIC_SKIPPABLE_MASK) == ZSTD_MAGIC_SKIPPABLE_START) { /* skippable frame */
1753
2215
  zds->expected = MEM_readLE32(zds->headerBuffer + ZSTD_FRAMEIDSIZE);
1754
2216
  zds->stage = ZSTDds_skipFrame;
1755
2217
  } else {
@@ -1765,11 +2227,13 @@ size_t ZSTD_decompressStream(ZSTD_DStream* zds, ZSTD_outBuffer* output, ZSTD_inB
1765
2227
  zds->fParams.windowSize = MAX(zds->fParams.windowSize, 1U << ZSTD_WINDOWLOG_ABSOLUTEMIN);
1766
2228
  RETURN_ERROR_IF(zds->fParams.windowSize > zds->maxWindowSize,
1767
2229
  frameParameter_windowTooLarge, "");
2230
+ if (zds->maxBlockSizeParam != 0)
2231
+ zds->fParams.blockSizeMax = MIN(zds->fParams.blockSizeMax, (unsigned)zds->maxBlockSizeParam);
1768
2232
 
1769
2233
  /* Adapt buffer sizes to frame header instructions */
1770
2234
  { size_t const neededInBuffSize = MAX(zds->fParams.blockSizeMax, 4 /* frame checksum */);
1771
2235
  size_t const neededOutBuffSize = zds->outBufferMode == ZSTD_bm_buffered
1772
- ? ZSTD_decodingBufferSize_min(zds->fParams.windowSize, zds->fParams.frameContentSize)
2236
+ ? ZSTD_decodingBufferSize_internal(zds->fParams.windowSize, zds->fParams.frameContentSize, zds->fParams.blockSizeMax)
1773
2237
  : 0;
1774
2238
 
1775
2239
  ZSTD_DCtx_updateOversizedDuration(zds, neededInBuffSize, neededOutBuffSize);
@@ -1801,7 +2265,7 @@ size_t ZSTD_decompressStream(ZSTD_DStream* zds, ZSTD_outBuffer* output, ZSTD_inB
1801
2265
  zds->outBuffSize = neededOutBuffSize;
1802
2266
  } } }
1803
2267
  zds->streamStage = zdss_read;
1804
- /* fall-through */
2268
+ ZSTD_FALLTHROUGH;
1805
2269
 
1806
2270
  case zdss_read:
1807
2271
  DEBUGLOG(5, "stage zdss_read");
@@ -1814,13 +2278,14 @@ size_t ZSTD_decompressStream(ZSTD_DStream* zds, ZSTD_outBuffer* output, ZSTD_inB
1814
2278
  }
1815
2279
  if ((size_t)(iend-ip) >= neededInSize) { /* decode directly from src */
1816
2280
  FORWARD_IF_ERROR(ZSTD_decompressContinueStream(zds, &op, oend, ip, neededInSize), "");
2281
+ assert(ip != NULL);
1817
2282
  ip += neededInSize;
1818
2283
  /* Function modifies the stage so we must break */
1819
2284
  break;
1820
2285
  } }
1821
2286
  if (ip==iend) { someMoreWork = 0; break; } /* no more input */
1822
2287
  zds->streamStage = zdss_load;
1823
- /* fall-through */
2288
+ ZSTD_FALLTHROUGH;
1824
2289
 
1825
2290
  case zdss_load:
1826
2291
  { size_t const neededInSize = ZSTD_nextSrcSizeToDecompress(zds);
@@ -1828,7 +2293,7 @@ size_t ZSTD_decompressStream(ZSTD_DStream* zds, ZSTD_outBuffer* output, ZSTD_inB
1828
2293
  int const isSkipFrame = ZSTD_isSkipFrame(zds);
1829
2294
  size_t loadedSize;
1830
2295
  /* At this point we shouldn't be decompressing a block that we can stream. */
1831
- assert(neededInSize == ZSTD_nextSrcSizeToDecompressWithInputSize(zds, iend - ip));
2296
+ assert(neededInSize == ZSTD_nextSrcSizeToDecompressWithInputSize(zds, (size_t)(iend - ip)));
1832
2297
  if (isSkipFrame) {
1833
2298
  loadedSize = MIN(toLoad, (size_t)(iend-ip));
1834
2299
  } else {
@@ -1837,8 +2302,11 @@ size_t ZSTD_decompressStream(ZSTD_DStream* zds, ZSTD_outBuffer* output, ZSTD_inB
1837
2302
  "should never happen");
1838
2303
  loadedSize = ZSTD_limitCopy(zds->inBuff + zds->inPos, toLoad, ip, (size_t)(iend-ip));
1839
2304
  }
1840
- ip += loadedSize;
1841
- zds->inPos += loadedSize;
2305
+ if (loadedSize != 0) {
2306
+ /* ip may be NULL */
2307
+ ip += loadedSize;
2308
+ zds->inPos += loadedSize;
2309
+ }
1842
2310
  if (loadedSize < toLoad) { someMoreWork = 0; break; } /* not enough input, wait for more */
1843
2311
 
1844
2312
  /* decode loaded input */
@@ -1848,14 +2316,17 @@ size_t ZSTD_decompressStream(ZSTD_DStream* zds, ZSTD_outBuffer* output, ZSTD_inB
1848
2316
  break;
1849
2317
  }
1850
2318
  case zdss_flush:
1851
- { size_t const toFlushSize = zds->outEnd - zds->outStart;
2319
+ {
2320
+ size_t const toFlushSize = zds->outEnd - zds->outStart;
1852
2321
  size_t const flushedSize = ZSTD_limitCopy(op, (size_t)(oend-op), zds->outBuff + zds->outStart, toFlushSize);
1853
- op += flushedSize;
2322
+
2323
+ op = op ? op + flushedSize : op;
2324
+
1854
2325
  zds->outStart += flushedSize;
1855
2326
  if (flushedSize == toFlushSize) { /* flush completed */
1856
2327
  zds->streamStage = zdss_read;
1857
2328
  if ( (zds->outBuffSize < zds->fParams.frameContentSize)
1858
- && (zds->outStart + zds->fParams.blockSizeMax > zds->outBuffSize) ) {
2329
+ && (zds->outStart + zds->fParams.blockSizeMax > zds->outBuffSize) ) {
1859
2330
  DEBUGLOG(5, "restart filling outBuff from beginning (left:%i, needed:%u)",
1860
2331
  (int)(zds->outBuffSize - zds->outStart),
1861
2332
  (U32)zds->fParams.blockSizeMax);
@@ -1869,7 +2340,7 @@ size_t ZSTD_decompressStream(ZSTD_DStream* zds, ZSTD_outBuffer* output, ZSTD_inB
1869
2340
 
1870
2341
  default:
1871
2342
  assert(0); /* impossible */
1872
- RETURN_ERROR(GENERIC, "impossible to reach"); /* some compiler require default to do something */
2343
+ RETURN_ERROR(GENERIC, "impossible to reach"); /* some compilers require default to do something */
1873
2344
  } }
1874
2345
 
1875
2346
  /* result */
@@ -1882,8 +2353,8 @@ size_t ZSTD_decompressStream(ZSTD_DStream* zds, ZSTD_outBuffer* output, ZSTD_inB
1882
2353
  if ((ip==istart) && (op==ostart)) { /* no forward progress */
1883
2354
  zds->noForwardProgress ++;
1884
2355
  if (zds->noForwardProgress >= ZSTD_NO_FORWARD_PROGRESS_MAX) {
1885
- RETURN_ERROR_IF(op==oend, dstSize_tooSmall, "");
1886
- RETURN_ERROR_IF(ip==iend, srcSize_wrong, "");
2356
+ RETURN_ERROR_IF(op==oend, noForwardProgress_destFull, "");
2357
+ RETURN_ERROR_IF(ip==iend, noForwardProgress_inputEmpty, "");
1887
2358
  assert(0);
1888
2359
  }
1889
2360
  } else {
@@ -1920,11 +2391,17 @@ size_t ZSTD_decompressStream_simpleArgs (
1920
2391
  void* dst, size_t dstCapacity, size_t* dstPos,
1921
2392
  const void* src, size_t srcSize, size_t* srcPos)
1922
2393
  {
1923
- ZSTD_outBuffer output = { dst, dstCapacity, *dstPos };
1924
- ZSTD_inBuffer input = { src, srcSize, *srcPos };
1925
- /* ZSTD_compress_generic() will check validity of dstPos and srcPos */
1926
- size_t const cErr = ZSTD_decompressStream(dctx, &output, &input);
1927
- *dstPos = output.pos;
1928
- *srcPos = input.pos;
1929
- return cErr;
2394
+ ZSTD_outBuffer output;
2395
+ ZSTD_inBuffer input;
2396
+ output.dst = dst;
2397
+ output.size = dstCapacity;
2398
+ output.pos = *dstPos;
2399
+ input.src = src;
2400
+ input.size = srcSize;
2401
+ input.pos = *srcPos;
2402
+ { size_t const cErr = ZSTD_decompressStream(dctx, &output, &input);
2403
+ *dstPos = output.pos;
2404
+ *srcPos = input.pos;
2405
+ return cErr;
2406
+ }
1930
2407
  }