zstd-ruby 1.4.5.0 → 1.5.5.0

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 (115) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +2 -0
  3. data/README.md +78 -5
  4. data/Rakefile +8 -2
  5. data/ext/zstdruby/common.h +15 -0
  6. data/ext/zstdruby/extconf.rb +3 -2
  7. data/ext/zstdruby/libzstd/common/allocations.h +55 -0
  8. data/ext/zstdruby/libzstd/common/bits.h +200 -0
  9. data/ext/zstdruby/libzstd/common/bitstream.h +45 -62
  10. data/ext/zstdruby/libzstd/common/compiler.h +205 -22
  11. data/ext/zstdruby/libzstd/common/cpu.h +1 -3
  12. data/ext/zstdruby/libzstd/common/debug.c +1 -1
  13. data/ext/zstdruby/libzstd/common/debug.h +12 -19
  14. data/ext/zstdruby/libzstd/common/entropy_common.c +172 -48
  15. data/ext/zstdruby/libzstd/common/error_private.c +10 -2
  16. data/ext/zstdruby/libzstd/common/error_private.h +82 -3
  17. data/ext/zstdruby/libzstd/common/fse.h +37 -86
  18. data/ext/zstdruby/libzstd/common/fse_decompress.c +117 -92
  19. data/ext/zstdruby/libzstd/common/huf.h +99 -166
  20. data/ext/zstdruby/libzstd/common/mem.h +124 -142
  21. data/ext/zstdruby/libzstd/common/pool.c +54 -27
  22. data/ext/zstdruby/libzstd/common/pool.h +10 -4
  23. data/ext/zstdruby/libzstd/common/portability_macros.h +156 -0
  24. data/ext/zstdruby/libzstd/common/threading.c +74 -19
  25. data/ext/zstdruby/libzstd/common/threading.h +5 -10
  26. data/ext/zstdruby/libzstd/common/xxhash.c +7 -847
  27. data/ext/zstdruby/libzstd/common/xxhash.h +5568 -167
  28. data/ext/zstdruby/libzstd/common/zstd_common.c +2 -37
  29. data/ext/zstdruby/libzstd/common/zstd_deps.h +111 -0
  30. data/ext/zstdruby/libzstd/common/zstd_internal.h +132 -187
  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 +83 -157
  34. data/ext/zstdruby/libzstd/compress/hist.c +27 -29
  35. data/ext/zstdruby/libzstd/compress/hist.h +2 -2
  36. data/ext/zstdruby/libzstd/compress/huf_compress.c +916 -279
  37. data/ext/zstdruby/libzstd/compress/zstd_compress.c +3773 -1019
  38. data/ext/zstdruby/libzstd/compress/zstd_compress_internal.h +610 -203
  39. data/ext/zstdruby/libzstd/compress/zstd_compress_literals.c +119 -42
  40. data/ext/zstdruby/libzstd/compress/zstd_compress_literals.h +16 -6
  41. data/ext/zstdruby/libzstd/compress/zstd_compress_sequences.c +42 -19
  42. data/ext/zstdruby/libzstd/compress/zstd_compress_sequences.h +1 -1
  43. data/ext/zstdruby/libzstd/compress/zstd_compress_superblock.c +49 -317
  44. data/ext/zstdruby/libzstd/compress/zstd_compress_superblock.h +1 -1
  45. data/ext/zstdruby/libzstd/compress/zstd_cwksp.h +320 -103
  46. data/ext/zstdruby/libzstd/compress/zstd_double_fast.c +388 -151
  47. data/ext/zstdruby/libzstd/compress/zstd_double_fast.h +3 -2
  48. data/ext/zstdruby/libzstd/compress/zstd_fast.c +729 -265
  49. data/ext/zstdruby/libzstd/compress/zstd_fast.h +3 -2
  50. data/ext/zstdruby/libzstd/compress/zstd_lazy.c +1270 -251
  51. data/ext/zstdruby/libzstd/compress/zstd_lazy.h +61 -1
  52. data/ext/zstdruby/libzstd/compress/zstd_ldm.c +324 -219
  53. data/ext/zstdruby/libzstd/compress/zstd_ldm.h +9 -2
  54. data/ext/zstdruby/libzstd/compress/zstd_ldm_geartab.h +106 -0
  55. data/ext/zstdruby/libzstd/compress/zstd_opt.c +481 -209
  56. data/ext/zstdruby/libzstd/compress/zstd_opt.h +1 -1
  57. data/ext/zstdruby/libzstd/compress/zstdmt_compress.c +181 -457
  58. data/ext/zstdruby/libzstd/compress/zstdmt_compress.h +34 -113
  59. data/ext/zstdruby/libzstd/decompress/huf_decompress.c +1199 -565
  60. data/ext/zstdruby/libzstd/decompress/huf_decompress_amd64.S +576 -0
  61. data/ext/zstdruby/libzstd/decompress/zstd_ddict.c +12 -12
  62. data/ext/zstdruby/libzstd/decompress/zstd_ddict.h +2 -2
  63. data/ext/zstdruby/libzstd/decompress/zstd_decompress.c +627 -157
  64. data/ext/zstdruby/libzstd/decompress/zstd_decompress_block.c +1086 -326
  65. data/ext/zstdruby/libzstd/decompress/zstd_decompress_block.h +19 -5
  66. data/ext/zstdruby/libzstd/decompress/zstd_decompress_internal.h +62 -13
  67. data/ext/zstdruby/libzstd/dictBuilder/cover.c +73 -52
  68. data/ext/zstdruby/libzstd/dictBuilder/cover.h +7 -6
  69. data/ext/zstdruby/libzstd/dictBuilder/divsufsort.c +1 -1
  70. data/ext/zstdruby/libzstd/dictBuilder/fastcover.c +44 -35
  71. data/ext/zstdruby/libzstd/dictBuilder/zdict.c +103 -111
  72. data/ext/zstdruby/libzstd/{dictBuilder/zdict.h → zdict.h} +203 -34
  73. data/ext/zstdruby/libzstd/zstd.h +1217 -287
  74. data/ext/zstdruby/libzstd/{common/zstd_errors.h → zstd_errors.h} +28 -8
  75. data/ext/zstdruby/main.c +20 -0
  76. data/ext/zstdruby/skippable_frame.c +63 -0
  77. data/ext/zstdruby/streaming_compress.c +177 -0
  78. data/ext/zstdruby/streaming_compress.h +5 -0
  79. data/ext/zstdruby/streaming_decompress.c +123 -0
  80. data/ext/zstdruby/zstdruby.c +114 -32
  81. data/lib/zstd-ruby/version.rb +1 -1
  82. data/lib/zstd-ruby.rb +0 -1
  83. data/zstd-ruby.gemspec +1 -1
  84. metadata +19 -36
  85. data/.travis.yml +0 -14
  86. data/ext/zstdruby/libzstd/.gitignore +0 -3
  87. data/ext/zstdruby/libzstd/BUCK +0 -234
  88. data/ext/zstdruby/libzstd/Makefile +0 -354
  89. data/ext/zstdruby/libzstd/README.md +0 -179
  90. data/ext/zstdruby/libzstd/deprecated/zbuff.h +0 -214
  91. data/ext/zstdruby/libzstd/deprecated/zbuff_common.c +0 -26
  92. data/ext/zstdruby/libzstd/deprecated/zbuff_compress.c +0 -147
  93. data/ext/zstdruby/libzstd/deprecated/zbuff_decompress.c +0 -75
  94. data/ext/zstdruby/libzstd/dll/example/Makefile +0 -48
  95. data/ext/zstdruby/libzstd/dll/example/README.md +0 -69
  96. data/ext/zstdruby/libzstd/dll/example/build_package.bat +0 -20
  97. data/ext/zstdruby/libzstd/dll/example/fullbench-dll.sln +0 -25
  98. data/ext/zstdruby/libzstd/dll/example/fullbench-dll.vcxproj +0 -181
  99. data/ext/zstdruby/libzstd/legacy/zstd_legacy.h +0 -415
  100. data/ext/zstdruby/libzstd/legacy/zstd_v01.c +0 -2158
  101. data/ext/zstdruby/libzstd/legacy/zstd_v01.h +0 -94
  102. data/ext/zstdruby/libzstd/legacy/zstd_v02.c +0 -3518
  103. data/ext/zstdruby/libzstd/legacy/zstd_v02.h +0 -93
  104. data/ext/zstdruby/libzstd/legacy/zstd_v03.c +0 -3160
  105. data/ext/zstdruby/libzstd/legacy/zstd_v03.h +0 -93
  106. data/ext/zstdruby/libzstd/legacy/zstd_v04.c +0 -3647
  107. data/ext/zstdruby/libzstd/legacy/zstd_v04.h +0 -142
  108. data/ext/zstdruby/libzstd/legacy/zstd_v05.c +0 -4050
  109. data/ext/zstdruby/libzstd/legacy/zstd_v05.h +0 -162
  110. data/ext/zstdruby/libzstd/legacy/zstd_v06.c +0 -4154
  111. data/ext/zstdruby/libzstd/legacy/zstd_v06.h +0 -172
  112. data/ext/zstdruby/libzstd/legacy/zstd_v07.c +0 -4541
  113. data/ext/zstdruby/libzstd/legacy/zstd_v07.h +0 -187
  114. data/ext/zstdruby/libzstd/libzstd.pc.in +0 -15
  115. data/ext/zstdruby/zstdruby.h +0 -6
@@ -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
@@ -55,23 +55,165 @@
55
55
  /*-*******************************************************
56
56
  * Dependencies
57
57
  *********************************************************/
58
- #include <string.h> /* memcpy, memmove, memset */
59
- #include "../common/cpu.h" /* bmi2 */
58
+ #include "../common/allocations.h" /* ZSTD_customMalloc, ZSTD_customCalloc, ZSTD_customFree */
59
+ #include "../common/zstd_deps.h" /* ZSTD_memcpy, ZSTD_memmove, ZSTD_memset */
60
60
  #include "../common/mem.h" /* low level memory routines */
61
61
  #define FSE_STATIC_LINKING_ONLY
62
62
  #include "../common/fse.h"
63
- #define HUF_STATIC_LINKING_ONLY
64
63
  #include "../common/huf.h"
64
+ #include "../common/xxhash.h" /* XXH64_reset, XXH64_update, XXH64_digest, XXH64 */
65
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
+ #include "../common/bits.h" /* ZSTD_highbit32 */
69
70
 
70
71
  #if defined(ZSTD_LEGACY_SUPPORT) && (ZSTD_LEGACY_SUPPORT>=1)
71
72
  # include "../legacy/zstd_legacy.h"
72
73
  #endif
73
74
 
74
75
 
76
+
77
+ /*************************************
78
+ * Multiple DDicts Hashset internals *
79
+ *************************************/
80
+
81
+ #define DDICT_HASHSET_MAX_LOAD_FACTOR_COUNT_MULT 4
82
+ #define DDICT_HASHSET_MAX_LOAD_FACTOR_SIZE_MULT 3 /* These two constants represent SIZE_MULT/COUNT_MULT load factor without using a float.
83
+ * Currently, that means a 0.75 load factor.
84
+ * So, if count * COUNT_MULT / size * SIZE_MULT != 0, then we've exceeded
85
+ * the load factor of the ddict hash set.
86
+ */
87
+
88
+ #define DDICT_HASHSET_TABLE_BASE_SIZE 64
89
+ #define DDICT_HASHSET_RESIZE_FACTOR 2
90
+
91
+ /* Hash function to determine starting position of dict insertion within the table
92
+ * Returns an index between [0, hashSet->ddictPtrTableSize]
93
+ */
94
+ static size_t ZSTD_DDictHashSet_getIndex(const ZSTD_DDictHashSet* hashSet, U32 dictID) {
95
+ const U64 hash = XXH64(&dictID, sizeof(U32), 0);
96
+ /* DDict ptr table size is a multiple of 2, use size - 1 as mask to get index within [0, hashSet->ddictPtrTableSize) */
97
+ return hash & (hashSet->ddictPtrTableSize - 1);
98
+ }
99
+
100
+ /* Adds DDict to a hashset without resizing it.
101
+ * If inserting a DDict with a dictID that already exists in the set, replaces the one in the set.
102
+ * Returns 0 if successful, or a zstd error code if something went wrong.
103
+ */
104
+ static size_t ZSTD_DDictHashSet_emplaceDDict(ZSTD_DDictHashSet* hashSet, const ZSTD_DDict* ddict) {
105
+ const U32 dictID = ZSTD_getDictID_fromDDict(ddict);
106
+ size_t idx = ZSTD_DDictHashSet_getIndex(hashSet, dictID);
107
+ const size_t idxRangeMask = hashSet->ddictPtrTableSize - 1;
108
+ RETURN_ERROR_IF(hashSet->ddictPtrCount == hashSet->ddictPtrTableSize, GENERIC, "Hash set is full!");
109
+ DEBUGLOG(4, "Hashed index: for dictID: %u is %zu", dictID, idx);
110
+ while (hashSet->ddictPtrTable[idx] != NULL) {
111
+ /* Replace existing ddict if inserting ddict with same dictID */
112
+ if (ZSTD_getDictID_fromDDict(hashSet->ddictPtrTable[idx]) == dictID) {
113
+ DEBUGLOG(4, "DictID already exists, replacing rather than adding");
114
+ hashSet->ddictPtrTable[idx] = ddict;
115
+ return 0;
116
+ }
117
+ idx &= idxRangeMask;
118
+ idx++;
119
+ }
120
+ DEBUGLOG(4, "Final idx after probing for dictID %u is: %zu", dictID, idx);
121
+ hashSet->ddictPtrTable[idx] = ddict;
122
+ hashSet->ddictPtrCount++;
123
+ return 0;
124
+ }
125
+
126
+ /* Expands hash table by factor of DDICT_HASHSET_RESIZE_FACTOR and
127
+ * rehashes all values, allocates new table, frees old table.
128
+ * Returns 0 on success, otherwise a zstd error code.
129
+ */
130
+ static size_t ZSTD_DDictHashSet_expand(ZSTD_DDictHashSet* hashSet, ZSTD_customMem customMem) {
131
+ size_t newTableSize = hashSet->ddictPtrTableSize * DDICT_HASHSET_RESIZE_FACTOR;
132
+ const ZSTD_DDict** newTable = (const ZSTD_DDict**)ZSTD_customCalloc(sizeof(ZSTD_DDict*) * newTableSize, customMem);
133
+ const ZSTD_DDict** oldTable = hashSet->ddictPtrTable;
134
+ size_t oldTableSize = hashSet->ddictPtrTableSize;
135
+ size_t i;
136
+
137
+ DEBUGLOG(4, "Expanding DDict hash table! Old size: %zu new size: %zu", oldTableSize, newTableSize);
138
+ RETURN_ERROR_IF(!newTable, memory_allocation, "Expanded hashset allocation failed!");
139
+ hashSet->ddictPtrTable = newTable;
140
+ hashSet->ddictPtrTableSize = newTableSize;
141
+ hashSet->ddictPtrCount = 0;
142
+ for (i = 0; i < oldTableSize; ++i) {
143
+ if (oldTable[i] != NULL) {
144
+ FORWARD_IF_ERROR(ZSTD_DDictHashSet_emplaceDDict(hashSet, oldTable[i]), "");
145
+ }
146
+ }
147
+ ZSTD_customFree((void*)oldTable, customMem);
148
+ DEBUGLOG(4, "Finished re-hash");
149
+ return 0;
150
+ }
151
+
152
+ /* Fetches a DDict with the given dictID
153
+ * Returns the ZSTD_DDict* with the requested dictID. If it doesn't exist, then returns NULL.
154
+ */
155
+ static const ZSTD_DDict* ZSTD_DDictHashSet_getDDict(ZSTD_DDictHashSet* hashSet, U32 dictID) {
156
+ size_t idx = ZSTD_DDictHashSet_getIndex(hashSet, dictID);
157
+ const size_t idxRangeMask = hashSet->ddictPtrTableSize - 1;
158
+ DEBUGLOG(4, "Hashed index: for dictID: %u is %zu", dictID, idx);
159
+ for (;;) {
160
+ size_t currDictID = ZSTD_getDictID_fromDDict(hashSet->ddictPtrTable[idx]);
161
+ if (currDictID == dictID || currDictID == 0) {
162
+ /* currDictID == 0 implies a NULL ddict entry */
163
+ break;
164
+ } else {
165
+ idx &= idxRangeMask; /* Goes to start of table when we reach the end */
166
+ idx++;
167
+ }
168
+ }
169
+ DEBUGLOG(4, "Final idx after probing for dictID %u is: %zu", dictID, idx);
170
+ return hashSet->ddictPtrTable[idx];
171
+ }
172
+
173
+ /* Allocates space for and returns a ddict hash set
174
+ * The hash set's ZSTD_DDict* table has all values automatically set to NULL to begin with.
175
+ * Returns NULL if allocation failed.
176
+ */
177
+ static ZSTD_DDictHashSet* ZSTD_createDDictHashSet(ZSTD_customMem customMem) {
178
+ ZSTD_DDictHashSet* ret = (ZSTD_DDictHashSet*)ZSTD_customMalloc(sizeof(ZSTD_DDictHashSet), customMem);
179
+ DEBUGLOG(4, "Allocating new hash set");
180
+ if (!ret)
181
+ return NULL;
182
+ ret->ddictPtrTable = (const ZSTD_DDict**)ZSTD_customCalloc(DDICT_HASHSET_TABLE_BASE_SIZE * sizeof(ZSTD_DDict*), customMem);
183
+ if (!ret->ddictPtrTable) {
184
+ ZSTD_customFree(ret, customMem);
185
+ return NULL;
186
+ }
187
+ ret->ddictPtrTableSize = DDICT_HASHSET_TABLE_BASE_SIZE;
188
+ ret->ddictPtrCount = 0;
189
+ return ret;
190
+ }
191
+
192
+ /* Frees the table of ZSTD_DDict* within a hashset, then frees the hashset itself.
193
+ * Note: The ZSTD_DDict* within the table are NOT freed.
194
+ */
195
+ static void ZSTD_freeDDictHashSet(ZSTD_DDictHashSet* hashSet, ZSTD_customMem customMem) {
196
+ DEBUGLOG(4, "Freeing ddict hash set");
197
+ if (hashSet && hashSet->ddictPtrTable) {
198
+ ZSTD_customFree((void*)hashSet->ddictPtrTable, customMem);
199
+ }
200
+ if (hashSet) {
201
+ ZSTD_customFree(hashSet, customMem);
202
+ }
203
+ }
204
+
205
+ /* Public function: Adds a DDict into the ZSTD_DDictHashSet, possibly triggering a resize of the hash set.
206
+ * Returns 0 on success, or a ZSTD error.
207
+ */
208
+ static size_t ZSTD_DDictHashSet_addDDict(ZSTD_DDictHashSet* hashSet, const ZSTD_DDict* ddict, ZSTD_customMem customMem) {
209
+ DEBUGLOG(4, "Adding dict ID: %u to hashset with - Count: %zu Tablesize: %zu", ZSTD_getDictID_fromDDict(ddict), hashSet->ddictPtrCount, hashSet->ddictPtrTableSize);
210
+ if (hashSet->ddictPtrCount * DDICT_HASHSET_MAX_LOAD_FACTOR_COUNT_MULT / hashSet->ddictPtrTableSize * DDICT_HASHSET_MAX_LOAD_FACTOR_SIZE_MULT != 0) {
211
+ FORWARD_IF_ERROR(ZSTD_DDictHashSet_expand(hashSet, customMem), "");
212
+ }
213
+ FORWARD_IF_ERROR(ZSTD_DDictHashSet_emplaceDDict(hashSet, ddict), "");
214
+ return 0;
215
+ }
216
+
75
217
  /*-*************************************************************
76
218
  * Context management
77
219
  ***************************************************************/
@@ -94,11 +236,20 @@ static size_t ZSTD_startingInputLength(ZSTD_format_e format)
94
236
  return startingInputLength;
95
237
  }
96
238
 
239
+ static void ZSTD_DCtx_resetParameters(ZSTD_DCtx* dctx)
240
+ {
241
+ assert(dctx->streamStage == zdss_init);
242
+ dctx->format = ZSTD_f_zstd1;
243
+ dctx->maxWindowSize = ZSTD_MAXWINDOWSIZE_DEFAULT;
244
+ dctx->outBufferMode = ZSTD_bm_buffered;
245
+ dctx->forceIgnoreChecksum = ZSTD_d_validateChecksum;
246
+ dctx->refMultipleDDicts = ZSTD_rmd_refSingleDDict;
247
+ dctx->disableHufAsm = 0;
248
+ }
249
+
97
250
  static void ZSTD_initDCtx_internal(ZSTD_DCtx* dctx)
98
251
  {
99
- dctx->format = ZSTD_f_zstd1; /* ZSTD_decompressBegin() invokes ZSTD_startingInputLength() with argument dctx->format */
100
252
  dctx->staticSize = 0;
101
- dctx->maxWindowSize = ZSTD_MAXWINDOWSIZE_DEFAULT;
102
253
  dctx->ddict = NULL;
103
254
  dctx->ddictLocal = NULL;
104
255
  dctx->dictEnd = NULL;
@@ -108,12 +259,17 @@ static void ZSTD_initDCtx_internal(ZSTD_DCtx* dctx)
108
259
  dctx->inBuffSize = 0;
109
260
  dctx->outBuffSize = 0;
110
261
  dctx->streamStage = zdss_init;
262
+ #if defined(ZSTD_LEGACY_SUPPORT) && (ZSTD_LEGACY_SUPPORT>=1)
111
263
  dctx->legacyContext = NULL;
112
264
  dctx->previousLegacyVersion = 0;
265
+ #endif
113
266
  dctx->noForwardProgress = 0;
114
267
  dctx->oversizedDuration = 0;
115
- dctx->bmi2 = ZSTD_cpuid_bmi2(ZSTD_cpuid());
116
- dctx->outBufferMode = ZSTD_obm_buffered;
268
+ #if DYNAMIC_BMI2
269
+ dctx->bmi2 = ZSTD_cpuSupportsBmi2();
270
+ #endif
271
+ dctx->ddictSet = NULL;
272
+ ZSTD_DCtx_resetParameters(dctx);
117
273
  #ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
118
274
  dctx->dictContentEndForFuzzing = NULL;
119
275
  #endif
@@ -132,11 +288,10 @@ ZSTD_DCtx* ZSTD_initStaticDCtx(void *workspace, size_t workspaceSize)
132
288
  return dctx;
133
289
  }
134
290
 
135
- ZSTD_DCtx* ZSTD_createDCtx_advanced(ZSTD_customMem customMem)
136
- {
137
- if (!customMem.customAlloc ^ !customMem.customFree) return NULL;
291
+ static ZSTD_DCtx* ZSTD_createDCtx_internal(ZSTD_customMem customMem) {
292
+ if ((!customMem.customAlloc) ^ (!customMem.customFree)) return NULL;
138
293
 
139
- { ZSTD_DCtx* const dctx = (ZSTD_DCtx*)ZSTD_malloc(sizeof(*dctx), customMem);
294
+ { ZSTD_DCtx* const dctx = (ZSTD_DCtx*)ZSTD_customMalloc(sizeof(*dctx), customMem);
140
295
  if (!dctx) return NULL;
141
296
  dctx->customMem = customMem;
142
297
  ZSTD_initDCtx_internal(dctx);
@@ -144,10 +299,15 @@ ZSTD_DCtx* ZSTD_createDCtx_advanced(ZSTD_customMem customMem)
144
299
  }
145
300
  }
146
301
 
302
+ ZSTD_DCtx* ZSTD_createDCtx_advanced(ZSTD_customMem customMem)
303
+ {
304
+ return ZSTD_createDCtx_internal(customMem);
305
+ }
306
+
147
307
  ZSTD_DCtx* ZSTD_createDCtx(void)
148
308
  {
149
309
  DEBUGLOG(3, "ZSTD_createDCtx");
150
- return ZSTD_createDCtx_advanced(ZSTD_defaultCMem);
310
+ return ZSTD_createDCtx_internal(ZSTD_defaultCMem);
151
311
  }
152
312
 
153
313
  static void ZSTD_clearDict(ZSTD_DCtx* dctx)
@@ -164,13 +324,17 @@ size_t ZSTD_freeDCtx(ZSTD_DCtx* dctx)
164
324
  RETURN_ERROR_IF(dctx->staticSize, memory_allocation, "not compatible with static DCtx");
165
325
  { ZSTD_customMem const cMem = dctx->customMem;
166
326
  ZSTD_clearDict(dctx);
167
- ZSTD_free(dctx->inBuff, cMem);
327
+ ZSTD_customFree(dctx->inBuff, cMem);
168
328
  dctx->inBuff = NULL;
169
329
  #if defined(ZSTD_LEGACY_SUPPORT) && (ZSTD_LEGACY_SUPPORT >= 1)
170
330
  if (dctx->legacyContext)
171
331
  ZSTD_freeLegacyStreamContext(dctx->legacyContext, dctx->previousLegacyVersion);
172
332
  #endif
173
- ZSTD_free(dctx, cMem);
333
+ if (dctx->ddictSet) {
334
+ ZSTD_freeDDictHashSet(dctx->ddictSet, cMem);
335
+ dctx->ddictSet = NULL;
336
+ }
337
+ ZSTD_customFree(dctx, cMem);
174
338
  return 0;
175
339
  }
176
340
  }
@@ -179,7 +343,30 @@ size_t ZSTD_freeDCtx(ZSTD_DCtx* dctx)
179
343
  void ZSTD_copyDCtx(ZSTD_DCtx* dstDCtx, const ZSTD_DCtx* srcDCtx)
180
344
  {
181
345
  size_t const toCopy = (size_t)((char*)(&dstDCtx->inBuff) - (char*)dstDCtx);
182
- memcpy(dstDCtx, srcDCtx, toCopy); /* no need to copy workspace */
346
+ ZSTD_memcpy(dstDCtx, srcDCtx, toCopy); /* no need to copy workspace */
347
+ }
348
+
349
+ /* Given a dctx with a digested frame params, re-selects the correct ZSTD_DDict based on
350
+ * the requested dict ID from the frame. If there exists a reference to the correct ZSTD_DDict, then
351
+ * accordingly sets the ddict to be used to decompress the frame.
352
+ *
353
+ * If no DDict is found, then no action is taken, and the ZSTD_DCtx::ddict remains as-is.
354
+ *
355
+ * ZSTD_d_refMultipleDDicts must be enabled for this function to be called.
356
+ */
357
+ static void ZSTD_DCtx_selectFrameDDict(ZSTD_DCtx* dctx) {
358
+ assert(dctx->refMultipleDDicts && dctx->ddictSet);
359
+ DEBUGLOG(4, "Adjusting DDict based on requested dict ID from frame");
360
+ if (dctx->ddict) {
361
+ const ZSTD_DDict* frameDDict = ZSTD_DDictHashSet_getDDict(dctx->ddictSet, dctx->fParams.dictID);
362
+ if (frameDDict) {
363
+ DEBUGLOG(4, "DDict found!");
364
+ ZSTD_clearDict(dctx);
365
+ dctx->dictID = dctx->fParams.dictID;
366
+ dctx->ddict = frameDDict;
367
+ dctx->dictUses = ZSTD_use_indefinitely;
368
+ }
369
+ }
183
370
  }
184
371
 
185
372
 
@@ -205,6 +392,19 @@ unsigned ZSTD_isFrame(const void* buffer, size_t size)
205
392
  return 0;
206
393
  }
207
394
 
395
+ /*! ZSTD_isSkippableFrame() :
396
+ * Tells if the content of `buffer` starts with a valid Frame Identifier for a skippable frame.
397
+ * Note : Frame Identifier is 4 bytes. If `size < 4`, @return will always be 0.
398
+ */
399
+ unsigned ZSTD_isSkippableFrame(const void* buffer, size_t size)
400
+ {
401
+ if (size < ZSTD_FRAMEIDSIZE) return 0;
402
+ { U32 const magic = MEM_readLE32(buffer);
403
+ if ((magic & ZSTD_MAGIC_SKIPPABLE_MASK) == ZSTD_MAGIC_SKIPPABLE_START) return 1;
404
+ }
405
+ return 0;
406
+ }
407
+
208
408
  /** ZSTD_frameHeaderSize_internal() :
209
409
  * srcSize must be large enough to reach header size fields.
210
410
  * note : only works for formats ZSTD_f_zstd1 and ZSTD_f_zstd1_magicless.
@@ -240,23 +440,47 @@ size_t ZSTD_frameHeaderSize(const void* src, size_t srcSize)
240
440
  * note : only works for formats ZSTD_f_zstd1 and ZSTD_f_zstd1_magicless
241
441
  * @return : 0, `zfhPtr` is correctly filled,
242
442
  * >0, `srcSize` is too small, value is wanted `srcSize` amount,
243
- * or an error code, which can be tested using ZSTD_isError() */
443
+ ** or an error code, which can be tested using ZSTD_isError() */
244
444
  size_t ZSTD_getFrameHeader_advanced(ZSTD_frameHeader* zfhPtr, const void* src, size_t srcSize, ZSTD_format_e format)
245
445
  {
246
446
  const BYTE* ip = (const BYTE*)src;
247
447
  size_t const minInputSize = ZSTD_startingInputLength(format);
248
448
 
249
- 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 */
250
- if (srcSize < minInputSize) return minInputSize;
251
- RETURN_ERROR_IF(src==NULL, GENERIC, "invalid parameter");
449
+ DEBUGLOG(5, "ZSTD_getFrameHeader_advanced: minInputSize = %zu, srcSize = %zu", minInputSize, srcSize);
450
+
451
+ if (srcSize > 0) {
452
+ /* note : technically could be considered an assert(), since it's an invalid entry */
453
+ RETURN_ERROR_IF(src==NULL, GENERIC, "invalid parameter : src==NULL, but srcSize>0");
454
+ }
455
+ if (srcSize < minInputSize) {
456
+ if (srcSize > 0 && format != ZSTD_f_zstd1_magicless) {
457
+ /* when receiving less than @minInputSize bytes,
458
+ * control these bytes at least correspond to a supported magic number
459
+ * in order to error out early if they don't.
460
+ **/
461
+ size_t const toCopy = MIN(4, srcSize);
462
+ unsigned char hbuf[4]; MEM_writeLE32(hbuf, ZSTD_MAGICNUMBER);
463
+ assert(src != NULL);
464
+ ZSTD_memcpy(hbuf, src, toCopy);
465
+ if ( MEM_readLE32(hbuf) != ZSTD_MAGICNUMBER ) {
466
+ /* not a zstd frame : let's check if it's a skippable frame */
467
+ MEM_writeLE32(hbuf, ZSTD_MAGIC_SKIPPABLE_START);
468
+ ZSTD_memcpy(hbuf, src, toCopy);
469
+ if ((MEM_readLE32(hbuf) & ZSTD_MAGIC_SKIPPABLE_MASK) != ZSTD_MAGIC_SKIPPABLE_START) {
470
+ RETURN_ERROR(prefix_unknown,
471
+ "first bytes don't correspond to any supported magic number");
472
+ } } }
473
+ return minInputSize;
474
+ }
252
475
 
476
+ 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 */
253
477
  if ( (format != ZSTD_f_zstd1_magicless)
254
478
  && (MEM_readLE32(src) != ZSTD_MAGICNUMBER) ) {
255
479
  if ((MEM_readLE32(src) & ZSTD_MAGIC_SKIPPABLE_MASK) == ZSTD_MAGIC_SKIPPABLE_START) {
256
480
  /* skippable frame */
257
481
  if (srcSize < ZSTD_SKIPPABLEHEADERSIZE)
258
482
  return ZSTD_SKIPPABLEHEADERSIZE; /* magic number + frame length */
259
- memset(zfhPtr, 0, sizeof(*zfhPtr));
483
+ ZSTD_memset(zfhPtr, 0, sizeof(*zfhPtr));
260
484
  zfhPtr->frameContentSize = MEM_readLE32((const char *)src + ZSTD_FRAMEIDSIZE);
261
485
  zfhPtr->frameType = ZSTD_skippableFrame;
262
486
  return 0;
@@ -291,7 +515,9 @@ size_t ZSTD_getFrameHeader_advanced(ZSTD_frameHeader* zfhPtr, const void* src, s
291
515
  }
292
516
  switch(dictIDSizeCode)
293
517
  {
294
- default: assert(0); /* impossible */
518
+ default:
519
+ assert(0); /* impossible */
520
+ ZSTD_FALLTHROUGH;
295
521
  case 0 : break;
296
522
  case 1 : dictID = ip[pos]; pos++; break;
297
523
  case 2 : dictID = MEM_readLE16(ip+pos); pos+=2; break;
@@ -299,7 +525,9 @@ size_t ZSTD_getFrameHeader_advanced(ZSTD_frameHeader* zfhPtr, const void* src, s
299
525
  }
300
526
  switch(fcsID)
301
527
  {
302
- default: assert(0); /* impossible */
528
+ default:
529
+ assert(0); /* impossible */
530
+ ZSTD_FALLTHROUGH;
303
531
  case 0 : if (singleSegment) frameContentSize = ip[pos]; break;
304
532
  case 1 : frameContentSize = MEM_readLE16(ip+pos)+256; break;
305
533
  case 2 : frameContentSize = MEM_readLE32(ip+pos); break;
@@ -328,7 +556,6 @@ size_t ZSTD_getFrameHeader(ZSTD_frameHeader* zfhPtr, const void* src, size_t src
328
556
  return ZSTD_getFrameHeader_advanced(zfhPtr, src, srcSize, ZSTD_f_zstd1);
329
557
  }
330
558
 
331
-
332
559
  /** ZSTD_getFrameContentSize() :
333
560
  * compatible with legacy mode
334
561
  * @return : decompressed size of the single frame pointed to be `src` if known, otherwise
@@ -362,18 +589,52 @@ static size_t readSkippableFrameSize(void const* src, size_t srcSize)
362
589
  sizeU32 = MEM_readLE32((BYTE const*)src + ZSTD_FRAMEIDSIZE);
363
590
  RETURN_ERROR_IF((U32)(sizeU32 + ZSTD_SKIPPABLEHEADERSIZE) < sizeU32,
364
591
  frameParameter_unsupported, "");
365
- {
366
- size_t const skippableSize = skippableHeaderSize + sizeU32;
592
+ { size_t const skippableSize = skippableHeaderSize + sizeU32;
367
593
  RETURN_ERROR_IF(skippableSize > srcSize, srcSize_wrong, "");
368
594
  return skippableSize;
369
595
  }
370
596
  }
371
597
 
598
+ /*! ZSTD_readSkippableFrame() :
599
+ * Retrieves content of a skippable frame, and writes it to dst buffer.
600
+ *
601
+ * The parameter magicVariant will receive the magicVariant that was supplied when the frame was written,
602
+ * i.e. magicNumber - ZSTD_MAGIC_SKIPPABLE_START. This can be NULL if the caller is not interested
603
+ * in the magicVariant.
604
+ *
605
+ * Returns an error if destination buffer is not large enough, or if this is not a valid skippable frame.
606
+ *
607
+ * @return : number of bytes written or a ZSTD error.
608
+ */
609
+ size_t ZSTD_readSkippableFrame(void* dst, size_t dstCapacity,
610
+ unsigned* magicVariant, /* optional, can be NULL */
611
+ const void* src, size_t srcSize)
612
+ {
613
+ RETURN_ERROR_IF(srcSize < ZSTD_SKIPPABLEHEADERSIZE, srcSize_wrong, "");
614
+
615
+ { U32 const magicNumber = MEM_readLE32(src);
616
+ size_t skippableFrameSize = readSkippableFrameSize(src, srcSize);
617
+ size_t skippableContentSize = skippableFrameSize - ZSTD_SKIPPABLEHEADERSIZE;
618
+
619
+ /* check input validity */
620
+ RETURN_ERROR_IF(!ZSTD_isSkippableFrame(src, srcSize), frameParameter_unsupported, "");
621
+ RETURN_ERROR_IF(skippableFrameSize < ZSTD_SKIPPABLEHEADERSIZE || skippableFrameSize > srcSize, srcSize_wrong, "");
622
+ RETURN_ERROR_IF(skippableContentSize > dstCapacity, dstSize_tooSmall, "");
623
+
624
+ /* deliver payload */
625
+ if (skippableContentSize > 0 && dst != NULL)
626
+ ZSTD_memcpy(dst, (const BYTE *)src + ZSTD_SKIPPABLEHEADERSIZE, skippableContentSize);
627
+ if (magicVariant != NULL)
628
+ *magicVariant = magicNumber - ZSTD_MAGIC_SKIPPABLE_START;
629
+ return skippableContentSize;
630
+ }
631
+ }
632
+
372
633
  /** ZSTD_findDecompressedSize() :
373
- * compatible with legacy mode
374
634
  * `srcSize` must be the exact length of some number of ZSTD compressed and/or
375
635
  * skippable frames
376
- * @return : decompressed size of the frames contained */
636
+ * note: compatible with legacy mode
637
+ * @return : decompressed size of the frames contained */
377
638
  unsigned long long ZSTD_findDecompressedSize(const void* src, size_t srcSize)
378
639
  {
379
640
  unsigned long long totalDstSize = 0;
@@ -383,9 +644,7 @@ unsigned long long ZSTD_findDecompressedSize(const void* src, size_t srcSize)
383
644
 
384
645
  if ((magicNumber & ZSTD_MAGIC_SKIPPABLE_MASK) == ZSTD_MAGIC_SKIPPABLE_START) {
385
646
  size_t const skippableSize = readSkippableFrameSize(src, srcSize);
386
- if (ZSTD_isError(skippableSize)) {
387
- return ZSTD_CONTENTSIZE_ERROR;
388
- }
647
+ if (ZSTD_isError(skippableSize)) return ZSTD_CONTENTSIZE_ERROR;
389
648
  assert(skippableSize <= srcSize);
390
649
 
391
650
  src = (const BYTE *)src + skippableSize;
@@ -393,17 +652,17 @@ unsigned long long ZSTD_findDecompressedSize(const void* src, size_t srcSize)
393
652
  continue;
394
653
  }
395
654
 
396
- { unsigned long long const ret = ZSTD_getFrameContentSize(src, srcSize);
397
- if (ret >= ZSTD_CONTENTSIZE_ERROR) return ret;
655
+ { unsigned long long const fcs = ZSTD_getFrameContentSize(src, srcSize);
656
+ if (fcs >= ZSTD_CONTENTSIZE_ERROR) return fcs;
398
657
 
399
- /* check for overflow */
400
- if (totalDstSize + ret < totalDstSize) return ZSTD_CONTENTSIZE_ERROR;
401
- totalDstSize += ret;
658
+ if (totalDstSize + fcs < totalDstSize)
659
+ return ZSTD_CONTENTSIZE_ERROR; /* check for overflow */
660
+ totalDstSize += fcs;
402
661
  }
662
+ /* skip to next frame */
403
663
  { size_t const frameSrcSize = ZSTD_findFrameCompressedSize(src, srcSize);
404
- if (ZSTD_isError(frameSrcSize)) {
405
- return ZSTD_CONTENTSIZE_ERROR;
406
- }
664
+ if (ZSTD_isError(frameSrcSize)) return ZSTD_CONTENTSIZE_ERROR;
665
+ assert(frameSrcSize <= srcSize);
407
666
 
408
667
  src = (const BYTE *)src + frameSrcSize;
409
668
  srcSize -= frameSrcSize;
@@ -433,12 +692,19 @@ unsigned long long ZSTD_getDecompressedSize(const void* src, size_t srcSize)
433
692
 
434
693
  /** ZSTD_decodeFrameHeader() :
435
694
  * `headerSize` must be the size provided by ZSTD_frameHeaderSize().
695
+ * If multiple DDict references are enabled, also will choose the correct DDict to use.
436
696
  * @return : 0 if success, or an error code, which can be tested using ZSTD_isError() */
437
697
  static size_t ZSTD_decodeFrameHeader(ZSTD_DCtx* dctx, const void* src, size_t headerSize)
438
698
  {
439
699
  size_t const result = ZSTD_getFrameHeader_advanced(&(dctx->fParams), src, headerSize, dctx->format);
440
700
  if (ZSTD_isError(result)) return result; /* invalid header */
441
701
  RETURN_ERROR_IF(result>0, srcSize_wrong, "headerSize too small");
702
+
703
+ /* Reference DDict requested by frame if dctx references multiple ddicts */
704
+ if (dctx->refMultipleDDicts == ZSTD_rmd_refMultipleDDicts && dctx->ddictSet) {
705
+ ZSTD_DCtx_selectFrameDDict(dctx);
706
+ }
707
+
442
708
  #ifndef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
443
709
  /* Skip the dictID check in fuzzing mode, because it makes the search
444
710
  * harder.
@@ -446,7 +712,9 @@ static size_t ZSTD_decodeFrameHeader(ZSTD_DCtx* dctx, const void* src, size_t he
446
712
  RETURN_ERROR_IF(dctx->fParams.dictID && (dctx->dictID != dctx->fParams.dictID),
447
713
  dictionary_wrong, "");
448
714
  #endif
449
- if (dctx->fParams.checksumFlag) XXH64_reset(&dctx->xxhState, 0);
715
+ dctx->validateChecksum = (dctx->fParams.checksumFlag && !dctx->forceIgnoreChecksum) ? 1 : 0;
716
+ if (dctx->validateChecksum) XXH64_reset(&dctx->xxhState, 0);
717
+ dctx->processedCSize += headerSize;
450
718
  return 0;
451
719
  }
452
720
 
@@ -461,7 +729,7 @@ static ZSTD_frameSizeInfo ZSTD_errorFrameSizeInfo(size_t ret)
461
729
  static ZSTD_frameSizeInfo ZSTD_findFrameSizeInfo(const void* src, size_t srcSize)
462
730
  {
463
731
  ZSTD_frameSizeInfo frameSizeInfo;
464
- memset(&frameSizeInfo, 0, sizeof(ZSTD_frameSizeInfo));
732
+ ZSTD_memset(&frameSizeInfo, 0, sizeof(ZSTD_frameSizeInfo));
465
733
 
466
734
  #if defined(ZSTD_LEGACY_SUPPORT) && (ZSTD_LEGACY_SUPPORT >= 1)
467
735
  if (ZSTD_isLegacy(src, srcSize))
@@ -516,10 +784,11 @@ static ZSTD_frameSizeInfo ZSTD_findFrameSizeInfo(const void* src, size_t srcSize
516
784
  ip += 4;
517
785
  }
518
786
 
519
- frameSizeInfo.compressedSize = ip - ipstart;
787
+ frameSizeInfo.nbBlocks = nbBlocks;
788
+ frameSizeInfo.compressedSize = (size_t)(ip - ipstart);
520
789
  frameSizeInfo.decompressedBound = (zfh.frameContentSize != ZSTD_CONTENTSIZE_UNKNOWN)
521
790
  ? zfh.frameContentSize
522
- : nbBlocks * zfh.blockSizeMax;
791
+ : (unsigned long long)nbBlocks * zfh.blockSizeMax;
523
792
  return frameSizeInfo;
524
793
  }
525
794
  }
@@ -559,6 +828,48 @@ unsigned long long ZSTD_decompressBound(const void* src, size_t srcSize)
559
828
  return bound;
560
829
  }
561
830
 
831
+ size_t ZSTD_decompressionMargin(void const* src, size_t srcSize)
832
+ {
833
+ size_t margin = 0;
834
+ unsigned maxBlockSize = 0;
835
+
836
+ /* Iterate over each frame */
837
+ while (srcSize > 0) {
838
+ ZSTD_frameSizeInfo const frameSizeInfo = ZSTD_findFrameSizeInfo(src, srcSize);
839
+ size_t const compressedSize = frameSizeInfo.compressedSize;
840
+ unsigned long long const decompressedBound = frameSizeInfo.decompressedBound;
841
+ ZSTD_frameHeader zfh;
842
+
843
+ FORWARD_IF_ERROR(ZSTD_getFrameHeader(&zfh, src, srcSize), "");
844
+ if (ZSTD_isError(compressedSize) || decompressedBound == ZSTD_CONTENTSIZE_ERROR)
845
+ return ERROR(corruption_detected);
846
+
847
+ if (zfh.frameType == ZSTD_frame) {
848
+ /* Add the frame header to our margin */
849
+ margin += zfh.headerSize;
850
+ /* Add the checksum to our margin */
851
+ margin += zfh.checksumFlag ? 4 : 0;
852
+ /* Add 3 bytes per block */
853
+ margin += 3 * frameSizeInfo.nbBlocks;
854
+
855
+ /* Compute the max block size */
856
+ maxBlockSize = MAX(maxBlockSize, zfh.blockSizeMax);
857
+ } else {
858
+ assert(zfh.frameType == ZSTD_skippableFrame);
859
+ /* Add the entire skippable frame size to our margin. */
860
+ margin += compressedSize;
861
+ }
862
+
863
+ assert(srcSize >= compressedSize);
864
+ src = (const BYTE*)src + compressedSize;
865
+ srcSize -= compressedSize;
866
+ }
867
+
868
+ /* Add the max block size back to the margin. */
869
+ margin += maxBlockSize;
870
+
871
+ return margin;
872
+ }
562
873
 
563
874
  /*-*************************************************************
564
875
  * Frame decoding
@@ -569,7 +880,7 @@ unsigned long long ZSTD_decompressBound(const void* src, size_t srcSize)
569
880
  size_t ZSTD_insertBlock(ZSTD_DCtx* dctx, const void* blockStart, size_t blockSize)
570
881
  {
571
882
  DEBUGLOG(5, "ZSTD_insertBlock: %u bytes", (unsigned)blockSize);
572
- ZSTD_checkContinuity(dctx, blockStart);
883
+ ZSTD_checkContinuity(dctx, blockStart, blockSize);
573
884
  dctx->previousDstEnd = (const char*)blockStart + blockSize;
574
885
  return blockSize;
575
886
  }
@@ -579,12 +890,12 @@ static size_t ZSTD_copyRawBlock(void* dst, size_t dstCapacity,
579
890
  const void* src, size_t srcSize)
580
891
  {
581
892
  DEBUGLOG(5, "ZSTD_copyRawBlock");
893
+ RETURN_ERROR_IF(srcSize > dstCapacity, dstSize_tooSmall, "");
582
894
  if (dst == NULL) {
583
895
  if (srcSize == 0) return 0;
584
896
  RETURN_ERROR(dstBuffer_null, "");
585
897
  }
586
- RETURN_ERROR_IF(srcSize > dstCapacity, dstSize_tooSmall, "");
587
- memcpy(dst, src, srcSize);
898
+ ZSTD_memmove(dst, src, srcSize);
588
899
  return srcSize;
589
900
  }
590
901
 
@@ -592,15 +903,41 @@ static size_t ZSTD_setRleBlock(void* dst, size_t dstCapacity,
592
903
  BYTE b,
593
904
  size_t regenSize)
594
905
  {
906
+ RETURN_ERROR_IF(regenSize > dstCapacity, dstSize_tooSmall, "");
595
907
  if (dst == NULL) {
596
908
  if (regenSize == 0) return 0;
597
909
  RETURN_ERROR(dstBuffer_null, "");
598
910
  }
599
- RETURN_ERROR_IF(regenSize > dstCapacity, dstSize_tooSmall, "");
600
- memset(dst, b, regenSize);
911
+ ZSTD_memset(dst, b, regenSize);
601
912
  return regenSize;
602
913
  }
603
914
 
915
+ static void ZSTD_DCtx_trace_end(ZSTD_DCtx const* dctx, U64 uncompressedSize, U64 compressedSize, unsigned streaming)
916
+ {
917
+ #if ZSTD_TRACE
918
+ if (dctx->traceCtx && ZSTD_trace_decompress_end != NULL) {
919
+ ZSTD_Trace trace;
920
+ ZSTD_memset(&trace, 0, sizeof(trace));
921
+ trace.version = ZSTD_VERSION_NUMBER;
922
+ trace.streaming = streaming;
923
+ if (dctx->ddict) {
924
+ trace.dictionaryID = ZSTD_getDictID_fromDDict(dctx->ddict);
925
+ trace.dictionarySize = ZSTD_DDict_dictSize(dctx->ddict);
926
+ trace.dictionaryIsCold = dctx->ddictIsCold;
927
+ }
928
+ trace.uncompressedSize = (size_t)uncompressedSize;
929
+ trace.compressedSize = (size_t)compressedSize;
930
+ trace.dctx = dctx;
931
+ ZSTD_trace_decompress_end(dctx->traceCtx, &trace);
932
+ }
933
+ #else
934
+ (void)dctx;
935
+ (void)uncompressedSize;
936
+ (void)compressedSize;
937
+ (void)streaming;
938
+ #endif
939
+ }
940
+
604
941
 
605
942
  /*! ZSTD_decompressFrame() :
606
943
  * @dctx must be properly initialized
@@ -610,8 +947,9 @@ static size_t ZSTD_decompressFrame(ZSTD_DCtx* dctx,
610
947
  void* dst, size_t dstCapacity,
611
948
  const void** srcPtr, size_t *srcSizePtr)
612
949
  {
613
- const BYTE* ip = (const BYTE*)(*srcPtr);
614
- BYTE* const ostart = (BYTE* const)dst;
950
+ const BYTE* const istart = (const BYTE*)(*srcPtr);
951
+ const BYTE* ip = istart;
952
+ BYTE* const ostart = (BYTE*)dst;
615
953
  BYTE* const oend = dstCapacity != 0 ? ostart + dstCapacity : ostart;
616
954
  BYTE* op = ostart;
617
955
  size_t remainingSrcSize = *srcSizePtr;
@@ -635,6 +973,7 @@ static size_t ZSTD_decompressFrame(ZSTD_DCtx* dctx,
635
973
 
636
974
  /* Loop on each block */
637
975
  while (1) {
976
+ BYTE* oBlockEnd = oend;
638
977
  size_t decodedSize;
639
978
  blockProperties_t blockProperties;
640
979
  size_t const cBlockSize = ZSTD_getcBlockSize(ip, remainingSrcSize, &blockProperties);
@@ -644,16 +983,34 @@ static size_t ZSTD_decompressFrame(ZSTD_DCtx* dctx,
644
983
  remainingSrcSize -= ZSTD_blockHeaderSize;
645
984
  RETURN_ERROR_IF(cBlockSize > remainingSrcSize, srcSize_wrong, "");
646
985
 
986
+ if (ip >= op && ip < oBlockEnd) {
987
+ /* We are decompressing in-place. Limit the output pointer so that we
988
+ * don't overwrite the block that we are currently reading. This will
989
+ * fail decompression if the input & output pointers aren't spaced
990
+ * far enough apart.
991
+ *
992
+ * This is important to set, even when the pointers are far enough
993
+ * apart, because ZSTD_decompressBlock_internal() can decide to store
994
+ * literals in the output buffer, after the block it is decompressing.
995
+ * Since we don't want anything to overwrite our input, we have to tell
996
+ * ZSTD_decompressBlock_internal to never write past ip.
997
+ *
998
+ * See ZSTD_allocateLiteralsBuffer() for reference.
999
+ */
1000
+ oBlockEnd = op + (ip - op);
1001
+ }
1002
+
647
1003
  switch(blockProperties.blockType)
648
1004
  {
649
1005
  case bt_compressed:
650
- decodedSize = ZSTD_decompressBlock_internal(dctx, op, oend-op, ip, cBlockSize, /* frame */ 1);
1006
+ decodedSize = ZSTD_decompressBlock_internal(dctx, op, (size_t)(oBlockEnd-op), ip, cBlockSize, /* frame */ 1, not_streaming);
651
1007
  break;
652
1008
  case bt_raw :
653
- decodedSize = ZSTD_copyRawBlock(op, oend-op, ip, cBlockSize);
1009
+ /* Use oend instead of oBlockEnd because this function is safe to overlap. It uses memmove. */
1010
+ decodedSize = ZSTD_copyRawBlock(op, (size_t)(oend-op), ip, cBlockSize);
654
1011
  break;
655
1012
  case bt_rle :
656
- decodedSize = ZSTD_setRleBlock(op, oend-op, *ip, blockProperties.origSize);
1013
+ decodedSize = ZSTD_setRleBlock(op, (size_t)(oBlockEnd-op), *ip, blockProperties.origSize);
657
1014
  break;
658
1015
  case bt_reserved :
659
1016
  default:
@@ -661,7 +1018,7 @@ static size_t ZSTD_decompressFrame(ZSTD_DCtx* dctx,
661
1018
  }
662
1019
 
663
1020
  if (ZSTD_isError(decodedSize)) return decodedSize;
664
- if (dctx->fParams.checksumFlag)
1021
+ if (dctx->validateChecksum)
665
1022
  XXH64_update(&dctx->xxhState, op, decodedSize);
666
1023
  if (decodedSize != 0)
667
1024
  op += decodedSize;
@@ -676,19 +1033,22 @@ static size_t ZSTD_decompressFrame(ZSTD_DCtx* dctx,
676
1033
  corruption_detected, "");
677
1034
  }
678
1035
  if (dctx->fParams.checksumFlag) { /* Frame content checksum verification */
679
- U32 const checkCalc = (U32)XXH64_digest(&dctx->xxhState);
680
- U32 checkRead;
681
1036
  RETURN_ERROR_IF(remainingSrcSize<4, checksum_wrong, "");
682
- checkRead = MEM_readLE32(ip);
683
- RETURN_ERROR_IF(checkRead != checkCalc, checksum_wrong, "");
1037
+ if (!dctx->forceIgnoreChecksum) {
1038
+ U32 const checkCalc = (U32)XXH64_digest(&dctx->xxhState);
1039
+ U32 checkRead;
1040
+ checkRead = MEM_readLE32(ip);
1041
+ RETURN_ERROR_IF(checkRead != checkCalc, checksum_wrong, "");
1042
+ }
684
1043
  ip += 4;
685
1044
  remainingSrcSize -= 4;
686
1045
  }
687
-
1046
+ ZSTD_DCtx_trace_end(dctx, (U64)(op-ostart), (U64)(ip-istart), /* streaming */ 0);
688
1047
  /* Allow caller to get size read */
1048
+ DEBUGLOG(4, "ZSTD_decompressFrame: decompressed frame of size %zi, consuming %zi bytes of input", op-ostart, ip - (const BYTE*)*srcPtr);
689
1049
  *srcPtr = ip;
690
1050
  *srcSizePtr = remainingSrcSize;
691
- return op-ostart;
1051
+ return (size_t)(op-ostart);
692
1052
  }
693
1053
 
694
1054
  static size_t ZSTD_decompressMultiFrame(ZSTD_DCtx* dctx,
@@ -721,7 +1081,7 @@ static size_t ZSTD_decompressMultiFrame(ZSTD_DCtx* dctx,
721
1081
  decodedSize = ZSTD_decompressLegacy(dst, dstCapacity, src, frameSize, dict, dictSize);
722
1082
  if (ZSTD_isError(decodedSize)) return decodedSize;
723
1083
 
724
- assert(decodedSize <=- dstCapacity);
1084
+ assert(decodedSize <= dstCapacity);
725
1085
  dst = (BYTE*)dst + decodedSize;
726
1086
  dstCapacity -= decodedSize;
727
1087
 
@@ -732,17 +1092,18 @@ static size_t ZSTD_decompressMultiFrame(ZSTD_DCtx* dctx,
732
1092
  }
733
1093
  #endif
734
1094
 
735
- { U32 const magicNumber = MEM_readLE32(src);
736
- DEBUGLOG(4, "reading magic number %08X (expecting %08X)",
737
- (unsigned)magicNumber, ZSTD_MAGICNUMBER);
1095
+ if (srcSize >= 4) {
1096
+ U32 const magicNumber = MEM_readLE32(src);
1097
+ DEBUGLOG(5, "reading magic number %08X", (unsigned)magicNumber);
738
1098
  if ((magicNumber & ZSTD_MAGIC_SKIPPABLE_MASK) == ZSTD_MAGIC_SKIPPABLE_START) {
1099
+ /* skippable frame detected : skip it */
739
1100
  size_t const skippableSize = readSkippableFrameSize(src, srcSize);
740
- FORWARD_IF_ERROR(skippableSize, "readSkippableFrameSize failed");
1101
+ FORWARD_IF_ERROR(skippableSize, "invalid skippable frame");
741
1102
  assert(skippableSize <= srcSize);
742
1103
 
743
1104
  src = (const BYTE *)src + skippableSize;
744
1105
  srcSize -= skippableSize;
745
- continue;
1106
+ continue; /* check next frame */
746
1107
  } }
747
1108
 
748
1109
  if (ddict) {
@@ -753,7 +1114,7 @@ static size_t ZSTD_decompressMultiFrame(ZSTD_DCtx* dctx,
753
1114
  * use this in all cases but ddict */
754
1115
  FORWARD_IF_ERROR(ZSTD_decompressBegin_usingDict(dctx, dict, dictSize), "");
755
1116
  }
756
- ZSTD_checkContinuity(dctx, dst);
1117
+ ZSTD_checkContinuity(dctx, dst, dstCapacity);
757
1118
 
758
1119
  { const size_t res = ZSTD_decompressFrame(dctx, dst, dstCapacity,
759
1120
  &src, &srcSize);
@@ -761,15 +1122,13 @@ static size_t ZSTD_decompressMultiFrame(ZSTD_DCtx* dctx,
761
1122
  (ZSTD_getErrorCode(res) == ZSTD_error_prefix_unknown)
762
1123
  && (moreThan1Frame==1),
763
1124
  srcSize_wrong,
764
- "at least one frame successfully completed, but following "
765
- "bytes are garbage: it's more likely to be a srcSize error, "
766
- "specifying more bytes than compressed size of frame(s). This "
767
- "error message replaces ERROR(prefix_unknown), which would be "
768
- "confusing, as the first header is actually correct. Note that "
769
- "one could be unlucky, it might be a corruption error instead, "
770
- "happening right at the place where we expect zstd magic "
771
- "bytes. But this is _much_ less likely than a srcSize field "
772
- "error.");
1125
+ "At least one frame successfully completed, "
1126
+ "but following bytes are garbage: "
1127
+ "it's more likely to be a srcSize error, "
1128
+ "specifying more input bytes than size of frame(s). "
1129
+ "Note: one could be unlucky, it might be a corruption error instead, "
1130
+ "happening right at the place where we expect zstd magic bytes. "
1131
+ "But this is _much_ less likely than a srcSize field error.");
773
1132
  if (ZSTD_isError(res)) return res;
774
1133
  assert(res <= dstCapacity);
775
1134
  if (res != 0)
@@ -781,7 +1140,7 @@ static size_t ZSTD_decompressMultiFrame(ZSTD_DCtx* dctx,
781
1140
 
782
1141
  RETURN_ERROR_IF(srcSize, srcSize_wrong, "input not entirely consumed");
783
1142
 
784
- return (BYTE*)dst - (BYTE*)dststart;
1143
+ return (size_t)((BYTE*)dst - (BYTE*)dststart);
785
1144
  }
786
1145
 
787
1146
  size_t ZSTD_decompress_usingDict(ZSTD_DCtx* dctx,
@@ -798,7 +1157,7 @@ static ZSTD_DDict const* ZSTD_getDDict(ZSTD_DCtx* dctx)
798
1157
  switch (dctx->dictUses) {
799
1158
  default:
800
1159
  assert(0 /* Impossible */);
801
- /* fall-through */
1160
+ ZSTD_FALLTHROUGH;
802
1161
  case ZSTD_dont_use:
803
1162
  ZSTD_clearDict(dctx);
804
1163
  return NULL;
@@ -820,7 +1179,7 @@ size_t ZSTD_decompress(void* dst, size_t dstCapacity, const void* src, size_t sr
820
1179
  {
821
1180
  #if defined(ZSTD_HEAPMODE) && (ZSTD_HEAPMODE>=1)
822
1181
  size_t regenSize;
823
- ZSTD_DCtx* const dctx = ZSTD_createDCtx();
1182
+ ZSTD_DCtx* const dctx = ZSTD_createDCtx_internal(ZSTD_defaultCMem);
824
1183
  RETURN_ERROR_IF(dctx==NULL, memory_allocation, "NULL pointer!");
825
1184
  regenSize = ZSTD_decompressDCtx(dctx, dst, dstCapacity, src, srcSize);
826
1185
  ZSTD_freeDCtx(dctx);
@@ -840,8 +1199,8 @@ size_t ZSTD_decompress(void* dst, size_t dstCapacity, const void* src, size_t sr
840
1199
  size_t ZSTD_nextSrcSizeToDecompress(ZSTD_DCtx* dctx) { return dctx->expected; }
841
1200
 
842
1201
  /**
843
- * Similar to ZSTD_nextSrcSizeToDecompress(), but when when a block input can be streamed,
844
- * we allow taking a partial block as the input. Currently only raw uncompressed blocks can
1202
+ * Similar to ZSTD_nextSrcSizeToDecompress(), but when a block input can be streamed, we
1203
+ * allow taking a partial block as the input. Currently only raw uncompressed blocks can
845
1204
  * be streamed.
846
1205
  *
847
1206
  * For blocks that can be streamed, this allows us to reduce the latency until we produce
@@ -854,7 +1213,7 @@ static size_t ZSTD_nextSrcSizeToDecompressWithInputSize(ZSTD_DCtx* dctx, size_t
854
1213
  return dctx->expected;
855
1214
  if (dctx->bType != bt_raw)
856
1215
  return dctx->expected;
857
- return MIN(MAX(inputSize, 1), dctx->expected);
1216
+ return BOUNDED(1, inputSize, dctx->expected);
858
1217
  }
859
1218
 
860
1219
  ZSTD_nextInputType_e ZSTD_nextInputType(ZSTD_DCtx* dctx) {
@@ -862,7 +1221,9 @@ ZSTD_nextInputType_e ZSTD_nextInputType(ZSTD_DCtx* dctx) {
862
1221
  {
863
1222
  default: /* should not happen */
864
1223
  assert(0);
1224
+ ZSTD_FALLTHROUGH;
865
1225
  case ZSTDds_getFrameHeaderSize:
1226
+ ZSTD_FALLTHROUGH;
866
1227
  case ZSTDds_decodeFrameHeader:
867
1228
  return ZSTDnit_frameHeader;
868
1229
  case ZSTDds_decodeBlockHeader:
@@ -874,6 +1235,7 @@ ZSTD_nextInputType_e ZSTD_nextInputType(ZSTD_DCtx* dctx) {
874
1235
  case ZSTDds_checkChecksum:
875
1236
  return ZSTDnit_checksum;
876
1237
  case ZSTDds_decodeSkippableHeader:
1238
+ ZSTD_FALLTHROUGH;
877
1239
  case ZSTDds_skipFrame:
878
1240
  return ZSTDnit_skippableFrame;
879
1241
  }
@@ -890,7 +1252,9 @@ size_t ZSTD_decompressContinue(ZSTD_DCtx* dctx, void* dst, size_t dstCapacity, c
890
1252
  DEBUGLOG(5, "ZSTD_decompressContinue (srcSize:%u)", (unsigned)srcSize);
891
1253
  /* Sanity check */
892
1254
  RETURN_ERROR_IF(srcSize != ZSTD_nextSrcSizeToDecompressWithInputSize(dctx, srcSize), srcSize_wrong, "not allowed");
893
- if (dstCapacity) ZSTD_checkContinuity(dctx, dst);
1255
+ ZSTD_checkContinuity(dctx, dst, dstCapacity);
1256
+
1257
+ dctx->processedCSize += srcSize;
894
1258
 
895
1259
  switch (dctx->stage)
896
1260
  {
@@ -899,21 +1263,21 @@ size_t ZSTD_decompressContinue(ZSTD_DCtx* dctx, void* dst, size_t dstCapacity, c
899
1263
  if (dctx->format == ZSTD_f_zstd1) { /* allows header */
900
1264
  assert(srcSize >= ZSTD_FRAMEIDSIZE); /* to read skippable magic number */
901
1265
  if ((MEM_readLE32(src) & ZSTD_MAGIC_SKIPPABLE_MASK) == ZSTD_MAGIC_SKIPPABLE_START) { /* skippable frame */
902
- memcpy(dctx->headerBuffer, src, srcSize);
1266
+ ZSTD_memcpy(dctx->headerBuffer, src, srcSize);
903
1267
  dctx->expected = ZSTD_SKIPPABLEHEADERSIZE - srcSize; /* remaining to load to get full skippable frame header */
904
1268
  dctx->stage = ZSTDds_decodeSkippableHeader;
905
1269
  return 0;
906
1270
  } }
907
1271
  dctx->headerSize = ZSTD_frameHeaderSize_internal(src, srcSize, dctx->format);
908
1272
  if (ZSTD_isError(dctx->headerSize)) return dctx->headerSize;
909
- memcpy(dctx->headerBuffer, src, srcSize);
1273
+ ZSTD_memcpy(dctx->headerBuffer, src, srcSize);
910
1274
  dctx->expected = dctx->headerSize - srcSize;
911
1275
  dctx->stage = ZSTDds_decodeFrameHeader;
912
1276
  return 0;
913
1277
 
914
1278
  case ZSTDds_decodeFrameHeader:
915
1279
  assert(src != NULL);
916
- memcpy(dctx->headerBuffer + (dctx->headerSize - srcSize), src, srcSize);
1280
+ ZSTD_memcpy(dctx->headerBuffer + (dctx->headerSize - srcSize), src, srcSize);
917
1281
  FORWARD_IF_ERROR(ZSTD_decodeFrameHeader(dctx, dctx->headerBuffer, dctx->headerSize), "");
918
1282
  dctx->expected = ZSTD_blockHeaderSize;
919
1283
  dctx->stage = ZSTDds_decodeBlockHeader;
@@ -955,7 +1319,7 @@ size_t ZSTD_decompressContinue(ZSTD_DCtx* dctx, void* dst, size_t dstCapacity, c
955
1319
  {
956
1320
  case bt_compressed:
957
1321
  DEBUGLOG(5, "ZSTD_decompressContinue: case bt_compressed");
958
- rSize = ZSTD_decompressBlock_internal(dctx, dst, dstCapacity, src, srcSize, /* frame */ 1);
1322
+ rSize = ZSTD_decompressBlock_internal(dctx, dst, dstCapacity, src, srcSize, /* frame */ 1, is_streaming);
959
1323
  dctx->expected = 0; /* Streaming not supported */
960
1324
  break;
961
1325
  case bt_raw :
@@ -977,7 +1341,7 @@ size_t ZSTD_decompressContinue(ZSTD_DCtx* dctx, void* dst, size_t dstCapacity, c
977
1341
  RETURN_ERROR_IF(rSize > dctx->fParams.blockSizeMax, corruption_detected, "Decompressed Block Size Exceeds Maximum");
978
1342
  DEBUGLOG(5, "ZSTD_decompressContinue: decoded size from block : %u", (unsigned)rSize);
979
1343
  dctx->decodedSize += rSize;
980
- if (dctx->fParams.checksumFlag) XXH64_update(&dctx->xxhState, dst, rSize);
1344
+ if (dctx->validateChecksum) XXH64_update(&dctx->xxhState, dst, rSize);
981
1345
  dctx->previousDstEnd = (char*)dst + rSize;
982
1346
 
983
1347
  /* Stay on the same stage until we are finished streaming the block. */
@@ -995,6 +1359,7 @@ size_t ZSTD_decompressContinue(ZSTD_DCtx* dctx, void* dst, size_t dstCapacity, c
995
1359
  dctx->expected = 4;
996
1360
  dctx->stage = ZSTDds_checkChecksum;
997
1361
  } else {
1362
+ ZSTD_DCtx_trace_end(dctx, dctx->decodedSize, dctx->processedCSize, /* streaming */ 1);
998
1363
  dctx->expected = 0; /* ends here */
999
1364
  dctx->stage = ZSTDds_getFrameHeaderSize;
1000
1365
  }
@@ -1007,10 +1372,14 @@ size_t ZSTD_decompressContinue(ZSTD_DCtx* dctx, void* dst, size_t dstCapacity, c
1007
1372
 
1008
1373
  case ZSTDds_checkChecksum:
1009
1374
  assert(srcSize == 4); /* guaranteed by dctx->expected */
1010
- { U32 const h32 = (U32)XXH64_digest(&dctx->xxhState);
1011
- U32 const check32 = MEM_readLE32(src);
1012
- DEBUGLOG(4, "ZSTD_decompressContinue: checksum : calculated %08X :: %08X read", (unsigned)h32, (unsigned)check32);
1013
- RETURN_ERROR_IF(check32 != h32, checksum_wrong, "");
1375
+ {
1376
+ if (dctx->validateChecksum) {
1377
+ U32 const h32 = (U32)XXH64_digest(&dctx->xxhState);
1378
+ U32 const check32 = MEM_readLE32(src);
1379
+ DEBUGLOG(4, "ZSTD_decompressContinue: checksum : calculated %08X :: %08X read", (unsigned)h32, (unsigned)check32);
1380
+ RETURN_ERROR_IF(check32 != h32, checksum_wrong, "");
1381
+ }
1382
+ ZSTD_DCtx_trace_end(dctx, dctx->decodedSize, dctx->processedCSize, /* streaming */ 1);
1014
1383
  dctx->expected = 0;
1015
1384
  dctx->stage = ZSTDds_getFrameHeaderSize;
1016
1385
  return 0;
@@ -1019,7 +1388,7 @@ size_t ZSTD_decompressContinue(ZSTD_DCtx* dctx, void* dst, size_t dstCapacity, c
1019
1388
  case ZSTDds_decodeSkippableHeader:
1020
1389
  assert(src != NULL);
1021
1390
  assert(srcSize <= ZSTD_SKIPPABLEHEADERSIZE);
1022
- memcpy(dctx->headerBuffer + (ZSTD_SKIPPABLEHEADERSIZE - srcSize), src, srcSize); /* complete skippable header */
1391
+ ZSTD_memcpy(dctx->headerBuffer + (ZSTD_SKIPPABLEHEADERSIZE - srcSize), src, srcSize); /* complete skippable header */
1023
1392
  dctx->expected = MEM_readLE32(dctx->headerBuffer + ZSTD_FRAMEIDSIZE); /* note : dctx->expected can grow seriously large, beyond local buffer size */
1024
1393
  dctx->stage = ZSTDds_skipFrame;
1025
1394
  return 0;
@@ -1031,7 +1400,7 @@ size_t ZSTD_decompressContinue(ZSTD_DCtx* dctx, void* dst, size_t dstCapacity, c
1031
1400
 
1032
1401
  default:
1033
1402
  assert(0); /* impossible */
1034
- RETURN_ERROR(GENERIC, "impossible to reach"); /* some compiler require default to do something */
1403
+ RETURN_ERROR(GENERIC, "impossible to reach"); /* some compilers require default to do something */
1035
1404
  }
1036
1405
  }
1037
1406
 
@@ -1072,11 +1441,11 @@ ZSTD_loadDEntropy(ZSTD_entropyDTables_t* entropy,
1072
1441
  /* in minimal huffman, we always use X1 variants */
1073
1442
  size_t const hSize = HUF_readDTableX1_wksp(entropy->hufTable,
1074
1443
  dictPtr, dictEnd - dictPtr,
1075
- workspace, workspaceSize);
1444
+ workspace, workspaceSize, /* flags */ 0);
1076
1445
  #else
1077
1446
  size_t const hSize = HUF_readDTableX2_wksp(entropy->hufTable,
1078
- dictPtr, dictEnd - dictPtr,
1079
- workspace, workspaceSize);
1447
+ dictPtr, (size_t)(dictEnd - dictPtr),
1448
+ workspace, workspaceSize, /* flags */ 0);
1080
1449
  #endif
1081
1450
  RETURN_ERROR_IF(HUF_isError(hSize), dictionary_corrupted, "");
1082
1451
  dictPtr += hSize;
@@ -1084,40 +1453,46 @@ ZSTD_loadDEntropy(ZSTD_entropyDTables_t* entropy,
1084
1453
 
1085
1454
  { short offcodeNCount[MaxOff+1];
1086
1455
  unsigned offcodeMaxValue = MaxOff, offcodeLog;
1087
- size_t const offcodeHeaderSize = FSE_readNCount(offcodeNCount, &offcodeMaxValue, &offcodeLog, dictPtr, dictEnd-dictPtr);
1456
+ size_t const offcodeHeaderSize = FSE_readNCount(offcodeNCount, &offcodeMaxValue, &offcodeLog, dictPtr, (size_t)(dictEnd-dictPtr));
1088
1457
  RETURN_ERROR_IF(FSE_isError(offcodeHeaderSize), dictionary_corrupted, "");
1089
1458
  RETURN_ERROR_IF(offcodeMaxValue > MaxOff, dictionary_corrupted, "");
1090
1459
  RETURN_ERROR_IF(offcodeLog > OffFSELog, dictionary_corrupted, "");
1091
1460
  ZSTD_buildFSETable( entropy->OFTable,
1092
1461
  offcodeNCount, offcodeMaxValue,
1093
1462
  OF_base, OF_bits,
1094
- offcodeLog);
1463
+ offcodeLog,
1464
+ entropy->workspace, sizeof(entropy->workspace),
1465
+ /* bmi2 */0);
1095
1466
  dictPtr += offcodeHeaderSize;
1096
1467
  }
1097
1468
 
1098
1469
  { short matchlengthNCount[MaxML+1];
1099
1470
  unsigned matchlengthMaxValue = MaxML, matchlengthLog;
1100
- size_t const matchlengthHeaderSize = FSE_readNCount(matchlengthNCount, &matchlengthMaxValue, &matchlengthLog, dictPtr, dictEnd-dictPtr);
1471
+ size_t const matchlengthHeaderSize = FSE_readNCount(matchlengthNCount, &matchlengthMaxValue, &matchlengthLog, dictPtr, (size_t)(dictEnd-dictPtr));
1101
1472
  RETURN_ERROR_IF(FSE_isError(matchlengthHeaderSize), dictionary_corrupted, "");
1102
1473
  RETURN_ERROR_IF(matchlengthMaxValue > MaxML, dictionary_corrupted, "");
1103
1474
  RETURN_ERROR_IF(matchlengthLog > MLFSELog, dictionary_corrupted, "");
1104
1475
  ZSTD_buildFSETable( entropy->MLTable,
1105
1476
  matchlengthNCount, matchlengthMaxValue,
1106
1477
  ML_base, ML_bits,
1107
- matchlengthLog);
1478
+ matchlengthLog,
1479
+ entropy->workspace, sizeof(entropy->workspace),
1480
+ /* bmi2 */ 0);
1108
1481
  dictPtr += matchlengthHeaderSize;
1109
1482
  }
1110
1483
 
1111
1484
  { short litlengthNCount[MaxLL+1];
1112
1485
  unsigned litlengthMaxValue = MaxLL, litlengthLog;
1113
- size_t const litlengthHeaderSize = FSE_readNCount(litlengthNCount, &litlengthMaxValue, &litlengthLog, dictPtr, dictEnd-dictPtr);
1486
+ size_t const litlengthHeaderSize = FSE_readNCount(litlengthNCount, &litlengthMaxValue, &litlengthLog, dictPtr, (size_t)(dictEnd-dictPtr));
1114
1487
  RETURN_ERROR_IF(FSE_isError(litlengthHeaderSize), dictionary_corrupted, "");
1115
1488
  RETURN_ERROR_IF(litlengthMaxValue > MaxLL, dictionary_corrupted, "");
1116
1489
  RETURN_ERROR_IF(litlengthLog > LLFSELog, dictionary_corrupted, "");
1117
1490
  ZSTD_buildFSETable( entropy->LLTable,
1118
1491
  litlengthNCount, litlengthMaxValue,
1119
1492
  LL_base, LL_bits,
1120
- litlengthLog);
1493
+ litlengthLog,
1494
+ entropy->workspace, sizeof(entropy->workspace),
1495
+ /* bmi2 */ 0);
1121
1496
  dictPtr += litlengthHeaderSize;
1122
1497
  }
1123
1498
 
@@ -1131,7 +1506,7 @@ ZSTD_loadDEntropy(ZSTD_entropyDTables_t* entropy,
1131
1506
  entropy->rep[i] = rep;
1132
1507
  } }
1133
1508
 
1134
- return dictPtr - (const BYTE*)dict;
1509
+ return (size_t)(dictPtr - (const BYTE*)dict);
1135
1510
  }
1136
1511
 
1137
1512
  static size_t ZSTD_decompress_insertDictionary(ZSTD_DCtx* dctx, const void* dict, size_t dictSize)
@@ -1158,19 +1533,23 @@ static size_t ZSTD_decompress_insertDictionary(ZSTD_DCtx* dctx, const void* dict
1158
1533
  size_t ZSTD_decompressBegin(ZSTD_DCtx* dctx)
1159
1534
  {
1160
1535
  assert(dctx != NULL);
1536
+ #if ZSTD_TRACE
1537
+ dctx->traceCtx = (ZSTD_trace_decompress_begin != NULL) ? ZSTD_trace_decompress_begin(dctx) : 0;
1538
+ #endif
1161
1539
  dctx->expected = ZSTD_startingInputLength(dctx->format); /* dctx->format must be properly set */
1162
1540
  dctx->stage = ZSTDds_getFrameHeaderSize;
1541
+ dctx->processedCSize = 0;
1163
1542
  dctx->decodedSize = 0;
1164
1543
  dctx->previousDstEnd = NULL;
1165
1544
  dctx->prefixStart = NULL;
1166
1545
  dctx->virtualStart = NULL;
1167
1546
  dctx->dictEnd = NULL;
1168
- dctx->entropy.hufTable[0] = (HUF_DTable)((HufLog)*0x1000001); /* cover both little and big endian */
1547
+ dctx->entropy.hufTable[0] = (HUF_DTable)((ZSTD_HUFFDTABLE_CAPACITY_LOG)*0x1000001); /* cover both little and big endian */
1169
1548
  dctx->litEntropy = dctx->fseEntropy = 0;
1170
1549
  dctx->dictID = 0;
1171
1550
  dctx->bType = bt_reserved;
1172
1551
  ZSTD_STATIC_ASSERT(sizeof(dctx->entropy.rep) == sizeof(repStartValue));
1173
- memcpy(dctx->entropy.rep, repStartValue, sizeof(repStartValue)); /* initial repcodes */
1552
+ ZSTD_memcpy(dctx->entropy.rep, repStartValue, sizeof(repStartValue)); /* initial repcodes */
1174
1553
  dctx->LLTptr = dctx->entropy.LLTable;
1175
1554
  dctx->MLTptr = dctx->entropy.MLTable;
1176
1555
  dctx->OFTptr = dctx->entropy.OFTable;
@@ -1227,7 +1606,7 @@ unsigned ZSTD_getDictID_fromDict(const void* dict, size_t dictSize)
1227
1606
  * This could for one of the following reasons :
1228
1607
  * - The frame does not require a dictionary (most common case).
1229
1608
  * - The frame was built with dictID intentionally removed.
1230
- * Needed dictionary is a hidden information.
1609
+ * Needed dictionary is a hidden piece of information.
1231
1610
  * Note : this use case also happens when using a non-conformant dictionary.
1232
1611
  * - `srcSize` is too small, and as a result, frame header could not be decoded.
1233
1612
  * Note : possible if `srcSize < ZSTD_FRAMEHEADERSIZE_MAX`.
@@ -1236,7 +1615,7 @@ unsigned ZSTD_getDictID_fromDict(const void* dict, size_t dictSize)
1236
1615
  * ZSTD_getFrameHeader(), which will provide a more precise error code. */
1237
1616
  unsigned ZSTD_getDictID_fromFrame(const void* src, size_t srcSize)
1238
1617
  {
1239
- ZSTD_frameHeader zfp = { 0, 0, 0, ZSTD_frame, 0, 0, 0 };
1618
+ ZSTD_frameHeader zfp = { 0, 0, 0, ZSTD_frame, 0, 0, 0, 0, 0 };
1240
1619
  size_t const hError = ZSTD_getFrameHeader(&zfp, src, srcSize);
1241
1620
  if (ZSTD_isError(hError)) return 0;
1242
1621
  return zfp.dictID;
@@ -1265,7 +1644,7 @@ size_t ZSTD_decompress_usingDDict(ZSTD_DCtx* dctx,
1265
1644
  ZSTD_DStream* ZSTD_createDStream(void)
1266
1645
  {
1267
1646
  DEBUGLOG(3, "ZSTD_createDStream");
1268
- return ZSTD_createDStream_advanced(ZSTD_defaultCMem);
1647
+ return ZSTD_createDCtx_internal(ZSTD_defaultCMem);
1269
1648
  }
1270
1649
 
1271
1650
  ZSTD_DStream* ZSTD_initStaticDStream(void *workspace, size_t workspaceSize)
@@ -1275,7 +1654,7 @@ ZSTD_DStream* ZSTD_initStaticDStream(void *workspace, size_t workspaceSize)
1275
1654
 
1276
1655
  ZSTD_DStream* ZSTD_createDStream_advanced(ZSTD_customMem customMem)
1277
1656
  {
1278
- return ZSTD_createDCtx_advanced(customMem);
1657
+ return ZSTD_createDCtx_internal(customMem);
1279
1658
  }
1280
1659
 
1281
1660
  size_t ZSTD_freeDStream(ZSTD_DStream* zds)
@@ -1343,7 +1722,9 @@ size_t ZSTD_initDStream_usingDict(ZSTD_DStream* zds, const void* dict, size_t di
1343
1722
  size_t ZSTD_initDStream(ZSTD_DStream* zds)
1344
1723
  {
1345
1724
  DEBUGLOG(4, "ZSTD_initDStream");
1346
- return ZSTD_initDStream_usingDDict(zds, NULL);
1725
+ FORWARD_IF_ERROR(ZSTD_DCtx_reset(zds, ZSTD_reset_session_only), "");
1726
+ FORWARD_IF_ERROR(ZSTD_DCtx_refDDict(zds, NULL), "");
1727
+ return ZSTD_startingInputLength(zds->format);
1347
1728
  }
1348
1729
 
1349
1730
  /* ZSTD_initDStream_usingDDict() :
@@ -1351,6 +1732,7 @@ size_t ZSTD_initDStream(ZSTD_DStream* zds)
1351
1732
  * this function cannot fail */
1352
1733
  size_t ZSTD_initDStream_usingDDict(ZSTD_DStream* dctx, const ZSTD_DDict* ddict)
1353
1734
  {
1735
+ DEBUGLOG(4, "ZSTD_initDStream_usingDDict");
1354
1736
  FORWARD_IF_ERROR( ZSTD_DCtx_reset(dctx, ZSTD_reset_session_only) , "");
1355
1737
  FORWARD_IF_ERROR( ZSTD_DCtx_refDDict(dctx, ddict) , "");
1356
1738
  return ZSTD_startingInputLength(dctx->format);
@@ -1361,6 +1743,7 @@ size_t ZSTD_initDStream_usingDDict(ZSTD_DStream* dctx, const ZSTD_DDict* ddict)
1361
1743
  * this function cannot fail */
1362
1744
  size_t ZSTD_resetDStream(ZSTD_DStream* dctx)
1363
1745
  {
1746
+ DEBUGLOG(4, "ZSTD_resetDStream");
1364
1747
  FORWARD_IF_ERROR(ZSTD_DCtx_reset(dctx, ZSTD_reset_session_only), "");
1365
1748
  return ZSTD_startingInputLength(dctx->format);
1366
1749
  }
@@ -1373,6 +1756,16 @@ size_t ZSTD_DCtx_refDDict(ZSTD_DCtx* dctx, const ZSTD_DDict* ddict)
1373
1756
  if (ddict) {
1374
1757
  dctx->ddict = ddict;
1375
1758
  dctx->dictUses = ZSTD_use_indefinitely;
1759
+ if (dctx->refMultipleDDicts == ZSTD_rmd_refMultipleDDicts) {
1760
+ if (dctx->ddictSet == NULL) {
1761
+ dctx->ddictSet = ZSTD_createDDictHashSet(dctx->customMem);
1762
+ if (!dctx->ddictSet) {
1763
+ RETURN_ERROR(memory_allocation, "Failed to allocate memory for hash set!");
1764
+ }
1765
+ }
1766
+ assert(!dctx->staticSize); /* Impossible: ddictSet cannot have been allocated if static dctx */
1767
+ FORWARD_IF_ERROR(ZSTD_DDictHashSet_addDDict(dctx->ddictSet, ddict, dctx->customMem), "");
1768
+ }
1376
1769
  }
1377
1770
  return 0;
1378
1771
  }
@@ -1394,7 +1787,7 @@ size_t ZSTD_DCtx_setMaxWindowSize(ZSTD_DCtx* dctx, size_t maxWindowSize)
1394
1787
 
1395
1788
  size_t ZSTD_DCtx_setFormat(ZSTD_DCtx* dctx, ZSTD_format_e format)
1396
1789
  {
1397
- return ZSTD_DCtx_setParameter(dctx, ZSTD_d_format, format);
1790
+ return ZSTD_DCtx_setParameter(dctx, ZSTD_d_format, (int)format);
1398
1791
  }
1399
1792
 
1400
1793
  ZSTD_bounds ZSTD_dParam_getBounds(ZSTD_dParameter dParam)
@@ -1411,9 +1804,22 @@ ZSTD_bounds ZSTD_dParam_getBounds(ZSTD_dParameter dParam)
1411
1804
  ZSTD_STATIC_ASSERT(ZSTD_f_zstd1 < ZSTD_f_zstd1_magicless);
1412
1805
  return bounds;
1413
1806
  case ZSTD_d_stableOutBuffer:
1414
- bounds.lowerBound = (int)ZSTD_obm_buffered;
1415
- bounds.upperBound = (int)ZSTD_obm_stable;
1807
+ bounds.lowerBound = (int)ZSTD_bm_buffered;
1808
+ bounds.upperBound = (int)ZSTD_bm_stable;
1416
1809
  return bounds;
1810
+ case ZSTD_d_forceIgnoreChecksum:
1811
+ bounds.lowerBound = (int)ZSTD_d_validateChecksum;
1812
+ bounds.upperBound = (int)ZSTD_d_ignoreChecksum;
1813
+ return bounds;
1814
+ case ZSTD_d_refMultipleDDicts:
1815
+ bounds.lowerBound = (int)ZSTD_rmd_refSingleDDict;
1816
+ bounds.upperBound = (int)ZSTD_rmd_refMultipleDDicts;
1817
+ return bounds;
1818
+ case ZSTD_d_disableHuffmanAssembly:
1819
+ bounds.lowerBound = 0;
1820
+ bounds.upperBound = 1;
1821
+ return bounds;
1822
+
1417
1823
  default:;
1418
1824
  }
1419
1825
  bounds.error = ERROR(parameter_unsupported);
@@ -1436,6 +1842,32 @@ static int ZSTD_dParam_withinBounds(ZSTD_dParameter dParam, int value)
1436
1842
  RETURN_ERROR_IF(!ZSTD_dParam_withinBounds(p, v), parameter_outOfBound, ""); \
1437
1843
  }
1438
1844
 
1845
+ size_t ZSTD_DCtx_getParameter(ZSTD_DCtx* dctx, ZSTD_dParameter param, int* value)
1846
+ {
1847
+ switch (param) {
1848
+ case ZSTD_d_windowLogMax:
1849
+ *value = (int)ZSTD_highbit32((U32)dctx->maxWindowSize);
1850
+ return 0;
1851
+ case ZSTD_d_format:
1852
+ *value = (int)dctx->format;
1853
+ return 0;
1854
+ case ZSTD_d_stableOutBuffer:
1855
+ *value = (int)dctx->outBufferMode;
1856
+ return 0;
1857
+ case ZSTD_d_forceIgnoreChecksum:
1858
+ *value = (int)dctx->forceIgnoreChecksum;
1859
+ return 0;
1860
+ case ZSTD_d_refMultipleDDicts:
1861
+ *value = (int)dctx->refMultipleDDicts;
1862
+ return 0;
1863
+ case ZSTD_d_disableHuffmanAssembly:
1864
+ *value = (int)dctx->disableHufAsm;
1865
+ return 0;
1866
+ default:;
1867
+ }
1868
+ RETURN_ERROR(parameter_unsupported, "");
1869
+ }
1870
+
1439
1871
  size_t ZSTD_DCtx_setParameter(ZSTD_DCtx* dctx, ZSTD_dParameter dParam, int value)
1440
1872
  {
1441
1873
  RETURN_ERROR_IF(dctx->streamStage != zdss_init, stage_wrong, "");
@@ -1451,7 +1883,22 @@ size_t ZSTD_DCtx_setParameter(ZSTD_DCtx* dctx, ZSTD_dParameter dParam, int value
1451
1883
  return 0;
1452
1884
  case ZSTD_d_stableOutBuffer:
1453
1885
  CHECK_DBOUNDS(ZSTD_d_stableOutBuffer, value);
1454
- dctx->outBufferMode = (ZSTD_outBufferMode_e)value;
1886
+ dctx->outBufferMode = (ZSTD_bufferMode_e)value;
1887
+ return 0;
1888
+ case ZSTD_d_forceIgnoreChecksum:
1889
+ CHECK_DBOUNDS(ZSTD_d_forceIgnoreChecksum, value);
1890
+ dctx->forceIgnoreChecksum = (ZSTD_forceIgnoreChecksum_e)value;
1891
+ return 0;
1892
+ case ZSTD_d_refMultipleDDicts:
1893
+ CHECK_DBOUNDS(ZSTD_d_refMultipleDDicts, value);
1894
+ if (dctx->staticSize != 0) {
1895
+ RETURN_ERROR(parameter_unsupported, "Static dctx does not support multiple DDicts!");
1896
+ }
1897
+ dctx->refMultipleDDicts = (ZSTD_refMultipleDDicts_e)value;
1898
+ return 0;
1899
+ case ZSTD_d_disableHuffmanAssembly:
1900
+ CHECK_DBOUNDS(ZSTD_d_disableHuffmanAssembly, value);
1901
+ dctx->disableHufAsm = value != 0;
1455
1902
  return 0;
1456
1903
  default:;
1457
1904
  }
@@ -1469,8 +1916,7 @@ size_t ZSTD_DCtx_reset(ZSTD_DCtx* dctx, ZSTD_ResetDirective reset)
1469
1916
  || (reset == ZSTD_reset_session_and_parameters) ) {
1470
1917
  RETURN_ERROR_IF(dctx->streamStage != zdss_init, stage_wrong, "");
1471
1918
  ZSTD_clearDict(dctx);
1472
- dctx->format = ZSTD_f_zstd1;
1473
- dctx->maxWindowSize = ZSTD_MAXWINDOWSIZE_DEFAULT;
1919
+ ZSTD_DCtx_resetParameters(dctx);
1474
1920
  }
1475
1921
  return 0;
1476
1922
  }
@@ -1484,7 +1930,8 @@ size_t ZSTD_sizeof_DStream(const ZSTD_DStream* dctx)
1484
1930
  size_t ZSTD_decodingBufferSize_min(unsigned long long windowSize, unsigned long long frameContentSize)
1485
1931
  {
1486
1932
  size_t const blockSize = (size_t) MIN(windowSize, ZSTD_BLOCKSIZE_MAX);
1487
- unsigned long long const neededRBSize = windowSize + blockSize + (WILDCOPY_OVERLENGTH * 2);
1933
+ /* 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*/
1934
+ unsigned long long const neededRBSize = windowSize + blockSize + ZSTD_BLOCKSIZE_MAX + (WILDCOPY_OVERLENGTH * 2);
1488
1935
  unsigned long long const neededSize = MIN(frameContentSize, neededRBSize);
1489
1936
  size_t const minRBSize = (size_t) neededSize;
1490
1937
  RETURN_ERROR_IF((unsigned long long)minRBSize != neededSize,
@@ -1524,7 +1971,7 @@ static void ZSTD_DCtx_updateOversizedDuration(ZSTD_DStream* zds, size_t const ne
1524
1971
  {
1525
1972
  if (ZSTD_DCtx_isOverflow(zds, neededInBuffSize, neededOutBuffSize))
1526
1973
  zds->oversizedDuration++;
1527
- else
1974
+ else
1528
1975
  zds->oversizedDuration = 0;
1529
1976
  }
1530
1977
 
@@ -1538,7 +1985,7 @@ static size_t ZSTD_checkOutBuffer(ZSTD_DStream const* zds, ZSTD_outBuffer const*
1538
1985
  {
1539
1986
  ZSTD_outBuffer const expect = zds->expectedOutBuffer;
1540
1987
  /* No requirement when ZSTD_obm_stable is not enabled. */
1541
- if (zds->outBufferMode != ZSTD_obm_stable)
1988
+ if (zds->outBufferMode != ZSTD_bm_stable)
1542
1989
  return 0;
1543
1990
  /* Any buffer is allowed in zdss_init, this must be the same for every other call until
1544
1991
  * the context is reset.
@@ -1548,7 +1995,7 @@ static size_t ZSTD_checkOutBuffer(ZSTD_DStream const* zds, ZSTD_outBuffer const*
1548
1995
  /* The buffer must match our expectation exactly. */
1549
1996
  if (expect.dst == output->dst && expect.pos == output->pos && expect.size == output->size)
1550
1997
  return 0;
1551
- RETURN_ERROR(dstBuffer_wrong, "ZSTD_obm_stable enabled but output differs!");
1998
+ RETURN_ERROR(dstBuffer_wrong, "ZSTD_d_stableOutBuffer enabled but output differs!");
1552
1999
  }
1553
2000
 
1554
2001
  /* Calls ZSTD_decompressContinue() with the right parameters for ZSTD_decompressStream()
@@ -1560,7 +2007,7 @@ static size_t ZSTD_decompressContinueStream(
1560
2007
  ZSTD_DStream* zds, char** op, char* oend,
1561
2008
  void const* src, size_t srcSize) {
1562
2009
  int const isSkipFrame = ZSTD_isSkipFrame(zds);
1563
- if (zds->outBufferMode == ZSTD_obm_buffered) {
2010
+ if (zds->outBufferMode == ZSTD_bm_buffered) {
1564
2011
  size_t const dstSize = isSkipFrame ? 0 : zds->outBuffSize - zds->outStart;
1565
2012
  size_t const decodedSize = ZSTD_decompressContinue(zds,
1566
2013
  zds->outBuff + zds->outStart, dstSize, src, srcSize);
@@ -1573,14 +2020,14 @@ static size_t ZSTD_decompressContinueStream(
1573
2020
  }
1574
2021
  } else {
1575
2022
  /* Write directly into the output buffer */
1576
- size_t const dstSize = isSkipFrame ? 0 : oend - *op;
2023
+ size_t const dstSize = isSkipFrame ? 0 : (size_t)(oend - *op);
1577
2024
  size_t const decodedSize = ZSTD_decompressContinue(zds, *op, dstSize, src, srcSize);
1578
2025
  FORWARD_IF_ERROR(decodedSize, "");
1579
2026
  *op += decodedSize;
1580
2027
  /* Flushing is not needed. */
1581
2028
  zds->streamStage = zdss_read;
1582
2029
  assert(*op <= oend);
1583
- assert(zds->outBufferMode == ZSTD_obm_stable);
2030
+ assert(zds->outBufferMode == ZSTD_bm_stable);
1584
2031
  }
1585
2032
  return 0;
1586
2033
  }
@@ -1618,10 +2065,12 @@ size_t ZSTD_decompressStream(ZSTD_DStream* zds, ZSTD_outBuffer* output, ZSTD_inB
1618
2065
  DEBUGLOG(5, "stage zdss_init => transparent reset ");
1619
2066
  zds->streamStage = zdss_loadHeader;
1620
2067
  zds->lhSize = zds->inPos = zds->outStart = zds->outEnd = 0;
2068
+ #if defined(ZSTD_LEGACY_SUPPORT) && (ZSTD_LEGACY_SUPPORT>=1)
1621
2069
  zds->legacyVersion = 0;
2070
+ #endif
1622
2071
  zds->hostageByte = 0;
1623
2072
  zds->expectedOutBuffer = *output;
1624
- /* fall-through */
2073
+ ZSTD_FALLTHROUGH;
1625
2074
 
1626
2075
  case zdss_loadHeader :
1627
2076
  DEBUGLOG(5, "stage zdss_loadHeader (srcSize : %u)", (U32)(iend - ip));
@@ -1635,7 +2084,9 @@ size_t ZSTD_decompressStream(ZSTD_DStream* zds, ZSTD_outBuffer* output, ZSTD_inB
1635
2084
  } }
1636
2085
  #endif
1637
2086
  { size_t const hSize = ZSTD_getFrameHeader_advanced(&zds->fParams, zds->headerBuffer, zds->lhSize, zds->format);
1638
- DEBUGLOG(5, "header size : %u", (U32)hSize);
2087
+ if (zds->refMultipleDDicts && zds->ddictSet) {
2088
+ ZSTD_DCtx_selectFrameDDict(zds);
2089
+ }
1639
2090
  if (ZSTD_isError(hSize)) {
1640
2091
  #if defined(ZSTD_LEGACY_SUPPORT) && (ZSTD_LEGACY_SUPPORT>=1)
1641
2092
  U32 const legacyVersion = ZSTD_isLegacy(istart, iend-istart);
@@ -1663,14 +2114,19 @@ size_t ZSTD_decompressStream(ZSTD_DStream* zds, ZSTD_outBuffer* output, ZSTD_inB
1663
2114
  assert(iend >= ip);
1664
2115
  if (toLoad > remainingInput) { /* not enough input to load full header */
1665
2116
  if (remainingInput > 0) {
1666
- memcpy(zds->headerBuffer + zds->lhSize, ip, remainingInput);
2117
+ ZSTD_memcpy(zds->headerBuffer + zds->lhSize, ip, remainingInput);
1667
2118
  zds->lhSize += remainingInput;
1668
2119
  }
1669
2120
  input->pos = input->size;
2121
+ /* check first few bytes */
2122
+ FORWARD_IF_ERROR(
2123
+ ZSTD_getFrameHeader_advanced(&zds->fParams, zds->headerBuffer, zds->lhSize, zds->format),
2124
+ "First few bytes detected incorrect" );
2125
+ /* return hint input size */
1670
2126
  return (MAX((size_t)ZSTD_FRAMEHEADERSIZE_MIN(zds->format), hSize) - zds->lhSize) + ZSTD_blockHeaderSize; /* remaining header bytes + next block header */
1671
2127
  }
1672
2128
  assert(ip != NULL);
1673
- memcpy(zds->headerBuffer + zds->lhSize, ip, toLoad); zds->lhSize = hSize; ip += toLoad;
2129
+ ZSTD_memcpy(zds->headerBuffer + zds->lhSize, ip, toLoad); zds->lhSize = hSize; ip += toLoad;
1674
2130
  break;
1675
2131
  } }
1676
2132
 
@@ -1678,14 +2134,15 @@ size_t ZSTD_decompressStream(ZSTD_DStream* zds, ZSTD_outBuffer* output, ZSTD_inB
1678
2134
  if (zds->fParams.frameContentSize != ZSTD_CONTENTSIZE_UNKNOWN
1679
2135
  && zds->fParams.frameType != ZSTD_skippableFrame
1680
2136
  && (U64)(size_t)(oend-op) >= zds->fParams.frameContentSize) {
1681
- size_t const cSize = ZSTD_findFrameCompressedSize(istart, iend-istart);
2137
+ size_t const cSize = ZSTD_findFrameCompressedSize(istart, (size_t)(iend-istart));
1682
2138
  if (cSize <= (size_t)(iend-istart)) {
1683
2139
  /* shortcut : using single-pass mode */
1684
- size_t const decompressedSize = ZSTD_decompress_usingDDict(zds, op, oend-op, istart, cSize, ZSTD_getDDict(zds));
2140
+ size_t const decompressedSize = ZSTD_decompress_usingDDict(zds, op, (size_t)(oend-op), istart, cSize, ZSTD_getDDict(zds));
1685
2141
  if (ZSTD_isError(decompressedSize)) return decompressedSize;
1686
2142
  DEBUGLOG(4, "shortcut to single-pass ZSTD_decompress_usingDDict()")
2143
+ assert(istart != NULL);
1687
2144
  ip = istart + cSize;
1688
- op += decompressedSize;
2145
+ op = op ? op + decompressedSize : op; /* can occur if frameContentSize = 0 (empty frame) */
1689
2146
  zds->expected = 0;
1690
2147
  zds->streamStage = zdss_init;
1691
2148
  someMoreWork = 0;
@@ -1693,7 +2150,7 @@ size_t ZSTD_decompressStream(ZSTD_DStream* zds, ZSTD_outBuffer* output, ZSTD_inB
1693
2150
  } }
1694
2151
 
1695
2152
  /* Check output buffer is large enough for ZSTD_odm_stable. */
1696
- if (zds->outBufferMode == ZSTD_obm_stable
2153
+ if (zds->outBufferMode == ZSTD_bm_stable
1697
2154
  && zds->fParams.frameType != ZSTD_skippableFrame
1698
2155
  && zds->fParams.frameContentSize != ZSTD_CONTENTSIZE_UNKNOWN
1699
2156
  && (U64)(size_t)(oend-op) < zds->fParams.frameContentSize) {
@@ -1723,7 +2180,7 @@ size_t ZSTD_decompressStream(ZSTD_DStream* zds, ZSTD_outBuffer* output, ZSTD_inB
1723
2180
 
1724
2181
  /* Adapt buffer sizes to frame header instructions */
1725
2182
  { size_t const neededInBuffSize = MAX(zds->fParams.blockSizeMax, 4 /* frame checksum */);
1726
- size_t const neededOutBuffSize = zds->outBufferMode == ZSTD_obm_buffered
2183
+ size_t const neededOutBuffSize = zds->outBufferMode == ZSTD_bm_buffered
1727
2184
  ? ZSTD_decodingBufferSize_min(zds->fParams.windowSize, zds->fParams.frameContentSize)
1728
2185
  : 0;
1729
2186
 
@@ -1731,7 +2188,7 @@ size_t ZSTD_decompressStream(ZSTD_DStream* zds, ZSTD_outBuffer* output, ZSTD_inB
1731
2188
 
1732
2189
  { int const tooSmall = (zds->inBuffSize < neededInBuffSize) || (zds->outBuffSize < neededOutBuffSize);
1733
2190
  int const tooLarge = ZSTD_DCtx_isOversizedTooLong(zds);
1734
-
2191
+
1735
2192
  if (tooSmall || tooLarge) {
1736
2193
  size_t const bufferSize = neededInBuffSize + neededOutBuffSize;
1737
2194
  DEBUGLOG(4, "inBuff : from %u to %u",
@@ -1745,10 +2202,10 @@ size_t ZSTD_decompressStream(ZSTD_DStream* zds, ZSTD_outBuffer* output, ZSTD_inB
1745
2202
  bufferSize > zds->staticSize - sizeof(ZSTD_DCtx),
1746
2203
  memory_allocation, "");
1747
2204
  } else {
1748
- ZSTD_free(zds->inBuff, zds->customMem);
2205
+ ZSTD_customFree(zds->inBuff, zds->customMem);
1749
2206
  zds->inBuffSize = 0;
1750
2207
  zds->outBuffSize = 0;
1751
- zds->inBuff = (char*)ZSTD_malloc(bufferSize, zds->customMem);
2208
+ zds->inBuff = (char*)ZSTD_customMalloc(bufferSize, zds->customMem);
1752
2209
  RETURN_ERROR_IF(zds->inBuff == NULL, memory_allocation, "");
1753
2210
  }
1754
2211
  zds->inBuffSize = neededInBuffSize;
@@ -1756,11 +2213,11 @@ size_t ZSTD_decompressStream(ZSTD_DStream* zds, ZSTD_outBuffer* output, ZSTD_inB
1756
2213
  zds->outBuffSize = neededOutBuffSize;
1757
2214
  } } }
1758
2215
  zds->streamStage = zdss_read;
1759
- /* fall-through */
2216
+ ZSTD_FALLTHROUGH;
1760
2217
 
1761
2218
  case zdss_read:
1762
2219
  DEBUGLOG(5, "stage zdss_read");
1763
- { size_t const neededInSize = ZSTD_nextSrcSizeToDecompressWithInputSize(zds, iend - ip);
2220
+ { size_t const neededInSize = ZSTD_nextSrcSizeToDecompressWithInputSize(zds, (size_t)(iend - ip));
1764
2221
  DEBUGLOG(5, "neededInSize = %u", (U32)neededInSize);
1765
2222
  if (neededInSize==0) { /* end of frame */
1766
2223
  zds->streamStage = zdss_init;
@@ -1769,13 +2226,14 @@ size_t ZSTD_decompressStream(ZSTD_DStream* zds, ZSTD_outBuffer* output, ZSTD_inB
1769
2226
  }
1770
2227
  if ((size_t)(iend-ip) >= neededInSize) { /* decode directly from src */
1771
2228
  FORWARD_IF_ERROR(ZSTD_decompressContinueStream(zds, &op, oend, ip, neededInSize), "");
2229
+ assert(ip != NULL);
1772
2230
  ip += neededInSize;
1773
2231
  /* Function modifies the stage so we must break */
1774
2232
  break;
1775
2233
  } }
1776
2234
  if (ip==iend) { someMoreWork = 0; break; } /* no more input */
1777
2235
  zds->streamStage = zdss_load;
1778
- /* fall-through */
2236
+ ZSTD_FALLTHROUGH;
1779
2237
 
1780
2238
  case zdss_load:
1781
2239
  { size_t const neededInSize = ZSTD_nextSrcSizeToDecompress(zds);
@@ -1783,17 +2241,20 @@ size_t ZSTD_decompressStream(ZSTD_DStream* zds, ZSTD_outBuffer* output, ZSTD_inB
1783
2241
  int const isSkipFrame = ZSTD_isSkipFrame(zds);
1784
2242
  size_t loadedSize;
1785
2243
  /* At this point we shouldn't be decompressing a block that we can stream. */
1786
- assert(neededInSize == ZSTD_nextSrcSizeToDecompressWithInputSize(zds, iend - ip));
2244
+ assert(neededInSize == ZSTD_nextSrcSizeToDecompressWithInputSize(zds, (size_t)(iend - ip)));
1787
2245
  if (isSkipFrame) {
1788
2246
  loadedSize = MIN(toLoad, (size_t)(iend-ip));
1789
2247
  } else {
1790
2248
  RETURN_ERROR_IF(toLoad > zds->inBuffSize - zds->inPos,
1791
2249
  corruption_detected,
1792
2250
  "should never happen");
1793
- loadedSize = ZSTD_limitCopy(zds->inBuff + zds->inPos, toLoad, ip, iend-ip);
2251
+ loadedSize = ZSTD_limitCopy(zds->inBuff + zds->inPos, toLoad, ip, (size_t)(iend-ip));
2252
+ }
2253
+ if (loadedSize != 0) {
2254
+ /* ip may be NULL */
2255
+ ip += loadedSize;
2256
+ zds->inPos += loadedSize;
1794
2257
  }
1795
- ip += loadedSize;
1796
- zds->inPos += loadedSize;
1797
2258
  if (loadedSize < toLoad) { someMoreWork = 0; break; } /* not enough input, wait for more */
1798
2259
 
1799
2260
  /* decode loaded input */
@@ -1803,14 +2264,17 @@ size_t ZSTD_decompressStream(ZSTD_DStream* zds, ZSTD_outBuffer* output, ZSTD_inB
1803
2264
  break;
1804
2265
  }
1805
2266
  case zdss_flush:
1806
- { size_t const toFlushSize = zds->outEnd - zds->outStart;
1807
- size_t const flushedSize = ZSTD_limitCopy(op, oend-op, zds->outBuff + zds->outStart, toFlushSize);
1808
- op += flushedSize;
2267
+ {
2268
+ size_t const toFlushSize = zds->outEnd - zds->outStart;
2269
+ size_t const flushedSize = ZSTD_limitCopy(op, (size_t)(oend-op), zds->outBuff + zds->outStart, toFlushSize);
2270
+
2271
+ op = op ? op + flushedSize : op;
2272
+
1809
2273
  zds->outStart += flushedSize;
1810
2274
  if (flushedSize == toFlushSize) { /* flush completed */
1811
2275
  zds->streamStage = zdss_read;
1812
2276
  if ( (zds->outBuffSize < zds->fParams.frameContentSize)
1813
- && (zds->outStart + zds->fParams.blockSizeMax > zds->outBuffSize) ) {
2277
+ && (zds->outStart + zds->fParams.blockSizeMax > zds->outBuffSize) ) {
1814
2278
  DEBUGLOG(5, "restart filling outBuff from beginning (left:%i, needed:%u)",
1815
2279
  (int)(zds->outBuffSize - zds->outStart),
1816
2280
  (U32)zds->fParams.blockSizeMax);
@@ -1824,7 +2288,7 @@ size_t ZSTD_decompressStream(ZSTD_DStream* zds, ZSTD_outBuffer* output, ZSTD_inB
1824
2288
 
1825
2289
  default:
1826
2290
  assert(0); /* impossible */
1827
- RETURN_ERROR(GENERIC, "impossible to reach"); /* some compiler require default to do something */
2291
+ RETURN_ERROR(GENERIC, "impossible to reach"); /* some compilers require default to do something */
1828
2292
  } }
1829
2293
 
1830
2294
  /* result */
@@ -1837,8 +2301,8 @@ size_t ZSTD_decompressStream(ZSTD_DStream* zds, ZSTD_outBuffer* output, ZSTD_inB
1837
2301
  if ((ip==istart) && (op==ostart)) { /* no forward progress */
1838
2302
  zds->noForwardProgress ++;
1839
2303
  if (zds->noForwardProgress >= ZSTD_NO_FORWARD_PROGRESS_MAX) {
1840
- RETURN_ERROR_IF(op==oend, dstSize_tooSmall, "");
1841
- RETURN_ERROR_IF(ip==iend, srcSize_wrong, "");
2304
+ RETURN_ERROR_IF(op==oend, noForwardProgress_destFull, "");
2305
+ RETURN_ERROR_IF(ip==iend, noForwardProgress_inputEmpty, "");
1842
2306
  assert(0);
1843
2307
  }
1844
2308
  } else {
@@ -1875,11 +2339,17 @@ size_t ZSTD_decompressStream_simpleArgs (
1875
2339
  void* dst, size_t dstCapacity, size_t* dstPos,
1876
2340
  const void* src, size_t srcSize, size_t* srcPos)
1877
2341
  {
1878
- ZSTD_outBuffer output = { dst, dstCapacity, *dstPos };
1879
- ZSTD_inBuffer input = { src, srcSize, *srcPos };
1880
- /* ZSTD_compress_generic() will check validity of dstPos and srcPos */
1881
- size_t const cErr = ZSTD_decompressStream(dctx, &output, &input);
1882
- *dstPos = output.pos;
1883
- *srcPos = input.pos;
1884
- return cErr;
2342
+ ZSTD_outBuffer output;
2343
+ ZSTD_inBuffer input;
2344
+ output.dst = dst;
2345
+ output.size = dstCapacity;
2346
+ output.pos = *dstPos;
2347
+ input.src = src;
2348
+ input.size = srcSize;
2349
+ input.pos = *srcPos;
2350
+ { size_t const cErr = ZSTD_decompressStream(dctx, &output, &input);
2351
+ *dstPos = output.pos;
2352
+ *srcPos = input.pos;
2353
+ return cErr;
2354
+ }
1885
2355
  }