zstd-ruby 1.4.4.0 → 1.5.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (102) hide show
  1. checksums.yaml +4 -4
  2. data/.github/dependabot.yml +8 -0
  3. data/.github/workflows/ruby.yml +35 -0
  4. data/README.md +2 -2
  5. data/ext/zstdruby/extconf.rb +1 -0
  6. data/ext/zstdruby/libzstd/BUCK +5 -7
  7. data/ext/zstdruby/libzstd/Makefile +241 -173
  8. data/ext/zstdruby/libzstd/README.md +76 -18
  9. data/ext/zstdruby/libzstd/common/bitstream.h +75 -57
  10. data/ext/zstdruby/libzstd/common/compiler.h +196 -20
  11. data/ext/zstdruby/libzstd/common/cpu.h +1 -3
  12. data/ext/zstdruby/libzstd/common/debug.c +11 -31
  13. data/ext/zstdruby/libzstd/common/debug.h +22 -49
  14. data/ext/zstdruby/libzstd/common/entropy_common.c +208 -76
  15. data/ext/zstdruby/libzstd/common/error_private.c +3 -1
  16. data/ext/zstdruby/libzstd/common/error_private.h +87 -4
  17. data/ext/zstdruby/libzstd/common/fse.h +51 -42
  18. data/ext/zstdruby/libzstd/common/fse_decompress.c +149 -57
  19. data/ext/zstdruby/libzstd/common/huf.h +60 -54
  20. data/ext/zstdruby/libzstd/common/mem.h +87 -98
  21. data/ext/zstdruby/libzstd/common/pool.c +23 -17
  22. data/ext/zstdruby/libzstd/common/pool.h +3 -3
  23. data/ext/zstdruby/libzstd/common/portability_macros.h +131 -0
  24. data/ext/zstdruby/libzstd/common/threading.c +10 -8
  25. data/ext/zstdruby/libzstd/common/threading.h +4 -3
  26. data/ext/zstdruby/libzstd/common/xxhash.c +15 -873
  27. data/ext/zstdruby/libzstd/common/xxhash.h +5572 -191
  28. data/ext/zstdruby/libzstd/common/zstd_common.c +10 -10
  29. data/ext/zstdruby/libzstd/common/zstd_deps.h +111 -0
  30. data/ext/zstdruby/libzstd/common/zstd_internal.h +252 -108
  31. data/ext/zstdruby/libzstd/common/zstd_trace.h +163 -0
  32. data/ext/zstdruby/libzstd/compress/clevels.h +134 -0
  33. data/ext/zstdruby/libzstd/compress/fse_compress.c +105 -85
  34. data/ext/zstdruby/libzstd/compress/hist.c +41 -63
  35. data/ext/zstdruby/libzstd/compress/hist.h +13 -33
  36. data/ext/zstdruby/libzstd/compress/huf_compress.c +831 -259
  37. data/ext/zstdruby/libzstd/compress/zstd_compress.c +3213 -1007
  38. data/ext/zstdruby/libzstd/compress/zstd_compress_internal.h +493 -71
  39. data/ext/zstdruby/libzstd/compress/zstd_compress_literals.c +21 -16
  40. data/ext/zstdruby/libzstd/compress/zstd_compress_literals.h +4 -2
  41. data/ext/zstdruby/libzstd/compress/zstd_compress_sequences.c +51 -24
  42. data/ext/zstdruby/libzstd/compress/zstd_compress_sequences.h +10 -3
  43. data/ext/zstdruby/libzstd/compress/zstd_compress_superblock.c +573 -0
  44. data/ext/zstdruby/libzstd/compress/zstd_compress_superblock.h +32 -0
  45. data/ext/zstdruby/libzstd/compress/zstd_cwksp.h +208 -81
  46. data/ext/zstdruby/libzstd/compress/zstd_double_fast.c +315 -137
  47. data/ext/zstdruby/libzstd/compress/zstd_double_fast.h +2 -2
  48. data/ext/zstdruby/libzstd/compress/zstd_fast.c +319 -128
  49. data/ext/zstdruby/libzstd/compress/zstd_fast.h +2 -2
  50. data/ext/zstdruby/libzstd/compress/zstd_lazy.c +1156 -171
  51. data/ext/zstdruby/libzstd/compress/zstd_lazy.h +59 -1
  52. data/ext/zstdruby/libzstd/compress/zstd_ldm.c +331 -206
  53. data/ext/zstdruby/libzstd/compress/zstd_ldm.h +15 -3
  54. data/ext/zstdruby/libzstd/compress/zstd_ldm_geartab.h +106 -0
  55. data/ext/zstdruby/libzstd/compress/zstd_opt.c +403 -226
  56. data/ext/zstdruby/libzstd/compress/zstd_opt.h +1 -1
  57. data/ext/zstdruby/libzstd/compress/zstdmt_compress.c +188 -453
  58. data/ext/zstdruby/libzstd/compress/zstdmt_compress.h +32 -114
  59. data/ext/zstdruby/libzstd/decompress/huf_decompress.c +1065 -410
  60. data/ext/zstdruby/libzstd/decompress/huf_decompress_amd64.S +571 -0
  61. data/ext/zstdruby/libzstd/decompress/zstd_ddict.c +20 -16
  62. data/ext/zstdruby/libzstd/decompress/zstd_ddict.h +3 -3
  63. data/ext/zstdruby/libzstd/decompress/zstd_decompress.c +691 -230
  64. data/ext/zstdruby/libzstd/decompress/zstd_decompress_block.c +1072 -323
  65. data/ext/zstdruby/libzstd/decompress/zstd_decompress_block.h +16 -7
  66. data/ext/zstdruby/libzstd/decompress/zstd_decompress_internal.h +71 -10
  67. data/ext/zstdruby/libzstd/deprecated/zbuff.h +3 -3
  68. data/ext/zstdruby/libzstd/deprecated/zbuff_common.c +2 -2
  69. data/ext/zstdruby/libzstd/deprecated/zbuff_compress.c +24 -4
  70. data/ext/zstdruby/libzstd/deprecated/zbuff_decompress.c +1 -1
  71. data/ext/zstdruby/libzstd/dictBuilder/cover.c +57 -40
  72. data/ext/zstdruby/libzstd/dictBuilder/cover.h +20 -9
  73. data/ext/zstdruby/libzstd/dictBuilder/divsufsort.c +1 -1
  74. data/ext/zstdruby/libzstd/dictBuilder/fastcover.c +54 -35
  75. data/ext/zstdruby/libzstd/dictBuilder/zdict.c +151 -57
  76. data/ext/zstdruby/libzstd/dll/example/Makefile +2 -1
  77. data/ext/zstdruby/libzstd/dll/example/README.md +16 -22
  78. data/ext/zstdruby/libzstd/legacy/zstd_legacy.h +4 -4
  79. data/ext/zstdruby/libzstd/legacy/zstd_v01.c +25 -19
  80. data/ext/zstdruby/libzstd/legacy/zstd_v01.h +1 -1
  81. data/ext/zstdruby/libzstd/legacy/zstd_v02.c +18 -14
  82. data/ext/zstdruby/libzstd/legacy/zstd_v02.h +1 -1
  83. data/ext/zstdruby/libzstd/legacy/zstd_v03.c +18 -14
  84. data/ext/zstdruby/libzstd/legacy/zstd_v03.h +1 -1
  85. data/ext/zstdruby/libzstd/legacy/zstd_v04.c +22 -16
  86. data/ext/zstdruby/libzstd/legacy/zstd_v04.h +1 -1
  87. data/ext/zstdruby/libzstd/legacy/zstd_v05.c +29 -25
  88. data/ext/zstdruby/libzstd/legacy/zstd_v05.h +2 -2
  89. data/ext/zstdruby/libzstd/legacy/zstd_v06.c +29 -25
  90. data/ext/zstdruby/libzstd/legacy/zstd_v06.h +1 -1
  91. data/ext/zstdruby/libzstd/legacy/zstd_v07.c +34 -26
  92. data/ext/zstdruby/libzstd/legacy/zstd_v07.h +1 -1
  93. data/ext/zstdruby/libzstd/libzstd.mk +185 -0
  94. data/ext/zstdruby/libzstd/libzstd.pc.in +4 -3
  95. data/ext/zstdruby/libzstd/modulemap/module.modulemap +4 -0
  96. data/ext/zstdruby/libzstd/{dictBuilder/zdict.h → zdict.h} +201 -31
  97. data/ext/zstdruby/libzstd/zstd.h +760 -234
  98. data/ext/zstdruby/libzstd/{common/zstd_errors.h → zstd_errors.h} +3 -1
  99. data/ext/zstdruby/zstdruby.c +2 -2
  100. data/lib/zstd-ruby/version.rb +1 -1
  101. metadata +20 -9
  102. data/.travis.yml +0 -14
@@ -1,5 +1,5 @@
1
1
  /*
2
- * Copyright (c) 2016-present, Yann Collet, Facebook, Inc.
2
+ * Copyright (c) Yann Collet, Facebook, Inc.
3
3
  * All rights reserved.
4
4
  *
5
5
  * This source code is licensed under both the BSD-style license (found in the
@@ -55,23 +55,164 @@
55
55
  /*-*******************************************************
56
56
  * Dependencies
57
57
  *********************************************************/
58
- #include <string.h> /* memcpy, memmove, memset */
59
- #include "cpu.h" /* bmi2 */
60
- #include "mem.h" /* low level memory routines */
58
+ #include "../common/zstd_deps.h" /* ZSTD_memcpy, ZSTD_memmove, ZSTD_memset */
59
+ #include "../common/mem.h" /* low level memory routines */
61
60
  #define FSE_STATIC_LINKING_ONLY
62
- #include "fse.h"
61
+ #include "../common/fse.h"
63
62
  #define HUF_STATIC_LINKING_ONLY
64
- #include "huf.h"
65
- #include "zstd_internal.h" /* blockProperties_t */
63
+ #include "../common/huf.h"
64
+ #include "../common/xxhash.h" /* XXH64_reset, XXH64_update, XXH64_digest, XXH64 */
65
+ #include "../common/zstd_internal.h" /* blockProperties_t */
66
66
  #include "zstd_decompress_internal.h" /* ZSTD_DCtx */
67
67
  #include "zstd_ddict.h" /* ZSTD_DDictDictContent */
68
68
  #include "zstd_decompress_block.h" /* ZSTD_decompressBlock_internal */
69
69
 
70
70
  #if defined(ZSTD_LEGACY_SUPPORT) && (ZSTD_LEGACY_SUPPORT>=1)
71
- # include "zstd_legacy.h"
71
+ # include "../legacy/zstd_legacy.h"
72
72
  #endif
73
73
 
74
74
 
75
+
76
+ /*************************************
77
+ * Multiple DDicts Hashset internals *
78
+ *************************************/
79
+
80
+ #define DDICT_HASHSET_MAX_LOAD_FACTOR_COUNT_MULT 4
81
+ #define DDICT_HASHSET_MAX_LOAD_FACTOR_SIZE_MULT 3 /* These two constants represent SIZE_MULT/COUNT_MULT load factor without using a float.
82
+ * Currently, that means a 0.75 load factor.
83
+ * So, if count * COUNT_MULT / size * SIZE_MULT != 0, then we've exceeded
84
+ * the load factor of the ddict hash set.
85
+ */
86
+
87
+ #define DDICT_HASHSET_TABLE_BASE_SIZE 64
88
+ #define DDICT_HASHSET_RESIZE_FACTOR 2
89
+
90
+ /* Hash function to determine starting position of dict insertion within the table
91
+ * Returns an index between [0, hashSet->ddictPtrTableSize]
92
+ */
93
+ static size_t ZSTD_DDictHashSet_getIndex(const ZSTD_DDictHashSet* hashSet, U32 dictID) {
94
+ const U64 hash = XXH64(&dictID, sizeof(U32), 0);
95
+ /* DDict ptr table size is a multiple of 2, use size - 1 as mask to get index within [0, hashSet->ddictPtrTableSize) */
96
+ return hash & (hashSet->ddictPtrTableSize - 1);
97
+ }
98
+
99
+ /* Adds DDict to a hashset without resizing it.
100
+ * If inserting a DDict with a dictID that already exists in the set, replaces the one in the set.
101
+ * Returns 0 if successful, or a zstd error code if something went wrong.
102
+ */
103
+ static size_t ZSTD_DDictHashSet_emplaceDDict(ZSTD_DDictHashSet* hashSet, const ZSTD_DDict* ddict) {
104
+ const U32 dictID = ZSTD_getDictID_fromDDict(ddict);
105
+ size_t idx = ZSTD_DDictHashSet_getIndex(hashSet, dictID);
106
+ const size_t idxRangeMask = hashSet->ddictPtrTableSize - 1;
107
+ RETURN_ERROR_IF(hashSet->ddictPtrCount == hashSet->ddictPtrTableSize, GENERIC, "Hash set is full!");
108
+ DEBUGLOG(4, "Hashed index: for dictID: %u is %zu", dictID, idx);
109
+ while (hashSet->ddictPtrTable[idx] != NULL) {
110
+ /* Replace existing ddict if inserting ddict with same dictID */
111
+ if (ZSTD_getDictID_fromDDict(hashSet->ddictPtrTable[idx]) == dictID) {
112
+ DEBUGLOG(4, "DictID already exists, replacing rather than adding");
113
+ hashSet->ddictPtrTable[idx] = ddict;
114
+ return 0;
115
+ }
116
+ idx &= idxRangeMask;
117
+ idx++;
118
+ }
119
+ DEBUGLOG(4, "Final idx after probing for dictID %u is: %zu", dictID, idx);
120
+ hashSet->ddictPtrTable[idx] = ddict;
121
+ hashSet->ddictPtrCount++;
122
+ return 0;
123
+ }
124
+
125
+ /* Expands hash table by factor of DDICT_HASHSET_RESIZE_FACTOR and
126
+ * rehashes all values, allocates new table, frees old table.
127
+ * Returns 0 on success, otherwise a zstd error code.
128
+ */
129
+ static size_t ZSTD_DDictHashSet_expand(ZSTD_DDictHashSet* hashSet, ZSTD_customMem customMem) {
130
+ size_t newTableSize = hashSet->ddictPtrTableSize * DDICT_HASHSET_RESIZE_FACTOR;
131
+ const ZSTD_DDict** newTable = (const ZSTD_DDict**)ZSTD_customCalloc(sizeof(ZSTD_DDict*) * newTableSize, customMem);
132
+ const ZSTD_DDict** oldTable = hashSet->ddictPtrTable;
133
+ size_t oldTableSize = hashSet->ddictPtrTableSize;
134
+ size_t i;
135
+
136
+ DEBUGLOG(4, "Expanding DDict hash table! Old size: %zu new size: %zu", oldTableSize, newTableSize);
137
+ RETURN_ERROR_IF(!newTable, memory_allocation, "Expanded hashset allocation failed!");
138
+ hashSet->ddictPtrTable = newTable;
139
+ hashSet->ddictPtrTableSize = newTableSize;
140
+ hashSet->ddictPtrCount = 0;
141
+ for (i = 0; i < oldTableSize; ++i) {
142
+ if (oldTable[i] != NULL) {
143
+ FORWARD_IF_ERROR(ZSTD_DDictHashSet_emplaceDDict(hashSet, oldTable[i]), "");
144
+ }
145
+ }
146
+ ZSTD_customFree((void*)oldTable, customMem);
147
+ DEBUGLOG(4, "Finished re-hash");
148
+ return 0;
149
+ }
150
+
151
+ /* Fetches a DDict with the given dictID
152
+ * Returns the ZSTD_DDict* with the requested dictID. If it doesn't exist, then returns NULL.
153
+ */
154
+ static const ZSTD_DDict* ZSTD_DDictHashSet_getDDict(ZSTD_DDictHashSet* hashSet, U32 dictID) {
155
+ size_t idx = ZSTD_DDictHashSet_getIndex(hashSet, dictID);
156
+ const size_t idxRangeMask = hashSet->ddictPtrTableSize - 1;
157
+ DEBUGLOG(4, "Hashed index: for dictID: %u is %zu", dictID, idx);
158
+ for (;;) {
159
+ size_t currDictID = ZSTD_getDictID_fromDDict(hashSet->ddictPtrTable[idx]);
160
+ if (currDictID == dictID || currDictID == 0) {
161
+ /* currDictID == 0 implies a NULL ddict entry */
162
+ break;
163
+ } else {
164
+ idx &= idxRangeMask; /* Goes to start of table when we reach the end */
165
+ idx++;
166
+ }
167
+ }
168
+ DEBUGLOG(4, "Final idx after probing for dictID %u is: %zu", dictID, idx);
169
+ return hashSet->ddictPtrTable[idx];
170
+ }
171
+
172
+ /* Allocates space for and returns a ddict hash set
173
+ * The hash set's ZSTD_DDict* table has all values automatically set to NULL to begin with.
174
+ * Returns NULL if allocation failed.
175
+ */
176
+ static ZSTD_DDictHashSet* ZSTD_createDDictHashSet(ZSTD_customMem customMem) {
177
+ ZSTD_DDictHashSet* ret = (ZSTD_DDictHashSet*)ZSTD_customMalloc(sizeof(ZSTD_DDictHashSet), customMem);
178
+ DEBUGLOG(4, "Allocating new hash set");
179
+ if (!ret)
180
+ return NULL;
181
+ ret->ddictPtrTable = (const ZSTD_DDict**)ZSTD_customCalloc(DDICT_HASHSET_TABLE_BASE_SIZE * sizeof(ZSTD_DDict*), customMem);
182
+ if (!ret->ddictPtrTable) {
183
+ ZSTD_customFree(ret, customMem);
184
+ return NULL;
185
+ }
186
+ ret->ddictPtrTableSize = DDICT_HASHSET_TABLE_BASE_SIZE;
187
+ ret->ddictPtrCount = 0;
188
+ return ret;
189
+ }
190
+
191
+ /* Frees the table of ZSTD_DDict* within a hashset, then frees the hashset itself.
192
+ * Note: The ZSTD_DDict* within the table are NOT freed.
193
+ */
194
+ static void ZSTD_freeDDictHashSet(ZSTD_DDictHashSet* hashSet, ZSTD_customMem customMem) {
195
+ DEBUGLOG(4, "Freeing ddict hash set");
196
+ if (hashSet && hashSet->ddictPtrTable) {
197
+ ZSTD_customFree((void*)hashSet->ddictPtrTable, customMem);
198
+ }
199
+ if (hashSet) {
200
+ ZSTD_customFree(hashSet, customMem);
201
+ }
202
+ }
203
+
204
+ /* Public function: Adds a DDict into the ZSTD_DDictHashSet, possibly triggering a resize of the hash set.
205
+ * Returns 0 on success, or a ZSTD error.
206
+ */
207
+ static size_t ZSTD_DDictHashSet_addDDict(ZSTD_DDictHashSet* hashSet, const ZSTD_DDict* ddict, ZSTD_customMem customMem) {
208
+ DEBUGLOG(4, "Adding dict ID: %u to hashset with - Count: %zu Tablesize: %zu", ZSTD_getDictID_fromDDict(ddict), hashSet->ddictPtrCount, hashSet->ddictPtrTableSize);
209
+ if (hashSet->ddictPtrCount * DDICT_HASHSET_MAX_LOAD_FACTOR_COUNT_MULT / hashSet->ddictPtrTableSize * DDICT_HASHSET_MAX_LOAD_FACTOR_SIZE_MULT != 0) {
210
+ FORWARD_IF_ERROR(ZSTD_DDictHashSet_expand(hashSet, customMem), "");
211
+ }
212
+ FORWARD_IF_ERROR(ZSTD_DDictHashSet_emplaceDDict(hashSet, ddict), "");
213
+ return 0;
214
+ }
215
+
75
216
  /*-*************************************************************
76
217
  * Context management
77
218
  ***************************************************************/
@@ -94,11 +235,19 @@ static size_t ZSTD_startingInputLength(ZSTD_format_e format)
94
235
  return startingInputLength;
95
236
  }
96
237
 
238
+ static void ZSTD_DCtx_resetParameters(ZSTD_DCtx* dctx)
239
+ {
240
+ assert(dctx->streamStage == zdss_init);
241
+ dctx->format = ZSTD_f_zstd1;
242
+ dctx->maxWindowSize = ZSTD_MAXWINDOWSIZE_DEFAULT;
243
+ dctx->outBufferMode = ZSTD_bm_buffered;
244
+ dctx->forceIgnoreChecksum = ZSTD_d_validateChecksum;
245
+ dctx->refMultipleDDicts = ZSTD_rmd_refSingleDDict;
246
+ }
247
+
97
248
  static void ZSTD_initDCtx_internal(ZSTD_DCtx* dctx)
98
249
  {
99
- dctx->format = ZSTD_f_zstd1; /* ZSTD_decompressBegin() invokes ZSTD_startingInputLength() with argument dctx->format */
100
250
  dctx->staticSize = 0;
101
- dctx->maxWindowSize = ZSTD_MAXWINDOWSIZE_DEFAULT;
102
251
  dctx->ddict = NULL;
103
252
  dctx->ddictLocal = NULL;
104
253
  dctx->dictEnd = NULL;
@@ -108,10 +257,20 @@ static void ZSTD_initDCtx_internal(ZSTD_DCtx* dctx)
108
257
  dctx->inBuffSize = 0;
109
258
  dctx->outBuffSize = 0;
110
259
  dctx->streamStage = zdss_init;
260
+ #if defined(ZSTD_LEGACY_SUPPORT) && (ZSTD_LEGACY_SUPPORT>=1)
111
261
  dctx->legacyContext = NULL;
112
262
  dctx->previousLegacyVersion = 0;
263
+ #endif
113
264
  dctx->noForwardProgress = 0;
114
- dctx->bmi2 = ZSTD_cpuid_bmi2(ZSTD_cpuid());
265
+ dctx->oversizedDuration = 0;
266
+ #if DYNAMIC_BMI2
267
+ dctx->bmi2 = ZSTD_cpuSupportsBmi2();
268
+ #endif
269
+ dctx->ddictSet = NULL;
270
+ ZSTD_DCtx_resetParameters(dctx);
271
+ #ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
272
+ dctx->dictContentEndForFuzzing = NULL;
273
+ #endif
115
274
  }
116
275
 
117
276
  ZSTD_DCtx* ZSTD_initStaticDCtx(void *workspace, size_t workspaceSize)
@@ -127,11 +286,10 @@ ZSTD_DCtx* ZSTD_initStaticDCtx(void *workspace, size_t workspaceSize)
127
286
  return dctx;
128
287
  }
129
288
 
130
- ZSTD_DCtx* ZSTD_createDCtx_advanced(ZSTD_customMem customMem)
131
- {
132
- if (!customMem.customAlloc ^ !customMem.customFree) return NULL;
289
+ static ZSTD_DCtx* ZSTD_createDCtx_internal(ZSTD_customMem customMem) {
290
+ if ((!customMem.customAlloc) ^ (!customMem.customFree)) return NULL;
133
291
 
134
- { ZSTD_DCtx* const dctx = (ZSTD_DCtx*)ZSTD_malloc(sizeof(*dctx), customMem);
292
+ { ZSTD_DCtx* const dctx = (ZSTD_DCtx*)ZSTD_customMalloc(sizeof(*dctx), customMem);
135
293
  if (!dctx) return NULL;
136
294
  dctx->customMem = customMem;
137
295
  ZSTD_initDCtx_internal(dctx);
@@ -139,10 +297,15 @@ ZSTD_DCtx* ZSTD_createDCtx_advanced(ZSTD_customMem customMem)
139
297
  }
140
298
  }
141
299
 
300
+ ZSTD_DCtx* ZSTD_createDCtx_advanced(ZSTD_customMem customMem)
301
+ {
302
+ return ZSTD_createDCtx_internal(customMem);
303
+ }
304
+
142
305
  ZSTD_DCtx* ZSTD_createDCtx(void)
143
306
  {
144
307
  DEBUGLOG(3, "ZSTD_createDCtx");
145
- return ZSTD_createDCtx_advanced(ZSTD_defaultCMem);
308
+ return ZSTD_createDCtx_internal(ZSTD_defaultCMem);
146
309
  }
147
310
 
148
311
  static void ZSTD_clearDict(ZSTD_DCtx* dctx)
@@ -159,13 +322,17 @@ size_t ZSTD_freeDCtx(ZSTD_DCtx* dctx)
159
322
  RETURN_ERROR_IF(dctx->staticSize, memory_allocation, "not compatible with static DCtx");
160
323
  { ZSTD_customMem const cMem = dctx->customMem;
161
324
  ZSTD_clearDict(dctx);
162
- ZSTD_free(dctx->inBuff, cMem);
325
+ ZSTD_customFree(dctx->inBuff, cMem);
163
326
  dctx->inBuff = NULL;
164
327
  #if defined(ZSTD_LEGACY_SUPPORT) && (ZSTD_LEGACY_SUPPORT >= 1)
165
328
  if (dctx->legacyContext)
166
329
  ZSTD_freeLegacyStreamContext(dctx->legacyContext, dctx->previousLegacyVersion);
167
330
  #endif
168
- ZSTD_free(dctx, cMem);
331
+ if (dctx->ddictSet) {
332
+ ZSTD_freeDDictHashSet(dctx->ddictSet, cMem);
333
+ dctx->ddictSet = NULL;
334
+ }
335
+ ZSTD_customFree(dctx, cMem);
169
336
  return 0;
170
337
  }
171
338
  }
@@ -174,7 +341,30 @@ size_t ZSTD_freeDCtx(ZSTD_DCtx* dctx)
174
341
  void ZSTD_copyDCtx(ZSTD_DCtx* dstDCtx, const ZSTD_DCtx* srcDCtx)
175
342
  {
176
343
  size_t const toCopy = (size_t)((char*)(&dstDCtx->inBuff) - (char*)dstDCtx);
177
- memcpy(dstDCtx, srcDCtx, toCopy); /* no need to copy workspace */
344
+ ZSTD_memcpy(dstDCtx, srcDCtx, toCopy); /* no need to copy workspace */
345
+ }
346
+
347
+ /* Given a dctx with a digested frame params, re-selects the correct ZSTD_DDict based on
348
+ * the requested dict ID from the frame. If there exists a reference to the correct ZSTD_DDict, then
349
+ * accordingly sets the ddict to be used to decompress the frame.
350
+ *
351
+ * If no DDict is found, then no action is taken, and the ZSTD_DCtx::ddict remains as-is.
352
+ *
353
+ * ZSTD_d_refMultipleDDicts must be enabled for this function to be called.
354
+ */
355
+ static void ZSTD_DCtx_selectFrameDDict(ZSTD_DCtx* dctx) {
356
+ assert(dctx->refMultipleDDicts && dctx->ddictSet);
357
+ DEBUGLOG(4, "Adjusting DDict based on requested dict ID from frame");
358
+ if (dctx->ddict) {
359
+ const ZSTD_DDict* frameDDict = ZSTD_DDictHashSet_getDDict(dctx->ddictSet, dctx->fParams.dictID);
360
+ if (frameDDict) {
361
+ DEBUGLOG(4, "DDict found!");
362
+ ZSTD_clearDict(dctx);
363
+ dctx->dictID = dctx->fParams.dictID;
364
+ dctx->ddict = frameDDict;
365
+ dctx->dictUses = ZSTD_use_indefinitely;
366
+ }
367
+ }
178
368
  }
179
369
 
180
370
 
@@ -200,6 +390,19 @@ unsigned ZSTD_isFrame(const void* buffer, size_t size)
200
390
  return 0;
201
391
  }
202
392
 
393
+ /*! ZSTD_isSkippableFrame() :
394
+ * Tells if the content of `buffer` starts with a valid Frame Identifier for a skippable frame.
395
+ * Note : Frame Identifier is 4 bytes. If `size < 4`, @return will always be 0.
396
+ */
397
+ unsigned ZSTD_isSkippableFrame(const void* buffer, size_t size)
398
+ {
399
+ if (size < ZSTD_FRAMEIDSIZE) return 0;
400
+ { U32 const magic = MEM_readLE32(buffer);
401
+ if ((magic & ZSTD_MAGIC_SKIPPABLE_MASK) == ZSTD_MAGIC_SKIPPABLE_START) return 1;
402
+ }
403
+ return 0;
404
+ }
405
+
203
406
  /** ZSTD_frameHeaderSize_internal() :
204
407
  * srcSize must be large enough to reach header size fields.
205
408
  * note : only works for formats ZSTD_f_zstd1 and ZSTD_f_zstd1_magicless.
@@ -208,7 +411,7 @@ unsigned ZSTD_isFrame(const void* buffer, size_t size)
208
411
  static size_t ZSTD_frameHeaderSize_internal(const void* src, size_t srcSize, ZSTD_format_e format)
209
412
  {
210
413
  size_t const minInputSize = ZSTD_startingInputLength(format);
211
- RETURN_ERROR_IF(srcSize < minInputSize, srcSize_wrong);
414
+ RETURN_ERROR_IF(srcSize < minInputSize, srcSize_wrong, "");
212
415
 
213
416
  { BYTE const fhd = ((const BYTE*)src)[minInputSize-1];
214
417
  U32 const dictID= fhd & 3;
@@ -241,7 +444,7 @@ size_t ZSTD_getFrameHeader_advanced(ZSTD_frameHeader* zfhPtr, const void* src, s
241
444
  const BYTE* ip = (const BYTE*)src;
242
445
  size_t const minInputSize = ZSTD_startingInputLength(format);
243
446
 
244
- 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 */
447
+ 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 */
245
448
  if (srcSize < minInputSize) return minInputSize;
246
449
  RETURN_ERROR_IF(src==NULL, GENERIC, "invalid parameter");
247
450
 
@@ -251,12 +454,12 @@ size_t ZSTD_getFrameHeader_advanced(ZSTD_frameHeader* zfhPtr, const void* src, s
251
454
  /* skippable frame */
252
455
  if (srcSize < ZSTD_SKIPPABLEHEADERSIZE)
253
456
  return ZSTD_SKIPPABLEHEADERSIZE; /* magic number + frame length */
254
- memset(zfhPtr, 0, sizeof(*zfhPtr));
457
+ ZSTD_memset(zfhPtr, 0, sizeof(*zfhPtr));
255
458
  zfhPtr->frameContentSize = MEM_readLE32((const char *)src + ZSTD_FRAMEIDSIZE);
256
459
  zfhPtr->frameType = ZSTD_skippableFrame;
257
460
  return 0;
258
461
  }
259
- RETURN_ERROR(prefix_unknown);
462
+ RETURN_ERROR(prefix_unknown, "");
260
463
  }
261
464
 
262
465
  /* ensure there is enough `srcSize` to fully read/decode frame header */
@@ -280,13 +483,15 @@ size_t ZSTD_getFrameHeader_advanced(ZSTD_frameHeader* zfhPtr, const void* src, s
280
483
  if (!singleSegment) {
281
484
  BYTE const wlByte = ip[pos++];
282
485
  U32 const windowLog = (wlByte >> 3) + ZSTD_WINDOWLOG_ABSOLUTEMIN;
283
- RETURN_ERROR_IF(windowLog > ZSTD_WINDOWLOG_MAX, frameParameter_windowTooLarge);
486
+ RETURN_ERROR_IF(windowLog > ZSTD_WINDOWLOG_MAX, frameParameter_windowTooLarge, "");
284
487
  windowSize = (1ULL << windowLog);
285
488
  windowSize += (windowSize >> 3) * (wlByte&7);
286
489
  }
287
490
  switch(dictIDSizeCode)
288
491
  {
289
- default: assert(0); /* impossible */
492
+ default:
493
+ assert(0); /* impossible */
494
+ ZSTD_FALLTHROUGH;
290
495
  case 0 : break;
291
496
  case 1 : dictID = ip[pos]; pos++; break;
292
497
  case 2 : dictID = MEM_readLE16(ip+pos); pos+=2; break;
@@ -294,7 +499,9 @@ size_t ZSTD_getFrameHeader_advanced(ZSTD_frameHeader* zfhPtr, const void* src, s
294
499
  }
295
500
  switch(fcsID)
296
501
  {
297
- default: assert(0); /* impossible */
502
+ default:
503
+ assert(0); /* impossible */
504
+ ZSTD_FALLTHROUGH;
298
505
  case 0 : if (singleSegment) frameContentSize = ip[pos]; break;
299
506
  case 1 : frameContentSize = MEM_readLE16(ip+pos)+256; break;
300
507
  case 2 : frameContentSize = MEM_readLE32(ip+pos); break;
@@ -323,7 +530,6 @@ size_t ZSTD_getFrameHeader(ZSTD_frameHeader* zfhPtr, const void* src, size_t src
323
530
  return ZSTD_getFrameHeader_advanced(zfhPtr, src, srcSize, ZSTD_f_zstd1);
324
531
  }
325
532
 
326
-
327
533
  /** ZSTD_getFrameContentSize() :
328
534
  * compatible with legacy mode
329
535
  * @return : decompressed size of the single frame pointed to be `src` if known, otherwise
@@ -352,18 +558,49 @@ static size_t readSkippableFrameSize(void const* src, size_t srcSize)
352
558
  size_t const skippableHeaderSize = ZSTD_SKIPPABLEHEADERSIZE;
353
559
  U32 sizeU32;
354
560
 
355
- RETURN_ERROR_IF(srcSize < ZSTD_SKIPPABLEHEADERSIZE, srcSize_wrong);
561
+ RETURN_ERROR_IF(srcSize < ZSTD_SKIPPABLEHEADERSIZE, srcSize_wrong, "");
356
562
 
357
563
  sizeU32 = MEM_readLE32((BYTE const*)src + ZSTD_FRAMEIDSIZE);
358
564
  RETURN_ERROR_IF((U32)(sizeU32 + ZSTD_SKIPPABLEHEADERSIZE) < sizeU32,
359
- frameParameter_unsupported);
565
+ frameParameter_unsupported, "");
360
566
  {
361
567
  size_t const skippableSize = skippableHeaderSize + sizeU32;
362
- RETURN_ERROR_IF(skippableSize > srcSize, srcSize_wrong);
568
+ RETURN_ERROR_IF(skippableSize > srcSize, srcSize_wrong, "");
363
569
  return skippableSize;
364
570
  }
365
571
  }
366
572
 
573
+ /*! ZSTD_readSkippableFrame() :
574
+ * Retrieves a zstd skippable frame containing data given by src, and writes it to dst buffer.
575
+ *
576
+ * The parameter magicVariant will receive the magicVariant that was supplied when the frame was written,
577
+ * i.e. magicNumber - ZSTD_MAGIC_SKIPPABLE_START. This can be NULL if the caller is not interested
578
+ * in the magicVariant.
579
+ *
580
+ * Returns an error if destination buffer is not large enough, or if the frame is not skippable.
581
+ *
582
+ * @return : number of bytes written or a ZSTD error.
583
+ */
584
+ ZSTDLIB_API size_t ZSTD_readSkippableFrame(void* dst, size_t dstCapacity, unsigned* magicVariant,
585
+ const void* src, size_t srcSize)
586
+ {
587
+ U32 const magicNumber = MEM_readLE32(src);
588
+ size_t skippableFrameSize = readSkippableFrameSize(src, srcSize);
589
+ size_t skippableContentSize = skippableFrameSize - ZSTD_SKIPPABLEHEADERSIZE;
590
+
591
+ /* check input validity */
592
+ RETURN_ERROR_IF(!ZSTD_isSkippableFrame(src, srcSize), frameParameter_unsupported, "");
593
+ RETURN_ERROR_IF(skippableFrameSize < ZSTD_SKIPPABLEHEADERSIZE || skippableFrameSize > srcSize, srcSize_wrong, "");
594
+ RETURN_ERROR_IF(skippableContentSize > dstCapacity, dstSize_tooSmall, "");
595
+
596
+ /* deliver payload */
597
+ if (skippableContentSize > 0 && dst != NULL)
598
+ ZSTD_memcpy(dst, (const BYTE *)src + ZSTD_SKIPPABLEHEADERSIZE, skippableContentSize);
599
+ if (magicVariant != NULL)
600
+ *magicVariant = magicNumber - ZSTD_MAGIC_SKIPPABLE_START;
601
+ return skippableContentSize;
602
+ }
603
+
367
604
  /** ZSTD_findDecompressedSize() :
368
605
  * compatible with legacy mode
369
606
  * `srcSize` must be the exact length of some number of ZSTD compressed and/or
@@ -428,20 +665,29 @@ unsigned long long ZSTD_getDecompressedSize(const void* src, size_t srcSize)
428
665
 
429
666
  /** ZSTD_decodeFrameHeader() :
430
667
  * `headerSize` must be the size provided by ZSTD_frameHeaderSize().
668
+ * If multiple DDict references are enabled, also will choose the correct DDict to use.
431
669
  * @return : 0 if success, or an error code, which can be tested using ZSTD_isError() */
432
670
  static size_t ZSTD_decodeFrameHeader(ZSTD_DCtx* dctx, const void* src, size_t headerSize)
433
671
  {
434
672
  size_t const result = ZSTD_getFrameHeader_advanced(&(dctx->fParams), src, headerSize, dctx->format);
435
673
  if (ZSTD_isError(result)) return result; /* invalid header */
436
674
  RETURN_ERROR_IF(result>0, srcSize_wrong, "headerSize too small");
675
+
676
+ /* Reference DDict requested by frame if dctx references multiple ddicts */
677
+ if (dctx->refMultipleDDicts == ZSTD_rmd_refMultipleDDicts && dctx->ddictSet) {
678
+ ZSTD_DCtx_selectFrameDDict(dctx);
679
+ }
680
+
437
681
  #ifndef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
438
682
  /* Skip the dictID check in fuzzing mode, because it makes the search
439
683
  * harder.
440
684
  */
441
685
  RETURN_ERROR_IF(dctx->fParams.dictID && (dctx->dictID != dctx->fParams.dictID),
442
- dictionary_wrong);
686
+ dictionary_wrong, "");
443
687
  #endif
444
- if (dctx->fParams.checksumFlag) XXH64_reset(&dctx->xxhState, 0);
688
+ dctx->validateChecksum = (dctx->fParams.checksumFlag && !dctx->forceIgnoreChecksum) ? 1 : 0;
689
+ if (dctx->validateChecksum) XXH64_reset(&dctx->xxhState, 0);
690
+ dctx->processedCSize += headerSize;
445
691
  return 0;
446
692
  }
447
693
 
@@ -456,7 +702,7 @@ static ZSTD_frameSizeInfo ZSTD_errorFrameSizeInfo(size_t ret)
456
702
  static ZSTD_frameSizeInfo ZSTD_findFrameSizeInfo(const void* src, size_t srcSize)
457
703
  {
458
704
  ZSTD_frameSizeInfo frameSizeInfo;
459
- memset(&frameSizeInfo, 0, sizeof(ZSTD_frameSizeInfo));
705
+ ZSTD_memset(&frameSizeInfo, 0, sizeof(ZSTD_frameSizeInfo));
460
706
 
461
707
  #if defined(ZSTD_LEGACY_SUPPORT) && (ZSTD_LEGACY_SUPPORT >= 1)
462
708
  if (ZSTD_isLegacy(src, srcSize))
@@ -511,7 +757,7 @@ static ZSTD_frameSizeInfo ZSTD_findFrameSizeInfo(const void* src, size_t srcSize
511
757
  ip += 4;
512
758
  }
513
759
 
514
- frameSizeInfo.compressedSize = ip - ipstart;
760
+ frameSizeInfo.compressedSize = (size_t)(ip - ipstart);
515
761
  frameSizeInfo.decompressedBound = (zfh.frameContentSize != ZSTD_CONTENTSIZE_UNKNOWN)
516
762
  ? zfh.frameContentSize
517
763
  : nbBlocks * zfh.blockSizeMax;
@@ -559,23 +805,12 @@ unsigned long long ZSTD_decompressBound(const void* src, size_t srcSize)
559
805
  * Frame decoding
560
806
  ***************************************************************/
561
807
 
562
-
563
- void ZSTD_checkContinuity(ZSTD_DCtx* dctx, const void* dst)
564
- {
565
- if (dst != dctx->previousDstEnd) { /* not contiguous */
566
- dctx->dictEnd = dctx->previousDstEnd;
567
- dctx->virtualStart = (const char*)dst - ((const char*)(dctx->previousDstEnd) - (const char*)(dctx->prefixStart));
568
- dctx->prefixStart = dst;
569
- dctx->previousDstEnd = dst;
570
- }
571
- }
572
-
573
808
  /** ZSTD_insertBlock() :
574
809
  * insert `src` block into `dctx` history. Useful to track uncompressed blocks. */
575
810
  size_t ZSTD_insertBlock(ZSTD_DCtx* dctx, const void* blockStart, size_t blockSize)
576
811
  {
577
812
  DEBUGLOG(5, "ZSTD_insertBlock: %u bytes", (unsigned)blockSize);
578
- ZSTD_checkContinuity(dctx, blockStart);
813
+ ZSTD_checkContinuity(dctx, blockStart, blockSize);
579
814
  dctx->previousDstEnd = (const char*)blockStart + blockSize;
580
815
  return blockSize;
581
816
  }
@@ -585,12 +820,12 @@ static size_t ZSTD_copyRawBlock(void* dst, size_t dstCapacity,
585
820
  const void* src, size_t srcSize)
586
821
  {
587
822
  DEBUGLOG(5, "ZSTD_copyRawBlock");
823
+ RETURN_ERROR_IF(srcSize > dstCapacity, dstSize_tooSmall, "");
588
824
  if (dst == NULL) {
589
825
  if (srcSize == 0) return 0;
590
- RETURN_ERROR(dstBuffer_null);
826
+ RETURN_ERROR(dstBuffer_null, "");
591
827
  }
592
- RETURN_ERROR_IF(srcSize > dstCapacity, dstSize_tooSmall);
593
- memcpy(dst, src, srcSize);
828
+ ZSTD_memcpy(dst, src, srcSize);
594
829
  return srcSize;
595
830
  }
596
831
 
@@ -598,15 +833,41 @@ static size_t ZSTD_setRleBlock(void* dst, size_t dstCapacity,
598
833
  BYTE b,
599
834
  size_t regenSize)
600
835
  {
836
+ RETURN_ERROR_IF(regenSize > dstCapacity, dstSize_tooSmall, "");
601
837
  if (dst == NULL) {
602
838
  if (regenSize == 0) return 0;
603
- RETURN_ERROR(dstBuffer_null);
839
+ RETURN_ERROR(dstBuffer_null, "");
604
840
  }
605
- RETURN_ERROR_IF(regenSize > dstCapacity, dstSize_tooSmall);
606
- memset(dst, b, regenSize);
841
+ ZSTD_memset(dst, b, regenSize);
607
842
  return regenSize;
608
843
  }
609
844
 
845
+ static void ZSTD_DCtx_trace_end(ZSTD_DCtx const* dctx, U64 uncompressedSize, U64 compressedSize, unsigned streaming)
846
+ {
847
+ #if ZSTD_TRACE
848
+ if (dctx->traceCtx && ZSTD_trace_decompress_end != NULL) {
849
+ ZSTD_Trace trace;
850
+ ZSTD_memset(&trace, 0, sizeof(trace));
851
+ trace.version = ZSTD_VERSION_NUMBER;
852
+ trace.streaming = streaming;
853
+ if (dctx->ddict) {
854
+ trace.dictionaryID = ZSTD_getDictID_fromDDict(dctx->ddict);
855
+ trace.dictionarySize = ZSTD_DDict_dictSize(dctx->ddict);
856
+ trace.dictionaryIsCold = dctx->ddictIsCold;
857
+ }
858
+ trace.uncompressedSize = (size_t)uncompressedSize;
859
+ trace.compressedSize = (size_t)compressedSize;
860
+ trace.dctx = dctx;
861
+ ZSTD_trace_decompress_end(dctx->traceCtx, &trace);
862
+ }
863
+ #else
864
+ (void)dctx;
865
+ (void)uncompressedSize;
866
+ (void)compressedSize;
867
+ (void)streaming;
868
+ #endif
869
+ }
870
+
610
871
 
611
872
  /*! ZSTD_decompressFrame() :
612
873
  * @dctx must be properly initialized
@@ -616,9 +877,10 @@ static size_t ZSTD_decompressFrame(ZSTD_DCtx* dctx,
616
877
  void* dst, size_t dstCapacity,
617
878
  const void** srcPtr, size_t *srcSizePtr)
618
879
  {
619
- const BYTE* ip = (const BYTE*)(*srcPtr);
620
- BYTE* const ostart = (BYTE* const)dst;
621
- BYTE* const oend = ostart + dstCapacity;
880
+ const BYTE* const istart = (const BYTE*)(*srcPtr);
881
+ const BYTE* ip = istart;
882
+ BYTE* const ostart = (BYTE*)dst;
883
+ BYTE* const oend = dstCapacity != 0 ? ostart + dstCapacity : ostart;
622
884
  BYTE* op = ostart;
623
885
  size_t remainingSrcSize = *srcSizePtr;
624
886
 
@@ -627,15 +889,15 @@ static size_t ZSTD_decompressFrame(ZSTD_DCtx* dctx,
627
889
  /* check */
628
890
  RETURN_ERROR_IF(
629
891
  remainingSrcSize < ZSTD_FRAMEHEADERSIZE_MIN(dctx->format)+ZSTD_blockHeaderSize,
630
- srcSize_wrong);
892
+ srcSize_wrong, "");
631
893
 
632
894
  /* Frame Header */
633
895
  { size_t const frameHeaderSize = ZSTD_frameHeaderSize_internal(
634
896
  ip, ZSTD_FRAMEHEADERSIZE_PREFIX(dctx->format), dctx->format);
635
897
  if (ZSTD_isError(frameHeaderSize)) return frameHeaderSize;
636
898
  RETURN_ERROR_IF(remainingSrcSize < frameHeaderSize+ZSTD_blockHeaderSize,
637
- srcSize_wrong);
638
- FORWARD_IF_ERROR( ZSTD_decodeFrameHeader(dctx, ip, frameHeaderSize) );
899
+ srcSize_wrong, "");
900
+ FORWARD_IF_ERROR( ZSTD_decodeFrameHeader(dctx, ip, frameHeaderSize) , "");
639
901
  ip += frameHeaderSize; remainingSrcSize -= frameHeaderSize;
640
902
  }
641
903
 
@@ -648,28 +910,30 @@ static size_t ZSTD_decompressFrame(ZSTD_DCtx* dctx,
648
910
 
649
911
  ip += ZSTD_blockHeaderSize;
650
912
  remainingSrcSize -= ZSTD_blockHeaderSize;
651
- RETURN_ERROR_IF(cBlockSize > remainingSrcSize, srcSize_wrong);
913
+ RETURN_ERROR_IF(cBlockSize > remainingSrcSize, srcSize_wrong, "");
652
914
 
653
915
  switch(blockProperties.blockType)
654
916
  {
655
917
  case bt_compressed:
656
- decodedSize = ZSTD_decompressBlock_internal(dctx, op, oend-op, ip, cBlockSize, /* frame */ 1);
918
+ decodedSize = ZSTD_decompressBlock_internal(dctx, op, (size_t)(oend-op), ip, cBlockSize, /* frame */ 1, not_streaming);
657
919
  break;
658
920
  case bt_raw :
659
- decodedSize = ZSTD_copyRawBlock(op, oend-op, ip, cBlockSize);
921
+ decodedSize = ZSTD_copyRawBlock(op, (size_t)(oend-op), ip, cBlockSize);
660
922
  break;
661
923
  case bt_rle :
662
- decodedSize = ZSTD_setRleBlock(op, oend-op, *ip, blockProperties.origSize);
924
+ decodedSize = ZSTD_setRleBlock(op, (size_t)(oend-op), *ip, blockProperties.origSize);
663
925
  break;
664
926
  case bt_reserved :
665
927
  default:
666
- RETURN_ERROR(corruption_detected);
928
+ RETURN_ERROR(corruption_detected, "invalid block type");
667
929
  }
668
930
 
669
931
  if (ZSTD_isError(decodedSize)) return decodedSize;
670
- if (dctx->fParams.checksumFlag)
932
+ if (dctx->validateChecksum)
671
933
  XXH64_update(&dctx->xxhState, op, decodedSize);
672
- op += decodedSize;
934
+ if (decodedSize != 0)
935
+ op += decodedSize;
936
+ assert(ip != NULL);
673
937
  ip += cBlockSize;
674
938
  remainingSrcSize -= cBlockSize;
675
939
  if (blockProperties.lastBlock) break;
@@ -677,22 +941,24 @@ static size_t ZSTD_decompressFrame(ZSTD_DCtx* dctx,
677
941
 
678
942
  if (dctx->fParams.frameContentSize != ZSTD_CONTENTSIZE_UNKNOWN) {
679
943
  RETURN_ERROR_IF((U64)(op-ostart) != dctx->fParams.frameContentSize,
680
- corruption_detected);
944
+ corruption_detected, "");
681
945
  }
682
946
  if (dctx->fParams.checksumFlag) { /* Frame content checksum verification */
683
- U32 const checkCalc = (U32)XXH64_digest(&dctx->xxhState);
684
- U32 checkRead;
685
- RETURN_ERROR_IF(remainingSrcSize<4, checksum_wrong);
686
- checkRead = MEM_readLE32(ip);
687
- RETURN_ERROR_IF(checkRead != checkCalc, checksum_wrong);
947
+ RETURN_ERROR_IF(remainingSrcSize<4, checksum_wrong, "");
948
+ if (!dctx->forceIgnoreChecksum) {
949
+ U32 const checkCalc = (U32)XXH64_digest(&dctx->xxhState);
950
+ U32 checkRead;
951
+ checkRead = MEM_readLE32(ip);
952
+ RETURN_ERROR_IF(checkRead != checkCalc, checksum_wrong, "");
953
+ }
688
954
  ip += 4;
689
955
  remainingSrcSize -= 4;
690
956
  }
691
-
957
+ ZSTD_DCtx_trace_end(dctx, (U64)(op-ostart), (U64)(ip-istart), /* streaming */ 0);
692
958
  /* Allow caller to get size read */
693
959
  *srcPtr = ip;
694
960
  *srcSizePtr = remainingSrcSize;
695
- return op-ostart;
961
+ return (size_t)(op-ostart);
696
962
  }
697
963
 
698
964
  static size_t ZSTD_decompressMultiFrame(ZSTD_DCtx* dctx,
@@ -725,7 +991,7 @@ static size_t ZSTD_decompressMultiFrame(ZSTD_DCtx* dctx,
725
991
  decodedSize = ZSTD_decompressLegacy(dst, dstCapacity, src, frameSize, dict, dictSize);
726
992
  if (ZSTD_isError(decodedSize)) return decodedSize;
727
993
 
728
- assert(decodedSize <=- dstCapacity);
994
+ assert(decodedSize <= dstCapacity);
729
995
  dst = (BYTE*)dst + decodedSize;
730
996
  dstCapacity -= decodedSize;
731
997
 
@@ -741,7 +1007,7 @@ static size_t ZSTD_decompressMultiFrame(ZSTD_DCtx* dctx,
741
1007
  (unsigned)magicNumber, ZSTD_MAGICNUMBER);
742
1008
  if ((magicNumber & ZSTD_MAGIC_SKIPPABLE_MASK) == ZSTD_MAGIC_SKIPPABLE_START) {
743
1009
  size_t const skippableSize = readSkippableFrameSize(src, srcSize);
744
- FORWARD_IF_ERROR(skippableSize);
1010
+ FORWARD_IF_ERROR(skippableSize, "readSkippableFrameSize failed");
745
1011
  assert(skippableSize <= srcSize);
746
1012
 
747
1013
  src = (const BYTE *)src + skippableSize;
@@ -751,13 +1017,13 @@ static size_t ZSTD_decompressMultiFrame(ZSTD_DCtx* dctx,
751
1017
 
752
1018
  if (ddict) {
753
1019
  /* we were called from ZSTD_decompress_usingDDict */
754
- FORWARD_IF_ERROR(ZSTD_decompressBegin_usingDDict(dctx, ddict));
1020
+ FORWARD_IF_ERROR(ZSTD_decompressBegin_usingDDict(dctx, ddict), "");
755
1021
  } else {
756
1022
  /* this will initialize correctly with no dict if dict == NULL, so
757
1023
  * use this in all cases but ddict */
758
- FORWARD_IF_ERROR(ZSTD_decompressBegin_usingDict(dctx, dict, dictSize));
1024
+ FORWARD_IF_ERROR(ZSTD_decompressBegin_usingDict(dctx, dict, dictSize), "");
759
1025
  }
760
- ZSTD_checkContinuity(dctx, dst);
1026
+ ZSTD_checkContinuity(dctx, dst, dstCapacity);
761
1027
 
762
1028
  { const size_t res = ZSTD_decompressFrame(dctx, dst, dstCapacity,
763
1029
  &src, &srcSize);
@@ -765,18 +1031,17 @@ static size_t ZSTD_decompressMultiFrame(ZSTD_DCtx* dctx,
765
1031
  (ZSTD_getErrorCode(res) == ZSTD_error_prefix_unknown)
766
1032
  && (moreThan1Frame==1),
767
1033
  srcSize_wrong,
768
- "at least one frame successfully completed, but following "
769
- "bytes are garbage: it's more likely to be a srcSize error, "
770
- "specifying more bytes than compressed size of frame(s). This "
771
- "error message replaces ERROR(prefix_unknown), which would be "
772
- "confusing, as the first header is actually correct. Note that "
773
- "one could be unlucky, it might be a corruption error instead, "
774
- "happening right at the place where we expect zstd magic "
775
- "bytes. But this is _much_ less likely than a srcSize field "
776
- "error.");
1034
+ "At least one frame successfully completed, "
1035
+ "but following bytes are garbage: "
1036
+ "it's more likely to be a srcSize error, "
1037
+ "specifying more input bytes than size of frame(s). "
1038
+ "Note: one could be unlucky, it might be a corruption error instead, "
1039
+ "happening right at the place where we expect zstd magic bytes. "
1040
+ "But this is _much_ less likely than a srcSize field error.");
777
1041
  if (ZSTD_isError(res)) return res;
778
1042
  assert(res <= dstCapacity);
779
- dst = (BYTE*)dst + res;
1043
+ if (res != 0)
1044
+ dst = (BYTE*)dst + res;
780
1045
  dstCapacity -= res;
781
1046
  }
782
1047
  moreThan1Frame = 1;
@@ -784,7 +1049,7 @@ static size_t ZSTD_decompressMultiFrame(ZSTD_DCtx* dctx,
784
1049
 
785
1050
  RETURN_ERROR_IF(srcSize, srcSize_wrong, "input not entirely consumed");
786
1051
 
787
- return (BYTE*)dst - (BYTE*)dststart;
1052
+ return (size_t)((BYTE*)dst - (BYTE*)dststart);
788
1053
  }
789
1054
 
790
1055
  size_t ZSTD_decompress_usingDict(ZSTD_DCtx* dctx,
@@ -801,7 +1066,7 @@ static ZSTD_DDict const* ZSTD_getDDict(ZSTD_DCtx* dctx)
801
1066
  switch (dctx->dictUses) {
802
1067
  default:
803
1068
  assert(0 /* Impossible */);
804
- /* fall-through */
1069
+ ZSTD_FALLTHROUGH;
805
1070
  case ZSTD_dont_use:
806
1071
  ZSTD_clearDict(dctx);
807
1072
  return NULL;
@@ -823,8 +1088,8 @@ size_t ZSTD_decompress(void* dst, size_t dstCapacity, const void* src, size_t sr
823
1088
  {
824
1089
  #if defined(ZSTD_HEAPMODE) && (ZSTD_HEAPMODE>=1)
825
1090
  size_t regenSize;
826
- ZSTD_DCtx* const dctx = ZSTD_createDCtx();
827
- RETURN_ERROR_IF(dctx==NULL, memory_allocation);
1091
+ ZSTD_DCtx* const dctx = ZSTD_createDCtx_internal(ZSTD_defaultCMem);
1092
+ RETURN_ERROR_IF(dctx==NULL, memory_allocation, "NULL pointer!");
828
1093
  regenSize = ZSTD_decompressDCtx(dctx, dst, dstCapacity, src, srcSize);
829
1094
  ZSTD_freeDCtx(dctx);
830
1095
  return regenSize;
@@ -842,12 +1107,32 @@ size_t ZSTD_decompress(void* dst, size_t dstCapacity, const void* src, size_t sr
842
1107
  ****************************************/
843
1108
  size_t ZSTD_nextSrcSizeToDecompress(ZSTD_DCtx* dctx) { return dctx->expected; }
844
1109
 
1110
+ /**
1111
+ * Similar to ZSTD_nextSrcSizeToDecompress(), but when when a block input can be streamed,
1112
+ * we allow taking a partial block as the input. Currently only raw uncompressed blocks can
1113
+ * be streamed.
1114
+ *
1115
+ * For blocks that can be streamed, this allows us to reduce the latency until we produce
1116
+ * output, and avoid copying the input.
1117
+ *
1118
+ * @param inputSize - The total amount of input that the caller currently has.
1119
+ */
1120
+ static size_t ZSTD_nextSrcSizeToDecompressWithInputSize(ZSTD_DCtx* dctx, size_t inputSize) {
1121
+ if (!(dctx->stage == ZSTDds_decompressBlock || dctx->stage == ZSTDds_decompressLastBlock))
1122
+ return dctx->expected;
1123
+ if (dctx->bType != bt_raw)
1124
+ return dctx->expected;
1125
+ return BOUNDED(1, inputSize, dctx->expected);
1126
+ }
1127
+
845
1128
  ZSTD_nextInputType_e ZSTD_nextInputType(ZSTD_DCtx* dctx) {
846
1129
  switch(dctx->stage)
847
1130
  {
848
1131
  default: /* should not happen */
849
1132
  assert(0);
1133
+ ZSTD_FALLTHROUGH;
850
1134
  case ZSTDds_getFrameHeaderSize:
1135
+ ZSTD_FALLTHROUGH;
851
1136
  case ZSTDds_decodeFrameHeader:
852
1137
  return ZSTDnit_frameHeader;
853
1138
  case ZSTDds_decodeBlockHeader:
@@ -859,6 +1144,7 @@ ZSTD_nextInputType_e ZSTD_nextInputType(ZSTD_DCtx* dctx) {
859
1144
  case ZSTDds_checkChecksum:
860
1145
  return ZSTDnit_checksum;
861
1146
  case ZSTDds_decodeSkippableHeader:
1147
+ ZSTD_FALLTHROUGH;
862
1148
  case ZSTDds_skipFrame:
863
1149
  return ZSTDnit_skippableFrame;
864
1150
  }
@@ -874,8 +1160,10 @@ size_t ZSTD_decompressContinue(ZSTD_DCtx* dctx, void* dst, size_t dstCapacity, c
874
1160
  {
875
1161
  DEBUGLOG(5, "ZSTD_decompressContinue (srcSize:%u)", (unsigned)srcSize);
876
1162
  /* Sanity check */
877
- RETURN_ERROR_IF(srcSize != dctx->expected, srcSize_wrong, "not allowed");
878
- if (dstCapacity) ZSTD_checkContinuity(dctx, dst);
1163
+ RETURN_ERROR_IF(srcSize != ZSTD_nextSrcSizeToDecompressWithInputSize(dctx, srcSize), srcSize_wrong, "not allowed");
1164
+ ZSTD_checkContinuity(dctx, dst, dstCapacity);
1165
+
1166
+ dctx->processedCSize += srcSize;
879
1167
 
880
1168
  switch (dctx->stage)
881
1169
  {
@@ -884,22 +1172,22 @@ size_t ZSTD_decompressContinue(ZSTD_DCtx* dctx, void* dst, size_t dstCapacity, c
884
1172
  if (dctx->format == ZSTD_f_zstd1) { /* allows header */
885
1173
  assert(srcSize >= ZSTD_FRAMEIDSIZE); /* to read skippable magic number */
886
1174
  if ((MEM_readLE32(src) & ZSTD_MAGIC_SKIPPABLE_MASK) == ZSTD_MAGIC_SKIPPABLE_START) { /* skippable frame */
887
- memcpy(dctx->headerBuffer, src, srcSize);
1175
+ ZSTD_memcpy(dctx->headerBuffer, src, srcSize);
888
1176
  dctx->expected = ZSTD_SKIPPABLEHEADERSIZE - srcSize; /* remaining to load to get full skippable frame header */
889
1177
  dctx->stage = ZSTDds_decodeSkippableHeader;
890
1178
  return 0;
891
1179
  } }
892
1180
  dctx->headerSize = ZSTD_frameHeaderSize_internal(src, srcSize, dctx->format);
893
1181
  if (ZSTD_isError(dctx->headerSize)) return dctx->headerSize;
894
- memcpy(dctx->headerBuffer, src, srcSize);
1182
+ ZSTD_memcpy(dctx->headerBuffer, src, srcSize);
895
1183
  dctx->expected = dctx->headerSize - srcSize;
896
1184
  dctx->stage = ZSTDds_decodeFrameHeader;
897
1185
  return 0;
898
1186
 
899
1187
  case ZSTDds_decodeFrameHeader:
900
1188
  assert(src != NULL);
901
- memcpy(dctx->headerBuffer + (dctx->headerSize - srcSize), src, srcSize);
902
- FORWARD_IF_ERROR(ZSTD_decodeFrameHeader(dctx, dctx->headerBuffer, dctx->headerSize));
1189
+ ZSTD_memcpy(dctx->headerBuffer + (dctx->headerSize - srcSize), src, srcSize);
1190
+ FORWARD_IF_ERROR(ZSTD_decodeFrameHeader(dctx, dctx->headerBuffer, dctx->headerSize), "");
903
1191
  dctx->expected = ZSTD_blockHeaderSize;
904
1192
  dctx->stage = ZSTDds_decodeBlockHeader;
905
1193
  return 0;
@@ -940,51 +1228,67 @@ size_t ZSTD_decompressContinue(ZSTD_DCtx* dctx, void* dst, size_t dstCapacity, c
940
1228
  {
941
1229
  case bt_compressed:
942
1230
  DEBUGLOG(5, "ZSTD_decompressContinue: case bt_compressed");
943
- rSize = ZSTD_decompressBlock_internal(dctx, dst, dstCapacity, src, srcSize, /* frame */ 1);
1231
+ rSize = ZSTD_decompressBlock_internal(dctx, dst, dstCapacity, src, srcSize, /* frame */ 1, is_streaming);
1232
+ dctx->expected = 0; /* Streaming not supported */
944
1233
  break;
945
1234
  case bt_raw :
1235
+ assert(srcSize <= dctx->expected);
946
1236
  rSize = ZSTD_copyRawBlock(dst, dstCapacity, src, srcSize);
1237
+ FORWARD_IF_ERROR(rSize, "ZSTD_copyRawBlock failed");
1238
+ assert(rSize == srcSize);
1239
+ dctx->expected -= rSize;
947
1240
  break;
948
1241
  case bt_rle :
949
1242
  rSize = ZSTD_setRleBlock(dst, dstCapacity, *(const BYTE*)src, dctx->rleSize);
1243
+ dctx->expected = 0; /* Streaming not supported */
950
1244
  break;
951
1245
  case bt_reserved : /* should never happen */
952
1246
  default:
953
- RETURN_ERROR(corruption_detected);
1247
+ RETURN_ERROR(corruption_detected, "invalid block type");
954
1248
  }
955
- if (ZSTD_isError(rSize)) return rSize;
1249
+ FORWARD_IF_ERROR(rSize, "");
956
1250
  RETURN_ERROR_IF(rSize > dctx->fParams.blockSizeMax, corruption_detected, "Decompressed Block Size Exceeds Maximum");
957
1251
  DEBUGLOG(5, "ZSTD_decompressContinue: decoded size from block : %u", (unsigned)rSize);
958
1252
  dctx->decodedSize += rSize;
959
- if (dctx->fParams.checksumFlag) XXH64_update(&dctx->xxhState, dst, rSize);
1253
+ if (dctx->validateChecksum) XXH64_update(&dctx->xxhState, dst, rSize);
1254
+ dctx->previousDstEnd = (char*)dst + rSize;
1255
+
1256
+ /* Stay on the same stage until we are finished streaming the block. */
1257
+ if (dctx->expected > 0) {
1258
+ return rSize;
1259
+ }
960
1260
 
961
1261
  if (dctx->stage == ZSTDds_decompressLastBlock) { /* end of frame */
962
1262
  DEBUGLOG(4, "ZSTD_decompressContinue: decoded size from frame : %u", (unsigned)dctx->decodedSize);
963
1263
  RETURN_ERROR_IF(
964
1264
  dctx->fParams.frameContentSize != ZSTD_CONTENTSIZE_UNKNOWN
965
1265
  && dctx->decodedSize != dctx->fParams.frameContentSize,
966
- corruption_detected);
1266
+ corruption_detected, "");
967
1267
  if (dctx->fParams.checksumFlag) { /* another round for frame checksum */
968
1268
  dctx->expected = 4;
969
1269
  dctx->stage = ZSTDds_checkChecksum;
970
1270
  } else {
1271
+ ZSTD_DCtx_trace_end(dctx, dctx->decodedSize, dctx->processedCSize, /* streaming */ 1);
971
1272
  dctx->expected = 0; /* ends here */
972
1273
  dctx->stage = ZSTDds_getFrameHeaderSize;
973
1274
  }
974
1275
  } else {
975
1276
  dctx->stage = ZSTDds_decodeBlockHeader;
976
1277
  dctx->expected = ZSTD_blockHeaderSize;
977
- dctx->previousDstEnd = (char*)dst + rSize;
978
1278
  }
979
1279
  return rSize;
980
1280
  }
981
1281
 
982
1282
  case ZSTDds_checkChecksum:
983
1283
  assert(srcSize == 4); /* guaranteed by dctx->expected */
984
- { U32 const h32 = (U32)XXH64_digest(&dctx->xxhState);
985
- U32 const check32 = MEM_readLE32(src);
986
- DEBUGLOG(4, "ZSTD_decompressContinue: checksum : calculated %08X :: %08X read", (unsigned)h32, (unsigned)check32);
987
- RETURN_ERROR_IF(check32 != h32, checksum_wrong);
1284
+ {
1285
+ if (dctx->validateChecksum) {
1286
+ U32 const h32 = (U32)XXH64_digest(&dctx->xxhState);
1287
+ U32 const check32 = MEM_readLE32(src);
1288
+ DEBUGLOG(4, "ZSTD_decompressContinue: checksum : calculated %08X :: %08X read", (unsigned)h32, (unsigned)check32);
1289
+ RETURN_ERROR_IF(check32 != h32, checksum_wrong, "");
1290
+ }
1291
+ ZSTD_DCtx_trace_end(dctx, dctx->decodedSize, dctx->processedCSize, /* streaming */ 1);
988
1292
  dctx->expected = 0;
989
1293
  dctx->stage = ZSTDds_getFrameHeaderSize;
990
1294
  return 0;
@@ -993,7 +1297,7 @@ size_t ZSTD_decompressContinue(ZSTD_DCtx* dctx, void* dst, size_t dstCapacity, c
993
1297
  case ZSTDds_decodeSkippableHeader:
994
1298
  assert(src != NULL);
995
1299
  assert(srcSize <= ZSTD_SKIPPABLEHEADERSIZE);
996
- memcpy(dctx->headerBuffer + (ZSTD_SKIPPABLEHEADERSIZE - srcSize), src, srcSize); /* complete skippable header */
1300
+ ZSTD_memcpy(dctx->headerBuffer + (ZSTD_SKIPPABLEHEADERSIZE - srcSize), src, srcSize); /* complete skippable header */
997
1301
  dctx->expected = MEM_readLE32(dctx->headerBuffer + ZSTD_FRAMEIDSIZE); /* note : dctx->expected can grow seriously large, beyond local buffer size */
998
1302
  dctx->stage = ZSTDds_skipFrame;
999
1303
  return 0;
@@ -1005,7 +1309,7 @@ size_t ZSTD_decompressContinue(ZSTD_DCtx* dctx, void* dst, size_t dstCapacity, c
1005
1309
 
1006
1310
  default:
1007
1311
  assert(0); /* impossible */
1008
- RETURN_ERROR(GENERIC); /* some compiler require default to do something */
1312
+ RETURN_ERROR(GENERIC, "impossible to reach"); /* some compiler require default to do something */
1009
1313
  }
1010
1314
  }
1011
1315
 
@@ -1016,6 +1320,10 @@ static size_t ZSTD_refDictContent(ZSTD_DCtx* dctx, const void* dict, size_t dict
1016
1320
  dctx->virtualStart = (const char*)dict - ((const char*)(dctx->previousDstEnd) - (const char*)(dctx->prefixStart));
1017
1321
  dctx->prefixStart = dict;
1018
1322
  dctx->previousDstEnd = (const char*)dict + dictSize;
1323
+ #ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
1324
+ dctx->dictContentBeginForFuzzing = dctx->prefixStart;
1325
+ dctx->dictContentEndForFuzzing = dctx->previousDstEnd;
1326
+ #endif
1019
1327
  return 0;
1020
1328
  }
1021
1329
 
@@ -1029,7 +1337,7 @@ ZSTD_loadDEntropy(ZSTD_entropyDTables_t* entropy,
1029
1337
  const BYTE* dictPtr = (const BYTE*)dict;
1030
1338
  const BYTE* const dictEnd = dictPtr + dictSize;
1031
1339
 
1032
- RETURN_ERROR_IF(dictSize <= 8, dictionary_corrupted);
1340
+ RETURN_ERROR_IF(dictSize <= 8, dictionary_corrupted, "dict is too small");
1033
1341
  assert(MEM_readLE32(dict) == ZSTD_MAGIC_DICTIONARY); /* dict must be valid */
1034
1342
  dictPtr += 8; /* skip header = magic + dictID */
1035
1343
 
@@ -1045,63 +1353,69 @@ ZSTD_loadDEntropy(ZSTD_entropyDTables_t* entropy,
1045
1353
  workspace, workspaceSize);
1046
1354
  #else
1047
1355
  size_t const hSize = HUF_readDTableX2_wksp(entropy->hufTable,
1048
- dictPtr, dictEnd - dictPtr,
1356
+ dictPtr, (size_t)(dictEnd - dictPtr),
1049
1357
  workspace, workspaceSize);
1050
1358
  #endif
1051
- RETURN_ERROR_IF(HUF_isError(hSize), dictionary_corrupted);
1359
+ RETURN_ERROR_IF(HUF_isError(hSize), dictionary_corrupted, "");
1052
1360
  dictPtr += hSize;
1053
1361
  }
1054
1362
 
1055
1363
  { short offcodeNCount[MaxOff+1];
1056
1364
  unsigned offcodeMaxValue = MaxOff, offcodeLog;
1057
- size_t const offcodeHeaderSize = FSE_readNCount(offcodeNCount, &offcodeMaxValue, &offcodeLog, dictPtr, dictEnd-dictPtr);
1058
- RETURN_ERROR_IF(FSE_isError(offcodeHeaderSize), dictionary_corrupted);
1059
- RETURN_ERROR_IF(offcodeMaxValue > MaxOff, dictionary_corrupted);
1060
- RETURN_ERROR_IF(offcodeLog > OffFSELog, dictionary_corrupted);
1365
+ size_t const offcodeHeaderSize = FSE_readNCount(offcodeNCount, &offcodeMaxValue, &offcodeLog, dictPtr, (size_t)(dictEnd-dictPtr));
1366
+ RETURN_ERROR_IF(FSE_isError(offcodeHeaderSize), dictionary_corrupted, "");
1367
+ RETURN_ERROR_IF(offcodeMaxValue > MaxOff, dictionary_corrupted, "");
1368
+ RETURN_ERROR_IF(offcodeLog > OffFSELog, dictionary_corrupted, "");
1061
1369
  ZSTD_buildFSETable( entropy->OFTable,
1062
1370
  offcodeNCount, offcodeMaxValue,
1063
1371
  OF_base, OF_bits,
1064
- offcodeLog);
1372
+ offcodeLog,
1373
+ entropy->workspace, sizeof(entropy->workspace),
1374
+ /* bmi2 */0);
1065
1375
  dictPtr += offcodeHeaderSize;
1066
1376
  }
1067
1377
 
1068
1378
  { short matchlengthNCount[MaxML+1];
1069
1379
  unsigned matchlengthMaxValue = MaxML, matchlengthLog;
1070
- size_t const matchlengthHeaderSize = FSE_readNCount(matchlengthNCount, &matchlengthMaxValue, &matchlengthLog, dictPtr, dictEnd-dictPtr);
1071
- RETURN_ERROR_IF(FSE_isError(matchlengthHeaderSize), dictionary_corrupted);
1072
- RETURN_ERROR_IF(matchlengthMaxValue > MaxML, dictionary_corrupted);
1073
- RETURN_ERROR_IF(matchlengthLog > MLFSELog, dictionary_corrupted);
1380
+ size_t const matchlengthHeaderSize = FSE_readNCount(matchlengthNCount, &matchlengthMaxValue, &matchlengthLog, dictPtr, (size_t)(dictEnd-dictPtr));
1381
+ RETURN_ERROR_IF(FSE_isError(matchlengthHeaderSize), dictionary_corrupted, "");
1382
+ RETURN_ERROR_IF(matchlengthMaxValue > MaxML, dictionary_corrupted, "");
1383
+ RETURN_ERROR_IF(matchlengthLog > MLFSELog, dictionary_corrupted, "");
1074
1384
  ZSTD_buildFSETable( entropy->MLTable,
1075
1385
  matchlengthNCount, matchlengthMaxValue,
1076
1386
  ML_base, ML_bits,
1077
- matchlengthLog);
1387
+ matchlengthLog,
1388
+ entropy->workspace, sizeof(entropy->workspace),
1389
+ /* bmi2 */ 0);
1078
1390
  dictPtr += matchlengthHeaderSize;
1079
1391
  }
1080
1392
 
1081
1393
  { short litlengthNCount[MaxLL+1];
1082
1394
  unsigned litlengthMaxValue = MaxLL, litlengthLog;
1083
- size_t const litlengthHeaderSize = FSE_readNCount(litlengthNCount, &litlengthMaxValue, &litlengthLog, dictPtr, dictEnd-dictPtr);
1084
- RETURN_ERROR_IF(FSE_isError(litlengthHeaderSize), dictionary_corrupted);
1085
- RETURN_ERROR_IF(litlengthMaxValue > MaxLL, dictionary_corrupted);
1086
- RETURN_ERROR_IF(litlengthLog > LLFSELog, dictionary_corrupted);
1395
+ size_t const litlengthHeaderSize = FSE_readNCount(litlengthNCount, &litlengthMaxValue, &litlengthLog, dictPtr, (size_t)(dictEnd-dictPtr));
1396
+ RETURN_ERROR_IF(FSE_isError(litlengthHeaderSize), dictionary_corrupted, "");
1397
+ RETURN_ERROR_IF(litlengthMaxValue > MaxLL, dictionary_corrupted, "");
1398
+ RETURN_ERROR_IF(litlengthLog > LLFSELog, dictionary_corrupted, "");
1087
1399
  ZSTD_buildFSETable( entropy->LLTable,
1088
1400
  litlengthNCount, litlengthMaxValue,
1089
1401
  LL_base, LL_bits,
1090
- litlengthLog);
1402
+ litlengthLog,
1403
+ entropy->workspace, sizeof(entropy->workspace),
1404
+ /* bmi2 */ 0);
1091
1405
  dictPtr += litlengthHeaderSize;
1092
1406
  }
1093
1407
 
1094
- RETURN_ERROR_IF(dictPtr+12 > dictEnd, dictionary_corrupted);
1408
+ RETURN_ERROR_IF(dictPtr+12 > dictEnd, dictionary_corrupted, "");
1095
1409
  { int i;
1096
1410
  size_t const dictContentSize = (size_t)(dictEnd - (dictPtr+12));
1097
1411
  for (i=0; i<3; i++) {
1098
1412
  U32 const rep = MEM_readLE32(dictPtr); dictPtr += 4;
1099
1413
  RETURN_ERROR_IF(rep==0 || rep > dictContentSize,
1100
- dictionary_corrupted);
1414
+ dictionary_corrupted, "");
1101
1415
  entropy->rep[i] = rep;
1102
1416
  } }
1103
1417
 
1104
- return dictPtr - (const BYTE*)dict;
1418
+ return (size_t)(dictPtr - (const BYTE*)dict);
1105
1419
  }
1106
1420
 
1107
1421
  static size_t ZSTD_decompress_insertDictionary(ZSTD_DCtx* dctx, const void* dict, size_t dictSize)
@@ -1115,7 +1429,7 @@ static size_t ZSTD_decompress_insertDictionary(ZSTD_DCtx* dctx, const void* dict
1115
1429
 
1116
1430
  /* load entropy tables */
1117
1431
  { size_t const eSize = ZSTD_loadDEntropy(&dctx->entropy, dict, dictSize);
1118
- RETURN_ERROR_IF(ZSTD_isError(eSize), dictionary_corrupted);
1432
+ RETURN_ERROR_IF(ZSTD_isError(eSize), dictionary_corrupted, "");
1119
1433
  dict = (const char*)dict + eSize;
1120
1434
  dictSize -= eSize;
1121
1435
  }
@@ -1128,8 +1442,12 @@ static size_t ZSTD_decompress_insertDictionary(ZSTD_DCtx* dctx, const void* dict
1128
1442
  size_t ZSTD_decompressBegin(ZSTD_DCtx* dctx)
1129
1443
  {
1130
1444
  assert(dctx != NULL);
1445
+ #if ZSTD_TRACE
1446
+ dctx->traceCtx = (ZSTD_trace_decompress_begin != NULL) ? ZSTD_trace_decompress_begin(dctx) : 0;
1447
+ #endif
1131
1448
  dctx->expected = ZSTD_startingInputLength(dctx->format); /* dctx->format must be properly set */
1132
1449
  dctx->stage = ZSTDds_getFrameHeaderSize;
1450
+ dctx->processedCSize = 0;
1133
1451
  dctx->decodedSize = 0;
1134
1452
  dctx->previousDstEnd = NULL;
1135
1453
  dctx->prefixStart = NULL;
@@ -1138,8 +1456,9 @@ size_t ZSTD_decompressBegin(ZSTD_DCtx* dctx)
1138
1456
  dctx->entropy.hufTable[0] = (HUF_DTable)((HufLog)*0x1000001); /* cover both little and big endian */
1139
1457
  dctx->litEntropy = dctx->fseEntropy = 0;
1140
1458
  dctx->dictID = 0;
1459
+ dctx->bType = bt_reserved;
1141
1460
  ZSTD_STATIC_ASSERT(sizeof(dctx->entropy.rep) == sizeof(repStartValue));
1142
- memcpy(dctx->entropy.rep, repStartValue, sizeof(repStartValue)); /* initial repcodes */
1461
+ ZSTD_memcpy(dctx->entropy.rep, repStartValue, sizeof(repStartValue)); /* initial repcodes */
1143
1462
  dctx->LLTptr = dctx->entropy.LLTable;
1144
1463
  dctx->MLTptr = dctx->entropy.MLTable;
1145
1464
  dctx->OFTptr = dctx->entropy.OFTable;
@@ -1149,11 +1468,11 @@ size_t ZSTD_decompressBegin(ZSTD_DCtx* dctx)
1149
1468
 
1150
1469
  size_t ZSTD_decompressBegin_usingDict(ZSTD_DCtx* dctx, const void* dict, size_t dictSize)
1151
1470
  {
1152
- FORWARD_IF_ERROR( ZSTD_decompressBegin(dctx) );
1471
+ FORWARD_IF_ERROR( ZSTD_decompressBegin(dctx) , "");
1153
1472
  if (dict && dictSize)
1154
1473
  RETURN_ERROR_IF(
1155
1474
  ZSTD_isError(ZSTD_decompress_insertDictionary(dctx, dict, dictSize)),
1156
- dictionary_corrupted);
1475
+ dictionary_corrupted, "");
1157
1476
  return 0;
1158
1477
  }
1159
1478
 
@@ -1172,7 +1491,7 @@ size_t ZSTD_decompressBegin_usingDDict(ZSTD_DCtx* dctx, const ZSTD_DDict* ddict)
1172
1491
  DEBUGLOG(4, "DDict is %s",
1173
1492
  dctx->ddictIsCold ? "~cold~" : "hot!");
1174
1493
  }
1175
- FORWARD_IF_ERROR( ZSTD_decompressBegin(dctx) );
1494
+ FORWARD_IF_ERROR( ZSTD_decompressBegin(dctx) , "");
1176
1495
  if (ddict) { /* NULL ddict is equivalent to no dictionary */
1177
1496
  ZSTD_copyDDictParameters(dctx, ddict);
1178
1497
  }
@@ -1234,7 +1553,7 @@ size_t ZSTD_decompress_usingDDict(ZSTD_DCtx* dctx,
1234
1553
  ZSTD_DStream* ZSTD_createDStream(void)
1235
1554
  {
1236
1555
  DEBUGLOG(3, "ZSTD_createDStream");
1237
- return ZSTD_createDStream_advanced(ZSTD_defaultCMem);
1556
+ return ZSTD_createDCtx_internal(ZSTD_defaultCMem);
1238
1557
  }
1239
1558
 
1240
1559
  ZSTD_DStream* ZSTD_initStaticDStream(void *workspace, size_t workspaceSize)
@@ -1244,7 +1563,7 @@ ZSTD_DStream* ZSTD_initStaticDStream(void *workspace, size_t workspaceSize)
1244
1563
 
1245
1564
  ZSTD_DStream* ZSTD_createDStream_advanced(ZSTD_customMem customMem)
1246
1565
  {
1247
- return ZSTD_createDCtx_advanced(customMem);
1566
+ return ZSTD_createDCtx_internal(customMem);
1248
1567
  }
1249
1568
 
1250
1569
  size_t ZSTD_freeDStream(ZSTD_DStream* zds)
@@ -1263,11 +1582,11 @@ size_t ZSTD_DCtx_loadDictionary_advanced(ZSTD_DCtx* dctx,
1263
1582
  ZSTD_dictLoadMethod_e dictLoadMethod,
1264
1583
  ZSTD_dictContentType_e dictContentType)
1265
1584
  {
1266
- RETURN_ERROR_IF(dctx->streamStage != zdss_init, stage_wrong);
1585
+ RETURN_ERROR_IF(dctx->streamStage != zdss_init, stage_wrong, "");
1267
1586
  ZSTD_clearDict(dctx);
1268
1587
  if (dict && dictSize != 0) {
1269
1588
  dctx->ddictLocal = ZSTD_createDDict_advanced(dict, dictSize, dictLoadMethod, dictContentType, dctx->customMem);
1270
- RETURN_ERROR_IF(dctx->ddictLocal == NULL, memory_allocation);
1589
+ RETURN_ERROR_IF(dctx->ddictLocal == NULL, memory_allocation, "NULL pointer!");
1271
1590
  dctx->ddict = dctx->ddictLocal;
1272
1591
  dctx->dictUses = ZSTD_use_indefinitely;
1273
1592
  }
@@ -1286,7 +1605,7 @@ size_t ZSTD_DCtx_loadDictionary(ZSTD_DCtx* dctx, const void* dict, size_t dictSi
1286
1605
 
1287
1606
  size_t ZSTD_DCtx_refPrefix_advanced(ZSTD_DCtx* dctx, const void* prefix, size_t prefixSize, ZSTD_dictContentType_e dictContentType)
1288
1607
  {
1289
- FORWARD_IF_ERROR(ZSTD_DCtx_loadDictionary_advanced(dctx, prefix, prefixSize, ZSTD_dlm_byRef, dictContentType));
1608
+ FORWARD_IF_ERROR(ZSTD_DCtx_loadDictionary_advanced(dctx, prefix, prefixSize, ZSTD_dlm_byRef, dictContentType), "");
1290
1609
  dctx->dictUses = ZSTD_use_once;
1291
1610
  return 0;
1292
1611
  }
@@ -1303,8 +1622,8 @@ size_t ZSTD_DCtx_refPrefix(ZSTD_DCtx* dctx, const void* prefix, size_t prefixSiz
1303
1622
  size_t ZSTD_initDStream_usingDict(ZSTD_DStream* zds, const void* dict, size_t dictSize)
1304
1623
  {
1305
1624
  DEBUGLOG(4, "ZSTD_initDStream_usingDict");
1306
- FORWARD_IF_ERROR( ZSTD_DCtx_reset(zds, ZSTD_reset_session_only) );
1307
- FORWARD_IF_ERROR( ZSTD_DCtx_loadDictionary(zds, dict, dictSize) );
1625
+ FORWARD_IF_ERROR( ZSTD_DCtx_reset(zds, ZSTD_reset_session_only) , "");
1626
+ FORWARD_IF_ERROR( ZSTD_DCtx_loadDictionary(zds, dict, dictSize) , "");
1308
1627
  return ZSTD_startingInputLength(zds->format);
1309
1628
  }
1310
1629
 
@@ -1320,8 +1639,8 @@ size_t ZSTD_initDStream(ZSTD_DStream* zds)
1320
1639
  * this function cannot fail */
1321
1640
  size_t ZSTD_initDStream_usingDDict(ZSTD_DStream* dctx, const ZSTD_DDict* ddict)
1322
1641
  {
1323
- FORWARD_IF_ERROR( ZSTD_DCtx_reset(dctx, ZSTD_reset_session_only) );
1324
- FORWARD_IF_ERROR( ZSTD_DCtx_refDDict(dctx, ddict) );
1642
+ FORWARD_IF_ERROR( ZSTD_DCtx_reset(dctx, ZSTD_reset_session_only) , "");
1643
+ FORWARD_IF_ERROR( ZSTD_DCtx_refDDict(dctx, ddict) , "");
1325
1644
  return ZSTD_startingInputLength(dctx->format);
1326
1645
  }
1327
1646
 
@@ -1330,18 +1649,28 @@ size_t ZSTD_initDStream_usingDDict(ZSTD_DStream* dctx, const ZSTD_DDict* ddict)
1330
1649
  * this function cannot fail */
1331
1650
  size_t ZSTD_resetDStream(ZSTD_DStream* dctx)
1332
1651
  {
1333
- FORWARD_IF_ERROR(ZSTD_DCtx_reset(dctx, ZSTD_reset_session_only));
1652
+ FORWARD_IF_ERROR(ZSTD_DCtx_reset(dctx, ZSTD_reset_session_only), "");
1334
1653
  return ZSTD_startingInputLength(dctx->format);
1335
1654
  }
1336
1655
 
1337
1656
 
1338
1657
  size_t ZSTD_DCtx_refDDict(ZSTD_DCtx* dctx, const ZSTD_DDict* ddict)
1339
1658
  {
1340
- RETURN_ERROR_IF(dctx->streamStage != zdss_init, stage_wrong);
1659
+ RETURN_ERROR_IF(dctx->streamStage != zdss_init, stage_wrong, "");
1341
1660
  ZSTD_clearDict(dctx);
1342
1661
  if (ddict) {
1343
1662
  dctx->ddict = ddict;
1344
1663
  dctx->dictUses = ZSTD_use_indefinitely;
1664
+ if (dctx->refMultipleDDicts == ZSTD_rmd_refMultipleDDicts) {
1665
+ if (dctx->ddictSet == NULL) {
1666
+ dctx->ddictSet = ZSTD_createDDictHashSet(dctx->customMem);
1667
+ if (!dctx->ddictSet) {
1668
+ RETURN_ERROR(memory_allocation, "Failed to allocate memory for hash set!");
1669
+ }
1670
+ }
1671
+ assert(!dctx->staticSize); /* Impossible: ddictSet cannot have been allocated if static dctx */
1672
+ FORWARD_IF_ERROR(ZSTD_DDictHashSet_addDDict(dctx->ddictSet, ddict, dctx->customMem), "");
1673
+ }
1345
1674
  }
1346
1675
  return 0;
1347
1676
  }
@@ -1354,16 +1683,16 @@ size_t ZSTD_DCtx_setMaxWindowSize(ZSTD_DCtx* dctx, size_t maxWindowSize)
1354
1683
  ZSTD_bounds const bounds = ZSTD_dParam_getBounds(ZSTD_d_windowLogMax);
1355
1684
  size_t const min = (size_t)1 << bounds.lowerBound;
1356
1685
  size_t const max = (size_t)1 << bounds.upperBound;
1357
- RETURN_ERROR_IF(dctx->streamStage != zdss_init, stage_wrong);
1358
- RETURN_ERROR_IF(maxWindowSize < min, parameter_outOfBound);
1359
- RETURN_ERROR_IF(maxWindowSize > max, parameter_outOfBound);
1686
+ RETURN_ERROR_IF(dctx->streamStage != zdss_init, stage_wrong, "");
1687
+ RETURN_ERROR_IF(maxWindowSize < min, parameter_outOfBound, "");
1688
+ RETURN_ERROR_IF(maxWindowSize > max, parameter_outOfBound, "");
1360
1689
  dctx->maxWindowSize = maxWindowSize;
1361
1690
  return 0;
1362
1691
  }
1363
1692
 
1364
1693
  size_t ZSTD_DCtx_setFormat(ZSTD_DCtx* dctx, ZSTD_format_e format)
1365
1694
  {
1366
- return ZSTD_DCtx_setParameter(dctx, ZSTD_d_format, format);
1695
+ return ZSTD_DCtx_setParameter(dctx, ZSTD_d_format, (int)format);
1367
1696
  }
1368
1697
 
1369
1698
  ZSTD_bounds ZSTD_dParam_getBounds(ZSTD_dParameter dParam)
@@ -1379,6 +1708,18 @@ ZSTD_bounds ZSTD_dParam_getBounds(ZSTD_dParameter dParam)
1379
1708
  bounds.upperBound = (int)ZSTD_f_zstd1_magicless;
1380
1709
  ZSTD_STATIC_ASSERT(ZSTD_f_zstd1 < ZSTD_f_zstd1_magicless);
1381
1710
  return bounds;
1711
+ case ZSTD_d_stableOutBuffer:
1712
+ bounds.lowerBound = (int)ZSTD_bm_buffered;
1713
+ bounds.upperBound = (int)ZSTD_bm_stable;
1714
+ return bounds;
1715
+ case ZSTD_d_forceIgnoreChecksum:
1716
+ bounds.lowerBound = (int)ZSTD_d_validateChecksum;
1717
+ bounds.upperBound = (int)ZSTD_d_ignoreChecksum;
1718
+ return bounds;
1719
+ case ZSTD_d_refMultipleDDicts:
1720
+ bounds.lowerBound = (int)ZSTD_rmd_refSingleDDict;
1721
+ bounds.upperBound = (int)ZSTD_rmd_refMultipleDDicts;
1722
+ return bounds;
1382
1723
  default:;
1383
1724
  }
1384
1725
  bounds.error = ERROR(parameter_unsupported);
@@ -1398,12 +1739,35 @@ static int ZSTD_dParam_withinBounds(ZSTD_dParameter dParam, int value)
1398
1739
  }
1399
1740
 
1400
1741
  #define CHECK_DBOUNDS(p,v) { \
1401
- RETURN_ERROR_IF(!ZSTD_dParam_withinBounds(p, v), parameter_outOfBound); \
1742
+ RETURN_ERROR_IF(!ZSTD_dParam_withinBounds(p, v), parameter_outOfBound, ""); \
1743
+ }
1744
+
1745
+ size_t ZSTD_DCtx_getParameter(ZSTD_DCtx* dctx, ZSTD_dParameter param, int* value)
1746
+ {
1747
+ switch (param) {
1748
+ case ZSTD_d_windowLogMax:
1749
+ *value = (int)ZSTD_highbit32((U32)dctx->maxWindowSize);
1750
+ return 0;
1751
+ case ZSTD_d_format:
1752
+ *value = (int)dctx->format;
1753
+ return 0;
1754
+ case ZSTD_d_stableOutBuffer:
1755
+ *value = (int)dctx->outBufferMode;
1756
+ return 0;
1757
+ case ZSTD_d_forceIgnoreChecksum:
1758
+ *value = (int)dctx->forceIgnoreChecksum;
1759
+ return 0;
1760
+ case ZSTD_d_refMultipleDDicts:
1761
+ *value = (int)dctx->refMultipleDDicts;
1762
+ return 0;
1763
+ default:;
1764
+ }
1765
+ RETURN_ERROR(parameter_unsupported, "");
1402
1766
  }
1403
1767
 
1404
1768
  size_t ZSTD_DCtx_setParameter(ZSTD_DCtx* dctx, ZSTD_dParameter dParam, int value)
1405
1769
  {
1406
- RETURN_ERROR_IF(dctx->streamStage != zdss_init, stage_wrong);
1770
+ RETURN_ERROR_IF(dctx->streamStage != zdss_init, stage_wrong, "");
1407
1771
  switch(dParam) {
1408
1772
  case ZSTD_d_windowLogMax:
1409
1773
  if (value == 0) value = ZSTD_WINDOWLOG_LIMIT_DEFAULT;
@@ -1414,9 +1778,24 @@ size_t ZSTD_DCtx_setParameter(ZSTD_DCtx* dctx, ZSTD_dParameter dParam, int value
1414
1778
  CHECK_DBOUNDS(ZSTD_d_format, value);
1415
1779
  dctx->format = (ZSTD_format_e)value;
1416
1780
  return 0;
1781
+ case ZSTD_d_stableOutBuffer:
1782
+ CHECK_DBOUNDS(ZSTD_d_stableOutBuffer, value);
1783
+ dctx->outBufferMode = (ZSTD_bufferMode_e)value;
1784
+ return 0;
1785
+ case ZSTD_d_forceIgnoreChecksum:
1786
+ CHECK_DBOUNDS(ZSTD_d_forceIgnoreChecksum, value);
1787
+ dctx->forceIgnoreChecksum = (ZSTD_forceIgnoreChecksum_e)value;
1788
+ return 0;
1789
+ case ZSTD_d_refMultipleDDicts:
1790
+ CHECK_DBOUNDS(ZSTD_d_refMultipleDDicts, value);
1791
+ if (dctx->staticSize != 0) {
1792
+ RETURN_ERROR(parameter_unsupported, "Static dctx does not support multiple DDicts!");
1793
+ }
1794
+ dctx->refMultipleDDicts = (ZSTD_refMultipleDDicts_e)value;
1795
+ return 0;
1417
1796
  default:;
1418
1797
  }
1419
- RETURN_ERROR(parameter_unsupported);
1798
+ RETURN_ERROR(parameter_unsupported, "");
1420
1799
  }
1421
1800
 
1422
1801
  size_t ZSTD_DCtx_reset(ZSTD_DCtx* dctx, ZSTD_ResetDirective reset)
@@ -1428,10 +1807,9 @@ size_t ZSTD_DCtx_reset(ZSTD_DCtx* dctx, ZSTD_ResetDirective reset)
1428
1807
  }
1429
1808
  if ( (reset == ZSTD_reset_parameters)
1430
1809
  || (reset == ZSTD_reset_session_and_parameters) ) {
1431
- RETURN_ERROR_IF(dctx->streamStage != zdss_init, stage_wrong);
1810
+ RETURN_ERROR_IF(dctx->streamStage != zdss_init, stage_wrong, "");
1432
1811
  ZSTD_clearDict(dctx);
1433
- dctx->format = ZSTD_f_zstd1;
1434
- dctx->maxWindowSize = ZSTD_MAXWINDOWSIZE_DEFAULT;
1812
+ ZSTD_DCtx_resetParameters(dctx);
1435
1813
  }
1436
1814
  return 0;
1437
1815
  }
@@ -1445,11 +1823,12 @@ size_t ZSTD_sizeof_DStream(const ZSTD_DStream* dctx)
1445
1823
  size_t ZSTD_decodingBufferSize_min(unsigned long long windowSize, unsigned long long frameContentSize)
1446
1824
  {
1447
1825
  size_t const blockSize = (size_t) MIN(windowSize, ZSTD_BLOCKSIZE_MAX);
1448
- unsigned long long const neededRBSize = windowSize + blockSize + (WILDCOPY_OVERLENGTH * 2);
1826
+ /* space is needed to store the litbuffer after the output of a given block without stomping the extDict of a previous run, as well as to cover both windows against wildcopy*/
1827
+ unsigned long long const neededRBSize = windowSize + blockSize + ZSTD_BLOCKSIZE_MAX + (WILDCOPY_OVERLENGTH * 2);
1449
1828
  unsigned long long const neededSize = MIN(frameContentSize, neededRBSize);
1450
1829
  size_t const minRBSize = (size_t) neededSize;
1451
1830
  RETURN_ERROR_IF((unsigned long long)minRBSize != neededSize,
1452
- frameParameter_windowTooLarge);
1831
+ frameParameter_windowTooLarge, "");
1453
1832
  return minRBSize;
1454
1833
  }
1455
1834
 
@@ -1467,30 +1846,94 @@ size_t ZSTD_estimateDStreamSize_fromFrame(const void* src, size_t srcSize)
1467
1846
  ZSTD_frameHeader zfh;
1468
1847
  size_t const err = ZSTD_getFrameHeader(&zfh, src, srcSize);
1469
1848
  if (ZSTD_isError(err)) return err;
1470
- RETURN_ERROR_IF(err>0, srcSize_wrong);
1849
+ RETURN_ERROR_IF(err>0, srcSize_wrong, "");
1471
1850
  RETURN_ERROR_IF(zfh.windowSize > windowSizeMax,
1472
- frameParameter_windowTooLarge);
1851
+ frameParameter_windowTooLarge, "");
1473
1852
  return ZSTD_estimateDStreamSize((size_t)zfh.windowSize);
1474
1853
  }
1475
1854
 
1476
1855
 
1477
1856
  /* ***** Decompression ***** */
1478
1857
 
1479
- MEM_STATIC size_t ZSTD_limitCopy(void* dst, size_t dstCapacity, const void* src, size_t srcSize)
1858
+ static int ZSTD_DCtx_isOverflow(ZSTD_DStream* zds, size_t const neededInBuffSize, size_t const neededOutBuffSize)
1859
+ {
1860
+ return (zds->inBuffSize + zds->outBuffSize) >= (neededInBuffSize + neededOutBuffSize) * ZSTD_WORKSPACETOOLARGE_FACTOR;
1861
+ }
1862
+
1863
+ static void ZSTD_DCtx_updateOversizedDuration(ZSTD_DStream* zds, size_t const neededInBuffSize, size_t const neededOutBuffSize)
1864
+ {
1865
+ if (ZSTD_DCtx_isOverflow(zds, neededInBuffSize, neededOutBuffSize))
1866
+ zds->oversizedDuration++;
1867
+ else
1868
+ zds->oversizedDuration = 0;
1869
+ }
1870
+
1871
+ static int ZSTD_DCtx_isOversizedTooLong(ZSTD_DStream* zds)
1480
1872
  {
1481
- size_t const length = MIN(dstCapacity, srcSize);
1482
- memcpy(dst, src, length);
1483
- return length;
1873
+ return zds->oversizedDuration >= ZSTD_WORKSPACETOOLARGE_MAXDURATION;
1484
1874
  }
1485
1875
 
1876
+ /* Checks that the output buffer hasn't changed if ZSTD_obm_stable is used. */
1877
+ static size_t ZSTD_checkOutBuffer(ZSTD_DStream const* zds, ZSTD_outBuffer const* output)
1878
+ {
1879
+ ZSTD_outBuffer const expect = zds->expectedOutBuffer;
1880
+ /* No requirement when ZSTD_obm_stable is not enabled. */
1881
+ if (zds->outBufferMode != ZSTD_bm_stable)
1882
+ return 0;
1883
+ /* Any buffer is allowed in zdss_init, this must be the same for every other call until
1884
+ * the context is reset.
1885
+ */
1886
+ if (zds->streamStage == zdss_init)
1887
+ return 0;
1888
+ /* The buffer must match our expectation exactly. */
1889
+ if (expect.dst == output->dst && expect.pos == output->pos && expect.size == output->size)
1890
+ return 0;
1891
+ RETURN_ERROR(dstBuffer_wrong, "ZSTD_d_stableOutBuffer enabled but output differs!");
1892
+ }
1893
+
1894
+ /* Calls ZSTD_decompressContinue() with the right parameters for ZSTD_decompressStream()
1895
+ * and updates the stage and the output buffer state. This call is extracted so it can be
1896
+ * used both when reading directly from the ZSTD_inBuffer, and in buffered input mode.
1897
+ * NOTE: You must break after calling this function since the streamStage is modified.
1898
+ */
1899
+ static size_t ZSTD_decompressContinueStream(
1900
+ ZSTD_DStream* zds, char** op, char* oend,
1901
+ void const* src, size_t srcSize) {
1902
+ int const isSkipFrame = ZSTD_isSkipFrame(zds);
1903
+ if (zds->outBufferMode == ZSTD_bm_buffered) {
1904
+ size_t const dstSize = isSkipFrame ? 0 : zds->outBuffSize - zds->outStart;
1905
+ size_t const decodedSize = ZSTD_decompressContinue(zds,
1906
+ zds->outBuff + zds->outStart, dstSize, src, srcSize);
1907
+ FORWARD_IF_ERROR(decodedSize, "");
1908
+ if (!decodedSize && !isSkipFrame) {
1909
+ zds->streamStage = zdss_read;
1910
+ } else {
1911
+ zds->outEnd = zds->outStart + decodedSize;
1912
+ zds->streamStage = zdss_flush;
1913
+ }
1914
+ } else {
1915
+ /* Write directly into the output buffer */
1916
+ size_t const dstSize = isSkipFrame ? 0 : (size_t)(oend - *op);
1917
+ size_t const decodedSize = ZSTD_decompressContinue(zds, *op, dstSize, src, srcSize);
1918
+ FORWARD_IF_ERROR(decodedSize, "");
1919
+ *op += decodedSize;
1920
+ /* Flushing is not needed. */
1921
+ zds->streamStage = zdss_read;
1922
+ assert(*op <= oend);
1923
+ assert(zds->outBufferMode == ZSTD_bm_stable);
1924
+ }
1925
+ return 0;
1926
+ }
1486
1927
 
1487
1928
  size_t ZSTD_decompressStream(ZSTD_DStream* zds, ZSTD_outBuffer* output, ZSTD_inBuffer* input)
1488
1929
  {
1489
- const char* const istart = (const char*)(input->src) + input->pos;
1490
- const char* const iend = (const char*)(input->src) + input->size;
1930
+ const char* const src = (const char*)input->src;
1931
+ const char* const istart = input->pos != 0 ? src + input->pos : src;
1932
+ const char* const iend = input->size != 0 ? src + input->size : src;
1491
1933
  const char* ip = istart;
1492
- char* const ostart = (char*)(output->dst) + output->pos;
1493
- char* const oend = (char*)(output->dst) + output->size;
1934
+ char* const dst = (char*)output->dst;
1935
+ char* const ostart = output->pos != 0 ? dst + output->pos : dst;
1936
+ char* const oend = output->size != 0 ? dst + output->size : dst;
1494
1937
  char* op = ostart;
1495
1938
  U32 someMoreWork = 1;
1496
1939
 
@@ -1506,6 +1949,7 @@ size_t ZSTD_decompressStream(ZSTD_DStream* zds, ZSTD_outBuffer* output, ZSTD_inB
1506
1949
  "forbidden. out: pos: %u vs size: %u",
1507
1950
  (U32)output->pos, (U32)output->size);
1508
1951
  DEBUGLOG(5, "input size : %u", (U32)(input->size - input->pos));
1952
+ FORWARD_IF_ERROR(ZSTD_checkOutBuffer(zds, output), "");
1509
1953
 
1510
1954
  while (someMoreWork) {
1511
1955
  switch(zds->streamStage)
@@ -1514,9 +1958,12 @@ size_t ZSTD_decompressStream(ZSTD_DStream* zds, ZSTD_outBuffer* output, ZSTD_inB
1514
1958
  DEBUGLOG(5, "stage zdss_init => transparent reset ");
1515
1959
  zds->streamStage = zdss_loadHeader;
1516
1960
  zds->lhSize = zds->inPos = zds->outStart = zds->outEnd = 0;
1961
+ #if defined(ZSTD_LEGACY_SUPPORT) && (ZSTD_LEGACY_SUPPORT>=1)
1517
1962
  zds->legacyVersion = 0;
1963
+ #endif
1518
1964
  zds->hostageByte = 0;
1519
- /* fall-through */
1965
+ zds->expectedOutBuffer = *output;
1966
+ ZSTD_FALLTHROUGH;
1520
1967
 
1521
1968
  case zdss_loadHeader :
1522
1969
  DEBUGLOG(5, "stage zdss_loadHeader (srcSize : %u)", (U32)(iend - ip));
@@ -1530,6 +1977,9 @@ size_t ZSTD_decompressStream(ZSTD_DStream* zds, ZSTD_outBuffer* output, ZSTD_inB
1530
1977
  } }
1531
1978
  #endif
1532
1979
  { size_t const hSize = ZSTD_getFrameHeader_advanced(&zds->fParams, zds->headerBuffer, zds->lhSize, zds->format);
1980
+ if (zds->refMultipleDDicts && zds->ddictSet) {
1981
+ ZSTD_DCtx_selectFrameDDict(zds);
1982
+ }
1533
1983
  DEBUGLOG(5, "header size : %u", (U32)hSize);
1534
1984
  if (ZSTD_isError(hSize)) {
1535
1985
  #if defined(ZSTD_LEGACY_SUPPORT) && (ZSTD_LEGACY_SUPPORT>=1)
@@ -1543,7 +1993,7 @@ size_t ZSTD_decompressStream(ZSTD_DStream* zds, ZSTD_outBuffer* output, ZSTD_inB
1543
1993
  "legacy support is incompatible with static dctx");
1544
1994
  FORWARD_IF_ERROR(ZSTD_initLegacyStream(&zds->legacyContext,
1545
1995
  zds->previousLegacyVersion, legacyVersion,
1546
- dict, dictSize));
1996
+ dict, dictSize), "");
1547
1997
  zds->legacyVersion = zds->previousLegacyVersion = legacyVersion;
1548
1998
  { size_t const hint = ZSTD_decompressLegacyStream(zds->legacyContext, legacyVersion, output, input);
1549
1999
  if (hint==0) zds->streamStage = zdss_init; /* or stay in stage zdss_loadHeader */
@@ -1558,24 +2008,25 @@ size_t ZSTD_decompressStream(ZSTD_DStream* zds, ZSTD_outBuffer* output, ZSTD_inB
1558
2008
  assert(iend >= ip);
1559
2009
  if (toLoad > remainingInput) { /* not enough input to load full header */
1560
2010
  if (remainingInput > 0) {
1561
- memcpy(zds->headerBuffer + zds->lhSize, ip, remainingInput);
2011
+ ZSTD_memcpy(zds->headerBuffer + zds->lhSize, ip, remainingInput);
1562
2012
  zds->lhSize += remainingInput;
1563
2013
  }
1564
2014
  input->pos = input->size;
1565
2015
  return (MAX((size_t)ZSTD_FRAMEHEADERSIZE_MIN(zds->format), hSize) - zds->lhSize) + ZSTD_blockHeaderSize; /* remaining header bytes + next block header */
1566
2016
  }
1567
2017
  assert(ip != NULL);
1568
- memcpy(zds->headerBuffer + zds->lhSize, ip, toLoad); zds->lhSize = hSize; ip += toLoad;
2018
+ ZSTD_memcpy(zds->headerBuffer + zds->lhSize, ip, toLoad); zds->lhSize = hSize; ip += toLoad;
1569
2019
  break;
1570
2020
  } }
1571
2021
 
1572
2022
  /* check for single-pass mode opportunity */
1573
- if (zds->fParams.frameContentSize && zds->fParams.windowSize /* skippable frame if == 0 */
2023
+ if (zds->fParams.frameContentSize != ZSTD_CONTENTSIZE_UNKNOWN
2024
+ && zds->fParams.frameType != ZSTD_skippableFrame
1574
2025
  && (U64)(size_t)(oend-op) >= zds->fParams.frameContentSize) {
1575
- size_t const cSize = ZSTD_findFrameCompressedSize(istart, iend-istart);
2026
+ size_t const cSize = ZSTD_findFrameCompressedSize(istart, (size_t)(iend-istart));
1576
2027
  if (cSize <= (size_t)(iend-istart)) {
1577
2028
  /* shortcut : using single-pass mode */
1578
- size_t const decompressedSize = ZSTD_decompress_usingDDict(zds, op, oend-op, istart, cSize, ZSTD_getDDict(zds));
2029
+ size_t const decompressedSize = ZSTD_decompress_usingDDict(zds, op, (size_t)(oend-op), istart, cSize, ZSTD_getDDict(zds));
1579
2030
  if (ZSTD_isError(decompressedSize)) return decompressedSize;
1580
2031
  DEBUGLOG(4, "shortcut to single-pass ZSTD_decompress_usingDDict()")
1581
2032
  ip = istart + cSize;
@@ -1586,15 +2037,23 @@ size_t ZSTD_decompressStream(ZSTD_DStream* zds, ZSTD_outBuffer* output, ZSTD_inB
1586
2037
  break;
1587
2038
  } }
1588
2039
 
2040
+ /* Check output buffer is large enough for ZSTD_odm_stable. */
2041
+ if (zds->outBufferMode == ZSTD_bm_stable
2042
+ && zds->fParams.frameType != ZSTD_skippableFrame
2043
+ && zds->fParams.frameContentSize != ZSTD_CONTENTSIZE_UNKNOWN
2044
+ && (U64)(size_t)(oend-op) < zds->fParams.frameContentSize) {
2045
+ RETURN_ERROR(dstSize_tooSmall, "ZSTD_obm_stable passed but ZSTD_outBuffer is too small");
2046
+ }
2047
+
1589
2048
  /* Consume header (see ZSTDds_decodeFrameHeader) */
1590
2049
  DEBUGLOG(4, "Consume header");
1591
- FORWARD_IF_ERROR(ZSTD_decompressBegin_usingDDict(zds, ZSTD_getDDict(zds)));
2050
+ FORWARD_IF_ERROR(ZSTD_decompressBegin_usingDDict(zds, ZSTD_getDDict(zds)), "");
1592
2051
 
1593
2052
  if ((MEM_readLE32(zds->headerBuffer) & ZSTD_MAGIC_SKIPPABLE_MASK) == ZSTD_MAGIC_SKIPPABLE_START) { /* skippable frame */
1594
2053
  zds->expected = MEM_readLE32(zds->headerBuffer + ZSTD_FRAMEIDSIZE);
1595
2054
  zds->stage = ZSTDds_skipFrame;
1596
2055
  } else {
1597
- FORWARD_IF_ERROR(ZSTD_decodeFrameHeader(zds, zds->headerBuffer, zds->lhSize));
2056
+ FORWARD_IF_ERROR(ZSTD_decodeFrameHeader(zds, zds->headerBuffer, zds->lhSize), "");
1598
2057
  zds->expected = ZSTD_blockHeaderSize;
1599
2058
  zds->stage = ZSTDds_decodeBlockHeader;
1600
2059
  }
@@ -1605,40 +2064,48 @@ size_t ZSTD_decompressStream(ZSTD_DStream* zds, ZSTD_outBuffer* output, ZSTD_inB
1605
2064
  (U32)(zds->maxWindowSize >> 10) );
1606
2065
  zds->fParams.windowSize = MAX(zds->fParams.windowSize, 1U << ZSTD_WINDOWLOG_ABSOLUTEMIN);
1607
2066
  RETURN_ERROR_IF(zds->fParams.windowSize > zds->maxWindowSize,
1608
- frameParameter_windowTooLarge);
2067
+ frameParameter_windowTooLarge, "");
1609
2068
 
1610
2069
  /* Adapt buffer sizes to frame header instructions */
1611
2070
  { size_t const neededInBuffSize = MAX(zds->fParams.blockSizeMax, 4 /* frame checksum */);
1612
- size_t const neededOutBuffSize = ZSTD_decodingBufferSize_min(zds->fParams.windowSize, zds->fParams.frameContentSize);
1613
- if ((zds->inBuffSize < neededInBuffSize) || (zds->outBuffSize < neededOutBuffSize)) {
1614
- size_t const bufferSize = neededInBuffSize + neededOutBuffSize;
1615
- DEBUGLOG(4, "inBuff : from %u to %u",
1616
- (U32)zds->inBuffSize, (U32)neededInBuffSize);
1617
- DEBUGLOG(4, "outBuff : from %u to %u",
1618
- (U32)zds->outBuffSize, (U32)neededOutBuffSize);
1619
- if (zds->staticSize) { /* static DCtx */
1620
- DEBUGLOG(4, "staticSize : %u", (U32)zds->staticSize);
1621
- assert(zds->staticSize >= sizeof(ZSTD_DCtx)); /* controlled at init */
1622
- RETURN_ERROR_IF(
1623
- bufferSize > zds->staticSize - sizeof(ZSTD_DCtx),
1624
- memory_allocation);
1625
- } else {
1626
- ZSTD_free(zds->inBuff, zds->customMem);
1627
- zds->inBuffSize = 0;
1628
- zds->outBuffSize = 0;
1629
- zds->inBuff = (char*)ZSTD_malloc(bufferSize, zds->customMem);
1630
- RETURN_ERROR_IF(zds->inBuff == NULL, memory_allocation);
1631
- }
1632
- zds->inBuffSize = neededInBuffSize;
1633
- zds->outBuff = zds->inBuff + zds->inBuffSize;
1634
- zds->outBuffSize = neededOutBuffSize;
1635
- } }
2071
+ size_t const neededOutBuffSize = zds->outBufferMode == ZSTD_bm_buffered
2072
+ ? ZSTD_decodingBufferSize_min(zds->fParams.windowSize, zds->fParams.frameContentSize)
2073
+ : 0;
2074
+
2075
+ ZSTD_DCtx_updateOversizedDuration(zds, neededInBuffSize, neededOutBuffSize);
2076
+
2077
+ { int const tooSmall = (zds->inBuffSize < neededInBuffSize) || (zds->outBuffSize < neededOutBuffSize);
2078
+ int const tooLarge = ZSTD_DCtx_isOversizedTooLong(zds);
2079
+
2080
+ if (tooSmall || tooLarge) {
2081
+ size_t const bufferSize = neededInBuffSize + neededOutBuffSize;
2082
+ DEBUGLOG(4, "inBuff : from %u to %u",
2083
+ (U32)zds->inBuffSize, (U32)neededInBuffSize);
2084
+ DEBUGLOG(4, "outBuff : from %u to %u",
2085
+ (U32)zds->outBuffSize, (U32)neededOutBuffSize);
2086
+ if (zds->staticSize) { /* static DCtx */
2087
+ DEBUGLOG(4, "staticSize : %u", (U32)zds->staticSize);
2088
+ assert(zds->staticSize >= sizeof(ZSTD_DCtx)); /* controlled at init */
2089
+ RETURN_ERROR_IF(
2090
+ bufferSize > zds->staticSize - sizeof(ZSTD_DCtx),
2091
+ memory_allocation, "");
2092
+ } else {
2093
+ ZSTD_customFree(zds->inBuff, zds->customMem);
2094
+ zds->inBuffSize = 0;
2095
+ zds->outBuffSize = 0;
2096
+ zds->inBuff = (char*)ZSTD_customMalloc(bufferSize, zds->customMem);
2097
+ RETURN_ERROR_IF(zds->inBuff == NULL, memory_allocation, "");
2098
+ }
2099
+ zds->inBuffSize = neededInBuffSize;
2100
+ zds->outBuff = zds->inBuff + zds->inBuffSize;
2101
+ zds->outBuffSize = neededOutBuffSize;
2102
+ } } }
1636
2103
  zds->streamStage = zdss_read;
1637
- /* fall-through */
2104
+ ZSTD_FALLTHROUGH;
1638
2105
 
1639
2106
  case zdss_read:
1640
2107
  DEBUGLOG(5, "stage zdss_read");
1641
- { size_t const neededInSize = ZSTD_nextSrcSizeToDecompress(zds);
2108
+ { size_t const neededInSize = ZSTD_nextSrcSizeToDecompressWithInputSize(zds, (size_t)(iend - ip));
1642
2109
  DEBUGLOG(5, "neededInSize = %u", (U32)neededInSize);
1643
2110
  if (neededInSize==0) { /* end of frame */
1644
2111
  zds->streamStage = zdss_init;
@@ -1646,53 +2113,43 @@ size_t ZSTD_decompressStream(ZSTD_DStream* zds, ZSTD_outBuffer* output, ZSTD_inB
1646
2113
  break;
1647
2114
  }
1648
2115
  if ((size_t)(iend-ip) >= neededInSize) { /* decode directly from src */
1649
- int const isSkipFrame = ZSTD_isSkipFrame(zds);
1650
- size_t const decodedSize = ZSTD_decompressContinue(zds,
1651
- zds->outBuff + zds->outStart, (isSkipFrame ? 0 : zds->outBuffSize - zds->outStart),
1652
- ip, neededInSize);
1653
- if (ZSTD_isError(decodedSize)) return decodedSize;
2116
+ FORWARD_IF_ERROR(ZSTD_decompressContinueStream(zds, &op, oend, ip, neededInSize), "");
1654
2117
  ip += neededInSize;
1655
- if (!decodedSize && !isSkipFrame) break; /* this was just a header */
1656
- zds->outEnd = zds->outStart + decodedSize;
1657
- zds->streamStage = zdss_flush;
2118
+ /* Function modifies the stage so we must break */
1658
2119
  break;
1659
2120
  } }
1660
2121
  if (ip==iend) { someMoreWork = 0; break; } /* no more input */
1661
2122
  zds->streamStage = zdss_load;
1662
- /* fall-through */
2123
+ ZSTD_FALLTHROUGH;
1663
2124
 
1664
2125
  case zdss_load:
1665
2126
  { size_t const neededInSize = ZSTD_nextSrcSizeToDecompress(zds);
1666
2127
  size_t const toLoad = neededInSize - zds->inPos;
1667
2128
  int const isSkipFrame = ZSTD_isSkipFrame(zds);
1668
2129
  size_t loadedSize;
2130
+ /* At this point we shouldn't be decompressing a block that we can stream. */
2131
+ assert(neededInSize == ZSTD_nextSrcSizeToDecompressWithInputSize(zds, iend - ip));
1669
2132
  if (isSkipFrame) {
1670
2133
  loadedSize = MIN(toLoad, (size_t)(iend-ip));
1671
2134
  } else {
1672
2135
  RETURN_ERROR_IF(toLoad > zds->inBuffSize - zds->inPos,
1673
2136
  corruption_detected,
1674
2137
  "should never happen");
1675
- loadedSize = ZSTD_limitCopy(zds->inBuff + zds->inPos, toLoad, ip, iend-ip);
2138
+ loadedSize = ZSTD_limitCopy(zds->inBuff + zds->inPos, toLoad, ip, (size_t)(iend-ip));
1676
2139
  }
1677
2140
  ip += loadedSize;
1678
2141
  zds->inPos += loadedSize;
1679
2142
  if (loadedSize < toLoad) { someMoreWork = 0; break; } /* not enough input, wait for more */
1680
2143
 
1681
2144
  /* decode loaded input */
1682
- { size_t const decodedSize = ZSTD_decompressContinue(zds,
1683
- zds->outBuff + zds->outStart, zds->outBuffSize - zds->outStart,
1684
- zds->inBuff, neededInSize);
1685
- if (ZSTD_isError(decodedSize)) return decodedSize;
1686
- zds->inPos = 0; /* input is consumed */
1687
- if (!decodedSize && !isSkipFrame) { zds->streamStage = zdss_read; break; } /* this was just a header */
1688
- zds->outEnd = zds->outStart + decodedSize;
1689
- } }
1690
- zds->streamStage = zdss_flush;
1691
- /* fall-through */
1692
-
2145
+ zds->inPos = 0; /* input is consumed */
2146
+ FORWARD_IF_ERROR(ZSTD_decompressContinueStream(zds, &op, oend, zds->inBuff, neededInSize), "");
2147
+ /* Function modifies the stage so we must break */
2148
+ break;
2149
+ }
1693
2150
  case zdss_flush:
1694
2151
  { size_t const toFlushSize = zds->outEnd - zds->outStart;
1695
- size_t const flushedSize = ZSTD_limitCopy(op, oend-op, zds->outBuff + zds->outStart, toFlushSize);
2152
+ size_t const flushedSize = ZSTD_limitCopy(op, (size_t)(oend-op), zds->outBuff + zds->outStart, toFlushSize);
1696
2153
  op += flushedSize;
1697
2154
  zds->outStart += flushedSize;
1698
2155
  if (flushedSize == toFlushSize) { /* flush completed */
@@ -1712,17 +2169,21 @@ size_t ZSTD_decompressStream(ZSTD_DStream* zds, ZSTD_outBuffer* output, ZSTD_inB
1712
2169
 
1713
2170
  default:
1714
2171
  assert(0); /* impossible */
1715
- RETURN_ERROR(GENERIC); /* some compiler require default to do something */
2172
+ RETURN_ERROR(GENERIC, "impossible to reach"); /* some compiler require default to do something */
1716
2173
  } }
1717
2174
 
1718
2175
  /* result */
1719
2176
  input->pos = (size_t)(ip - (const char*)(input->src));
1720
2177
  output->pos = (size_t)(op - (char*)(output->dst));
2178
+
2179
+ /* Update the expected output buffer for ZSTD_obm_stable. */
2180
+ zds->expectedOutBuffer = *output;
2181
+
1721
2182
  if ((ip==istart) && (op==ostart)) { /* no forward progress */
1722
2183
  zds->noForwardProgress ++;
1723
2184
  if (zds->noForwardProgress >= ZSTD_NO_FORWARD_PROGRESS_MAX) {
1724
- RETURN_ERROR_IF(op==oend, dstSize_tooSmall);
1725
- RETURN_ERROR_IF(ip==iend, srcSize_wrong);
2185
+ RETURN_ERROR_IF(op==oend, dstSize_tooSmall, "");
2186
+ RETURN_ERROR_IF(ip==iend, srcSize_wrong, "");
1726
2187
  assert(0);
1727
2188
  }
1728
2189
  } else {