zstd-ruby 1.4.4.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 +74 -97
  10. data/ext/zstdruby/libzstd/common/compiler.h +219 -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 +184 -80
  15. data/ext/zstdruby/libzstd/common/error_private.c +11 -2
  16. data/ext/zstdruby/libzstd/common/error_private.h +87 -4
  17. data/ext/zstdruby/libzstd/common/fse.h +47 -116
  18. data/ext/zstdruby/libzstd/common/fse_decompress.c +127 -127
  19. data/ext/zstdruby/libzstd/common/huf.h +112 -197
  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 +11 -5
  23. data/ext/zstdruby/libzstd/common/portability_macros.h +156 -0
  24. data/ext/zstdruby/libzstd/common/threading.c +78 -22
  25. data/ext/zstdruby/libzstd/common/threading.h +9 -13
  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 +2 -37
  29. data/ext/zstdruby/libzstd/common/zstd_deps.h +111 -0
  30. data/ext/zstdruby/libzstd/common/zstd_internal.h +186 -144
  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 +99 -196
  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 +968 -331
  37. data/ext/zstdruby/libzstd/compress/zstd_compress.c +4120 -1191
  38. data/ext/zstdruby/libzstd/compress/zstd_compress_internal.h +688 -159
  39. data/ext/zstdruby/libzstd/compress/zstd_compress_literals.c +121 -40
  40. data/ext/zstdruby/libzstd/compress/zstd_compress_literals.h +16 -6
  41. data/ext/zstdruby/libzstd/compress/zstd_compress_sequences.c +62 -35
  42. data/ext/zstdruby/libzstd/compress/zstd_compress_sequences.h +10 -3
  43. data/ext/zstdruby/libzstd/compress/zstd_compress_superblock.c +577 -0
  44. data/ext/zstdruby/libzstd/compress/zstd_compress_superblock.h +32 -0
  45. data/ext/zstdruby/libzstd/compress/zstd_cwksp.h +322 -115
  46. data/ext/zstdruby/libzstd/compress/zstd_double_fast.c +394 -154
  47. data/ext/zstdruby/libzstd/compress/zstd_double_fast.h +4 -3
  48. data/ext/zstdruby/libzstd/compress/zstd_fast.c +729 -253
  49. data/ext/zstdruby/libzstd/compress/zstd_fast.h +4 -3
  50. data/ext/zstdruby/libzstd/compress/zstd_lazy.c +1289 -247
  51. data/ext/zstdruby/libzstd/compress/zstd_lazy.h +61 -1
  52. data/ext/zstdruby/libzstd/compress/zstd_ldm.c +339 -212
  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 +508 -282
  56. data/ext/zstdruby/libzstd/compress/zstd_opt.h +1 -1
  57. data/ext/zstdruby/libzstd/compress/zstdmt_compress.c +217 -466
  58. data/ext/zstdruby/libzstd/compress/zstdmt_compress.h +35 -114
  59. data/ext/zstdruby/libzstd/decompress/huf_decompress.c +1220 -572
  60. data/ext/zstdruby/libzstd/decompress/huf_decompress_amd64.S +576 -0
  61. data/ext/zstdruby/libzstd/decompress/zstd_ddict.c +23 -19
  62. data/ext/zstdruby/libzstd/decompress/zstd_ddict.h +3 -3
  63. data/ext/zstdruby/libzstd/decompress/zstd_decompress.c +859 -273
  64. data/ext/zstdruby/libzstd/decompress/zstd_decompress_block.c +1244 -375
  65. data/ext/zstdruby/libzstd/decompress/zstd_decompress_block.h +21 -7
  66. data/ext/zstdruby/libzstd/decompress/zstd_decompress_internal.h +74 -11
  67. data/ext/zstdruby/libzstd/dictBuilder/cover.c +75 -54
  68. data/ext/zstdruby/libzstd/dictBuilder/cover.h +20 -9
  69. data/ext/zstdruby/libzstd/dictBuilder/divsufsort.c +1 -1
  70. data/ext/zstdruby/libzstd/dictBuilder/fastcover.c +55 -36
  71. data/ext/zstdruby/libzstd/dictBuilder/zdict.c +126 -110
  72. data/ext/zstdruby/libzstd/{dictBuilder/zdict.h → zdict.h} +248 -56
  73. data/ext/zstdruby/libzstd/zstd.h +1277 -306
  74. data/ext/zstdruby/libzstd/{common/zstd_errors.h → zstd_errors.h} +29 -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 +24 -39
  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 -289
  89. data/ext/zstdruby/libzstd/README.md +0 -159
  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 -47
  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 -2152
  101. data/ext/zstdruby/libzstd/legacy/zstd_v01.h +0 -94
  102. data/ext/zstdruby/libzstd/legacy/zstd_v02.c +0 -3514
  103. data/ext/zstdruby/libzstd/legacy/zstd_v02.h +0 -93
  104. data/ext/zstdruby/libzstd/legacy/zstd_v03.c +0 -3156
  105. data/ext/zstdruby/libzstd/legacy/zstd_v03.h +0 -93
  106. data/ext/zstdruby/libzstd/legacy/zstd_v04.c +0 -3641
  107. data/ext/zstdruby/libzstd/legacy/zstd_v04.h +0 -142
  108. data/ext/zstdruby/libzstd/legacy/zstd_v05.c +0 -4046
  109. data/ext/zstdruby/libzstd/legacy/zstd_v05.h +0 -162
  110. data/ext/zstdruby/libzstd/legacy/zstd_v06.c +0 -4150
  111. data/ext/zstdruby/libzstd/legacy/zstd_v06.h +0 -172
  112. data/ext/zstdruby/libzstd/legacy/zstd_v07.c +0 -4533
  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-present, 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 "cpu.h" /* bmi2 */
60
- #include "mem.h" /* low level memory routines */
58
+ #include "../common/allocations.h" /* ZSTD_customMalloc, ZSTD_customCalloc, ZSTD_customFree */
59
+ #include "../common/zstd_deps.h" /* ZSTD_memcpy, ZSTD_memmove, ZSTD_memset */
60
+ #include "../common/mem.h" /* low level memory routines */
61
61
  #define FSE_STATIC_LINKING_ONLY
62
- #include "fse.h"
63
- #define HUF_STATIC_LINKING_ONLY
64
- #include "huf.h"
65
- #include "zstd_internal.h" /* blockProperties_t */
62
+ #include "../common/fse.h"
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
+ #include "../common/bits.h" /* ZSTD_highbit32 */
69
70
 
70
71
  #if defined(ZSTD_LEGACY_SUPPORT) && (ZSTD_LEGACY_SUPPORT>=1)
71
- # include "zstd_legacy.h"
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,10 +259,20 @@ 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
- dctx->bmi2 = ZSTD_cpuid_bmi2(ZSTD_cpuid());
267
+ dctx->oversizedDuration = 0;
268
+ #if DYNAMIC_BMI2
269
+ dctx->bmi2 = ZSTD_cpuSupportsBmi2();
270
+ #endif
271
+ dctx->ddictSet = NULL;
272
+ ZSTD_DCtx_resetParameters(dctx);
273
+ #ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
274
+ dctx->dictContentEndForFuzzing = NULL;
275
+ #endif
115
276
  }
116
277
 
117
278
  ZSTD_DCtx* ZSTD_initStaticDCtx(void *workspace, size_t workspaceSize)
@@ -127,11 +288,10 @@ ZSTD_DCtx* ZSTD_initStaticDCtx(void *workspace, size_t workspaceSize)
127
288
  return dctx;
128
289
  }
129
290
 
130
- ZSTD_DCtx* ZSTD_createDCtx_advanced(ZSTD_customMem customMem)
131
- {
132
- 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;
133
293
 
134
- { ZSTD_DCtx* const dctx = (ZSTD_DCtx*)ZSTD_malloc(sizeof(*dctx), customMem);
294
+ { ZSTD_DCtx* const dctx = (ZSTD_DCtx*)ZSTD_customMalloc(sizeof(*dctx), customMem);
135
295
  if (!dctx) return NULL;
136
296
  dctx->customMem = customMem;
137
297
  ZSTD_initDCtx_internal(dctx);
@@ -139,10 +299,15 @@ ZSTD_DCtx* ZSTD_createDCtx_advanced(ZSTD_customMem customMem)
139
299
  }
140
300
  }
141
301
 
302
+ ZSTD_DCtx* ZSTD_createDCtx_advanced(ZSTD_customMem customMem)
303
+ {
304
+ return ZSTD_createDCtx_internal(customMem);
305
+ }
306
+
142
307
  ZSTD_DCtx* ZSTD_createDCtx(void)
143
308
  {
144
309
  DEBUGLOG(3, "ZSTD_createDCtx");
145
- return ZSTD_createDCtx_advanced(ZSTD_defaultCMem);
310
+ return ZSTD_createDCtx_internal(ZSTD_defaultCMem);
146
311
  }
147
312
 
148
313
  static void ZSTD_clearDict(ZSTD_DCtx* dctx)
@@ -159,13 +324,17 @@ size_t ZSTD_freeDCtx(ZSTD_DCtx* dctx)
159
324
  RETURN_ERROR_IF(dctx->staticSize, memory_allocation, "not compatible with static DCtx");
160
325
  { ZSTD_customMem const cMem = dctx->customMem;
161
326
  ZSTD_clearDict(dctx);
162
- ZSTD_free(dctx->inBuff, cMem);
327
+ ZSTD_customFree(dctx->inBuff, cMem);
163
328
  dctx->inBuff = NULL;
164
329
  #if defined(ZSTD_LEGACY_SUPPORT) && (ZSTD_LEGACY_SUPPORT >= 1)
165
330
  if (dctx->legacyContext)
166
331
  ZSTD_freeLegacyStreamContext(dctx->legacyContext, dctx->previousLegacyVersion);
167
332
  #endif
168
- ZSTD_free(dctx, cMem);
333
+ if (dctx->ddictSet) {
334
+ ZSTD_freeDDictHashSet(dctx->ddictSet, cMem);
335
+ dctx->ddictSet = NULL;
336
+ }
337
+ ZSTD_customFree(dctx, cMem);
169
338
  return 0;
170
339
  }
171
340
  }
@@ -174,7 +343,30 @@ size_t ZSTD_freeDCtx(ZSTD_DCtx* dctx)
174
343
  void ZSTD_copyDCtx(ZSTD_DCtx* dstDCtx, const ZSTD_DCtx* srcDCtx)
175
344
  {
176
345
  size_t const toCopy = (size_t)((char*)(&dstDCtx->inBuff) - (char*)dstDCtx);
177
- 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
+ }
178
370
  }
179
371
 
180
372
 
@@ -200,6 +392,19 @@ unsigned ZSTD_isFrame(const void* buffer, size_t size)
200
392
  return 0;
201
393
  }
202
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
+
203
408
  /** ZSTD_frameHeaderSize_internal() :
204
409
  * srcSize must be large enough to reach header size fields.
205
410
  * note : only works for formats ZSTD_f_zstd1 and ZSTD_f_zstd1_magicless.
@@ -208,7 +413,7 @@ unsigned ZSTD_isFrame(const void* buffer, size_t size)
208
413
  static size_t ZSTD_frameHeaderSize_internal(const void* src, size_t srcSize, ZSTD_format_e format)
209
414
  {
210
415
  size_t const minInputSize = ZSTD_startingInputLength(format);
211
- RETURN_ERROR_IF(srcSize < minInputSize, srcSize_wrong);
416
+ RETURN_ERROR_IF(srcSize < minInputSize, srcSize_wrong, "");
212
417
 
213
418
  { BYTE const fhd = ((const BYTE*)src)[minInputSize-1];
214
419
  U32 const dictID= fhd & 3;
@@ -235,28 +440,52 @@ size_t ZSTD_frameHeaderSize(const void* src, size_t srcSize)
235
440
  * note : only works for formats ZSTD_f_zstd1 and ZSTD_f_zstd1_magicless
236
441
  * @return : 0, `zfhPtr` is correctly filled,
237
442
  * >0, `srcSize` is too small, value is wanted `srcSize` amount,
238
- * or an error code, which can be tested using ZSTD_isError() */
443
+ ** or an error code, which can be tested using ZSTD_isError() */
239
444
  size_t ZSTD_getFrameHeader_advanced(ZSTD_frameHeader* zfhPtr, const void* src, size_t srcSize, ZSTD_format_e format)
240
445
  {
241
446
  const BYTE* ip = (const BYTE*)src;
242
447
  size_t const minInputSize = ZSTD_startingInputLength(format);
243
448
 
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 */
245
- if (srcSize < minInputSize) return minInputSize;
246
- 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
+ }
247
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 */
248
477
  if ( (format != ZSTD_f_zstd1_magicless)
249
478
  && (MEM_readLE32(src) != ZSTD_MAGICNUMBER) ) {
250
479
  if ((MEM_readLE32(src) & ZSTD_MAGIC_SKIPPABLE_MASK) == ZSTD_MAGIC_SKIPPABLE_START) {
251
480
  /* skippable frame */
252
481
  if (srcSize < ZSTD_SKIPPABLEHEADERSIZE)
253
482
  return ZSTD_SKIPPABLEHEADERSIZE; /* magic number + frame length */
254
- memset(zfhPtr, 0, sizeof(*zfhPtr));
483
+ ZSTD_memset(zfhPtr, 0, sizeof(*zfhPtr));
255
484
  zfhPtr->frameContentSize = MEM_readLE32((const char *)src + ZSTD_FRAMEIDSIZE);
256
485
  zfhPtr->frameType = ZSTD_skippableFrame;
257
486
  return 0;
258
487
  }
259
- RETURN_ERROR(prefix_unknown);
488
+ RETURN_ERROR(prefix_unknown, "");
260
489
  }
261
490
 
262
491
  /* ensure there is enough `srcSize` to fully read/decode frame header */
@@ -280,13 +509,15 @@ size_t ZSTD_getFrameHeader_advanced(ZSTD_frameHeader* zfhPtr, const void* src, s
280
509
  if (!singleSegment) {
281
510
  BYTE const wlByte = ip[pos++];
282
511
  U32 const windowLog = (wlByte >> 3) + ZSTD_WINDOWLOG_ABSOLUTEMIN;
283
- RETURN_ERROR_IF(windowLog > ZSTD_WINDOWLOG_MAX, frameParameter_windowTooLarge);
512
+ RETURN_ERROR_IF(windowLog > ZSTD_WINDOWLOG_MAX, frameParameter_windowTooLarge, "");
284
513
  windowSize = (1ULL << windowLog);
285
514
  windowSize += (windowSize >> 3) * (wlByte&7);
286
515
  }
287
516
  switch(dictIDSizeCode)
288
517
  {
289
- default: assert(0); /* impossible */
518
+ default:
519
+ assert(0); /* impossible */
520
+ ZSTD_FALLTHROUGH;
290
521
  case 0 : break;
291
522
  case 1 : dictID = ip[pos]; pos++; break;
292
523
  case 2 : dictID = MEM_readLE16(ip+pos); pos+=2; break;
@@ -294,7 +525,9 @@ size_t ZSTD_getFrameHeader_advanced(ZSTD_frameHeader* zfhPtr, const void* src, s
294
525
  }
295
526
  switch(fcsID)
296
527
  {
297
- default: assert(0); /* impossible */
528
+ default:
529
+ assert(0); /* impossible */
530
+ ZSTD_FALLTHROUGH;
298
531
  case 0 : if (singleSegment) frameContentSize = ip[pos]; break;
299
532
  case 1 : frameContentSize = MEM_readLE16(ip+pos)+256; break;
300
533
  case 2 : frameContentSize = MEM_readLE32(ip+pos); break;
@@ -323,7 +556,6 @@ size_t ZSTD_getFrameHeader(ZSTD_frameHeader* zfhPtr, const void* src, size_t src
323
556
  return ZSTD_getFrameHeader_advanced(zfhPtr, src, srcSize, ZSTD_f_zstd1);
324
557
  }
325
558
 
326
-
327
559
  /** ZSTD_getFrameContentSize() :
328
560
  * compatible with legacy mode
329
561
  * @return : decompressed size of the single frame pointed to be `src` if known, otherwise
@@ -352,23 +584,57 @@ static size_t readSkippableFrameSize(void const* src, size_t srcSize)
352
584
  size_t const skippableHeaderSize = ZSTD_SKIPPABLEHEADERSIZE;
353
585
  U32 sizeU32;
354
586
 
355
- RETURN_ERROR_IF(srcSize < ZSTD_SKIPPABLEHEADERSIZE, srcSize_wrong);
587
+ RETURN_ERROR_IF(srcSize < ZSTD_SKIPPABLEHEADERSIZE, srcSize_wrong, "");
356
588
 
357
589
  sizeU32 = MEM_readLE32((BYTE const*)src + ZSTD_FRAMEIDSIZE);
358
590
  RETURN_ERROR_IF((U32)(sizeU32 + ZSTD_SKIPPABLEHEADERSIZE) < sizeU32,
359
- frameParameter_unsupported);
360
- {
361
- size_t const skippableSize = skippableHeaderSize + sizeU32;
362
- RETURN_ERROR_IF(skippableSize > srcSize, srcSize_wrong);
591
+ frameParameter_unsupported, "");
592
+ { size_t const skippableSize = skippableHeaderSize + sizeU32;
593
+ RETURN_ERROR_IF(skippableSize > srcSize, srcSize_wrong, "");
363
594
  return skippableSize;
364
595
  }
365
596
  }
366
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
+
367
633
  /** ZSTD_findDecompressedSize() :
368
- * compatible with legacy mode
369
634
  * `srcSize` must be the exact length of some number of ZSTD compressed and/or
370
635
  * skippable frames
371
- * @return : decompressed size of the frames contained */
636
+ * note: compatible with legacy mode
637
+ * @return : decompressed size of the frames contained */
372
638
  unsigned long long ZSTD_findDecompressedSize(const void* src, size_t srcSize)
373
639
  {
374
640
  unsigned long long totalDstSize = 0;
@@ -378,9 +644,7 @@ unsigned long long ZSTD_findDecompressedSize(const void* src, size_t srcSize)
378
644
 
379
645
  if ((magicNumber & ZSTD_MAGIC_SKIPPABLE_MASK) == ZSTD_MAGIC_SKIPPABLE_START) {
380
646
  size_t const skippableSize = readSkippableFrameSize(src, srcSize);
381
- if (ZSTD_isError(skippableSize)) {
382
- return ZSTD_CONTENTSIZE_ERROR;
383
- }
647
+ if (ZSTD_isError(skippableSize)) return ZSTD_CONTENTSIZE_ERROR;
384
648
  assert(skippableSize <= srcSize);
385
649
 
386
650
  src = (const BYTE *)src + skippableSize;
@@ -388,17 +652,17 @@ unsigned long long ZSTD_findDecompressedSize(const void* src, size_t srcSize)
388
652
  continue;
389
653
  }
390
654
 
391
- { unsigned long long const ret = ZSTD_getFrameContentSize(src, srcSize);
392
- 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;
393
657
 
394
- /* check for overflow */
395
- if (totalDstSize + ret < totalDstSize) return ZSTD_CONTENTSIZE_ERROR;
396
- totalDstSize += ret;
658
+ if (totalDstSize + fcs < totalDstSize)
659
+ return ZSTD_CONTENTSIZE_ERROR; /* check for overflow */
660
+ totalDstSize += fcs;
397
661
  }
662
+ /* skip to next frame */
398
663
  { size_t const frameSrcSize = ZSTD_findFrameCompressedSize(src, srcSize);
399
- if (ZSTD_isError(frameSrcSize)) {
400
- return ZSTD_CONTENTSIZE_ERROR;
401
- }
664
+ if (ZSTD_isError(frameSrcSize)) return ZSTD_CONTENTSIZE_ERROR;
665
+ assert(frameSrcSize <= srcSize);
402
666
 
403
667
  src = (const BYTE *)src + frameSrcSize;
404
668
  srcSize -= frameSrcSize;
@@ -428,20 +692,29 @@ unsigned long long ZSTD_getDecompressedSize(const void* src, size_t srcSize)
428
692
 
429
693
  /** ZSTD_decodeFrameHeader() :
430
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.
431
696
  * @return : 0 if success, or an error code, which can be tested using ZSTD_isError() */
432
697
  static size_t ZSTD_decodeFrameHeader(ZSTD_DCtx* dctx, const void* src, size_t headerSize)
433
698
  {
434
699
  size_t const result = ZSTD_getFrameHeader_advanced(&(dctx->fParams), src, headerSize, dctx->format);
435
700
  if (ZSTD_isError(result)) return result; /* invalid header */
436
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
+
437
708
  #ifndef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
438
709
  /* Skip the dictID check in fuzzing mode, because it makes the search
439
710
  * harder.
440
711
  */
441
712
  RETURN_ERROR_IF(dctx->fParams.dictID && (dctx->dictID != dctx->fParams.dictID),
442
- dictionary_wrong);
713
+ dictionary_wrong, "");
443
714
  #endif
444
- 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;
445
718
  return 0;
446
719
  }
447
720
 
@@ -456,7 +729,7 @@ static ZSTD_frameSizeInfo ZSTD_errorFrameSizeInfo(size_t ret)
456
729
  static ZSTD_frameSizeInfo ZSTD_findFrameSizeInfo(const void* src, size_t srcSize)
457
730
  {
458
731
  ZSTD_frameSizeInfo frameSizeInfo;
459
- memset(&frameSizeInfo, 0, sizeof(ZSTD_frameSizeInfo));
732
+ ZSTD_memset(&frameSizeInfo, 0, sizeof(ZSTD_frameSizeInfo));
460
733
 
461
734
  #if defined(ZSTD_LEGACY_SUPPORT) && (ZSTD_LEGACY_SUPPORT >= 1)
462
735
  if (ZSTD_isLegacy(src, srcSize))
@@ -511,10 +784,11 @@ static ZSTD_frameSizeInfo ZSTD_findFrameSizeInfo(const void* src, size_t srcSize
511
784
  ip += 4;
512
785
  }
513
786
 
514
- frameSizeInfo.compressedSize = ip - ipstart;
787
+ frameSizeInfo.nbBlocks = nbBlocks;
788
+ frameSizeInfo.compressedSize = (size_t)(ip - ipstart);
515
789
  frameSizeInfo.decompressedBound = (zfh.frameContentSize != ZSTD_CONTENTSIZE_UNKNOWN)
516
790
  ? zfh.frameContentSize
517
- : nbBlocks * zfh.blockSizeMax;
791
+ : (unsigned long long)nbBlocks * zfh.blockSizeMax;
518
792
  return frameSizeInfo;
519
793
  }
520
794
  }
@@ -554,28 +828,59 @@ unsigned long long ZSTD_decompressBound(const void* src, size_t srcSize)
554
828
  return bound;
555
829
  }
556
830
 
831
+ size_t ZSTD_decompressionMargin(void const* src, size_t srcSize)
832
+ {
833
+ size_t margin = 0;
834
+ unsigned maxBlockSize = 0;
557
835
 
558
- /*-*************************************************************
559
- * Frame decoding
560
- ***************************************************************/
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;
561
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
+ }
562
862
 
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;
863
+ assert(srcSize >= compressedSize);
864
+ src = (const BYTE*)src + compressedSize;
865
+ srcSize -= compressedSize;
570
866
  }
867
+
868
+ /* Add the max block size back to the margin. */
869
+ margin += maxBlockSize;
870
+
871
+ return margin;
571
872
  }
572
873
 
874
+ /*-*************************************************************
875
+ * Frame decoding
876
+ ***************************************************************/
877
+
573
878
  /** ZSTD_insertBlock() :
574
879
  * insert `src` block into `dctx` history. Useful to track uncompressed blocks. */
575
880
  size_t ZSTD_insertBlock(ZSTD_DCtx* dctx, const void* blockStart, size_t blockSize)
576
881
  {
577
882
  DEBUGLOG(5, "ZSTD_insertBlock: %u bytes", (unsigned)blockSize);
578
- ZSTD_checkContinuity(dctx, blockStart);
883
+ ZSTD_checkContinuity(dctx, blockStart, blockSize);
579
884
  dctx->previousDstEnd = (const char*)blockStart + blockSize;
580
885
  return blockSize;
581
886
  }
@@ -585,12 +890,12 @@ static size_t ZSTD_copyRawBlock(void* dst, size_t dstCapacity,
585
890
  const void* src, size_t srcSize)
586
891
  {
587
892
  DEBUGLOG(5, "ZSTD_copyRawBlock");
893
+ RETURN_ERROR_IF(srcSize > dstCapacity, dstSize_tooSmall, "");
588
894
  if (dst == NULL) {
589
895
  if (srcSize == 0) return 0;
590
- RETURN_ERROR(dstBuffer_null);
896
+ RETURN_ERROR(dstBuffer_null, "");
591
897
  }
592
- RETURN_ERROR_IF(srcSize > dstCapacity, dstSize_tooSmall);
593
- memcpy(dst, src, srcSize);
898
+ ZSTD_memmove(dst, src, srcSize);
594
899
  return srcSize;
595
900
  }
596
901
 
@@ -598,15 +903,41 @@ static size_t ZSTD_setRleBlock(void* dst, size_t dstCapacity,
598
903
  BYTE b,
599
904
  size_t regenSize)
600
905
  {
906
+ RETURN_ERROR_IF(regenSize > dstCapacity, dstSize_tooSmall, "");
601
907
  if (dst == NULL) {
602
908
  if (regenSize == 0) return 0;
603
- RETURN_ERROR(dstBuffer_null);
909
+ RETURN_ERROR(dstBuffer_null, "");
604
910
  }
605
- RETURN_ERROR_IF(regenSize > dstCapacity, dstSize_tooSmall);
606
- memset(dst, b, regenSize);
911
+ ZSTD_memset(dst, b, regenSize);
607
912
  return regenSize;
608
913
  }
609
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
+
610
941
 
611
942
  /*! ZSTD_decompressFrame() :
612
943
  * @dctx must be properly initialized
@@ -616,9 +947,10 @@ static size_t ZSTD_decompressFrame(ZSTD_DCtx* dctx,
616
947
  void* dst, size_t dstCapacity,
617
948
  const void** srcPtr, size_t *srcSizePtr)
618
949
  {
619
- const BYTE* ip = (const BYTE*)(*srcPtr);
620
- BYTE* const ostart = (BYTE* const)dst;
621
- BYTE* const oend = ostart + dstCapacity;
950
+ const BYTE* const istart = (const BYTE*)(*srcPtr);
951
+ const BYTE* ip = istart;
952
+ BYTE* const ostart = (BYTE*)dst;
953
+ BYTE* const oend = dstCapacity != 0 ? ostart + dstCapacity : ostart;
622
954
  BYTE* op = ostart;
623
955
  size_t remainingSrcSize = *srcSizePtr;
624
956
 
@@ -627,20 +959,21 @@ static size_t ZSTD_decompressFrame(ZSTD_DCtx* dctx,
627
959
  /* check */
628
960
  RETURN_ERROR_IF(
629
961
  remainingSrcSize < ZSTD_FRAMEHEADERSIZE_MIN(dctx->format)+ZSTD_blockHeaderSize,
630
- srcSize_wrong);
962
+ srcSize_wrong, "");
631
963
 
632
964
  /* Frame Header */
633
965
  { size_t const frameHeaderSize = ZSTD_frameHeaderSize_internal(
634
966
  ip, ZSTD_FRAMEHEADERSIZE_PREFIX(dctx->format), dctx->format);
635
967
  if (ZSTD_isError(frameHeaderSize)) return frameHeaderSize;
636
968
  RETURN_ERROR_IF(remainingSrcSize < frameHeaderSize+ZSTD_blockHeaderSize,
637
- srcSize_wrong);
638
- FORWARD_IF_ERROR( ZSTD_decodeFrameHeader(dctx, ip, frameHeaderSize) );
969
+ srcSize_wrong, "");
970
+ FORWARD_IF_ERROR( ZSTD_decodeFrameHeader(dctx, ip, frameHeaderSize) , "");
639
971
  ip += frameHeaderSize; remainingSrcSize -= frameHeaderSize;
640
972
  }
641
973
 
642
974
  /* Loop on each block */
643
975
  while (1) {
976
+ BYTE* oBlockEnd = oend;
644
977
  size_t decodedSize;
645
978
  blockProperties_t blockProperties;
646
979
  size_t const cBlockSize = ZSTD_getcBlockSize(ip, remainingSrcSize, &blockProperties);
@@ -648,28 +981,48 @@ static size_t ZSTD_decompressFrame(ZSTD_DCtx* dctx,
648
981
 
649
982
  ip += ZSTD_blockHeaderSize;
650
983
  remainingSrcSize -= ZSTD_blockHeaderSize;
651
- RETURN_ERROR_IF(cBlockSize > remainingSrcSize, srcSize_wrong);
984
+ RETURN_ERROR_IF(cBlockSize > remainingSrcSize, srcSize_wrong, "");
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
+ }
652
1002
 
653
1003
  switch(blockProperties.blockType)
654
1004
  {
655
1005
  case bt_compressed:
656
- 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);
657
1007
  break;
658
1008
  case bt_raw :
659
- 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);
660
1011
  break;
661
1012
  case bt_rle :
662
- decodedSize = ZSTD_setRleBlock(op, oend-op, *ip, blockProperties.origSize);
1013
+ decodedSize = ZSTD_setRleBlock(op, (size_t)(oBlockEnd-op), *ip, blockProperties.origSize);
663
1014
  break;
664
1015
  case bt_reserved :
665
1016
  default:
666
- RETURN_ERROR(corruption_detected);
1017
+ RETURN_ERROR(corruption_detected, "invalid block type");
667
1018
  }
668
1019
 
669
1020
  if (ZSTD_isError(decodedSize)) return decodedSize;
670
- if (dctx->fParams.checksumFlag)
1021
+ if (dctx->validateChecksum)
671
1022
  XXH64_update(&dctx->xxhState, op, decodedSize);
672
- op += decodedSize;
1023
+ if (decodedSize != 0)
1024
+ op += decodedSize;
1025
+ assert(ip != NULL);
673
1026
  ip += cBlockSize;
674
1027
  remainingSrcSize -= cBlockSize;
675
1028
  if (blockProperties.lastBlock) break;
@@ -677,22 +1030,25 @@ static size_t ZSTD_decompressFrame(ZSTD_DCtx* dctx,
677
1030
 
678
1031
  if (dctx->fParams.frameContentSize != ZSTD_CONTENTSIZE_UNKNOWN) {
679
1032
  RETURN_ERROR_IF((U64)(op-ostart) != dctx->fParams.frameContentSize,
680
- corruption_detected);
1033
+ corruption_detected, "");
681
1034
  }
682
1035
  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);
1036
+ RETURN_ERROR_IF(remainingSrcSize<4, 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
+ }
688
1043
  ip += 4;
689
1044
  remainingSrcSize -= 4;
690
1045
  }
691
-
1046
+ ZSTD_DCtx_trace_end(dctx, (U64)(op-ostart), (U64)(ip-istart), /* streaming */ 0);
692
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);
693
1049
  *srcPtr = ip;
694
1050
  *srcSizePtr = remainingSrcSize;
695
- return op-ostart;
1051
+ return (size_t)(op-ostart);
696
1052
  }
697
1053
 
698
1054
  static size_t ZSTD_decompressMultiFrame(ZSTD_DCtx* dctx,
@@ -725,7 +1081,7 @@ static size_t ZSTD_decompressMultiFrame(ZSTD_DCtx* dctx,
725
1081
  decodedSize = ZSTD_decompressLegacy(dst, dstCapacity, src, frameSize, dict, dictSize);
726
1082
  if (ZSTD_isError(decodedSize)) return decodedSize;
727
1083
 
728
- assert(decodedSize <=- dstCapacity);
1084
+ assert(decodedSize <= dstCapacity);
729
1085
  dst = (BYTE*)dst + decodedSize;
730
1086
  dstCapacity -= decodedSize;
731
1087
 
@@ -736,28 +1092,29 @@ static size_t ZSTD_decompressMultiFrame(ZSTD_DCtx* dctx,
736
1092
  }
737
1093
  #endif
738
1094
 
739
- { U32 const magicNumber = MEM_readLE32(src);
740
- DEBUGLOG(4, "reading magic number %08X (expecting %08X)",
741
- (unsigned)magicNumber, ZSTD_MAGICNUMBER);
1095
+ if (srcSize >= 4) {
1096
+ U32 const magicNumber = MEM_readLE32(src);
1097
+ DEBUGLOG(5, "reading magic number %08X", (unsigned)magicNumber);
742
1098
  if ((magicNumber & ZSTD_MAGIC_SKIPPABLE_MASK) == ZSTD_MAGIC_SKIPPABLE_START) {
1099
+ /* skippable frame detected : skip it */
743
1100
  size_t const skippableSize = readSkippableFrameSize(src, srcSize);
744
- FORWARD_IF_ERROR(skippableSize);
1101
+ FORWARD_IF_ERROR(skippableSize, "invalid skippable frame");
745
1102
  assert(skippableSize <= srcSize);
746
1103
 
747
1104
  src = (const BYTE *)src + skippableSize;
748
1105
  srcSize -= skippableSize;
749
- continue;
1106
+ continue; /* check next frame */
750
1107
  } }
751
1108
 
752
1109
  if (ddict) {
753
1110
  /* we were called from ZSTD_decompress_usingDDict */
754
- FORWARD_IF_ERROR(ZSTD_decompressBegin_usingDDict(dctx, ddict));
1111
+ FORWARD_IF_ERROR(ZSTD_decompressBegin_usingDDict(dctx, ddict), "");
755
1112
  } else {
756
1113
  /* this will initialize correctly with no dict if dict == NULL, so
757
1114
  * use this in all cases but ddict */
758
- FORWARD_IF_ERROR(ZSTD_decompressBegin_usingDict(dctx, dict, dictSize));
1115
+ FORWARD_IF_ERROR(ZSTD_decompressBegin_usingDict(dctx, dict, dictSize), "");
759
1116
  }
760
- ZSTD_checkContinuity(dctx, dst);
1117
+ ZSTD_checkContinuity(dctx, dst, dstCapacity);
761
1118
 
762
1119
  { const size_t res = ZSTD_decompressFrame(dctx, dst, dstCapacity,
763
1120
  &src, &srcSize);
@@ -765,18 +1122,17 @@ static size_t ZSTD_decompressMultiFrame(ZSTD_DCtx* dctx,
765
1122
  (ZSTD_getErrorCode(res) == ZSTD_error_prefix_unknown)
766
1123
  && (moreThan1Frame==1),
767
1124
  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.");
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.");
777
1132
  if (ZSTD_isError(res)) return res;
778
1133
  assert(res <= dstCapacity);
779
- dst = (BYTE*)dst + res;
1134
+ if (res != 0)
1135
+ dst = (BYTE*)dst + res;
780
1136
  dstCapacity -= res;
781
1137
  }
782
1138
  moreThan1Frame = 1;
@@ -784,7 +1140,7 @@ static size_t ZSTD_decompressMultiFrame(ZSTD_DCtx* dctx,
784
1140
 
785
1141
  RETURN_ERROR_IF(srcSize, srcSize_wrong, "input not entirely consumed");
786
1142
 
787
- return (BYTE*)dst - (BYTE*)dststart;
1143
+ return (size_t)((BYTE*)dst - (BYTE*)dststart);
788
1144
  }
789
1145
 
790
1146
  size_t ZSTD_decompress_usingDict(ZSTD_DCtx* dctx,
@@ -801,7 +1157,7 @@ static ZSTD_DDict const* ZSTD_getDDict(ZSTD_DCtx* dctx)
801
1157
  switch (dctx->dictUses) {
802
1158
  default:
803
1159
  assert(0 /* Impossible */);
804
- /* fall-through */
1160
+ ZSTD_FALLTHROUGH;
805
1161
  case ZSTD_dont_use:
806
1162
  ZSTD_clearDict(dctx);
807
1163
  return NULL;
@@ -823,8 +1179,8 @@ size_t ZSTD_decompress(void* dst, size_t dstCapacity, const void* src, size_t sr
823
1179
  {
824
1180
  #if defined(ZSTD_HEAPMODE) && (ZSTD_HEAPMODE>=1)
825
1181
  size_t regenSize;
826
- ZSTD_DCtx* const dctx = ZSTD_createDCtx();
827
- RETURN_ERROR_IF(dctx==NULL, memory_allocation);
1182
+ ZSTD_DCtx* const dctx = ZSTD_createDCtx_internal(ZSTD_defaultCMem);
1183
+ RETURN_ERROR_IF(dctx==NULL, memory_allocation, "NULL pointer!");
828
1184
  regenSize = ZSTD_decompressDCtx(dctx, dst, dstCapacity, src, srcSize);
829
1185
  ZSTD_freeDCtx(dctx);
830
1186
  return regenSize;
@@ -842,12 +1198,32 @@ size_t ZSTD_decompress(void* dst, size_t dstCapacity, const void* src, size_t sr
842
1198
  ****************************************/
843
1199
  size_t ZSTD_nextSrcSizeToDecompress(ZSTD_DCtx* dctx) { return dctx->expected; }
844
1200
 
1201
+ /**
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
1204
+ * be streamed.
1205
+ *
1206
+ * For blocks that can be streamed, this allows us to reduce the latency until we produce
1207
+ * output, and avoid copying the input.
1208
+ *
1209
+ * @param inputSize - The total amount of input that the caller currently has.
1210
+ */
1211
+ static size_t ZSTD_nextSrcSizeToDecompressWithInputSize(ZSTD_DCtx* dctx, size_t inputSize) {
1212
+ if (!(dctx->stage == ZSTDds_decompressBlock || dctx->stage == ZSTDds_decompressLastBlock))
1213
+ return dctx->expected;
1214
+ if (dctx->bType != bt_raw)
1215
+ return dctx->expected;
1216
+ return BOUNDED(1, inputSize, dctx->expected);
1217
+ }
1218
+
845
1219
  ZSTD_nextInputType_e ZSTD_nextInputType(ZSTD_DCtx* dctx) {
846
1220
  switch(dctx->stage)
847
1221
  {
848
1222
  default: /* should not happen */
849
1223
  assert(0);
1224
+ ZSTD_FALLTHROUGH;
850
1225
  case ZSTDds_getFrameHeaderSize:
1226
+ ZSTD_FALLTHROUGH;
851
1227
  case ZSTDds_decodeFrameHeader:
852
1228
  return ZSTDnit_frameHeader;
853
1229
  case ZSTDds_decodeBlockHeader:
@@ -859,6 +1235,7 @@ ZSTD_nextInputType_e ZSTD_nextInputType(ZSTD_DCtx* dctx) {
859
1235
  case ZSTDds_checkChecksum:
860
1236
  return ZSTDnit_checksum;
861
1237
  case ZSTDds_decodeSkippableHeader:
1238
+ ZSTD_FALLTHROUGH;
862
1239
  case ZSTDds_skipFrame:
863
1240
  return ZSTDnit_skippableFrame;
864
1241
  }
@@ -874,8 +1251,10 @@ size_t ZSTD_decompressContinue(ZSTD_DCtx* dctx, void* dst, size_t dstCapacity, c
874
1251
  {
875
1252
  DEBUGLOG(5, "ZSTD_decompressContinue (srcSize:%u)", (unsigned)srcSize);
876
1253
  /* Sanity check */
877
- RETURN_ERROR_IF(srcSize != dctx->expected, srcSize_wrong, "not allowed");
878
- if (dstCapacity) ZSTD_checkContinuity(dctx, dst);
1254
+ RETURN_ERROR_IF(srcSize != ZSTD_nextSrcSizeToDecompressWithInputSize(dctx, srcSize), srcSize_wrong, "not allowed");
1255
+ ZSTD_checkContinuity(dctx, dst, dstCapacity);
1256
+
1257
+ dctx->processedCSize += srcSize;
879
1258
 
880
1259
  switch (dctx->stage)
881
1260
  {
@@ -884,22 +1263,22 @@ size_t ZSTD_decompressContinue(ZSTD_DCtx* dctx, void* dst, size_t dstCapacity, c
884
1263
  if (dctx->format == ZSTD_f_zstd1) { /* allows header */
885
1264
  assert(srcSize >= ZSTD_FRAMEIDSIZE); /* to read skippable magic number */
886
1265
  if ((MEM_readLE32(src) & ZSTD_MAGIC_SKIPPABLE_MASK) == ZSTD_MAGIC_SKIPPABLE_START) { /* skippable frame */
887
- memcpy(dctx->headerBuffer, src, srcSize);
1266
+ ZSTD_memcpy(dctx->headerBuffer, src, srcSize);
888
1267
  dctx->expected = ZSTD_SKIPPABLEHEADERSIZE - srcSize; /* remaining to load to get full skippable frame header */
889
1268
  dctx->stage = ZSTDds_decodeSkippableHeader;
890
1269
  return 0;
891
1270
  } }
892
1271
  dctx->headerSize = ZSTD_frameHeaderSize_internal(src, srcSize, dctx->format);
893
1272
  if (ZSTD_isError(dctx->headerSize)) return dctx->headerSize;
894
- memcpy(dctx->headerBuffer, src, srcSize);
1273
+ ZSTD_memcpy(dctx->headerBuffer, src, srcSize);
895
1274
  dctx->expected = dctx->headerSize - srcSize;
896
1275
  dctx->stage = ZSTDds_decodeFrameHeader;
897
1276
  return 0;
898
1277
 
899
1278
  case ZSTDds_decodeFrameHeader:
900
1279
  assert(src != NULL);
901
- memcpy(dctx->headerBuffer + (dctx->headerSize - srcSize), src, srcSize);
902
- FORWARD_IF_ERROR(ZSTD_decodeFrameHeader(dctx, dctx->headerBuffer, dctx->headerSize));
1280
+ ZSTD_memcpy(dctx->headerBuffer + (dctx->headerSize - srcSize), src, srcSize);
1281
+ FORWARD_IF_ERROR(ZSTD_decodeFrameHeader(dctx, dctx->headerBuffer, dctx->headerSize), "");
903
1282
  dctx->expected = ZSTD_blockHeaderSize;
904
1283
  dctx->stage = ZSTDds_decodeBlockHeader;
905
1284
  return 0;
@@ -940,51 +1319,67 @@ size_t ZSTD_decompressContinue(ZSTD_DCtx* dctx, void* dst, size_t dstCapacity, c
940
1319
  {
941
1320
  case bt_compressed:
942
1321
  DEBUGLOG(5, "ZSTD_decompressContinue: case bt_compressed");
943
- 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);
1323
+ dctx->expected = 0; /* Streaming not supported */
944
1324
  break;
945
1325
  case bt_raw :
1326
+ assert(srcSize <= dctx->expected);
946
1327
  rSize = ZSTD_copyRawBlock(dst, dstCapacity, src, srcSize);
1328
+ FORWARD_IF_ERROR(rSize, "ZSTD_copyRawBlock failed");
1329
+ assert(rSize == srcSize);
1330
+ dctx->expected -= rSize;
947
1331
  break;
948
1332
  case bt_rle :
949
1333
  rSize = ZSTD_setRleBlock(dst, dstCapacity, *(const BYTE*)src, dctx->rleSize);
1334
+ dctx->expected = 0; /* Streaming not supported */
950
1335
  break;
951
1336
  case bt_reserved : /* should never happen */
952
1337
  default:
953
- RETURN_ERROR(corruption_detected);
1338
+ RETURN_ERROR(corruption_detected, "invalid block type");
954
1339
  }
955
- if (ZSTD_isError(rSize)) return rSize;
1340
+ FORWARD_IF_ERROR(rSize, "");
956
1341
  RETURN_ERROR_IF(rSize > dctx->fParams.blockSizeMax, corruption_detected, "Decompressed Block Size Exceeds Maximum");
957
1342
  DEBUGLOG(5, "ZSTD_decompressContinue: decoded size from block : %u", (unsigned)rSize);
958
1343
  dctx->decodedSize += rSize;
959
- if (dctx->fParams.checksumFlag) XXH64_update(&dctx->xxhState, dst, rSize);
1344
+ if (dctx->validateChecksum) XXH64_update(&dctx->xxhState, dst, rSize);
1345
+ dctx->previousDstEnd = (char*)dst + rSize;
1346
+
1347
+ /* Stay on the same stage until we are finished streaming the block. */
1348
+ if (dctx->expected > 0) {
1349
+ return rSize;
1350
+ }
960
1351
 
961
1352
  if (dctx->stage == ZSTDds_decompressLastBlock) { /* end of frame */
962
1353
  DEBUGLOG(4, "ZSTD_decompressContinue: decoded size from frame : %u", (unsigned)dctx->decodedSize);
963
1354
  RETURN_ERROR_IF(
964
1355
  dctx->fParams.frameContentSize != ZSTD_CONTENTSIZE_UNKNOWN
965
1356
  && dctx->decodedSize != dctx->fParams.frameContentSize,
966
- corruption_detected);
1357
+ corruption_detected, "");
967
1358
  if (dctx->fParams.checksumFlag) { /* another round for frame checksum */
968
1359
  dctx->expected = 4;
969
1360
  dctx->stage = ZSTDds_checkChecksum;
970
1361
  } else {
1362
+ ZSTD_DCtx_trace_end(dctx, dctx->decodedSize, dctx->processedCSize, /* streaming */ 1);
971
1363
  dctx->expected = 0; /* ends here */
972
1364
  dctx->stage = ZSTDds_getFrameHeaderSize;
973
1365
  }
974
1366
  } else {
975
1367
  dctx->stage = ZSTDds_decodeBlockHeader;
976
1368
  dctx->expected = ZSTD_blockHeaderSize;
977
- dctx->previousDstEnd = (char*)dst + rSize;
978
1369
  }
979
1370
  return rSize;
980
1371
  }
981
1372
 
982
1373
  case ZSTDds_checkChecksum:
983
1374
  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);
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);
988
1383
  dctx->expected = 0;
989
1384
  dctx->stage = ZSTDds_getFrameHeaderSize;
990
1385
  return 0;
@@ -993,7 +1388,7 @@ size_t ZSTD_decompressContinue(ZSTD_DCtx* dctx, void* dst, size_t dstCapacity, c
993
1388
  case ZSTDds_decodeSkippableHeader:
994
1389
  assert(src != NULL);
995
1390
  assert(srcSize <= ZSTD_SKIPPABLEHEADERSIZE);
996
- memcpy(dctx->headerBuffer + (ZSTD_SKIPPABLEHEADERSIZE - srcSize), src, srcSize); /* complete skippable header */
1391
+ ZSTD_memcpy(dctx->headerBuffer + (ZSTD_SKIPPABLEHEADERSIZE - srcSize), src, srcSize); /* complete skippable header */
997
1392
  dctx->expected = MEM_readLE32(dctx->headerBuffer + ZSTD_FRAMEIDSIZE); /* note : dctx->expected can grow seriously large, beyond local buffer size */
998
1393
  dctx->stage = ZSTDds_skipFrame;
999
1394
  return 0;
@@ -1005,7 +1400,7 @@ size_t ZSTD_decompressContinue(ZSTD_DCtx* dctx, void* dst, size_t dstCapacity, c
1005
1400
 
1006
1401
  default:
1007
1402
  assert(0); /* impossible */
1008
- RETURN_ERROR(GENERIC); /* some compiler require default to do something */
1403
+ RETURN_ERROR(GENERIC, "impossible to reach"); /* some compilers require default to do something */
1009
1404
  }
1010
1405
  }
1011
1406
 
@@ -1016,6 +1411,10 @@ static size_t ZSTD_refDictContent(ZSTD_DCtx* dctx, const void* dict, size_t dict
1016
1411
  dctx->virtualStart = (const char*)dict - ((const char*)(dctx->previousDstEnd) - (const char*)(dctx->prefixStart));
1017
1412
  dctx->prefixStart = dict;
1018
1413
  dctx->previousDstEnd = (const char*)dict + dictSize;
1414
+ #ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
1415
+ dctx->dictContentBeginForFuzzing = dctx->prefixStart;
1416
+ dctx->dictContentEndForFuzzing = dctx->previousDstEnd;
1417
+ #endif
1019
1418
  return 0;
1020
1419
  }
1021
1420
 
@@ -1029,7 +1428,7 @@ ZSTD_loadDEntropy(ZSTD_entropyDTables_t* entropy,
1029
1428
  const BYTE* dictPtr = (const BYTE*)dict;
1030
1429
  const BYTE* const dictEnd = dictPtr + dictSize;
1031
1430
 
1032
- RETURN_ERROR_IF(dictSize <= 8, dictionary_corrupted);
1431
+ RETURN_ERROR_IF(dictSize <= 8, dictionary_corrupted, "dict is too small");
1033
1432
  assert(MEM_readLE32(dict) == ZSTD_MAGIC_DICTIONARY); /* dict must be valid */
1034
1433
  dictPtr += 8; /* skip header = magic + dictID */
1035
1434
 
@@ -1042,66 +1441,72 @@ ZSTD_loadDEntropy(ZSTD_entropyDTables_t* entropy,
1042
1441
  /* in minimal huffman, we always use X1 variants */
1043
1442
  size_t const hSize = HUF_readDTableX1_wksp(entropy->hufTable,
1044
1443
  dictPtr, dictEnd - dictPtr,
1045
- workspace, workspaceSize);
1444
+ workspace, workspaceSize, /* flags */ 0);
1046
1445
  #else
1047
1446
  size_t const hSize = HUF_readDTableX2_wksp(entropy->hufTable,
1048
- dictPtr, dictEnd - dictPtr,
1049
- workspace, workspaceSize);
1447
+ dictPtr, (size_t)(dictEnd - dictPtr),
1448
+ workspace, workspaceSize, /* flags */ 0);
1050
1449
  #endif
1051
- RETURN_ERROR_IF(HUF_isError(hSize), dictionary_corrupted);
1450
+ RETURN_ERROR_IF(HUF_isError(hSize), dictionary_corrupted, "");
1052
1451
  dictPtr += hSize;
1053
1452
  }
1054
1453
 
1055
1454
  { short offcodeNCount[MaxOff+1];
1056
1455
  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);
1456
+ size_t const offcodeHeaderSize = FSE_readNCount(offcodeNCount, &offcodeMaxValue, &offcodeLog, dictPtr, (size_t)(dictEnd-dictPtr));
1457
+ RETURN_ERROR_IF(FSE_isError(offcodeHeaderSize), dictionary_corrupted, "");
1458
+ RETURN_ERROR_IF(offcodeMaxValue > MaxOff, dictionary_corrupted, "");
1459
+ RETURN_ERROR_IF(offcodeLog > OffFSELog, dictionary_corrupted, "");
1061
1460
  ZSTD_buildFSETable( entropy->OFTable,
1062
1461
  offcodeNCount, offcodeMaxValue,
1063
1462
  OF_base, OF_bits,
1064
- offcodeLog);
1463
+ offcodeLog,
1464
+ entropy->workspace, sizeof(entropy->workspace),
1465
+ /* bmi2 */0);
1065
1466
  dictPtr += offcodeHeaderSize;
1066
1467
  }
1067
1468
 
1068
1469
  { short matchlengthNCount[MaxML+1];
1069
1470
  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);
1471
+ size_t const matchlengthHeaderSize = FSE_readNCount(matchlengthNCount, &matchlengthMaxValue, &matchlengthLog, dictPtr, (size_t)(dictEnd-dictPtr));
1472
+ RETURN_ERROR_IF(FSE_isError(matchlengthHeaderSize), dictionary_corrupted, "");
1473
+ RETURN_ERROR_IF(matchlengthMaxValue > MaxML, dictionary_corrupted, "");
1474
+ RETURN_ERROR_IF(matchlengthLog > MLFSELog, dictionary_corrupted, "");
1074
1475
  ZSTD_buildFSETable( entropy->MLTable,
1075
1476
  matchlengthNCount, matchlengthMaxValue,
1076
1477
  ML_base, ML_bits,
1077
- matchlengthLog);
1478
+ matchlengthLog,
1479
+ entropy->workspace, sizeof(entropy->workspace),
1480
+ /* bmi2 */ 0);
1078
1481
  dictPtr += matchlengthHeaderSize;
1079
1482
  }
1080
1483
 
1081
1484
  { short litlengthNCount[MaxLL+1];
1082
1485
  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);
1486
+ size_t const litlengthHeaderSize = FSE_readNCount(litlengthNCount, &litlengthMaxValue, &litlengthLog, dictPtr, (size_t)(dictEnd-dictPtr));
1487
+ RETURN_ERROR_IF(FSE_isError(litlengthHeaderSize), dictionary_corrupted, "");
1488
+ RETURN_ERROR_IF(litlengthMaxValue > MaxLL, dictionary_corrupted, "");
1489
+ RETURN_ERROR_IF(litlengthLog > LLFSELog, dictionary_corrupted, "");
1087
1490
  ZSTD_buildFSETable( entropy->LLTable,
1088
1491
  litlengthNCount, litlengthMaxValue,
1089
1492
  LL_base, LL_bits,
1090
- litlengthLog);
1493
+ litlengthLog,
1494
+ entropy->workspace, sizeof(entropy->workspace),
1495
+ /* bmi2 */ 0);
1091
1496
  dictPtr += litlengthHeaderSize;
1092
1497
  }
1093
1498
 
1094
- RETURN_ERROR_IF(dictPtr+12 > dictEnd, dictionary_corrupted);
1499
+ RETURN_ERROR_IF(dictPtr+12 > dictEnd, dictionary_corrupted, "");
1095
1500
  { int i;
1096
1501
  size_t const dictContentSize = (size_t)(dictEnd - (dictPtr+12));
1097
1502
  for (i=0; i<3; i++) {
1098
1503
  U32 const rep = MEM_readLE32(dictPtr); dictPtr += 4;
1099
1504
  RETURN_ERROR_IF(rep==0 || rep > dictContentSize,
1100
- dictionary_corrupted);
1505
+ dictionary_corrupted, "");
1101
1506
  entropy->rep[i] = rep;
1102
1507
  } }
1103
1508
 
1104
- return dictPtr - (const BYTE*)dict;
1509
+ return (size_t)(dictPtr - (const BYTE*)dict);
1105
1510
  }
1106
1511
 
1107
1512
  static size_t ZSTD_decompress_insertDictionary(ZSTD_DCtx* dctx, const void* dict, size_t dictSize)
@@ -1115,7 +1520,7 @@ static size_t ZSTD_decompress_insertDictionary(ZSTD_DCtx* dctx, const void* dict
1115
1520
 
1116
1521
  /* load entropy tables */
1117
1522
  { size_t const eSize = ZSTD_loadDEntropy(&dctx->entropy, dict, dictSize);
1118
- RETURN_ERROR_IF(ZSTD_isError(eSize), dictionary_corrupted);
1523
+ RETURN_ERROR_IF(ZSTD_isError(eSize), dictionary_corrupted, "");
1119
1524
  dict = (const char*)dict + eSize;
1120
1525
  dictSize -= eSize;
1121
1526
  }
@@ -1128,18 +1533,23 @@ static size_t ZSTD_decompress_insertDictionary(ZSTD_DCtx* dctx, const void* dict
1128
1533
  size_t ZSTD_decompressBegin(ZSTD_DCtx* dctx)
1129
1534
  {
1130
1535
  assert(dctx != NULL);
1536
+ #if ZSTD_TRACE
1537
+ dctx->traceCtx = (ZSTD_trace_decompress_begin != NULL) ? ZSTD_trace_decompress_begin(dctx) : 0;
1538
+ #endif
1131
1539
  dctx->expected = ZSTD_startingInputLength(dctx->format); /* dctx->format must be properly set */
1132
1540
  dctx->stage = ZSTDds_getFrameHeaderSize;
1541
+ dctx->processedCSize = 0;
1133
1542
  dctx->decodedSize = 0;
1134
1543
  dctx->previousDstEnd = NULL;
1135
1544
  dctx->prefixStart = NULL;
1136
1545
  dctx->virtualStart = NULL;
1137
1546
  dctx->dictEnd = NULL;
1138
- 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 */
1139
1548
  dctx->litEntropy = dctx->fseEntropy = 0;
1140
1549
  dctx->dictID = 0;
1550
+ dctx->bType = bt_reserved;
1141
1551
  ZSTD_STATIC_ASSERT(sizeof(dctx->entropy.rep) == sizeof(repStartValue));
1142
- memcpy(dctx->entropy.rep, repStartValue, sizeof(repStartValue)); /* initial repcodes */
1552
+ ZSTD_memcpy(dctx->entropy.rep, repStartValue, sizeof(repStartValue)); /* initial repcodes */
1143
1553
  dctx->LLTptr = dctx->entropy.LLTable;
1144
1554
  dctx->MLTptr = dctx->entropy.MLTable;
1145
1555
  dctx->OFTptr = dctx->entropy.OFTable;
@@ -1149,11 +1559,11 @@ size_t ZSTD_decompressBegin(ZSTD_DCtx* dctx)
1149
1559
 
1150
1560
  size_t ZSTD_decompressBegin_usingDict(ZSTD_DCtx* dctx, const void* dict, size_t dictSize)
1151
1561
  {
1152
- FORWARD_IF_ERROR( ZSTD_decompressBegin(dctx) );
1562
+ FORWARD_IF_ERROR( ZSTD_decompressBegin(dctx) , "");
1153
1563
  if (dict && dictSize)
1154
1564
  RETURN_ERROR_IF(
1155
1565
  ZSTD_isError(ZSTD_decompress_insertDictionary(dctx, dict, dictSize)),
1156
- dictionary_corrupted);
1566
+ dictionary_corrupted, "");
1157
1567
  return 0;
1158
1568
  }
1159
1569
 
@@ -1172,7 +1582,7 @@ size_t ZSTD_decompressBegin_usingDDict(ZSTD_DCtx* dctx, const ZSTD_DDict* ddict)
1172
1582
  DEBUGLOG(4, "DDict is %s",
1173
1583
  dctx->ddictIsCold ? "~cold~" : "hot!");
1174
1584
  }
1175
- FORWARD_IF_ERROR( ZSTD_decompressBegin(dctx) );
1585
+ FORWARD_IF_ERROR( ZSTD_decompressBegin(dctx) , "");
1176
1586
  if (ddict) { /* NULL ddict is equivalent to no dictionary */
1177
1587
  ZSTD_copyDDictParameters(dctx, ddict);
1178
1588
  }
@@ -1196,7 +1606,7 @@ unsigned ZSTD_getDictID_fromDict(const void* dict, size_t dictSize)
1196
1606
  * This could for one of the following reasons :
1197
1607
  * - The frame does not require a dictionary (most common case).
1198
1608
  * - The frame was built with dictID intentionally removed.
1199
- * Needed dictionary is a hidden information.
1609
+ * Needed dictionary is a hidden piece of information.
1200
1610
  * Note : this use case also happens when using a non-conformant dictionary.
1201
1611
  * - `srcSize` is too small, and as a result, frame header could not be decoded.
1202
1612
  * Note : possible if `srcSize < ZSTD_FRAMEHEADERSIZE_MAX`.
@@ -1205,7 +1615,7 @@ unsigned ZSTD_getDictID_fromDict(const void* dict, size_t dictSize)
1205
1615
  * ZSTD_getFrameHeader(), which will provide a more precise error code. */
1206
1616
  unsigned ZSTD_getDictID_fromFrame(const void* src, size_t srcSize)
1207
1617
  {
1208
- 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 };
1209
1619
  size_t const hError = ZSTD_getFrameHeader(&zfp, src, srcSize);
1210
1620
  if (ZSTD_isError(hError)) return 0;
1211
1621
  return zfp.dictID;
@@ -1234,7 +1644,7 @@ size_t ZSTD_decompress_usingDDict(ZSTD_DCtx* dctx,
1234
1644
  ZSTD_DStream* ZSTD_createDStream(void)
1235
1645
  {
1236
1646
  DEBUGLOG(3, "ZSTD_createDStream");
1237
- return ZSTD_createDStream_advanced(ZSTD_defaultCMem);
1647
+ return ZSTD_createDCtx_internal(ZSTD_defaultCMem);
1238
1648
  }
1239
1649
 
1240
1650
  ZSTD_DStream* ZSTD_initStaticDStream(void *workspace, size_t workspaceSize)
@@ -1244,7 +1654,7 @@ ZSTD_DStream* ZSTD_initStaticDStream(void *workspace, size_t workspaceSize)
1244
1654
 
1245
1655
  ZSTD_DStream* ZSTD_createDStream_advanced(ZSTD_customMem customMem)
1246
1656
  {
1247
- return ZSTD_createDCtx_advanced(customMem);
1657
+ return ZSTD_createDCtx_internal(customMem);
1248
1658
  }
1249
1659
 
1250
1660
  size_t ZSTD_freeDStream(ZSTD_DStream* zds)
@@ -1263,11 +1673,11 @@ size_t ZSTD_DCtx_loadDictionary_advanced(ZSTD_DCtx* dctx,
1263
1673
  ZSTD_dictLoadMethod_e dictLoadMethod,
1264
1674
  ZSTD_dictContentType_e dictContentType)
1265
1675
  {
1266
- RETURN_ERROR_IF(dctx->streamStage != zdss_init, stage_wrong);
1676
+ RETURN_ERROR_IF(dctx->streamStage != zdss_init, stage_wrong, "");
1267
1677
  ZSTD_clearDict(dctx);
1268
1678
  if (dict && dictSize != 0) {
1269
1679
  dctx->ddictLocal = ZSTD_createDDict_advanced(dict, dictSize, dictLoadMethod, dictContentType, dctx->customMem);
1270
- RETURN_ERROR_IF(dctx->ddictLocal == NULL, memory_allocation);
1680
+ RETURN_ERROR_IF(dctx->ddictLocal == NULL, memory_allocation, "NULL pointer!");
1271
1681
  dctx->ddict = dctx->ddictLocal;
1272
1682
  dctx->dictUses = ZSTD_use_indefinitely;
1273
1683
  }
@@ -1286,7 +1696,7 @@ size_t ZSTD_DCtx_loadDictionary(ZSTD_DCtx* dctx, const void* dict, size_t dictSi
1286
1696
 
1287
1697
  size_t ZSTD_DCtx_refPrefix_advanced(ZSTD_DCtx* dctx, const void* prefix, size_t prefixSize, ZSTD_dictContentType_e dictContentType)
1288
1698
  {
1289
- FORWARD_IF_ERROR(ZSTD_DCtx_loadDictionary_advanced(dctx, prefix, prefixSize, ZSTD_dlm_byRef, dictContentType));
1699
+ FORWARD_IF_ERROR(ZSTD_DCtx_loadDictionary_advanced(dctx, prefix, prefixSize, ZSTD_dlm_byRef, dictContentType), "");
1290
1700
  dctx->dictUses = ZSTD_use_once;
1291
1701
  return 0;
1292
1702
  }
@@ -1303,8 +1713,8 @@ size_t ZSTD_DCtx_refPrefix(ZSTD_DCtx* dctx, const void* prefix, size_t prefixSiz
1303
1713
  size_t ZSTD_initDStream_usingDict(ZSTD_DStream* zds, const void* dict, size_t dictSize)
1304
1714
  {
1305
1715
  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) );
1716
+ FORWARD_IF_ERROR( ZSTD_DCtx_reset(zds, ZSTD_reset_session_only) , "");
1717
+ FORWARD_IF_ERROR( ZSTD_DCtx_loadDictionary(zds, dict, dictSize) , "");
1308
1718
  return ZSTD_startingInputLength(zds->format);
1309
1719
  }
1310
1720
 
@@ -1312,7 +1722,9 @@ size_t ZSTD_initDStream_usingDict(ZSTD_DStream* zds, const void* dict, size_t di
1312
1722
  size_t ZSTD_initDStream(ZSTD_DStream* zds)
1313
1723
  {
1314
1724
  DEBUGLOG(4, "ZSTD_initDStream");
1315
- 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);
1316
1728
  }
1317
1729
 
1318
1730
  /* ZSTD_initDStream_usingDDict() :
@@ -1320,8 +1732,9 @@ size_t ZSTD_initDStream(ZSTD_DStream* zds)
1320
1732
  * this function cannot fail */
1321
1733
  size_t ZSTD_initDStream_usingDDict(ZSTD_DStream* dctx, const ZSTD_DDict* ddict)
1322
1734
  {
1323
- FORWARD_IF_ERROR( ZSTD_DCtx_reset(dctx, ZSTD_reset_session_only) );
1324
- FORWARD_IF_ERROR( ZSTD_DCtx_refDDict(dctx, ddict) );
1735
+ DEBUGLOG(4, "ZSTD_initDStream_usingDDict");
1736
+ FORWARD_IF_ERROR( ZSTD_DCtx_reset(dctx, ZSTD_reset_session_only) , "");
1737
+ FORWARD_IF_ERROR( ZSTD_DCtx_refDDict(dctx, ddict) , "");
1325
1738
  return ZSTD_startingInputLength(dctx->format);
1326
1739
  }
1327
1740
 
@@ -1330,18 +1743,29 @@ size_t ZSTD_initDStream_usingDDict(ZSTD_DStream* dctx, const ZSTD_DDict* ddict)
1330
1743
  * this function cannot fail */
1331
1744
  size_t ZSTD_resetDStream(ZSTD_DStream* dctx)
1332
1745
  {
1333
- FORWARD_IF_ERROR(ZSTD_DCtx_reset(dctx, ZSTD_reset_session_only));
1746
+ DEBUGLOG(4, "ZSTD_resetDStream");
1747
+ FORWARD_IF_ERROR(ZSTD_DCtx_reset(dctx, ZSTD_reset_session_only), "");
1334
1748
  return ZSTD_startingInputLength(dctx->format);
1335
1749
  }
1336
1750
 
1337
1751
 
1338
1752
  size_t ZSTD_DCtx_refDDict(ZSTD_DCtx* dctx, const ZSTD_DDict* ddict)
1339
1753
  {
1340
- RETURN_ERROR_IF(dctx->streamStage != zdss_init, stage_wrong);
1754
+ RETURN_ERROR_IF(dctx->streamStage != zdss_init, stage_wrong, "");
1341
1755
  ZSTD_clearDict(dctx);
1342
1756
  if (ddict) {
1343
1757
  dctx->ddict = ddict;
1344
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
+ }
1345
1769
  }
1346
1770
  return 0;
1347
1771
  }
@@ -1354,16 +1778,16 @@ size_t ZSTD_DCtx_setMaxWindowSize(ZSTD_DCtx* dctx, size_t maxWindowSize)
1354
1778
  ZSTD_bounds const bounds = ZSTD_dParam_getBounds(ZSTD_d_windowLogMax);
1355
1779
  size_t const min = (size_t)1 << bounds.lowerBound;
1356
1780
  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);
1781
+ RETURN_ERROR_IF(dctx->streamStage != zdss_init, stage_wrong, "");
1782
+ RETURN_ERROR_IF(maxWindowSize < min, parameter_outOfBound, "");
1783
+ RETURN_ERROR_IF(maxWindowSize > max, parameter_outOfBound, "");
1360
1784
  dctx->maxWindowSize = maxWindowSize;
1361
1785
  return 0;
1362
1786
  }
1363
1787
 
1364
1788
  size_t ZSTD_DCtx_setFormat(ZSTD_DCtx* dctx, ZSTD_format_e format)
1365
1789
  {
1366
- return ZSTD_DCtx_setParameter(dctx, ZSTD_d_format, format);
1790
+ return ZSTD_DCtx_setParameter(dctx, ZSTD_d_format, (int)format);
1367
1791
  }
1368
1792
 
1369
1793
  ZSTD_bounds ZSTD_dParam_getBounds(ZSTD_dParameter dParam)
@@ -1379,6 +1803,23 @@ ZSTD_bounds ZSTD_dParam_getBounds(ZSTD_dParameter dParam)
1379
1803
  bounds.upperBound = (int)ZSTD_f_zstd1_magicless;
1380
1804
  ZSTD_STATIC_ASSERT(ZSTD_f_zstd1 < ZSTD_f_zstd1_magicless);
1381
1805
  return bounds;
1806
+ case ZSTD_d_stableOutBuffer:
1807
+ bounds.lowerBound = (int)ZSTD_bm_buffered;
1808
+ bounds.upperBound = (int)ZSTD_bm_stable;
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
+
1382
1823
  default:;
1383
1824
  }
1384
1825
  bounds.error = ERROR(parameter_unsupported);
@@ -1398,12 +1839,38 @@ static int ZSTD_dParam_withinBounds(ZSTD_dParameter dParam, int value)
1398
1839
  }
1399
1840
 
1400
1841
  #define CHECK_DBOUNDS(p,v) { \
1401
- RETURN_ERROR_IF(!ZSTD_dParam_withinBounds(p, v), parameter_outOfBound); \
1842
+ RETURN_ERROR_IF(!ZSTD_dParam_withinBounds(p, v), parameter_outOfBound, ""); \
1843
+ }
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, "");
1402
1869
  }
1403
1870
 
1404
1871
  size_t ZSTD_DCtx_setParameter(ZSTD_DCtx* dctx, ZSTD_dParameter dParam, int value)
1405
1872
  {
1406
- RETURN_ERROR_IF(dctx->streamStage != zdss_init, stage_wrong);
1873
+ RETURN_ERROR_IF(dctx->streamStage != zdss_init, stage_wrong, "");
1407
1874
  switch(dParam) {
1408
1875
  case ZSTD_d_windowLogMax:
1409
1876
  if (value == 0) value = ZSTD_WINDOWLOG_LIMIT_DEFAULT;
@@ -1414,9 +1881,28 @@ size_t ZSTD_DCtx_setParameter(ZSTD_DCtx* dctx, ZSTD_dParameter dParam, int value
1414
1881
  CHECK_DBOUNDS(ZSTD_d_format, value);
1415
1882
  dctx->format = (ZSTD_format_e)value;
1416
1883
  return 0;
1884
+ case ZSTD_d_stableOutBuffer:
1885
+ CHECK_DBOUNDS(ZSTD_d_stableOutBuffer, 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;
1902
+ return 0;
1417
1903
  default:;
1418
1904
  }
1419
- RETURN_ERROR(parameter_unsupported);
1905
+ RETURN_ERROR(parameter_unsupported, "");
1420
1906
  }
1421
1907
 
1422
1908
  size_t ZSTD_DCtx_reset(ZSTD_DCtx* dctx, ZSTD_ResetDirective reset)
@@ -1428,10 +1914,9 @@ size_t ZSTD_DCtx_reset(ZSTD_DCtx* dctx, ZSTD_ResetDirective reset)
1428
1914
  }
1429
1915
  if ( (reset == ZSTD_reset_parameters)
1430
1916
  || (reset == ZSTD_reset_session_and_parameters) ) {
1431
- RETURN_ERROR_IF(dctx->streamStage != zdss_init, stage_wrong);
1917
+ RETURN_ERROR_IF(dctx->streamStage != zdss_init, stage_wrong, "");
1432
1918
  ZSTD_clearDict(dctx);
1433
- dctx->format = ZSTD_f_zstd1;
1434
- dctx->maxWindowSize = ZSTD_MAXWINDOWSIZE_DEFAULT;
1919
+ ZSTD_DCtx_resetParameters(dctx);
1435
1920
  }
1436
1921
  return 0;
1437
1922
  }
@@ -1445,11 +1930,12 @@ size_t ZSTD_sizeof_DStream(const ZSTD_DStream* dctx)
1445
1930
  size_t ZSTD_decodingBufferSize_min(unsigned long long windowSize, unsigned long long frameContentSize)
1446
1931
  {
1447
1932
  size_t const blockSize = (size_t) MIN(windowSize, ZSTD_BLOCKSIZE_MAX);
1448
- 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);
1449
1935
  unsigned long long const neededSize = MIN(frameContentSize, neededRBSize);
1450
1936
  size_t const minRBSize = (size_t) neededSize;
1451
1937
  RETURN_ERROR_IF((unsigned long long)minRBSize != neededSize,
1452
- frameParameter_windowTooLarge);
1938
+ frameParameter_windowTooLarge, "");
1453
1939
  return minRBSize;
1454
1940
  }
1455
1941
 
@@ -1467,30 +1953,94 @@ size_t ZSTD_estimateDStreamSize_fromFrame(const void* src, size_t srcSize)
1467
1953
  ZSTD_frameHeader zfh;
1468
1954
  size_t const err = ZSTD_getFrameHeader(&zfh, src, srcSize);
1469
1955
  if (ZSTD_isError(err)) return err;
1470
- RETURN_ERROR_IF(err>0, srcSize_wrong);
1956
+ RETURN_ERROR_IF(err>0, srcSize_wrong, "");
1471
1957
  RETURN_ERROR_IF(zfh.windowSize > windowSizeMax,
1472
- frameParameter_windowTooLarge);
1958
+ frameParameter_windowTooLarge, "");
1473
1959
  return ZSTD_estimateDStreamSize((size_t)zfh.windowSize);
1474
1960
  }
1475
1961
 
1476
1962
 
1477
1963
  /* ***** Decompression ***** */
1478
1964
 
1479
- MEM_STATIC size_t ZSTD_limitCopy(void* dst, size_t dstCapacity, const void* src, size_t srcSize)
1965
+ static int ZSTD_DCtx_isOverflow(ZSTD_DStream* zds, size_t const neededInBuffSize, size_t const neededOutBuffSize)
1480
1966
  {
1481
- size_t const length = MIN(dstCapacity, srcSize);
1482
- memcpy(dst, src, length);
1483
- return length;
1967
+ return (zds->inBuffSize + zds->outBuffSize) >= (neededInBuffSize + neededOutBuffSize) * ZSTD_WORKSPACETOOLARGE_FACTOR;
1484
1968
  }
1485
1969
 
1970
+ static void ZSTD_DCtx_updateOversizedDuration(ZSTD_DStream* zds, size_t const neededInBuffSize, size_t const neededOutBuffSize)
1971
+ {
1972
+ if (ZSTD_DCtx_isOverflow(zds, neededInBuffSize, neededOutBuffSize))
1973
+ zds->oversizedDuration++;
1974
+ else
1975
+ zds->oversizedDuration = 0;
1976
+ }
1977
+
1978
+ static int ZSTD_DCtx_isOversizedTooLong(ZSTD_DStream* zds)
1979
+ {
1980
+ return zds->oversizedDuration >= ZSTD_WORKSPACETOOLARGE_MAXDURATION;
1981
+ }
1982
+
1983
+ /* Checks that the output buffer hasn't changed if ZSTD_obm_stable is used. */
1984
+ static size_t ZSTD_checkOutBuffer(ZSTD_DStream const* zds, ZSTD_outBuffer const* output)
1985
+ {
1986
+ ZSTD_outBuffer const expect = zds->expectedOutBuffer;
1987
+ /* No requirement when ZSTD_obm_stable is not enabled. */
1988
+ if (zds->outBufferMode != ZSTD_bm_stable)
1989
+ return 0;
1990
+ /* Any buffer is allowed in zdss_init, this must be the same for every other call until
1991
+ * the context is reset.
1992
+ */
1993
+ if (zds->streamStage == zdss_init)
1994
+ return 0;
1995
+ /* The buffer must match our expectation exactly. */
1996
+ if (expect.dst == output->dst && expect.pos == output->pos && expect.size == output->size)
1997
+ return 0;
1998
+ RETURN_ERROR(dstBuffer_wrong, "ZSTD_d_stableOutBuffer enabled but output differs!");
1999
+ }
2000
+
2001
+ /* Calls ZSTD_decompressContinue() with the right parameters for ZSTD_decompressStream()
2002
+ * and updates the stage and the output buffer state. This call is extracted so it can be
2003
+ * used both when reading directly from the ZSTD_inBuffer, and in buffered input mode.
2004
+ * NOTE: You must break after calling this function since the streamStage is modified.
2005
+ */
2006
+ static size_t ZSTD_decompressContinueStream(
2007
+ ZSTD_DStream* zds, char** op, char* oend,
2008
+ void const* src, size_t srcSize) {
2009
+ int const isSkipFrame = ZSTD_isSkipFrame(zds);
2010
+ if (zds->outBufferMode == ZSTD_bm_buffered) {
2011
+ size_t const dstSize = isSkipFrame ? 0 : zds->outBuffSize - zds->outStart;
2012
+ size_t const decodedSize = ZSTD_decompressContinue(zds,
2013
+ zds->outBuff + zds->outStart, dstSize, src, srcSize);
2014
+ FORWARD_IF_ERROR(decodedSize, "");
2015
+ if (!decodedSize && !isSkipFrame) {
2016
+ zds->streamStage = zdss_read;
2017
+ } else {
2018
+ zds->outEnd = zds->outStart + decodedSize;
2019
+ zds->streamStage = zdss_flush;
2020
+ }
2021
+ } else {
2022
+ /* Write directly into the output buffer */
2023
+ size_t const dstSize = isSkipFrame ? 0 : (size_t)(oend - *op);
2024
+ size_t const decodedSize = ZSTD_decompressContinue(zds, *op, dstSize, src, srcSize);
2025
+ FORWARD_IF_ERROR(decodedSize, "");
2026
+ *op += decodedSize;
2027
+ /* Flushing is not needed. */
2028
+ zds->streamStage = zdss_read;
2029
+ assert(*op <= oend);
2030
+ assert(zds->outBufferMode == ZSTD_bm_stable);
2031
+ }
2032
+ return 0;
2033
+ }
1486
2034
 
1487
2035
  size_t ZSTD_decompressStream(ZSTD_DStream* zds, ZSTD_outBuffer* output, ZSTD_inBuffer* input)
1488
2036
  {
1489
- const char* const istart = (const char*)(input->src) + input->pos;
1490
- const char* const iend = (const char*)(input->src) + input->size;
2037
+ const char* const src = (const char*)input->src;
2038
+ const char* const istart = input->pos != 0 ? src + input->pos : src;
2039
+ const char* const iend = input->size != 0 ? src + input->size : src;
1491
2040
  const char* ip = istart;
1492
- char* const ostart = (char*)(output->dst) + output->pos;
1493
- char* const oend = (char*)(output->dst) + output->size;
2041
+ char* const dst = (char*)output->dst;
2042
+ char* const ostart = output->pos != 0 ? dst + output->pos : dst;
2043
+ char* const oend = output->size != 0 ? dst + output->size : dst;
1494
2044
  char* op = ostart;
1495
2045
  U32 someMoreWork = 1;
1496
2046
 
@@ -1506,6 +2056,7 @@ size_t ZSTD_decompressStream(ZSTD_DStream* zds, ZSTD_outBuffer* output, ZSTD_inB
1506
2056
  "forbidden. out: pos: %u vs size: %u",
1507
2057
  (U32)output->pos, (U32)output->size);
1508
2058
  DEBUGLOG(5, "input size : %u", (U32)(input->size - input->pos));
2059
+ FORWARD_IF_ERROR(ZSTD_checkOutBuffer(zds, output), "");
1509
2060
 
1510
2061
  while (someMoreWork) {
1511
2062
  switch(zds->streamStage)
@@ -1514,9 +2065,12 @@ size_t ZSTD_decompressStream(ZSTD_DStream* zds, ZSTD_outBuffer* output, ZSTD_inB
1514
2065
  DEBUGLOG(5, "stage zdss_init => transparent reset ");
1515
2066
  zds->streamStage = zdss_loadHeader;
1516
2067
  zds->lhSize = zds->inPos = zds->outStart = zds->outEnd = 0;
2068
+ #if defined(ZSTD_LEGACY_SUPPORT) && (ZSTD_LEGACY_SUPPORT>=1)
1517
2069
  zds->legacyVersion = 0;
2070
+ #endif
1518
2071
  zds->hostageByte = 0;
1519
- /* fall-through */
2072
+ zds->expectedOutBuffer = *output;
2073
+ ZSTD_FALLTHROUGH;
1520
2074
 
1521
2075
  case zdss_loadHeader :
1522
2076
  DEBUGLOG(5, "stage zdss_loadHeader (srcSize : %u)", (U32)(iend - ip));
@@ -1530,7 +2084,9 @@ size_t ZSTD_decompressStream(ZSTD_DStream* zds, ZSTD_outBuffer* output, ZSTD_inB
1530
2084
  } }
1531
2085
  #endif
1532
2086
  { size_t const hSize = ZSTD_getFrameHeader_advanced(&zds->fParams, zds->headerBuffer, zds->lhSize, zds->format);
1533
- DEBUGLOG(5, "header size : %u", (U32)hSize);
2087
+ if (zds->refMultipleDDicts && zds->ddictSet) {
2088
+ ZSTD_DCtx_selectFrameDDict(zds);
2089
+ }
1534
2090
  if (ZSTD_isError(hSize)) {
1535
2091
  #if defined(ZSTD_LEGACY_SUPPORT) && (ZSTD_LEGACY_SUPPORT>=1)
1536
2092
  U32 const legacyVersion = ZSTD_isLegacy(istart, iend-istart);
@@ -1543,7 +2099,7 @@ size_t ZSTD_decompressStream(ZSTD_DStream* zds, ZSTD_outBuffer* output, ZSTD_inB
1543
2099
  "legacy support is incompatible with static dctx");
1544
2100
  FORWARD_IF_ERROR(ZSTD_initLegacyStream(&zds->legacyContext,
1545
2101
  zds->previousLegacyVersion, legacyVersion,
1546
- dict, dictSize));
2102
+ dict, dictSize), "");
1547
2103
  zds->legacyVersion = zds->previousLegacyVersion = legacyVersion;
1548
2104
  { size_t const hint = ZSTD_decompressLegacyStream(zds->legacyContext, legacyVersion, output, input);
1549
2105
  if (hint==0) zds->streamStage = zdss_init; /* or stay in stage zdss_loadHeader */
@@ -1558,43 +2114,58 @@ size_t ZSTD_decompressStream(ZSTD_DStream* zds, ZSTD_outBuffer* output, ZSTD_inB
1558
2114
  assert(iend >= ip);
1559
2115
  if (toLoad > remainingInput) { /* not enough input to load full header */
1560
2116
  if (remainingInput > 0) {
1561
- memcpy(zds->headerBuffer + zds->lhSize, ip, remainingInput);
2117
+ ZSTD_memcpy(zds->headerBuffer + zds->lhSize, ip, remainingInput);
1562
2118
  zds->lhSize += remainingInput;
1563
2119
  }
1564
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 */
1565
2126
  return (MAX((size_t)ZSTD_FRAMEHEADERSIZE_MIN(zds->format), hSize) - zds->lhSize) + ZSTD_blockHeaderSize; /* remaining header bytes + next block header */
1566
2127
  }
1567
2128
  assert(ip != NULL);
1568
- 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;
1569
2130
  break;
1570
2131
  } }
1571
2132
 
1572
2133
  /* check for single-pass mode opportunity */
1573
- if (zds->fParams.frameContentSize && zds->fParams.windowSize /* skippable frame if == 0 */
2134
+ if (zds->fParams.frameContentSize != ZSTD_CONTENTSIZE_UNKNOWN
2135
+ && zds->fParams.frameType != ZSTD_skippableFrame
1574
2136
  && (U64)(size_t)(oend-op) >= zds->fParams.frameContentSize) {
1575
- size_t const cSize = ZSTD_findFrameCompressedSize(istart, iend-istart);
2137
+ size_t const cSize = ZSTD_findFrameCompressedSize(istart, (size_t)(iend-istart));
1576
2138
  if (cSize <= (size_t)(iend-istart)) {
1577
2139
  /* shortcut : using single-pass mode */
1578
- 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));
1579
2141
  if (ZSTD_isError(decompressedSize)) return decompressedSize;
1580
2142
  DEBUGLOG(4, "shortcut to single-pass ZSTD_decompress_usingDDict()")
2143
+ assert(istart != NULL);
1581
2144
  ip = istart + cSize;
1582
- op += decompressedSize;
2145
+ op = op ? op + decompressedSize : op; /* can occur if frameContentSize = 0 (empty frame) */
1583
2146
  zds->expected = 0;
1584
2147
  zds->streamStage = zdss_init;
1585
2148
  someMoreWork = 0;
1586
2149
  break;
1587
2150
  } }
1588
2151
 
2152
+ /* Check output buffer is large enough for ZSTD_odm_stable. */
2153
+ if (zds->outBufferMode == ZSTD_bm_stable
2154
+ && zds->fParams.frameType != ZSTD_skippableFrame
2155
+ && zds->fParams.frameContentSize != ZSTD_CONTENTSIZE_UNKNOWN
2156
+ && (U64)(size_t)(oend-op) < zds->fParams.frameContentSize) {
2157
+ RETURN_ERROR(dstSize_tooSmall, "ZSTD_obm_stable passed but ZSTD_outBuffer is too small");
2158
+ }
2159
+
1589
2160
  /* Consume header (see ZSTDds_decodeFrameHeader) */
1590
2161
  DEBUGLOG(4, "Consume header");
1591
- FORWARD_IF_ERROR(ZSTD_decompressBegin_usingDDict(zds, ZSTD_getDDict(zds)));
2162
+ FORWARD_IF_ERROR(ZSTD_decompressBegin_usingDDict(zds, ZSTD_getDDict(zds)), "");
1592
2163
 
1593
2164
  if ((MEM_readLE32(zds->headerBuffer) & ZSTD_MAGIC_SKIPPABLE_MASK) == ZSTD_MAGIC_SKIPPABLE_START) { /* skippable frame */
1594
2165
  zds->expected = MEM_readLE32(zds->headerBuffer + ZSTD_FRAMEIDSIZE);
1595
2166
  zds->stage = ZSTDds_skipFrame;
1596
2167
  } else {
1597
- FORWARD_IF_ERROR(ZSTD_decodeFrameHeader(zds, zds->headerBuffer, zds->lhSize));
2168
+ FORWARD_IF_ERROR(ZSTD_decodeFrameHeader(zds, zds->headerBuffer, zds->lhSize), "");
1598
2169
  zds->expected = ZSTD_blockHeaderSize;
1599
2170
  zds->stage = ZSTDds_decodeBlockHeader;
1600
2171
  }
@@ -1605,40 +2176,48 @@ size_t ZSTD_decompressStream(ZSTD_DStream* zds, ZSTD_outBuffer* output, ZSTD_inB
1605
2176
  (U32)(zds->maxWindowSize >> 10) );
1606
2177
  zds->fParams.windowSize = MAX(zds->fParams.windowSize, 1U << ZSTD_WINDOWLOG_ABSOLUTEMIN);
1607
2178
  RETURN_ERROR_IF(zds->fParams.windowSize > zds->maxWindowSize,
1608
- frameParameter_windowTooLarge);
2179
+ frameParameter_windowTooLarge, "");
1609
2180
 
1610
2181
  /* Adapt buffer sizes to frame header instructions */
1611
2182
  { 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
- } }
2183
+ size_t const neededOutBuffSize = zds->outBufferMode == ZSTD_bm_buffered
2184
+ ? ZSTD_decodingBufferSize_min(zds->fParams.windowSize, zds->fParams.frameContentSize)
2185
+ : 0;
2186
+
2187
+ ZSTD_DCtx_updateOversizedDuration(zds, neededInBuffSize, neededOutBuffSize);
2188
+
2189
+ { int const tooSmall = (zds->inBuffSize < neededInBuffSize) || (zds->outBuffSize < neededOutBuffSize);
2190
+ int const tooLarge = ZSTD_DCtx_isOversizedTooLong(zds);
2191
+
2192
+ if (tooSmall || tooLarge) {
2193
+ size_t const bufferSize = neededInBuffSize + neededOutBuffSize;
2194
+ DEBUGLOG(4, "inBuff : from %u to %u",
2195
+ (U32)zds->inBuffSize, (U32)neededInBuffSize);
2196
+ DEBUGLOG(4, "outBuff : from %u to %u",
2197
+ (U32)zds->outBuffSize, (U32)neededOutBuffSize);
2198
+ if (zds->staticSize) { /* static DCtx */
2199
+ DEBUGLOG(4, "staticSize : %u", (U32)zds->staticSize);
2200
+ assert(zds->staticSize >= sizeof(ZSTD_DCtx)); /* controlled at init */
2201
+ RETURN_ERROR_IF(
2202
+ bufferSize > zds->staticSize - sizeof(ZSTD_DCtx),
2203
+ memory_allocation, "");
2204
+ } else {
2205
+ ZSTD_customFree(zds->inBuff, zds->customMem);
2206
+ zds->inBuffSize = 0;
2207
+ zds->outBuffSize = 0;
2208
+ zds->inBuff = (char*)ZSTD_customMalloc(bufferSize, zds->customMem);
2209
+ RETURN_ERROR_IF(zds->inBuff == NULL, memory_allocation, "");
2210
+ }
2211
+ zds->inBuffSize = neededInBuffSize;
2212
+ zds->outBuff = zds->inBuff + zds->inBuffSize;
2213
+ zds->outBuffSize = neededOutBuffSize;
2214
+ } } }
1636
2215
  zds->streamStage = zdss_read;
1637
- /* fall-through */
2216
+ ZSTD_FALLTHROUGH;
1638
2217
 
1639
2218
  case zdss_read:
1640
2219
  DEBUGLOG(5, "stage zdss_read");
1641
- { size_t const neededInSize = ZSTD_nextSrcSizeToDecompress(zds);
2220
+ { size_t const neededInSize = ZSTD_nextSrcSizeToDecompressWithInputSize(zds, (size_t)(iend - ip));
1642
2221
  DEBUGLOG(5, "neededInSize = %u", (U32)neededInSize);
1643
2222
  if (neededInSize==0) { /* end of frame */
1644
2223
  zds->streamStage = zdss_init;
@@ -1646,59 +2225,56 @@ size_t ZSTD_decompressStream(ZSTD_DStream* zds, ZSTD_outBuffer* output, ZSTD_inB
1646
2225
  break;
1647
2226
  }
1648
2227
  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;
2228
+ FORWARD_IF_ERROR(ZSTD_decompressContinueStream(zds, &op, oend, ip, neededInSize), "");
2229
+ assert(ip != NULL);
1654
2230
  ip += neededInSize;
1655
- if (!decodedSize && !isSkipFrame) break; /* this was just a header */
1656
- zds->outEnd = zds->outStart + decodedSize;
1657
- zds->streamStage = zdss_flush;
2231
+ /* Function modifies the stage so we must break */
1658
2232
  break;
1659
2233
  } }
1660
2234
  if (ip==iend) { someMoreWork = 0; break; } /* no more input */
1661
2235
  zds->streamStage = zdss_load;
1662
- /* fall-through */
2236
+ ZSTD_FALLTHROUGH;
1663
2237
 
1664
2238
  case zdss_load:
1665
2239
  { size_t const neededInSize = ZSTD_nextSrcSizeToDecompress(zds);
1666
2240
  size_t const toLoad = neededInSize - zds->inPos;
1667
2241
  int const isSkipFrame = ZSTD_isSkipFrame(zds);
1668
2242
  size_t loadedSize;
2243
+ /* At this point we shouldn't be decompressing a block that we can stream. */
2244
+ assert(neededInSize == ZSTD_nextSrcSizeToDecompressWithInputSize(zds, (size_t)(iend - ip)));
1669
2245
  if (isSkipFrame) {
1670
2246
  loadedSize = MIN(toLoad, (size_t)(iend-ip));
1671
2247
  } else {
1672
2248
  RETURN_ERROR_IF(toLoad > zds->inBuffSize - zds->inPos,
1673
2249
  corruption_detected,
1674
2250
  "should never happen");
1675
- 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;
1676
2257
  }
1677
- ip += loadedSize;
1678
- zds->inPos += loadedSize;
1679
2258
  if (loadedSize < toLoad) { someMoreWork = 0; break; } /* not enough input, wait for more */
1680
2259
 
1681
2260
  /* 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
-
2261
+ zds->inPos = 0; /* input is consumed */
2262
+ FORWARD_IF_ERROR(ZSTD_decompressContinueStream(zds, &op, oend, zds->inBuff, neededInSize), "");
2263
+ /* Function modifies the stage so we must break */
2264
+ break;
2265
+ }
1693
2266
  case zdss_flush:
1694
- { size_t const toFlushSize = zds->outEnd - zds->outStart;
1695
- size_t const flushedSize = ZSTD_limitCopy(op, oend-op, zds->outBuff + zds->outStart, toFlushSize);
1696
- 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
+
1697
2273
  zds->outStart += flushedSize;
1698
2274
  if (flushedSize == toFlushSize) { /* flush completed */
1699
2275
  zds->streamStage = zdss_read;
1700
2276
  if ( (zds->outBuffSize < zds->fParams.frameContentSize)
1701
- && (zds->outStart + zds->fParams.blockSizeMax > zds->outBuffSize) ) {
2277
+ && (zds->outStart + zds->fParams.blockSizeMax > zds->outBuffSize) ) {
1702
2278
  DEBUGLOG(5, "restart filling outBuff from beginning (left:%i, needed:%u)",
1703
2279
  (int)(zds->outBuffSize - zds->outStart),
1704
2280
  (U32)zds->fParams.blockSizeMax);
@@ -1712,17 +2288,21 @@ size_t ZSTD_decompressStream(ZSTD_DStream* zds, ZSTD_outBuffer* output, ZSTD_inB
1712
2288
 
1713
2289
  default:
1714
2290
  assert(0); /* impossible */
1715
- RETURN_ERROR(GENERIC); /* some compiler require default to do something */
2291
+ RETURN_ERROR(GENERIC, "impossible to reach"); /* some compilers require default to do something */
1716
2292
  } }
1717
2293
 
1718
2294
  /* result */
1719
2295
  input->pos = (size_t)(ip - (const char*)(input->src));
1720
2296
  output->pos = (size_t)(op - (char*)(output->dst));
2297
+
2298
+ /* Update the expected output buffer for ZSTD_obm_stable. */
2299
+ zds->expectedOutBuffer = *output;
2300
+
1721
2301
  if ((ip==istart) && (op==ostart)) { /* no forward progress */
1722
2302
  zds->noForwardProgress ++;
1723
2303
  if (zds->noForwardProgress >= ZSTD_NO_FORWARD_PROGRESS_MAX) {
1724
- RETURN_ERROR_IF(op==oend, dstSize_tooSmall);
1725
- RETURN_ERROR_IF(ip==iend, srcSize_wrong);
2304
+ RETURN_ERROR_IF(op==oend, noForwardProgress_destFull, "");
2305
+ RETURN_ERROR_IF(ip==iend, noForwardProgress_inputEmpty, "");
1726
2306
  assert(0);
1727
2307
  }
1728
2308
  } else {
@@ -1759,11 +2339,17 @@ size_t ZSTD_decompressStream_simpleArgs (
1759
2339
  void* dst, size_t dstCapacity, size_t* dstPos,
1760
2340
  const void* src, size_t srcSize, size_t* srcPos)
1761
2341
  {
1762
- ZSTD_outBuffer output = { dst, dstCapacity, *dstPos };
1763
- ZSTD_inBuffer input = { src, srcSize, *srcPos };
1764
- /* ZSTD_compress_generic() will check validity of dstPos and srcPos */
1765
- size_t const cErr = ZSTD_decompressStream(dctx, &output, &input);
1766
- *dstPos = output.pos;
1767
- *srcPos = input.pos;
1768
- 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
+ }
1769
2355
  }