zstd-ruby 1.4.1.0 → 1.5.0.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 (96) hide show
  1. checksums.yaml +4 -4
  2. data/.github/dependabot.yml +8 -0
  3. data/.github/workflows/ruby.yml +35 -0
  4. data/README.md +2 -2
  5. data/ext/zstdruby/libzstd/BUCK +5 -7
  6. data/ext/zstdruby/libzstd/Makefile +304 -113
  7. data/ext/zstdruby/libzstd/README.md +83 -20
  8. data/ext/zstdruby/libzstd/common/bitstream.h +59 -51
  9. data/ext/zstdruby/libzstd/common/compiler.h +150 -8
  10. data/ext/zstdruby/libzstd/common/cpu.h +1 -3
  11. data/ext/zstdruby/libzstd/common/debug.c +11 -31
  12. data/ext/zstdruby/libzstd/common/debug.h +22 -49
  13. data/ext/zstdruby/libzstd/common/entropy_common.c +201 -75
  14. data/ext/zstdruby/libzstd/common/error_private.c +3 -1
  15. data/ext/zstdruby/libzstd/common/error_private.h +8 -4
  16. data/ext/zstdruby/libzstd/common/fse.h +50 -42
  17. data/ext/zstdruby/libzstd/common/fse_decompress.c +149 -55
  18. data/ext/zstdruby/libzstd/common/huf.h +43 -39
  19. data/ext/zstdruby/libzstd/common/mem.h +69 -25
  20. data/ext/zstdruby/libzstd/common/pool.c +30 -20
  21. data/ext/zstdruby/libzstd/common/pool.h +3 -3
  22. data/ext/zstdruby/libzstd/common/threading.c +51 -4
  23. data/ext/zstdruby/libzstd/common/threading.h +36 -4
  24. data/ext/zstdruby/libzstd/common/xxhash.c +40 -92
  25. data/ext/zstdruby/libzstd/common/xxhash.h +12 -32
  26. data/ext/zstdruby/libzstd/common/zstd_common.c +10 -10
  27. data/ext/zstdruby/libzstd/common/zstd_deps.h +111 -0
  28. data/ext/zstdruby/libzstd/common/zstd_internal.h +230 -111
  29. data/ext/zstdruby/libzstd/common/zstd_trace.h +154 -0
  30. data/ext/zstdruby/libzstd/compress/fse_compress.c +47 -63
  31. data/ext/zstdruby/libzstd/compress/hist.c +41 -63
  32. data/ext/zstdruby/libzstd/compress/hist.h +13 -33
  33. data/ext/zstdruby/libzstd/compress/huf_compress.c +332 -193
  34. data/ext/zstdruby/libzstd/compress/zstd_compress.c +3614 -1696
  35. data/ext/zstdruby/libzstd/compress/zstd_compress_internal.h +546 -86
  36. data/ext/zstdruby/libzstd/compress/zstd_compress_literals.c +158 -0
  37. data/ext/zstdruby/libzstd/compress/zstd_compress_literals.h +29 -0
  38. data/ext/zstdruby/libzstd/compress/zstd_compress_sequences.c +441 -0
  39. data/ext/zstdruby/libzstd/compress/zstd_compress_sequences.h +54 -0
  40. data/ext/zstdruby/libzstd/compress/zstd_compress_superblock.c +572 -0
  41. data/ext/zstdruby/libzstd/compress/zstd_compress_superblock.h +32 -0
  42. data/ext/zstdruby/libzstd/compress/zstd_cwksp.h +662 -0
  43. data/ext/zstdruby/libzstd/compress/zstd_double_fast.c +43 -41
  44. data/ext/zstdruby/libzstd/compress/zstd_double_fast.h +2 -2
  45. data/ext/zstdruby/libzstd/compress/zstd_fast.c +85 -80
  46. data/ext/zstdruby/libzstd/compress/zstd_fast.h +2 -2
  47. data/ext/zstdruby/libzstd/compress/zstd_lazy.c +1184 -111
  48. data/ext/zstdruby/libzstd/compress/zstd_lazy.h +59 -1
  49. data/ext/zstdruby/libzstd/compress/zstd_ldm.c +333 -208
  50. data/ext/zstdruby/libzstd/compress/zstd_ldm.h +15 -3
  51. data/ext/zstdruby/libzstd/compress/zstd_ldm_geartab.h +103 -0
  52. data/ext/zstdruby/libzstd/compress/zstd_opt.c +228 -129
  53. data/ext/zstdruby/libzstd/compress/zstd_opt.h +1 -1
  54. data/ext/zstdruby/libzstd/compress/zstdmt_compress.c +151 -440
  55. data/ext/zstdruby/libzstd/compress/zstdmt_compress.h +32 -114
  56. data/ext/zstdruby/libzstd/decompress/huf_decompress.c +395 -276
  57. data/ext/zstdruby/libzstd/decompress/zstd_ddict.c +20 -16
  58. data/ext/zstdruby/libzstd/decompress/zstd_ddict.h +3 -3
  59. data/ext/zstdruby/libzstd/decompress/zstd_decompress.c +630 -231
  60. data/ext/zstdruby/libzstd/decompress/zstd_decompress_block.c +606 -380
  61. data/ext/zstdruby/libzstd/decompress/zstd_decompress_block.h +8 -5
  62. data/ext/zstdruby/libzstd/decompress/zstd_decompress_internal.h +39 -9
  63. data/ext/zstdruby/libzstd/deprecated/zbuff.h +9 -8
  64. data/ext/zstdruby/libzstd/deprecated/zbuff_common.c +2 -2
  65. data/ext/zstdruby/libzstd/deprecated/zbuff_compress.c +1 -1
  66. data/ext/zstdruby/libzstd/deprecated/zbuff_decompress.c +1 -1
  67. data/ext/zstdruby/libzstd/dictBuilder/cover.c +55 -46
  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 +43 -31
  71. data/ext/zstdruby/libzstd/dictBuilder/zdict.c +53 -30
  72. data/ext/zstdruby/libzstd/dll/example/Makefile +2 -1
  73. data/ext/zstdruby/libzstd/dll/example/README.md +16 -22
  74. data/ext/zstdruby/libzstd/legacy/zstd_legacy.h +4 -4
  75. data/ext/zstdruby/libzstd/legacy/zstd_v01.c +24 -14
  76. data/ext/zstdruby/libzstd/legacy/zstd_v01.h +1 -1
  77. data/ext/zstdruby/libzstd/legacy/zstd_v02.c +17 -8
  78. data/ext/zstdruby/libzstd/legacy/zstd_v02.h +1 -1
  79. data/ext/zstdruby/libzstd/legacy/zstd_v03.c +17 -8
  80. data/ext/zstdruby/libzstd/legacy/zstd_v03.h +1 -1
  81. data/ext/zstdruby/libzstd/legacy/zstd_v04.c +25 -11
  82. data/ext/zstdruby/libzstd/legacy/zstd_v04.h +1 -1
  83. data/ext/zstdruby/libzstd/legacy/zstd_v05.c +43 -32
  84. data/ext/zstdruby/libzstd/legacy/zstd_v05.h +2 -2
  85. data/ext/zstdruby/libzstd/legacy/zstd_v06.c +27 -19
  86. data/ext/zstdruby/libzstd/legacy/zstd_v06.h +1 -1
  87. data/ext/zstdruby/libzstd/legacy/zstd_v07.c +32 -20
  88. data/ext/zstdruby/libzstd/legacy/zstd_v07.h +1 -1
  89. data/ext/zstdruby/libzstd/libzstd.pc.in +2 -1
  90. data/ext/zstdruby/libzstd/{dictBuilder/zdict.h → zdict.h} +201 -31
  91. data/ext/zstdruby/libzstd/zstd.h +740 -153
  92. data/ext/zstdruby/libzstd/{common/zstd_errors.h → zstd_errors.h} +3 -1
  93. data/lib/zstd-ruby/version.rb +1 -1
  94. data/zstd-ruby.gemspec +1 -1
  95. metadata +21 -10
  96. data/.travis.yml +0 -14
@@ -1,5 +1,5 @@
1
1
  /*
2
- * Copyright (c) 2016-present, Yann Collet, Facebook, Inc.
2
+ * Copyright (c) Yann Collet, Facebook, Inc.
3
3
  * All rights reserved.
4
4
  *
5
5
  * This source code is licensed under both the BSD-style license (found in the
@@ -14,18 +14,18 @@
14
14
  /*-*******************************************************
15
15
  * Dependencies
16
16
  *********************************************************/
17
- #include <string.h> /* memcpy, memmove, memset */
18
- #include "cpu.h" /* bmi2 */
19
- #include "mem.h" /* low level memory routines */
17
+ #include "../common/zstd_deps.h" /* ZSTD_memcpy, ZSTD_memmove, ZSTD_memset */
18
+ #include "../common/cpu.h" /* bmi2 */
19
+ #include "../common/mem.h" /* low level memory routines */
20
20
  #define FSE_STATIC_LINKING_ONLY
21
- #include "fse.h"
21
+ #include "../common/fse.h"
22
22
  #define HUF_STATIC_LINKING_ONLY
23
- #include "huf.h"
23
+ #include "../common/huf.h"
24
24
  #include "zstd_decompress_internal.h"
25
25
  #include "zstd_ddict.h"
26
26
 
27
27
  #if defined(ZSTD_LEGACY_SUPPORT) && (ZSTD_LEGACY_SUPPORT>=1)
28
- # include "zstd_legacy.h"
28
+ # include "../legacy/zstd_legacy.h"
29
29
  #endif
30
30
 
31
31
 
@@ -65,6 +65,10 @@ void ZSTD_copyDDictParameters(ZSTD_DCtx* dctx, const ZSTD_DDict* ddict)
65
65
  dctx->virtualStart = ddict->dictContent;
66
66
  dctx->dictEnd = (const BYTE*)ddict->dictContent + ddict->dictSize;
67
67
  dctx->previousDstEnd = dctx->dictEnd;
68
+ #ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
69
+ dctx->dictContentBeginForFuzzing = dctx->prefixStart;
70
+ dctx->dictContentEndForFuzzing = dctx->previousDstEnd;
71
+ #endif
68
72
  if (ddict->entropyPresent) {
69
73
  dctx->litEntropy = 1;
70
74
  dctx->fseEntropy = 1;
@@ -107,7 +111,7 @@ ZSTD_loadEntropy_intoDDict(ZSTD_DDict* ddict,
107
111
  /* load entropy tables */
108
112
  RETURN_ERROR_IF(ZSTD_isError(ZSTD_loadDEntropy(
109
113
  &ddict->entropy, ddict->dictContent, ddict->dictSize)),
110
- dictionary_corrupted);
114
+ dictionary_corrupted, "");
111
115
  ddict->entropyPresent = 1;
112
116
  return 0;
113
117
  }
@@ -123,17 +127,17 @@ static size_t ZSTD_initDDict_internal(ZSTD_DDict* ddict,
123
127
  ddict->dictContent = dict;
124
128
  if (!dict) dictSize = 0;
125
129
  } else {
126
- void* const internalBuffer = ZSTD_malloc(dictSize, ddict->cMem);
130
+ void* const internalBuffer = ZSTD_customMalloc(dictSize, ddict->cMem);
127
131
  ddict->dictBuffer = internalBuffer;
128
132
  ddict->dictContent = internalBuffer;
129
133
  if (!internalBuffer) return ERROR(memory_allocation);
130
- memcpy(internalBuffer, dict, dictSize);
134
+ ZSTD_memcpy(internalBuffer, dict, dictSize);
131
135
  }
132
136
  ddict->dictSize = dictSize;
133
137
  ddict->entropy.hufTable[0] = (HUF_DTable)((HufLog)*0x1000001); /* cover both little and big endian */
134
138
 
135
139
  /* parse dictionary content */
136
- FORWARD_IF_ERROR( ZSTD_loadEntropy_intoDDict(ddict, dictContentType) );
140
+ FORWARD_IF_ERROR( ZSTD_loadEntropy_intoDDict(ddict, dictContentType) , "");
137
141
 
138
142
  return 0;
139
143
  }
@@ -143,9 +147,9 @@ ZSTD_DDict* ZSTD_createDDict_advanced(const void* dict, size_t dictSize,
143
147
  ZSTD_dictContentType_e dictContentType,
144
148
  ZSTD_customMem customMem)
145
149
  {
146
- if (!customMem.customAlloc ^ !customMem.customFree) return NULL;
150
+ if ((!customMem.customAlloc) ^ (!customMem.customFree)) return NULL;
147
151
 
148
- { ZSTD_DDict* const ddict = (ZSTD_DDict*) ZSTD_malloc(sizeof(ZSTD_DDict), customMem);
152
+ { ZSTD_DDict* const ddict = (ZSTD_DDict*) ZSTD_customMalloc(sizeof(ZSTD_DDict), customMem);
149
153
  if (ddict == NULL) return NULL;
150
154
  ddict->cMem = customMem;
151
155
  { size_t const initResult = ZSTD_initDDict_internal(ddict,
@@ -194,7 +198,7 @@ const ZSTD_DDict* ZSTD_initStaticDDict(
194
198
  if ((size_t)sBuffer & 7) return NULL; /* 8-aligned */
195
199
  if (sBufferSize < neededSpace) return NULL;
196
200
  if (dictLoadMethod == ZSTD_dlm_byCopy) {
197
- memcpy(ddict+1, dict, dictSize); /* local copy */
201
+ ZSTD_memcpy(ddict+1, dict, dictSize); /* local copy */
198
202
  dict = ddict+1;
199
203
  }
200
204
  if (ZSTD_isError( ZSTD_initDDict_internal(ddict,
@@ -209,8 +213,8 @@ size_t ZSTD_freeDDict(ZSTD_DDict* ddict)
209
213
  {
210
214
  if (ddict==NULL) return 0; /* support free on NULL */
211
215
  { ZSTD_customMem const cMem = ddict->cMem;
212
- ZSTD_free(ddict->dictBuffer, cMem);
213
- ZSTD_free(ddict, cMem);
216
+ ZSTD_customFree(ddict->dictBuffer, cMem);
217
+ ZSTD_customFree(ddict, cMem);
214
218
  return 0;
215
219
  }
216
220
  }
@@ -1,5 +1,5 @@
1
1
  /*
2
- * Copyright (c) 2016-present, Yann Collet, Facebook, Inc.
2
+ * Copyright (c) Yann Collet, Facebook, Inc.
3
3
  * All rights reserved.
4
4
  *
5
5
  * This source code is licensed under both the BSD-style license (found in the
@@ -15,8 +15,8 @@
15
15
  /*-*******************************************************
16
16
  * Dependencies
17
17
  *********************************************************/
18
- #include <stddef.h> /* size_t */
19
- #include "zstd.h" /* ZSTD_DDict, and several public functions */
18
+ #include "../common/zstd_deps.h" /* size_t */
19
+ #include "../zstd.h" /* ZSTD_DDict, and several public functions */
20
20
 
21
21
 
22
22
  /*-*******************************************************
@@ -1,5 +1,5 @@
1
1
  /*
2
- * Copyright (c) 2016-present, Yann Collet, Facebook, Inc.
2
+ * Copyright (c) Yann Collet, Facebook, Inc.
3
3
  * All rights reserved.
4
4
  *
5
5
  * This source code is licensed under both the BSD-style license (found in the
@@ -55,23 +55,162 @@
55
55
  /*-*******************************************************
56
56
  * Dependencies
57
57
  *********************************************************/
58
- #include <string.h> /* memcpy, memmove, memset */
59
- #include "cpu.h" /* bmi2 */
60
- #include "mem.h" /* low level memory routines */
58
+ #include "../common/zstd_deps.h" /* ZSTD_memcpy, ZSTD_memmove, ZSTD_memset */
59
+ #include "../common/cpu.h" /* bmi2 */
60
+ #include "../common/mem.h" /* low level memory routines */
61
61
  #define FSE_STATIC_LINKING_ONLY
62
- #include "fse.h"
62
+ #include "../common/fse.h"
63
63
  #define HUF_STATIC_LINKING_ONLY
64
- #include "huf.h"
65
- #include "zstd_internal.h" /* blockProperties_t */
64
+ #include "../common/huf.h"
65
+ #include "../common/xxhash.h" /* XXH64_reset, XXH64_update, XXH64_digest, XXH64 */
66
+ #include "../common/zstd_internal.h" /* blockProperties_t */
66
67
  #include "zstd_decompress_internal.h" /* ZSTD_DCtx */
67
68
  #include "zstd_ddict.h" /* ZSTD_DDictDictContent */
68
69
  #include "zstd_decompress_block.h" /* ZSTD_decompressBlock_internal */
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
+ ret->ddictPtrTable = (const ZSTD_DDict**)ZSTD_customCalloc(DDICT_HASHSET_TABLE_BASE_SIZE * sizeof(ZSTD_DDict*), customMem);
181
+ ret->ddictPtrTableSize = DDICT_HASHSET_TABLE_BASE_SIZE;
182
+ ret->ddictPtrCount = 0;
183
+ if (!ret || !ret->ddictPtrTable) {
184
+ return NULL;
185
+ }
186
+ return ret;
187
+ }
188
+
189
+ /* Frees the table of ZSTD_DDict* within a hashset, then frees the hashset itself.
190
+ * Note: The ZSTD_DDict* within the table are NOT freed.
191
+ */
192
+ static void ZSTD_freeDDictHashSet(ZSTD_DDictHashSet* hashSet, ZSTD_customMem customMem) {
193
+ DEBUGLOG(4, "Freeing ddict hash set");
194
+ if (hashSet && hashSet->ddictPtrTable) {
195
+ ZSTD_customFree((void*)hashSet->ddictPtrTable, customMem);
196
+ }
197
+ if (hashSet) {
198
+ ZSTD_customFree(hashSet, customMem);
199
+ }
200
+ }
201
+
202
+ /* Public function: Adds a DDict into the ZSTD_DDictHashSet, possibly triggering a resize of the hash set.
203
+ * Returns 0 on success, or a ZSTD error.
204
+ */
205
+ static size_t ZSTD_DDictHashSet_addDDict(ZSTD_DDictHashSet* hashSet, const ZSTD_DDict* ddict, ZSTD_customMem customMem) {
206
+ DEBUGLOG(4, "Adding dict ID: %u to hashset with - Count: %zu Tablesize: %zu", ZSTD_getDictID_fromDDict(ddict), hashSet->ddictPtrCount, hashSet->ddictPtrTableSize);
207
+ if (hashSet->ddictPtrCount * DDICT_HASHSET_MAX_LOAD_FACTOR_COUNT_MULT / hashSet->ddictPtrTableSize * DDICT_HASHSET_MAX_LOAD_FACTOR_SIZE_MULT != 0) {
208
+ FORWARD_IF_ERROR(ZSTD_DDictHashSet_expand(hashSet, customMem), "");
209
+ }
210
+ FORWARD_IF_ERROR(ZSTD_DDictHashSet_emplaceDDict(hashSet, ddict), "");
211
+ return 0;
212
+ }
213
+
75
214
  /*-*************************************************************
76
215
  * Context management
77
216
  ***************************************************************/
@@ -88,20 +227,25 @@ size_t ZSTD_estimateDCtxSize(void) { return sizeof(ZSTD_DCtx); }
88
227
 
89
228
  static size_t ZSTD_startingInputLength(ZSTD_format_e format)
90
229
  {
91
- size_t const startingInputLength = (format==ZSTD_f_zstd1_magicless) ?
92
- ZSTD_FRAMEHEADERSIZE_PREFIX - ZSTD_FRAMEIDSIZE :
93
- ZSTD_FRAMEHEADERSIZE_PREFIX;
94
- ZSTD_STATIC_ASSERT(ZSTD_FRAMEHEADERSIZE_PREFIX >= ZSTD_FRAMEIDSIZE);
230
+ size_t const startingInputLength = ZSTD_FRAMEHEADERSIZE_PREFIX(format);
95
231
  /* only supports formats ZSTD_f_zstd1 and ZSTD_f_zstd1_magicless */
96
232
  assert( (format == ZSTD_f_zstd1) || (format == ZSTD_f_zstd1_magicless) );
97
233
  return startingInputLength;
98
234
  }
99
235
 
236
+ static void ZSTD_DCtx_resetParameters(ZSTD_DCtx* dctx)
237
+ {
238
+ assert(dctx->streamStage == zdss_init);
239
+ dctx->format = ZSTD_f_zstd1;
240
+ dctx->maxWindowSize = ZSTD_MAXWINDOWSIZE_DEFAULT;
241
+ dctx->outBufferMode = ZSTD_bm_buffered;
242
+ dctx->forceIgnoreChecksum = ZSTD_d_validateChecksum;
243
+ dctx->refMultipleDDicts = ZSTD_rmd_refSingleDDict;
244
+ }
245
+
100
246
  static void ZSTD_initDCtx_internal(ZSTD_DCtx* dctx)
101
247
  {
102
- dctx->format = ZSTD_f_zstd1; /* ZSTD_decompressBegin() invokes ZSTD_startingInputLength() with argument dctx->format */
103
248
  dctx->staticSize = 0;
104
- dctx->maxWindowSize = ZSTD_MAXWINDOWSIZE_DEFAULT;
105
249
  dctx->ddict = NULL;
106
250
  dctx->ddictLocal = NULL;
107
251
  dctx->dictEnd = NULL;
@@ -114,7 +258,13 @@ static void ZSTD_initDCtx_internal(ZSTD_DCtx* dctx)
114
258
  dctx->legacyContext = NULL;
115
259
  dctx->previousLegacyVersion = 0;
116
260
  dctx->noForwardProgress = 0;
261
+ dctx->oversizedDuration = 0;
117
262
  dctx->bmi2 = ZSTD_cpuid_bmi2(ZSTD_cpuid());
263
+ dctx->ddictSet = NULL;
264
+ ZSTD_DCtx_resetParameters(dctx);
265
+ #ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
266
+ dctx->dictContentEndForFuzzing = NULL;
267
+ #endif
118
268
  }
119
269
 
120
270
  ZSTD_DCtx* ZSTD_initStaticDCtx(void *workspace, size_t workspaceSize)
@@ -132,9 +282,9 @@ ZSTD_DCtx* ZSTD_initStaticDCtx(void *workspace, size_t workspaceSize)
132
282
 
133
283
  ZSTD_DCtx* ZSTD_createDCtx_advanced(ZSTD_customMem customMem)
134
284
  {
135
- if (!customMem.customAlloc ^ !customMem.customFree) return NULL;
285
+ if ((!customMem.customAlloc) ^ (!customMem.customFree)) return NULL;
136
286
 
137
- { ZSTD_DCtx* const dctx = (ZSTD_DCtx*)ZSTD_malloc(sizeof(*dctx), customMem);
287
+ { ZSTD_DCtx* const dctx = (ZSTD_DCtx*)ZSTD_customMalloc(sizeof(*dctx), customMem);
138
288
  if (!dctx) return NULL;
139
289
  dctx->customMem = customMem;
140
290
  ZSTD_initDCtx_internal(dctx);
@@ -162,13 +312,17 @@ size_t ZSTD_freeDCtx(ZSTD_DCtx* dctx)
162
312
  RETURN_ERROR_IF(dctx->staticSize, memory_allocation, "not compatible with static DCtx");
163
313
  { ZSTD_customMem const cMem = dctx->customMem;
164
314
  ZSTD_clearDict(dctx);
165
- ZSTD_free(dctx->inBuff, cMem);
315
+ ZSTD_customFree(dctx->inBuff, cMem);
166
316
  dctx->inBuff = NULL;
167
317
  #if defined(ZSTD_LEGACY_SUPPORT) && (ZSTD_LEGACY_SUPPORT >= 1)
168
318
  if (dctx->legacyContext)
169
319
  ZSTD_freeLegacyStreamContext(dctx->legacyContext, dctx->previousLegacyVersion);
170
320
  #endif
171
- ZSTD_free(dctx, cMem);
321
+ if (dctx->ddictSet) {
322
+ ZSTD_freeDDictHashSet(dctx->ddictSet, cMem);
323
+ dctx->ddictSet = NULL;
324
+ }
325
+ ZSTD_customFree(dctx, cMem);
172
326
  return 0;
173
327
  }
174
328
  }
@@ -177,7 +331,30 @@ size_t ZSTD_freeDCtx(ZSTD_DCtx* dctx)
177
331
  void ZSTD_copyDCtx(ZSTD_DCtx* dstDCtx, const ZSTD_DCtx* srcDCtx)
178
332
  {
179
333
  size_t const toCopy = (size_t)((char*)(&dstDCtx->inBuff) - (char*)dstDCtx);
180
- memcpy(dstDCtx, srcDCtx, toCopy); /* no need to copy workspace */
334
+ ZSTD_memcpy(dstDCtx, srcDCtx, toCopy); /* no need to copy workspace */
335
+ }
336
+
337
+ /* Given a dctx with a digested frame params, re-selects the correct ZSTD_DDict based on
338
+ * the requested dict ID from the frame. If there exists a reference to the correct ZSTD_DDict, then
339
+ * accordingly sets the ddict to be used to decompress the frame.
340
+ *
341
+ * If no DDict is found, then no action is taken, and the ZSTD_DCtx::ddict remains as-is.
342
+ *
343
+ * ZSTD_d_refMultipleDDicts must be enabled for this function to be called.
344
+ */
345
+ static void ZSTD_DCtx_selectFrameDDict(ZSTD_DCtx* dctx) {
346
+ assert(dctx->refMultipleDDicts && dctx->ddictSet);
347
+ DEBUGLOG(4, "Adjusting DDict based on requested dict ID from frame");
348
+ if (dctx->ddict) {
349
+ const ZSTD_DDict* frameDDict = ZSTD_DDictHashSet_getDDict(dctx->ddictSet, dctx->fParams.dictID);
350
+ if (frameDDict) {
351
+ DEBUGLOG(4, "DDict found!");
352
+ ZSTD_clearDict(dctx);
353
+ dctx->dictID = dctx->fParams.dictID;
354
+ dctx->ddict = frameDDict;
355
+ dctx->dictUses = ZSTD_use_indefinitely;
356
+ }
357
+ }
181
358
  }
182
359
 
183
360
 
@@ -211,7 +388,7 @@ unsigned ZSTD_isFrame(const void* buffer, size_t size)
211
388
  static size_t ZSTD_frameHeaderSize_internal(const void* src, size_t srcSize, ZSTD_format_e format)
212
389
  {
213
390
  size_t const minInputSize = ZSTD_startingInputLength(format);
214
- RETURN_ERROR_IF(srcSize < minInputSize, srcSize_wrong);
391
+ RETURN_ERROR_IF(srcSize < minInputSize, srcSize_wrong, "");
215
392
 
216
393
  { BYTE const fhd = ((const BYTE*)src)[minInputSize-1];
217
394
  U32 const dictID= fhd & 3;
@@ -244,7 +421,7 @@ size_t ZSTD_getFrameHeader_advanced(ZSTD_frameHeader* zfhPtr, const void* src, s
244
421
  const BYTE* ip = (const BYTE*)src;
245
422
  size_t const minInputSize = ZSTD_startingInputLength(format);
246
423
 
247
- 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 */
424
+ ZSTD_memset(zfhPtr, 0, sizeof(*zfhPtr)); /* not strictly necessary, but static analyzer do not understand that zfhPtr is only going to be read only if return value is zero, since they are 2 different signals */
248
425
  if (srcSize < minInputSize) return minInputSize;
249
426
  RETURN_ERROR_IF(src==NULL, GENERIC, "invalid parameter");
250
427
 
@@ -254,12 +431,12 @@ size_t ZSTD_getFrameHeader_advanced(ZSTD_frameHeader* zfhPtr, const void* src, s
254
431
  /* skippable frame */
255
432
  if (srcSize < ZSTD_SKIPPABLEHEADERSIZE)
256
433
  return ZSTD_SKIPPABLEHEADERSIZE; /* magic number + frame length */
257
- memset(zfhPtr, 0, sizeof(*zfhPtr));
434
+ ZSTD_memset(zfhPtr, 0, sizeof(*zfhPtr));
258
435
  zfhPtr->frameContentSize = MEM_readLE32((const char *)src + ZSTD_FRAMEIDSIZE);
259
436
  zfhPtr->frameType = ZSTD_skippableFrame;
260
437
  return 0;
261
438
  }
262
- RETURN_ERROR(prefix_unknown);
439
+ RETURN_ERROR(prefix_unknown, "");
263
440
  }
264
441
 
265
442
  /* ensure there is enough `srcSize` to fully read/decode frame header */
@@ -283,7 +460,7 @@ size_t ZSTD_getFrameHeader_advanced(ZSTD_frameHeader* zfhPtr, const void* src, s
283
460
  if (!singleSegment) {
284
461
  BYTE const wlByte = ip[pos++];
285
462
  U32 const windowLog = (wlByte >> 3) + ZSTD_WINDOWLOG_ABSOLUTEMIN;
286
- RETURN_ERROR_IF(windowLog > ZSTD_WINDOWLOG_MAX, frameParameter_windowTooLarge);
463
+ RETURN_ERROR_IF(windowLog > ZSTD_WINDOWLOG_MAX, frameParameter_windowTooLarge, "");
287
464
  windowSize = (1ULL << windowLog);
288
465
  windowSize += (windowSize >> 3) * (wlByte&7);
289
466
  }
@@ -355,14 +532,14 @@ static size_t readSkippableFrameSize(void const* src, size_t srcSize)
355
532
  size_t const skippableHeaderSize = ZSTD_SKIPPABLEHEADERSIZE;
356
533
  U32 sizeU32;
357
534
 
358
- RETURN_ERROR_IF(srcSize < ZSTD_SKIPPABLEHEADERSIZE, srcSize_wrong);
535
+ RETURN_ERROR_IF(srcSize < ZSTD_SKIPPABLEHEADERSIZE, srcSize_wrong, "");
359
536
 
360
537
  sizeU32 = MEM_readLE32((BYTE const*)src + ZSTD_FRAMEIDSIZE);
361
538
  RETURN_ERROR_IF((U32)(sizeU32 + ZSTD_SKIPPABLEHEADERSIZE) < sizeU32,
362
- frameParameter_unsupported);
539
+ frameParameter_unsupported, "");
363
540
  {
364
541
  size_t const skippableSize = skippableHeaderSize + sizeU32;
365
- RETURN_ERROR_IF(skippableSize > srcSize, srcSize_wrong);
542
+ RETURN_ERROR_IF(skippableSize > srcSize, srcSize_wrong, "");
366
543
  return skippableSize;
367
544
  }
368
545
  }
@@ -376,7 +553,7 @@ unsigned long long ZSTD_findDecompressedSize(const void* src, size_t srcSize)
376
553
  {
377
554
  unsigned long long totalDstSize = 0;
378
555
 
379
- while (srcSize >= ZSTD_FRAMEHEADERSIZE_PREFIX) {
556
+ while (srcSize >= ZSTD_startingInputLength(ZSTD_f_zstd1)) {
380
557
  U32 const magicNumber = MEM_readLE32(src);
381
558
 
382
559
  if ((magicNumber & ZSTD_MAGIC_SKIPPABLE_MASK) == ZSTD_MAGIC_SKIPPABLE_START) {
@@ -431,20 +608,29 @@ unsigned long long ZSTD_getDecompressedSize(const void* src, size_t srcSize)
431
608
 
432
609
  /** ZSTD_decodeFrameHeader() :
433
610
  * `headerSize` must be the size provided by ZSTD_frameHeaderSize().
611
+ * If multiple DDict references are enabled, also will choose the correct DDict to use.
434
612
  * @return : 0 if success, or an error code, which can be tested using ZSTD_isError() */
435
613
  static size_t ZSTD_decodeFrameHeader(ZSTD_DCtx* dctx, const void* src, size_t headerSize)
436
614
  {
437
615
  size_t const result = ZSTD_getFrameHeader_advanced(&(dctx->fParams), src, headerSize, dctx->format);
438
616
  if (ZSTD_isError(result)) return result; /* invalid header */
439
617
  RETURN_ERROR_IF(result>0, srcSize_wrong, "headerSize too small");
618
+
619
+ /* Reference DDict requested by frame if dctx references multiple ddicts */
620
+ if (dctx->refMultipleDDicts == ZSTD_rmd_refMultipleDDicts && dctx->ddictSet) {
621
+ ZSTD_DCtx_selectFrameDDict(dctx);
622
+ }
623
+
440
624
  #ifndef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
441
625
  /* Skip the dictID check in fuzzing mode, because it makes the search
442
626
  * harder.
443
627
  */
444
628
  RETURN_ERROR_IF(dctx->fParams.dictID && (dctx->dictID != dctx->fParams.dictID),
445
- dictionary_wrong);
629
+ dictionary_wrong, "");
446
630
  #endif
447
- if (dctx->fParams.checksumFlag) XXH64_reset(&dctx->xxhState, 0);
631
+ dctx->validateChecksum = (dctx->fParams.checksumFlag && !dctx->forceIgnoreChecksum) ? 1 : 0;
632
+ if (dctx->validateChecksum) XXH64_reset(&dctx->xxhState, 0);
633
+ dctx->processedCSize += headerSize;
448
634
  return 0;
449
635
  }
450
636
 
@@ -459,7 +645,7 @@ static ZSTD_frameSizeInfo ZSTD_errorFrameSizeInfo(size_t ret)
459
645
  static ZSTD_frameSizeInfo ZSTD_findFrameSizeInfo(const void* src, size_t srcSize)
460
646
  {
461
647
  ZSTD_frameSizeInfo frameSizeInfo;
462
- memset(&frameSizeInfo, 0, sizeof(ZSTD_frameSizeInfo));
648
+ ZSTD_memset(&frameSizeInfo, 0, sizeof(ZSTD_frameSizeInfo));
463
649
 
464
650
  #if defined(ZSTD_LEGACY_SUPPORT) && (ZSTD_LEGACY_SUPPORT >= 1)
465
651
  if (ZSTD_isLegacy(src, srcSize))
@@ -514,7 +700,7 @@ static ZSTD_frameSizeInfo ZSTD_findFrameSizeInfo(const void* src, size_t srcSize
514
700
  ip += 4;
515
701
  }
516
702
 
517
- frameSizeInfo.compressedSize = ip - ipstart;
703
+ frameSizeInfo.compressedSize = (size_t)(ip - ipstart);
518
704
  frameSizeInfo.decompressedBound = (zfh.frameContentSize != ZSTD_CONTENTSIZE_UNKNOWN)
519
705
  ? zfh.frameContentSize
520
706
  : nbBlocks * zfh.blockSizeMax;
@@ -562,22 +748,12 @@ unsigned long long ZSTD_decompressBound(const void* src, size_t srcSize)
562
748
  * Frame decoding
563
749
  ***************************************************************/
564
750
 
565
-
566
- void ZSTD_checkContinuity(ZSTD_DCtx* dctx, const void* dst)
567
- {
568
- if (dst != dctx->previousDstEnd) { /* not contiguous */
569
- dctx->dictEnd = dctx->previousDstEnd;
570
- dctx->virtualStart = (const char*)dst - ((const char*)(dctx->previousDstEnd) - (const char*)(dctx->prefixStart));
571
- dctx->prefixStart = dst;
572
- dctx->previousDstEnd = dst;
573
- }
574
- }
575
-
576
751
  /** ZSTD_insertBlock() :
577
- insert `src` block into `dctx` history. Useful to track uncompressed blocks. */
752
+ * insert `src` block into `dctx` history. Useful to track uncompressed blocks. */
578
753
  size_t ZSTD_insertBlock(ZSTD_DCtx* dctx, const void* blockStart, size_t blockSize)
579
754
  {
580
- ZSTD_checkContinuity(dctx, blockStart);
755
+ DEBUGLOG(5, "ZSTD_insertBlock: %u bytes", (unsigned)blockSize);
756
+ ZSTD_checkContinuity(dctx, blockStart, blockSize);
581
757
  dctx->previousDstEnd = (const char*)blockStart + blockSize;
582
758
  return blockSize;
583
759
  }
@@ -587,12 +763,12 @@ static size_t ZSTD_copyRawBlock(void* dst, size_t dstCapacity,
587
763
  const void* src, size_t srcSize)
588
764
  {
589
765
  DEBUGLOG(5, "ZSTD_copyRawBlock");
766
+ RETURN_ERROR_IF(srcSize > dstCapacity, dstSize_tooSmall, "");
590
767
  if (dst == NULL) {
591
768
  if (srcSize == 0) return 0;
592
- RETURN_ERROR(dstBuffer_null);
769
+ RETURN_ERROR(dstBuffer_null, "");
593
770
  }
594
- RETURN_ERROR_IF(srcSize > dstCapacity, dstSize_tooSmall);
595
- memcpy(dst, src, srcSize);
771
+ ZSTD_memcpy(dst, src, srcSize);
596
772
  return srcSize;
597
773
  }
598
774
 
@@ -600,15 +776,41 @@ static size_t ZSTD_setRleBlock(void* dst, size_t dstCapacity,
600
776
  BYTE b,
601
777
  size_t regenSize)
602
778
  {
779
+ RETURN_ERROR_IF(regenSize > dstCapacity, dstSize_tooSmall, "");
603
780
  if (dst == NULL) {
604
781
  if (regenSize == 0) return 0;
605
- RETURN_ERROR(dstBuffer_null);
782
+ RETURN_ERROR(dstBuffer_null, "");
606
783
  }
607
- RETURN_ERROR_IF(regenSize > dstCapacity, dstSize_tooSmall);
608
- memset(dst, b, regenSize);
784
+ ZSTD_memset(dst, b, regenSize);
609
785
  return regenSize;
610
786
  }
611
787
 
788
+ static void ZSTD_DCtx_trace_end(ZSTD_DCtx const* dctx, U64 uncompressedSize, U64 compressedSize, unsigned streaming)
789
+ {
790
+ #if ZSTD_TRACE
791
+ if (dctx->traceCtx && ZSTD_trace_decompress_end != NULL) {
792
+ ZSTD_Trace trace;
793
+ ZSTD_memset(&trace, 0, sizeof(trace));
794
+ trace.version = ZSTD_VERSION_NUMBER;
795
+ trace.streaming = streaming;
796
+ if (dctx->ddict) {
797
+ trace.dictionaryID = ZSTD_getDictID_fromDDict(dctx->ddict);
798
+ trace.dictionarySize = ZSTD_DDict_dictSize(dctx->ddict);
799
+ trace.dictionaryIsCold = dctx->ddictIsCold;
800
+ }
801
+ trace.uncompressedSize = (size_t)uncompressedSize;
802
+ trace.compressedSize = (size_t)compressedSize;
803
+ trace.dctx = dctx;
804
+ ZSTD_trace_decompress_end(dctx->traceCtx, &trace);
805
+ }
806
+ #else
807
+ (void)dctx;
808
+ (void)uncompressedSize;
809
+ (void)compressedSize;
810
+ (void)streaming;
811
+ #endif
812
+ }
813
+
612
814
 
613
815
  /*! ZSTD_decompressFrame() :
614
816
  * @dctx must be properly initialized
@@ -618,9 +820,10 @@ static size_t ZSTD_decompressFrame(ZSTD_DCtx* dctx,
618
820
  void* dst, size_t dstCapacity,
619
821
  const void** srcPtr, size_t *srcSizePtr)
620
822
  {
621
- const BYTE* ip = (const BYTE*)(*srcPtr);
622
- BYTE* const ostart = (BYTE* const)dst;
623
- BYTE* const oend = ostart + dstCapacity;
823
+ const BYTE* const istart = (const BYTE*)(*srcPtr);
824
+ const BYTE* ip = istart;
825
+ BYTE* const ostart = (BYTE*)dst;
826
+ BYTE* const oend = dstCapacity != 0 ? ostart + dstCapacity : ostart;
624
827
  BYTE* op = ostart;
625
828
  size_t remainingSrcSize = *srcSizePtr;
626
829
 
@@ -628,15 +831,16 @@ static size_t ZSTD_decompressFrame(ZSTD_DCtx* dctx,
628
831
 
629
832
  /* check */
630
833
  RETURN_ERROR_IF(
631
- remainingSrcSize < ZSTD_FRAMEHEADERSIZE_MIN+ZSTD_blockHeaderSize,
632
- srcSize_wrong);
834
+ remainingSrcSize < ZSTD_FRAMEHEADERSIZE_MIN(dctx->format)+ZSTD_blockHeaderSize,
835
+ srcSize_wrong, "");
633
836
 
634
837
  /* Frame Header */
635
- { size_t const frameHeaderSize = ZSTD_frameHeaderSize(ip, ZSTD_FRAMEHEADERSIZE_PREFIX);
838
+ { size_t const frameHeaderSize = ZSTD_frameHeaderSize_internal(
839
+ ip, ZSTD_FRAMEHEADERSIZE_PREFIX(dctx->format), dctx->format);
636
840
  if (ZSTD_isError(frameHeaderSize)) return frameHeaderSize;
637
841
  RETURN_ERROR_IF(remainingSrcSize < frameHeaderSize+ZSTD_blockHeaderSize,
638
- srcSize_wrong);
639
- FORWARD_IF_ERROR( ZSTD_decodeFrameHeader(dctx, ip, frameHeaderSize) );
842
+ srcSize_wrong, "");
843
+ FORWARD_IF_ERROR( ZSTD_decodeFrameHeader(dctx, ip, frameHeaderSize) , "");
640
844
  ip += frameHeaderSize; remainingSrcSize -= frameHeaderSize;
641
845
  }
642
846
 
@@ -649,28 +853,30 @@ static size_t ZSTD_decompressFrame(ZSTD_DCtx* dctx,
649
853
 
650
854
  ip += ZSTD_blockHeaderSize;
651
855
  remainingSrcSize -= ZSTD_blockHeaderSize;
652
- RETURN_ERROR_IF(cBlockSize > remainingSrcSize, srcSize_wrong);
856
+ RETURN_ERROR_IF(cBlockSize > remainingSrcSize, srcSize_wrong, "");
653
857
 
654
858
  switch(blockProperties.blockType)
655
859
  {
656
860
  case bt_compressed:
657
- decodedSize = ZSTD_decompressBlock_internal(dctx, op, oend-op, ip, cBlockSize, /* frame */ 1);
861
+ decodedSize = ZSTD_decompressBlock_internal(dctx, op, (size_t)(oend-op), ip, cBlockSize, /* frame */ 1);
658
862
  break;
659
863
  case bt_raw :
660
- decodedSize = ZSTD_copyRawBlock(op, oend-op, ip, cBlockSize);
864
+ decodedSize = ZSTD_copyRawBlock(op, (size_t)(oend-op), ip, cBlockSize);
661
865
  break;
662
866
  case bt_rle :
663
- decodedSize = ZSTD_setRleBlock(op, oend-op, *ip, blockProperties.origSize);
867
+ decodedSize = ZSTD_setRleBlock(op, (size_t)(oend-op), *ip, blockProperties.origSize);
664
868
  break;
665
869
  case bt_reserved :
666
870
  default:
667
- RETURN_ERROR(corruption_detected);
871
+ RETURN_ERROR(corruption_detected, "invalid block type");
668
872
  }
669
873
 
670
874
  if (ZSTD_isError(decodedSize)) return decodedSize;
671
- if (dctx->fParams.checksumFlag)
875
+ if (dctx->validateChecksum)
672
876
  XXH64_update(&dctx->xxhState, op, decodedSize);
673
- op += decodedSize;
877
+ if (decodedSize != 0)
878
+ op += decodedSize;
879
+ assert(ip != NULL);
674
880
  ip += cBlockSize;
675
881
  remainingSrcSize -= cBlockSize;
676
882
  if (blockProperties.lastBlock) break;
@@ -678,22 +884,24 @@ static size_t ZSTD_decompressFrame(ZSTD_DCtx* dctx,
678
884
 
679
885
  if (dctx->fParams.frameContentSize != ZSTD_CONTENTSIZE_UNKNOWN) {
680
886
  RETURN_ERROR_IF((U64)(op-ostart) != dctx->fParams.frameContentSize,
681
- corruption_detected);
887
+ corruption_detected, "");
682
888
  }
683
889
  if (dctx->fParams.checksumFlag) { /* Frame content checksum verification */
684
- U32 const checkCalc = (U32)XXH64_digest(&dctx->xxhState);
685
- U32 checkRead;
686
- RETURN_ERROR_IF(remainingSrcSize<4, checksum_wrong);
687
- checkRead = MEM_readLE32(ip);
688
- RETURN_ERROR_IF(checkRead != checkCalc, checksum_wrong);
890
+ RETURN_ERROR_IF(remainingSrcSize<4, checksum_wrong, "");
891
+ if (!dctx->forceIgnoreChecksum) {
892
+ U32 const checkCalc = (U32)XXH64_digest(&dctx->xxhState);
893
+ U32 checkRead;
894
+ checkRead = MEM_readLE32(ip);
895
+ RETURN_ERROR_IF(checkRead != checkCalc, checksum_wrong, "");
896
+ }
689
897
  ip += 4;
690
898
  remainingSrcSize -= 4;
691
899
  }
692
-
900
+ ZSTD_DCtx_trace_end(dctx, (U64)(op-ostart), (U64)(ip-istart), /* streaming */ 0);
693
901
  /* Allow caller to get size read */
694
902
  *srcPtr = ip;
695
903
  *srcSizePtr = remainingSrcSize;
696
- return op-ostart;
904
+ return (size_t)(op-ostart);
697
905
  }
698
906
 
699
907
  static size_t ZSTD_decompressMultiFrame(ZSTD_DCtx* dctx,
@@ -713,7 +921,7 @@ static size_t ZSTD_decompressMultiFrame(ZSTD_DCtx* dctx,
713
921
  dictSize = ZSTD_DDict_dictSize(ddict);
714
922
  }
715
923
 
716
- while (srcSize >= ZSTD_FRAMEHEADERSIZE_PREFIX) {
924
+ while (srcSize >= ZSTD_startingInputLength(dctx->format)) {
717
925
 
718
926
  #if defined(ZSTD_LEGACY_SUPPORT) && (ZSTD_LEGACY_SUPPORT >= 1)
719
927
  if (ZSTD_isLegacy(src, srcSize)) {
@@ -726,7 +934,7 @@ static size_t ZSTD_decompressMultiFrame(ZSTD_DCtx* dctx,
726
934
  decodedSize = ZSTD_decompressLegacy(dst, dstCapacity, src, frameSize, dict, dictSize);
727
935
  if (ZSTD_isError(decodedSize)) return decodedSize;
728
936
 
729
- assert(decodedSize <=- dstCapacity);
937
+ assert(decodedSize <= dstCapacity);
730
938
  dst = (BYTE*)dst + decodedSize;
731
939
  dstCapacity -= decodedSize;
732
940
 
@@ -742,7 +950,7 @@ static size_t ZSTD_decompressMultiFrame(ZSTD_DCtx* dctx,
742
950
  (unsigned)magicNumber, ZSTD_MAGICNUMBER);
743
951
  if ((magicNumber & ZSTD_MAGIC_SKIPPABLE_MASK) == ZSTD_MAGIC_SKIPPABLE_START) {
744
952
  size_t const skippableSize = readSkippableFrameSize(src, srcSize);
745
- FORWARD_IF_ERROR(skippableSize);
953
+ FORWARD_IF_ERROR(skippableSize, "readSkippableFrameSize failed");
746
954
  assert(skippableSize <= srcSize);
747
955
 
748
956
  src = (const BYTE *)src + skippableSize;
@@ -752,13 +960,13 @@ static size_t ZSTD_decompressMultiFrame(ZSTD_DCtx* dctx,
752
960
 
753
961
  if (ddict) {
754
962
  /* we were called from ZSTD_decompress_usingDDict */
755
- FORWARD_IF_ERROR(ZSTD_decompressBegin_usingDDict(dctx, ddict));
963
+ FORWARD_IF_ERROR(ZSTD_decompressBegin_usingDDict(dctx, ddict), "");
756
964
  } else {
757
965
  /* this will initialize correctly with no dict if dict == NULL, so
758
966
  * use this in all cases but ddict */
759
- FORWARD_IF_ERROR(ZSTD_decompressBegin_usingDict(dctx, dict, dictSize));
967
+ FORWARD_IF_ERROR(ZSTD_decompressBegin_usingDict(dctx, dict, dictSize), "");
760
968
  }
761
- ZSTD_checkContinuity(dctx, dst);
969
+ ZSTD_checkContinuity(dctx, dst, dstCapacity);
762
970
 
763
971
  { const size_t res = ZSTD_decompressFrame(dctx, dst, dstCapacity,
764
972
  &src, &srcSize);
@@ -766,18 +974,17 @@ static size_t ZSTD_decompressMultiFrame(ZSTD_DCtx* dctx,
766
974
  (ZSTD_getErrorCode(res) == ZSTD_error_prefix_unknown)
767
975
  && (moreThan1Frame==1),
768
976
  srcSize_wrong,
769
- "at least one frame successfully completed, but following "
770
- "bytes are garbage: it's more likely to be a srcSize error, "
771
- "specifying more bytes than compressed size of frame(s). This "
772
- "error message replaces ERROR(prefix_unknown), which would be "
773
- "confusing, as the first header is actually correct. Note that "
774
- "one could be unlucky, it might be a corruption error instead, "
775
- "happening right at the place where we expect zstd magic "
776
- "bytes. But this is _much_ less likely than a srcSize field "
777
- "error.");
977
+ "At least one frame successfully completed, "
978
+ "but following bytes are garbage: "
979
+ "it's more likely to be a srcSize error, "
980
+ "specifying more input bytes than size of frame(s). "
981
+ "Note: one could be unlucky, it might be a corruption error instead, "
982
+ "happening right at the place where we expect zstd magic bytes. "
983
+ "But this is _much_ less likely than a srcSize field error.");
778
984
  if (ZSTD_isError(res)) return res;
779
985
  assert(res <= dstCapacity);
780
- dst = (BYTE*)dst + res;
986
+ if (res != 0)
987
+ dst = (BYTE*)dst + res;
781
988
  dstCapacity -= res;
782
989
  }
783
990
  moreThan1Frame = 1;
@@ -785,7 +992,7 @@ static size_t ZSTD_decompressMultiFrame(ZSTD_DCtx* dctx,
785
992
 
786
993
  RETURN_ERROR_IF(srcSize, srcSize_wrong, "input not entirely consumed");
787
994
 
788
- return (BYTE*)dst - (BYTE*)dststart;
995
+ return (size_t)((BYTE*)dst - (BYTE*)dststart);
789
996
  }
790
997
 
791
998
  size_t ZSTD_decompress_usingDict(ZSTD_DCtx* dctx,
@@ -825,7 +1032,7 @@ size_t ZSTD_decompress(void* dst, size_t dstCapacity, const void* src, size_t sr
825
1032
  #if defined(ZSTD_HEAPMODE) && (ZSTD_HEAPMODE>=1)
826
1033
  size_t regenSize;
827
1034
  ZSTD_DCtx* const dctx = ZSTD_createDCtx();
828
- RETURN_ERROR_IF(dctx==NULL, memory_allocation);
1035
+ RETURN_ERROR_IF(dctx==NULL, memory_allocation, "NULL pointer!");
829
1036
  regenSize = ZSTD_decompressDCtx(dctx, dst, dstCapacity, src, srcSize);
830
1037
  ZSTD_freeDCtx(dctx);
831
1038
  return regenSize;
@@ -843,6 +1050,24 @@ size_t ZSTD_decompress(void* dst, size_t dstCapacity, const void* src, size_t sr
843
1050
  ****************************************/
844
1051
  size_t ZSTD_nextSrcSizeToDecompress(ZSTD_DCtx* dctx) { return dctx->expected; }
845
1052
 
1053
+ /**
1054
+ * Similar to ZSTD_nextSrcSizeToDecompress(), but when when a block input can be streamed,
1055
+ * we allow taking a partial block as the input. Currently only raw uncompressed blocks can
1056
+ * be streamed.
1057
+ *
1058
+ * For blocks that can be streamed, this allows us to reduce the latency until we produce
1059
+ * output, and avoid copying the input.
1060
+ *
1061
+ * @param inputSize - The total amount of input that the caller currently has.
1062
+ */
1063
+ static size_t ZSTD_nextSrcSizeToDecompressWithInputSize(ZSTD_DCtx* dctx, size_t inputSize) {
1064
+ if (!(dctx->stage == ZSTDds_decompressBlock || dctx->stage == ZSTDds_decompressLastBlock))
1065
+ return dctx->expected;
1066
+ if (dctx->bType != bt_raw)
1067
+ return dctx->expected;
1068
+ return MIN(MAX(inputSize, 1), dctx->expected);
1069
+ }
1070
+
846
1071
  ZSTD_nextInputType_e ZSTD_nextInputType(ZSTD_DCtx* dctx) {
847
1072
  switch(dctx->stage)
848
1073
  {
@@ -875,8 +1100,10 @@ size_t ZSTD_decompressContinue(ZSTD_DCtx* dctx, void* dst, size_t dstCapacity, c
875
1100
  {
876
1101
  DEBUGLOG(5, "ZSTD_decompressContinue (srcSize:%u)", (unsigned)srcSize);
877
1102
  /* Sanity check */
878
- RETURN_ERROR_IF(srcSize != dctx->expected, srcSize_wrong, "not allowed");
879
- if (dstCapacity) ZSTD_checkContinuity(dctx, dst);
1103
+ RETURN_ERROR_IF(srcSize != ZSTD_nextSrcSizeToDecompressWithInputSize(dctx, srcSize), srcSize_wrong, "not allowed");
1104
+ ZSTD_checkContinuity(dctx, dst, dstCapacity);
1105
+
1106
+ dctx->processedCSize += srcSize;
880
1107
 
881
1108
  switch (dctx->stage)
882
1109
  {
@@ -885,22 +1112,22 @@ size_t ZSTD_decompressContinue(ZSTD_DCtx* dctx, void* dst, size_t dstCapacity, c
885
1112
  if (dctx->format == ZSTD_f_zstd1) { /* allows header */
886
1113
  assert(srcSize >= ZSTD_FRAMEIDSIZE); /* to read skippable magic number */
887
1114
  if ((MEM_readLE32(src) & ZSTD_MAGIC_SKIPPABLE_MASK) == ZSTD_MAGIC_SKIPPABLE_START) { /* skippable frame */
888
- memcpy(dctx->headerBuffer, src, srcSize);
1115
+ ZSTD_memcpy(dctx->headerBuffer, src, srcSize);
889
1116
  dctx->expected = ZSTD_SKIPPABLEHEADERSIZE - srcSize; /* remaining to load to get full skippable frame header */
890
1117
  dctx->stage = ZSTDds_decodeSkippableHeader;
891
1118
  return 0;
892
1119
  } }
893
1120
  dctx->headerSize = ZSTD_frameHeaderSize_internal(src, srcSize, dctx->format);
894
1121
  if (ZSTD_isError(dctx->headerSize)) return dctx->headerSize;
895
- memcpy(dctx->headerBuffer, src, srcSize);
1122
+ ZSTD_memcpy(dctx->headerBuffer, src, srcSize);
896
1123
  dctx->expected = dctx->headerSize - srcSize;
897
1124
  dctx->stage = ZSTDds_decodeFrameHeader;
898
1125
  return 0;
899
1126
 
900
1127
  case ZSTDds_decodeFrameHeader:
901
1128
  assert(src != NULL);
902
- memcpy(dctx->headerBuffer + (dctx->headerSize - srcSize), src, srcSize);
903
- FORWARD_IF_ERROR(ZSTD_decodeFrameHeader(dctx, dctx->headerBuffer, dctx->headerSize));
1129
+ ZSTD_memcpy(dctx->headerBuffer + (dctx->headerSize - srcSize), src, srcSize);
1130
+ FORWARD_IF_ERROR(ZSTD_decodeFrameHeader(dctx, dctx->headerBuffer, dctx->headerSize), "");
904
1131
  dctx->expected = ZSTD_blockHeaderSize;
905
1132
  dctx->stage = ZSTDds_decodeBlockHeader;
906
1133
  return 0;
@@ -909,6 +1136,7 @@ size_t ZSTD_decompressContinue(ZSTD_DCtx* dctx, void* dst, size_t dstCapacity, c
909
1136
  { blockProperties_t bp;
910
1137
  size_t const cBlockSize = ZSTD_getcBlockSize(src, ZSTD_blockHeaderSize, &bp);
911
1138
  if (ZSTD_isError(cBlockSize)) return cBlockSize;
1139
+ RETURN_ERROR_IF(cBlockSize > dctx->fParams.blockSizeMax, corruption_detected, "Block Size Exceeds Maximum");
912
1140
  dctx->expected = cBlockSize;
913
1141
  dctx->bType = bp.blockType;
914
1142
  dctx->rleSize = bp.origSize;
@@ -941,49 +1169,66 @@ size_t ZSTD_decompressContinue(ZSTD_DCtx* dctx, void* dst, size_t dstCapacity, c
941
1169
  case bt_compressed:
942
1170
  DEBUGLOG(5, "ZSTD_decompressContinue: case bt_compressed");
943
1171
  rSize = ZSTD_decompressBlock_internal(dctx, dst, dstCapacity, src, srcSize, /* frame */ 1);
1172
+ dctx->expected = 0; /* Streaming not supported */
944
1173
  break;
945
1174
  case bt_raw :
1175
+ assert(srcSize <= dctx->expected);
946
1176
  rSize = ZSTD_copyRawBlock(dst, dstCapacity, src, srcSize);
1177
+ FORWARD_IF_ERROR(rSize, "ZSTD_copyRawBlock failed");
1178
+ assert(rSize == srcSize);
1179
+ dctx->expected -= rSize;
947
1180
  break;
948
1181
  case bt_rle :
949
1182
  rSize = ZSTD_setRleBlock(dst, dstCapacity, *(const BYTE*)src, dctx->rleSize);
1183
+ dctx->expected = 0; /* Streaming not supported */
950
1184
  break;
951
1185
  case bt_reserved : /* should never happen */
952
1186
  default:
953
- RETURN_ERROR(corruption_detected);
1187
+ RETURN_ERROR(corruption_detected, "invalid block type");
954
1188
  }
955
- if (ZSTD_isError(rSize)) return rSize;
1189
+ FORWARD_IF_ERROR(rSize, "");
1190
+ RETURN_ERROR_IF(rSize > dctx->fParams.blockSizeMax, corruption_detected, "Decompressed Block Size Exceeds Maximum");
956
1191
  DEBUGLOG(5, "ZSTD_decompressContinue: decoded size from block : %u", (unsigned)rSize);
957
1192
  dctx->decodedSize += rSize;
958
- if (dctx->fParams.checksumFlag) XXH64_update(&dctx->xxhState, dst, rSize);
1193
+ if (dctx->validateChecksum) XXH64_update(&dctx->xxhState, dst, rSize);
1194
+ dctx->previousDstEnd = (char*)dst + rSize;
1195
+
1196
+ /* Stay on the same stage until we are finished streaming the block. */
1197
+ if (dctx->expected > 0) {
1198
+ return rSize;
1199
+ }
959
1200
 
960
1201
  if (dctx->stage == ZSTDds_decompressLastBlock) { /* end of frame */
961
1202
  DEBUGLOG(4, "ZSTD_decompressContinue: decoded size from frame : %u", (unsigned)dctx->decodedSize);
962
1203
  RETURN_ERROR_IF(
963
1204
  dctx->fParams.frameContentSize != ZSTD_CONTENTSIZE_UNKNOWN
964
1205
  && dctx->decodedSize != dctx->fParams.frameContentSize,
965
- corruption_detected);
1206
+ corruption_detected, "");
966
1207
  if (dctx->fParams.checksumFlag) { /* another round for frame checksum */
967
1208
  dctx->expected = 4;
968
1209
  dctx->stage = ZSTDds_checkChecksum;
969
1210
  } else {
1211
+ ZSTD_DCtx_trace_end(dctx, dctx->decodedSize, dctx->processedCSize, /* streaming */ 1);
970
1212
  dctx->expected = 0; /* ends here */
971
1213
  dctx->stage = ZSTDds_getFrameHeaderSize;
972
1214
  }
973
1215
  } else {
974
1216
  dctx->stage = ZSTDds_decodeBlockHeader;
975
1217
  dctx->expected = ZSTD_blockHeaderSize;
976
- dctx->previousDstEnd = (char*)dst + rSize;
977
1218
  }
978
1219
  return rSize;
979
1220
  }
980
1221
 
981
1222
  case ZSTDds_checkChecksum:
982
1223
  assert(srcSize == 4); /* guaranteed by dctx->expected */
983
- { U32 const h32 = (U32)XXH64_digest(&dctx->xxhState);
984
- U32 const check32 = MEM_readLE32(src);
985
- DEBUGLOG(4, "ZSTD_decompressContinue: checksum : calculated %08X :: %08X read", (unsigned)h32, (unsigned)check32);
986
- RETURN_ERROR_IF(check32 != h32, checksum_wrong);
1224
+ {
1225
+ if (dctx->validateChecksum) {
1226
+ U32 const h32 = (U32)XXH64_digest(&dctx->xxhState);
1227
+ U32 const check32 = MEM_readLE32(src);
1228
+ DEBUGLOG(4, "ZSTD_decompressContinue: checksum : calculated %08X :: %08X read", (unsigned)h32, (unsigned)check32);
1229
+ RETURN_ERROR_IF(check32 != h32, checksum_wrong, "");
1230
+ }
1231
+ ZSTD_DCtx_trace_end(dctx, dctx->decodedSize, dctx->processedCSize, /* streaming */ 1);
987
1232
  dctx->expected = 0;
988
1233
  dctx->stage = ZSTDds_getFrameHeaderSize;
989
1234
  return 0;
@@ -992,7 +1237,7 @@ size_t ZSTD_decompressContinue(ZSTD_DCtx* dctx, void* dst, size_t dstCapacity, c
992
1237
  case ZSTDds_decodeSkippableHeader:
993
1238
  assert(src != NULL);
994
1239
  assert(srcSize <= ZSTD_SKIPPABLEHEADERSIZE);
995
- memcpy(dctx->headerBuffer + (ZSTD_SKIPPABLEHEADERSIZE - srcSize), src, srcSize); /* complete skippable header */
1240
+ ZSTD_memcpy(dctx->headerBuffer + (ZSTD_SKIPPABLEHEADERSIZE - srcSize), src, srcSize); /* complete skippable header */
996
1241
  dctx->expected = MEM_readLE32(dctx->headerBuffer + ZSTD_FRAMEIDSIZE); /* note : dctx->expected can grow seriously large, beyond local buffer size */
997
1242
  dctx->stage = ZSTDds_skipFrame;
998
1243
  return 0;
@@ -1004,7 +1249,7 @@ size_t ZSTD_decompressContinue(ZSTD_DCtx* dctx, void* dst, size_t dstCapacity, c
1004
1249
 
1005
1250
  default:
1006
1251
  assert(0); /* impossible */
1007
- RETURN_ERROR(GENERIC); /* some compiler require default to do something */
1252
+ RETURN_ERROR(GENERIC, "impossible to reach"); /* some compiler require default to do something */
1008
1253
  }
1009
1254
  }
1010
1255
 
@@ -1015,6 +1260,10 @@ static size_t ZSTD_refDictContent(ZSTD_DCtx* dctx, const void* dict, size_t dict
1015
1260
  dctx->virtualStart = (const char*)dict - ((const char*)(dctx->previousDstEnd) - (const char*)(dctx->prefixStart));
1016
1261
  dctx->prefixStart = dict;
1017
1262
  dctx->previousDstEnd = (const char*)dict + dictSize;
1263
+ #ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
1264
+ dctx->dictContentBeginForFuzzing = dctx->prefixStart;
1265
+ dctx->dictContentEndForFuzzing = dctx->previousDstEnd;
1266
+ #endif
1018
1267
  return 0;
1019
1268
  }
1020
1269
 
@@ -1028,7 +1277,7 @@ ZSTD_loadDEntropy(ZSTD_entropyDTables_t* entropy,
1028
1277
  const BYTE* dictPtr = (const BYTE*)dict;
1029
1278
  const BYTE* const dictEnd = dictPtr + dictSize;
1030
1279
 
1031
- RETURN_ERROR_IF(dictSize <= 8, dictionary_corrupted);
1280
+ RETURN_ERROR_IF(dictSize <= 8, dictionary_corrupted, "dict is too small");
1032
1281
  assert(MEM_readLE32(dict) == ZSTD_MAGIC_DICTIONARY); /* dict must be valid */
1033
1282
  dictPtr += 8; /* skip header = magic + dictID */
1034
1283
 
@@ -1044,63 +1293,69 @@ ZSTD_loadDEntropy(ZSTD_entropyDTables_t* entropy,
1044
1293
  workspace, workspaceSize);
1045
1294
  #else
1046
1295
  size_t const hSize = HUF_readDTableX2_wksp(entropy->hufTable,
1047
- dictPtr, dictEnd - dictPtr,
1296
+ dictPtr, (size_t)(dictEnd - dictPtr),
1048
1297
  workspace, workspaceSize);
1049
1298
  #endif
1050
- RETURN_ERROR_IF(HUF_isError(hSize), dictionary_corrupted);
1299
+ RETURN_ERROR_IF(HUF_isError(hSize), dictionary_corrupted, "");
1051
1300
  dictPtr += hSize;
1052
1301
  }
1053
1302
 
1054
1303
  { short offcodeNCount[MaxOff+1];
1055
1304
  unsigned offcodeMaxValue = MaxOff, offcodeLog;
1056
- size_t const offcodeHeaderSize = FSE_readNCount(offcodeNCount, &offcodeMaxValue, &offcodeLog, dictPtr, dictEnd-dictPtr);
1057
- RETURN_ERROR_IF(FSE_isError(offcodeHeaderSize), dictionary_corrupted);
1058
- RETURN_ERROR_IF(offcodeMaxValue > MaxOff, dictionary_corrupted);
1059
- RETURN_ERROR_IF(offcodeLog > OffFSELog, dictionary_corrupted);
1305
+ size_t const offcodeHeaderSize = FSE_readNCount(offcodeNCount, &offcodeMaxValue, &offcodeLog, dictPtr, (size_t)(dictEnd-dictPtr));
1306
+ RETURN_ERROR_IF(FSE_isError(offcodeHeaderSize), dictionary_corrupted, "");
1307
+ RETURN_ERROR_IF(offcodeMaxValue > MaxOff, dictionary_corrupted, "");
1308
+ RETURN_ERROR_IF(offcodeLog > OffFSELog, dictionary_corrupted, "");
1060
1309
  ZSTD_buildFSETable( entropy->OFTable,
1061
1310
  offcodeNCount, offcodeMaxValue,
1062
1311
  OF_base, OF_bits,
1063
- offcodeLog);
1312
+ offcodeLog,
1313
+ entropy->workspace, sizeof(entropy->workspace),
1314
+ /* bmi2 */0);
1064
1315
  dictPtr += offcodeHeaderSize;
1065
1316
  }
1066
1317
 
1067
1318
  { short matchlengthNCount[MaxML+1];
1068
1319
  unsigned matchlengthMaxValue = MaxML, matchlengthLog;
1069
- size_t const matchlengthHeaderSize = FSE_readNCount(matchlengthNCount, &matchlengthMaxValue, &matchlengthLog, dictPtr, dictEnd-dictPtr);
1070
- RETURN_ERROR_IF(FSE_isError(matchlengthHeaderSize), dictionary_corrupted);
1071
- RETURN_ERROR_IF(matchlengthMaxValue > MaxML, dictionary_corrupted);
1072
- RETURN_ERROR_IF(matchlengthLog > MLFSELog, dictionary_corrupted);
1320
+ size_t const matchlengthHeaderSize = FSE_readNCount(matchlengthNCount, &matchlengthMaxValue, &matchlengthLog, dictPtr, (size_t)(dictEnd-dictPtr));
1321
+ RETURN_ERROR_IF(FSE_isError(matchlengthHeaderSize), dictionary_corrupted, "");
1322
+ RETURN_ERROR_IF(matchlengthMaxValue > MaxML, dictionary_corrupted, "");
1323
+ RETURN_ERROR_IF(matchlengthLog > MLFSELog, dictionary_corrupted, "");
1073
1324
  ZSTD_buildFSETable( entropy->MLTable,
1074
1325
  matchlengthNCount, matchlengthMaxValue,
1075
1326
  ML_base, ML_bits,
1076
- matchlengthLog);
1327
+ matchlengthLog,
1328
+ entropy->workspace, sizeof(entropy->workspace),
1329
+ /* bmi2 */ 0);
1077
1330
  dictPtr += matchlengthHeaderSize;
1078
1331
  }
1079
1332
 
1080
1333
  { short litlengthNCount[MaxLL+1];
1081
1334
  unsigned litlengthMaxValue = MaxLL, litlengthLog;
1082
- size_t const litlengthHeaderSize = FSE_readNCount(litlengthNCount, &litlengthMaxValue, &litlengthLog, dictPtr, dictEnd-dictPtr);
1083
- RETURN_ERROR_IF(FSE_isError(litlengthHeaderSize), dictionary_corrupted);
1084
- RETURN_ERROR_IF(litlengthMaxValue > MaxLL, dictionary_corrupted);
1085
- RETURN_ERROR_IF(litlengthLog > LLFSELog, dictionary_corrupted);
1335
+ size_t const litlengthHeaderSize = FSE_readNCount(litlengthNCount, &litlengthMaxValue, &litlengthLog, dictPtr, (size_t)(dictEnd-dictPtr));
1336
+ RETURN_ERROR_IF(FSE_isError(litlengthHeaderSize), dictionary_corrupted, "");
1337
+ RETURN_ERROR_IF(litlengthMaxValue > MaxLL, dictionary_corrupted, "");
1338
+ RETURN_ERROR_IF(litlengthLog > LLFSELog, dictionary_corrupted, "");
1086
1339
  ZSTD_buildFSETable( entropy->LLTable,
1087
1340
  litlengthNCount, litlengthMaxValue,
1088
1341
  LL_base, LL_bits,
1089
- litlengthLog);
1342
+ litlengthLog,
1343
+ entropy->workspace, sizeof(entropy->workspace),
1344
+ /* bmi2 */ 0);
1090
1345
  dictPtr += litlengthHeaderSize;
1091
1346
  }
1092
1347
 
1093
- RETURN_ERROR_IF(dictPtr+12 > dictEnd, dictionary_corrupted);
1348
+ RETURN_ERROR_IF(dictPtr+12 > dictEnd, dictionary_corrupted, "");
1094
1349
  { int i;
1095
1350
  size_t const dictContentSize = (size_t)(dictEnd - (dictPtr+12));
1096
1351
  for (i=0; i<3; i++) {
1097
1352
  U32 const rep = MEM_readLE32(dictPtr); dictPtr += 4;
1098
- RETURN_ERROR_IF(rep==0 || rep >= dictContentSize,
1099
- dictionary_corrupted);
1353
+ RETURN_ERROR_IF(rep==0 || rep > dictContentSize,
1354
+ dictionary_corrupted, "");
1100
1355
  entropy->rep[i] = rep;
1101
1356
  } }
1102
1357
 
1103
- return dictPtr - (const BYTE*)dict;
1358
+ return (size_t)(dictPtr - (const BYTE*)dict);
1104
1359
  }
1105
1360
 
1106
1361
  static size_t ZSTD_decompress_insertDictionary(ZSTD_DCtx* dctx, const void* dict, size_t dictSize)
@@ -1114,7 +1369,7 @@ static size_t ZSTD_decompress_insertDictionary(ZSTD_DCtx* dctx, const void* dict
1114
1369
 
1115
1370
  /* load entropy tables */
1116
1371
  { size_t const eSize = ZSTD_loadDEntropy(&dctx->entropy, dict, dictSize);
1117
- RETURN_ERROR_IF(ZSTD_isError(eSize), dictionary_corrupted);
1372
+ RETURN_ERROR_IF(ZSTD_isError(eSize), dictionary_corrupted, "");
1118
1373
  dict = (const char*)dict + eSize;
1119
1374
  dictSize -= eSize;
1120
1375
  }
@@ -1127,8 +1382,12 @@ static size_t ZSTD_decompress_insertDictionary(ZSTD_DCtx* dctx, const void* dict
1127
1382
  size_t ZSTD_decompressBegin(ZSTD_DCtx* dctx)
1128
1383
  {
1129
1384
  assert(dctx != NULL);
1385
+ #if ZSTD_TRACE
1386
+ dctx->traceCtx = (ZSTD_trace_decompress_begin != NULL) ? ZSTD_trace_decompress_begin(dctx) : 0;
1387
+ #endif
1130
1388
  dctx->expected = ZSTD_startingInputLength(dctx->format); /* dctx->format must be properly set */
1131
1389
  dctx->stage = ZSTDds_getFrameHeaderSize;
1390
+ dctx->processedCSize = 0;
1132
1391
  dctx->decodedSize = 0;
1133
1392
  dctx->previousDstEnd = NULL;
1134
1393
  dctx->prefixStart = NULL;
@@ -1137,8 +1396,9 @@ size_t ZSTD_decompressBegin(ZSTD_DCtx* dctx)
1137
1396
  dctx->entropy.hufTable[0] = (HUF_DTable)((HufLog)*0x1000001); /* cover both little and big endian */
1138
1397
  dctx->litEntropy = dctx->fseEntropy = 0;
1139
1398
  dctx->dictID = 0;
1399
+ dctx->bType = bt_reserved;
1140
1400
  ZSTD_STATIC_ASSERT(sizeof(dctx->entropy.rep) == sizeof(repStartValue));
1141
- memcpy(dctx->entropy.rep, repStartValue, sizeof(repStartValue)); /* initial repcodes */
1401
+ ZSTD_memcpy(dctx->entropy.rep, repStartValue, sizeof(repStartValue)); /* initial repcodes */
1142
1402
  dctx->LLTptr = dctx->entropy.LLTable;
1143
1403
  dctx->MLTptr = dctx->entropy.MLTable;
1144
1404
  dctx->OFTptr = dctx->entropy.OFTable;
@@ -1148,11 +1408,11 @@ size_t ZSTD_decompressBegin(ZSTD_DCtx* dctx)
1148
1408
 
1149
1409
  size_t ZSTD_decompressBegin_usingDict(ZSTD_DCtx* dctx, const void* dict, size_t dictSize)
1150
1410
  {
1151
- FORWARD_IF_ERROR( ZSTD_decompressBegin(dctx) );
1411
+ FORWARD_IF_ERROR( ZSTD_decompressBegin(dctx) , "");
1152
1412
  if (dict && dictSize)
1153
1413
  RETURN_ERROR_IF(
1154
1414
  ZSTD_isError(ZSTD_decompress_insertDictionary(dctx, dict, dictSize)),
1155
- dictionary_corrupted);
1415
+ dictionary_corrupted, "");
1156
1416
  return 0;
1157
1417
  }
1158
1418
 
@@ -1171,7 +1431,7 @@ size_t ZSTD_decompressBegin_usingDDict(ZSTD_DCtx* dctx, const ZSTD_DDict* ddict)
1171
1431
  DEBUGLOG(4, "DDict is %s",
1172
1432
  dctx->ddictIsCold ? "~cold~" : "hot!");
1173
1433
  }
1174
- FORWARD_IF_ERROR( ZSTD_decompressBegin(dctx) );
1434
+ FORWARD_IF_ERROR( ZSTD_decompressBegin(dctx) , "");
1175
1435
  if (ddict) { /* NULL ddict is equivalent to no dictionary */
1176
1436
  ZSTD_copyDDictParameters(dctx, ddict);
1177
1437
  }
@@ -1262,11 +1522,11 @@ size_t ZSTD_DCtx_loadDictionary_advanced(ZSTD_DCtx* dctx,
1262
1522
  ZSTD_dictLoadMethod_e dictLoadMethod,
1263
1523
  ZSTD_dictContentType_e dictContentType)
1264
1524
  {
1265
- RETURN_ERROR_IF(dctx->streamStage != zdss_init, stage_wrong);
1525
+ RETURN_ERROR_IF(dctx->streamStage != zdss_init, stage_wrong, "");
1266
1526
  ZSTD_clearDict(dctx);
1267
- if (dict && dictSize >= 8) {
1527
+ if (dict && dictSize != 0) {
1268
1528
  dctx->ddictLocal = ZSTD_createDDict_advanced(dict, dictSize, dictLoadMethod, dictContentType, dctx->customMem);
1269
- RETURN_ERROR_IF(dctx->ddictLocal == NULL, memory_allocation);
1529
+ RETURN_ERROR_IF(dctx->ddictLocal == NULL, memory_allocation, "NULL pointer!");
1270
1530
  dctx->ddict = dctx->ddictLocal;
1271
1531
  dctx->dictUses = ZSTD_use_indefinitely;
1272
1532
  }
@@ -1285,7 +1545,7 @@ size_t ZSTD_DCtx_loadDictionary(ZSTD_DCtx* dctx, const void* dict, size_t dictSi
1285
1545
 
1286
1546
  size_t ZSTD_DCtx_refPrefix_advanced(ZSTD_DCtx* dctx, const void* prefix, size_t prefixSize, ZSTD_dictContentType_e dictContentType)
1287
1547
  {
1288
- FORWARD_IF_ERROR(ZSTD_DCtx_loadDictionary_advanced(dctx, prefix, prefixSize, ZSTD_dlm_byRef, dictContentType));
1548
+ FORWARD_IF_ERROR(ZSTD_DCtx_loadDictionary_advanced(dctx, prefix, prefixSize, ZSTD_dlm_byRef, dictContentType), "");
1289
1549
  dctx->dictUses = ZSTD_use_once;
1290
1550
  return 0;
1291
1551
  }
@@ -1297,14 +1557,14 @@ size_t ZSTD_DCtx_refPrefix(ZSTD_DCtx* dctx, const void* prefix, size_t prefixSiz
1297
1557
 
1298
1558
 
1299
1559
  /* ZSTD_initDStream_usingDict() :
1300
- * return : expected size, aka ZSTD_FRAMEHEADERSIZE_PREFIX.
1560
+ * return : expected size, aka ZSTD_startingInputLength().
1301
1561
  * this function cannot fail */
1302
1562
  size_t ZSTD_initDStream_usingDict(ZSTD_DStream* zds, const void* dict, size_t dictSize)
1303
1563
  {
1304
1564
  DEBUGLOG(4, "ZSTD_initDStream_usingDict");
1305
- FORWARD_IF_ERROR( ZSTD_DCtx_reset(zds, ZSTD_reset_session_only) );
1306
- FORWARD_IF_ERROR( ZSTD_DCtx_loadDictionary(zds, dict, dictSize) );
1307
- return ZSTD_FRAMEHEADERSIZE_PREFIX;
1565
+ FORWARD_IF_ERROR( ZSTD_DCtx_reset(zds, ZSTD_reset_session_only) , "");
1566
+ FORWARD_IF_ERROR( ZSTD_DCtx_loadDictionary(zds, dict, dictSize) , "");
1567
+ return ZSTD_startingInputLength(zds->format);
1308
1568
  }
1309
1569
 
1310
1570
  /* note : this variant can't fail */
@@ -1319,28 +1579,38 @@ size_t ZSTD_initDStream(ZSTD_DStream* zds)
1319
1579
  * this function cannot fail */
1320
1580
  size_t ZSTD_initDStream_usingDDict(ZSTD_DStream* dctx, const ZSTD_DDict* ddict)
1321
1581
  {
1322
- FORWARD_IF_ERROR( ZSTD_DCtx_reset(dctx, ZSTD_reset_session_only) );
1323
- FORWARD_IF_ERROR( ZSTD_DCtx_refDDict(dctx, ddict) );
1324
- return ZSTD_FRAMEHEADERSIZE_PREFIX;
1582
+ FORWARD_IF_ERROR( ZSTD_DCtx_reset(dctx, ZSTD_reset_session_only) , "");
1583
+ FORWARD_IF_ERROR( ZSTD_DCtx_refDDict(dctx, ddict) , "");
1584
+ return ZSTD_startingInputLength(dctx->format);
1325
1585
  }
1326
1586
 
1327
1587
  /* ZSTD_resetDStream() :
1328
- * return : expected size, aka ZSTD_FRAMEHEADERSIZE_PREFIX.
1588
+ * return : expected size, aka ZSTD_startingInputLength().
1329
1589
  * this function cannot fail */
1330
1590
  size_t ZSTD_resetDStream(ZSTD_DStream* dctx)
1331
1591
  {
1332
- FORWARD_IF_ERROR(ZSTD_DCtx_reset(dctx, ZSTD_reset_session_only));
1333
- return ZSTD_FRAMEHEADERSIZE_PREFIX;
1592
+ FORWARD_IF_ERROR(ZSTD_DCtx_reset(dctx, ZSTD_reset_session_only), "");
1593
+ return ZSTD_startingInputLength(dctx->format);
1334
1594
  }
1335
1595
 
1336
1596
 
1337
1597
  size_t ZSTD_DCtx_refDDict(ZSTD_DCtx* dctx, const ZSTD_DDict* ddict)
1338
1598
  {
1339
- RETURN_ERROR_IF(dctx->streamStage != zdss_init, stage_wrong);
1599
+ RETURN_ERROR_IF(dctx->streamStage != zdss_init, stage_wrong, "");
1340
1600
  ZSTD_clearDict(dctx);
1341
1601
  if (ddict) {
1342
1602
  dctx->ddict = ddict;
1343
1603
  dctx->dictUses = ZSTD_use_indefinitely;
1604
+ if (dctx->refMultipleDDicts == ZSTD_rmd_refMultipleDDicts) {
1605
+ if (dctx->ddictSet == NULL) {
1606
+ dctx->ddictSet = ZSTD_createDDictHashSet(dctx->customMem);
1607
+ if (!dctx->ddictSet) {
1608
+ RETURN_ERROR(memory_allocation, "Failed to allocate memory for hash set!");
1609
+ }
1610
+ }
1611
+ assert(!dctx->staticSize); /* Impossible: ddictSet cannot have been allocated if static dctx */
1612
+ FORWARD_IF_ERROR(ZSTD_DDictHashSet_addDDict(dctx->ddictSet, ddict, dctx->customMem), "");
1613
+ }
1344
1614
  }
1345
1615
  return 0;
1346
1616
  }
@@ -1353,16 +1623,16 @@ size_t ZSTD_DCtx_setMaxWindowSize(ZSTD_DCtx* dctx, size_t maxWindowSize)
1353
1623
  ZSTD_bounds const bounds = ZSTD_dParam_getBounds(ZSTD_d_windowLogMax);
1354
1624
  size_t const min = (size_t)1 << bounds.lowerBound;
1355
1625
  size_t const max = (size_t)1 << bounds.upperBound;
1356
- RETURN_ERROR_IF(dctx->streamStage != zdss_init, stage_wrong);
1357
- RETURN_ERROR_IF(maxWindowSize < min, parameter_outOfBound);
1358
- RETURN_ERROR_IF(maxWindowSize > max, parameter_outOfBound);
1626
+ RETURN_ERROR_IF(dctx->streamStage != zdss_init, stage_wrong, "");
1627
+ RETURN_ERROR_IF(maxWindowSize < min, parameter_outOfBound, "");
1628
+ RETURN_ERROR_IF(maxWindowSize > max, parameter_outOfBound, "");
1359
1629
  dctx->maxWindowSize = maxWindowSize;
1360
1630
  return 0;
1361
1631
  }
1362
1632
 
1363
1633
  size_t ZSTD_DCtx_setFormat(ZSTD_DCtx* dctx, ZSTD_format_e format)
1364
1634
  {
1365
- return ZSTD_DCtx_setParameter(dctx, ZSTD_d_format, format);
1635
+ return ZSTD_DCtx_setParameter(dctx, ZSTD_d_format, (int)format);
1366
1636
  }
1367
1637
 
1368
1638
  ZSTD_bounds ZSTD_dParam_getBounds(ZSTD_dParameter dParam)
@@ -1378,6 +1648,18 @@ ZSTD_bounds ZSTD_dParam_getBounds(ZSTD_dParameter dParam)
1378
1648
  bounds.upperBound = (int)ZSTD_f_zstd1_magicless;
1379
1649
  ZSTD_STATIC_ASSERT(ZSTD_f_zstd1 < ZSTD_f_zstd1_magicless);
1380
1650
  return bounds;
1651
+ case ZSTD_d_stableOutBuffer:
1652
+ bounds.lowerBound = (int)ZSTD_bm_buffered;
1653
+ bounds.upperBound = (int)ZSTD_bm_stable;
1654
+ return bounds;
1655
+ case ZSTD_d_forceIgnoreChecksum:
1656
+ bounds.lowerBound = (int)ZSTD_d_validateChecksum;
1657
+ bounds.upperBound = (int)ZSTD_d_ignoreChecksum;
1658
+ return bounds;
1659
+ case ZSTD_d_refMultipleDDicts:
1660
+ bounds.lowerBound = (int)ZSTD_rmd_refSingleDDict;
1661
+ bounds.upperBound = (int)ZSTD_rmd_refMultipleDDicts;
1662
+ return bounds;
1381
1663
  default:;
1382
1664
  }
1383
1665
  bounds.error = ERROR(parameter_unsupported);
@@ -1397,12 +1679,35 @@ static int ZSTD_dParam_withinBounds(ZSTD_dParameter dParam, int value)
1397
1679
  }
1398
1680
 
1399
1681
  #define CHECK_DBOUNDS(p,v) { \
1400
- RETURN_ERROR_IF(!ZSTD_dParam_withinBounds(p, v), parameter_outOfBound); \
1682
+ RETURN_ERROR_IF(!ZSTD_dParam_withinBounds(p, v), parameter_outOfBound, ""); \
1683
+ }
1684
+
1685
+ size_t ZSTD_DCtx_getParameter(ZSTD_DCtx* dctx, ZSTD_dParameter param, int* value)
1686
+ {
1687
+ switch (param) {
1688
+ case ZSTD_d_windowLogMax:
1689
+ *value = (int)ZSTD_highbit32((U32)dctx->maxWindowSize);
1690
+ return 0;
1691
+ case ZSTD_d_format:
1692
+ *value = (int)dctx->format;
1693
+ return 0;
1694
+ case ZSTD_d_stableOutBuffer:
1695
+ *value = (int)dctx->outBufferMode;
1696
+ return 0;
1697
+ case ZSTD_d_forceIgnoreChecksum:
1698
+ *value = (int)dctx->forceIgnoreChecksum;
1699
+ return 0;
1700
+ case ZSTD_d_refMultipleDDicts:
1701
+ *value = (int)dctx->refMultipleDDicts;
1702
+ return 0;
1703
+ default:;
1704
+ }
1705
+ RETURN_ERROR(parameter_unsupported, "");
1401
1706
  }
1402
1707
 
1403
1708
  size_t ZSTD_DCtx_setParameter(ZSTD_DCtx* dctx, ZSTD_dParameter dParam, int value)
1404
1709
  {
1405
- RETURN_ERROR_IF(dctx->streamStage != zdss_init, stage_wrong);
1710
+ RETURN_ERROR_IF(dctx->streamStage != zdss_init, stage_wrong, "");
1406
1711
  switch(dParam) {
1407
1712
  case ZSTD_d_windowLogMax:
1408
1713
  if (value == 0) value = ZSTD_WINDOWLOG_LIMIT_DEFAULT;
@@ -1413,9 +1718,24 @@ size_t ZSTD_DCtx_setParameter(ZSTD_DCtx* dctx, ZSTD_dParameter dParam, int value
1413
1718
  CHECK_DBOUNDS(ZSTD_d_format, value);
1414
1719
  dctx->format = (ZSTD_format_e)value;
1415
1720
  return 0;
1721
+ case ZSTD_d_stableOutBuffer:
1722
+ CHECK_DBOUNDS(ZSTD_d_stableOutBuffer, value);
1723
+ dctx->outBufferMode = (ZSTD_bufferMode_e)value;
1724
+ return 0;
1725
+ case ZSTD_d_forceIgnoreChecksum:
1726
+ CHECK_DBOUNDS(ZSTD_d_forceIgnoreChecksum, value);
1727
+ dctx->forceIgnoreChecksum = (ZSTD_forceIgnoreChecksum_e)value;
1728
+ return 0;
1729
+ case ZSTD_d_refMultipleDDicts:
1730
+ CHECK_DBOUNDS(ZSTD_d_refMultipleDDicts, value);
1731
+ if (dctx->staticSize != 0) {
1732
+ RETURN_ERROR(parameter_unsupported, "Static dctx does not support multiple DDicts!");
1733
+ }
1734
+ dctx->refMultipleDDicts = (ZSTD_refMultipleDDicts_e)value;
1735
+ return 0;
1416
1736
  default:;
1417
1737
  }
1418
- RETURN_ERROR(parameter_unsupported);
1738
+ RETURN_ERROR(parameter_unsupported, "");
1419
1739
  }
1420
1740
 
1421
1741
  size_t ZSTD_DCtx_reset(ZSTD_DCtx* dctx, ZSTD_ResetDirective reset)
@@ -1427,10 +1747,9 @@ size_t ZSTD_DCtx_reset(ZSTD_DCtx* dctx, ZSTD_ResetDirective reset)
1427
1747
  }
1428
1748
  if ( (reset == ZSTD_reset_parameters)
1429
1749
  || (reset == ZSTD_reset_session_and_parameters) ) {
1430
- RETURN_ERROR_IF(dctx->streamStage != zdss_init, stage_wrong);
1750
+ RETURN_ERROR_IF(dctx->streamStage != zdss_init, stage_wrong, "");
1431
1751
  ZSTD_clearDict(dctx);
1432
- dctx->format = ZSTD_f_zstd1;
1433
- dctx->maxWindowSize = ZSTD_MAXWINDOWSIZE_DEFAULT;
1752
+ ZSTD_DCtx_resetParameters(dctx);
1434
1753
  }
1435
1754
  return 0;
1436
1755
  }
@@ -1448,7 +1767,7 @@ size_t ZSTD_decodingBufferSize_min(unsigned long long windowSize, unsigned long
1448
1767
  unsigned long long const neededSize = MIN(frameContentSize, neededRBSize);
1449
1768
  size_t const minRBSize = (size_t) neededSize;
1450
1769
  RETURN_ERROR_IF((unsigned long long)minRBSize != neededSize,
1451
- frameParameter_windowTooLarge);
1770
+ frameParameter_windowTooLarge, "");
1452
1771
  return minRBSize;
1453
1772
  }
1454
1773
 
@@ -1466,30 +1785,94 @@ size_t ZSTD_estimateDStreamSize_fromFrame(const void* src, size_t srcSize)
1466
1785
  ZSTD_frameHeader zfh;
1467
1786
  size_t const err = ZSTD_getFrameHeader(&zfh, src, srcSize);
1468
1787
  if (ZSTD_isError(err)) return err;
1469
- RETURN_ERROR_IF(err>0, srcSize_wrong);
1788
+ RETURN_ERROR_IF(err>0, srcSize_wrong, "");
1470
1789
  RETURN_ERROR_IF(zfh.windowSize > windowSizeMax,
1471
- frameParameter_windowTooLarge);
1790
+ frameParameter_windowTooLarge, "");
1472
1791
  return ZSTD_estimateDStreamSize((size_t)zfh.windowSize);
1473
1792
  }
1474
1793
 
1475
1794
 
1476
1795
  /* ***** Decompression ***** */
1477
1796
 
1478
- MEM_STATIC size_t ZSTD_limitCopy(void* dst, size_t dstCapacity, const void* src, size_t srcSize)
1797
+ static int ZSTD_DCtx_isOverflow(ZSTD_DStream* zds, size_t const neededInBuffSize, size_t const neededOutBuffSize)
1798
+ {
1799
+ return (zds->inBuffSize + zds->outBuffSize) >= (neededInBuffSize + neededOutBuffSize) * ZSTD_WORKSPACETOOLARGE_FACTOR;
1800
+ }
1801
+
1802
+ static void ZSTD_DCtx_updateOversizedDuration(ZSTD_DStream* zds, size_t const neededInBuffSize, size_t const neededOutBuffSize)
1803
+ {
1804
+ if (ZSTD_DCtx_isOverflow(zds, neededInBuffSize, neededOutBuffSize))
1805
+ zds->oversizedDuration++;
1806
+ else
1807
+ zds->oversizedDuration = 0;
1808
+ }
1809
+
1810
+ static int ZSTD_DCtx_isOversizedTooLong(ZSTD_DStream* zds)
1479
1811
  {
1480
- size_t const length = MIN(dstCapacity, srcSize);
1481
- memcpy(dst, src, length);
1482
- return length;
1812
+ return zds->oversizedDuration >= ZSTD_WORKSPACETOOLARGE_MAXDURATION;
1813
+ }
1814
+
1815
+ /* Checks that the output buffer hasn't changed if ZSTD_obm_stable is used. */
1816
+ static size_t ZSTD_checkOutBuffer(ZSTD_DStream const* zds, ZSTD_outBuffer const* output)
1817
+ {
1818
+ ZSTD_outBuffer const expect = zds->expectedOutBuffer;
1819
+ /* No requirement when ZSTD_obm_stable is not enabled. */
1820
+ if (zds->outBufferMode != ZSTD_bm_stable)
1821
+ return 0;
1822
+ /* Any buffer is allowed in zdss_init, this must be the same for every other call until
1823
+ * the context is reset.
1824
+ */
1825
+ if (zds->streamStage == zdss_init)
1826
+ return 0;
1827
+ /* The buffer must match our expectation exactly. */
1828
+ if (expect.dst == output->dst && expect.pos == output->pos && expect.size == output->size)
1829
+ return 0;
1830
+ RETURN_ERROR(dstBuffer_wrong, "ZSTD_d_stableOutBuffer enabled but output differs!");
1483
1831
  }
1484
1832
 
1833
+ /* Calls ZSTD_decompressContinue() with the right parameters for ZSTD_decompressStream()
1834
+ * and updates the stage and the output buffer state. This call is extracted so it can be
1835
+ * used both when reading directly from the ZSTD_inBuffer, and in buffered input mode.
1836
+ * NOTE: You must break after calling this function since the streamStage is modified.
1837
+ */
1838
+ static size_t ZSTD_decompressContinueStream(
1839
+ ZSTD_DStream* zds, char** op, char* oend,
1840
+ void const* src, size_t srcSize) {
1841
+ int const isSkipFrame = ZSTD_isSkipFrame(zds);
1842
+ if (zds->outBufferMode == ZSTD_bm_buffered) {
1843
+ size_t const dstSize = isSkipFrame ? 0 : zds->outBuffSize - zds->outStart;
1844
+ size_t const decodedSize = ZSTD_decompressContinue(zds,
1845
+ zds->outBuff + zds->outStart, dstSize, src, srcSize);
1846
+ FORWARD_IF_ERROR(decodedSize, "");
1847
+ if (!decodedSize && !isSkipFrame) {
1848
+ zds->streamStage = zdss_read;
1849
+ } else {
1850
+ zds->outEnd = zds->outStart + decodedSize;
1851
+ zds->streamStage = zdss_flush;
1852
+ }
1853
+ } else {
1854
+ /* Write directly into the output buffer */
1855
+ size_t const dstSize = isSkipFrame ? 0 : (size_t)(oend - *op);
1856
+ size_t const decodedSize = ZSTD_decompressContinue(zds, *op, dstSize, src, srcSize);
1857
+ FORWARD_IF_ERROR(decodedSize, "");
1858
+ *op += decodedSize;
1859
+ /* Flushing is not needed. */
1860
+ zds->streamStage = zdss_read;
1861
+ assert(*op <= oend);
1862
+ assert(zds->outBufferMode == ZSTD_bm_stable);
1863
+ }
1864
+ return 0;
1865
+ }
1485
1866
 
1486
1867
  size_t ZSTD_decompressStream(ZSTD_DStream* zds, ZSTD_outBuffer* output, ZSTD_inBuffer* input)
1487
1868
  {
1488
- const char* const istart = (const char*)(input->src) + input->pos;
1489
- const char* const iend = (const char*)(input->src) + input->size;
1869
+ const char* const src = (const char*)input->src;
1870
+ const char* const istart = input->pos != 0 ? src + input->pos : src;
1871
+ const char* const iend = input->size != 0 ? src + input->size : src;
1490
1872
  const char* ip = istart;
1491
- char* const ostart = (char*)(output->dst) + output->pos;
1492
- char* const oend = (char*)(output->dst) + output->size;
1873
+ char* const dst = (char*)output->dst;
1874
+ char* const ostart = output->pos != 0 ? dst + output->pos : dst;
1875
+ char* const oend = output->size != 0 ? dst + output->size : dst;
1493
1876
  char* op = ostart;
1494
1877
  U32 someMoreWork = 1;
1495
1878
 
@@ -1505,6 +1888,7 @@ size_t ZSTD_decompressStream(ZSTD_DStream* zds, ZSTD_outBuffer* output, ZSTD_inB
1505
1888
  "forbidden. out: pos: %u vs size: %u",
1506
1889
  (U32)output->pos, (U32)output->size);
1507
1890
  DEBUGLOG(5, "input size : %u", (U32)(input->size - input->pos));
1891
+ FORWARD_IF_ERROR(ZSTD_checkOutBuffer(zds, output), "");
1508
1892
 
1509
1893
  while (someMoreWork) {
1510
1894
  switch(zds->streamStage)
@@ -1515,6 +1899,7 @@ size_t ZSTD_decompressStream(ZSTD_DStream* zds, ZSTD_outBuffer* output, ZSTD_inB
1515
1899
  zds->lhSize = zds->inPos = zds->outStart = zds->outEnd = 0;
1516
1900
  zds->legacyVersion = 0;
1517
1901
  zds->hostageByte = 0;
1902
+ zds->expectedOutBuffer = *output;
1518
1903
  /* fall-through */
1519
1904
 
1520
1905
  case zdss_loadHeader :
@@ -1529,6 +1914,9 @@ size_t ZSTD_decompressStream(ZSTD_DStream* zds, ZSTD_outBuffer* output, ZSTD_inB
1529
1914
  } }
1530
1915
  #endif
1531
1916
  { size_t const hSize = ZSTD_getFrameHeader_advanced(&zds->fParams, zds->headerBuffer, zds->lhSize, zds->format);
1917
+ if (zds->refMultipleDDicts && zds->ddictSet) {
1918
+ ZSTD_DCtx_selectFrameDDict(zds);
1919
+ }
1532
1920
  DEBUGLOG(5, "header size : %u", (U32)hSize);
1533
1921
  if (ZSTD_isError(hSize)) {
1534
1922
  #if defined(ZSTD_LEGACY_SUPPORT) && (ZSTD_LEGACY_SUPPORT>=1)
@@ -1542,7 +1930,7 @@ size_t ZSTD_decompressStream(ZSTD_DStream* zds, ZSTD_outBuffer* output, ZSTD_inB
1542
1930
  "legacy support is incompatible with static dctx");
1543
1931
  FORWARD_IF_ERROR(ZSTD_initLegacyStream(&zds->legacyContext,
1544
1932
  zds->previousLegacyVersion, legacyVersion,
1545
- dict, dictSize));
1933
+ dict, dictSize), "");
1546
1934
  zds->legacyVersion = zds->previousLegacyVersion = legacyVersion;
1547
1935
  { size_t const hint = ZSTD_decompressLegacyStream(zds->legacyContext, legacyVersion, output, input);
1548
1936
  if (hint==0) zds->streamStage = zdss_init; /* or stay in stage zdss_loadHeader */
@@ -1557,24 +1945,25 @@ size_t ZSTD_decompressStream(ZSTD_DStream* zds, ZSTD_outBuffer* output, ZSTD_inB
1557
1945
  assert(iend >= ip);
1558
1946
  if (toLoad > remainingInput) { /* not enough input to load full header */
1559
1947
  if (remainingInput > 0) {
1560
- memcpy(zds->headerBuffer + zds->lhSize, ip, remainingInput);
1948
+ ZSTD_memcpy(zds->headerBuffer + zds->lhSize, ip, remainingInput);
1561
1949
  zds->lhSize += remainingInput;
1562
1950
  }
1563
1951
  input->pos = input->size;
1564
- return (MAX(ZSTD_FRAMEHEADERSIZE_MIN, hSize) - zds->lhSize) + ZSTD_blockHeaderSize; /* remaining header bytes + next block header */
1952
+ return (MAX((size_t)ZSTD_FRAMEHEADERSIZE_MIN(zds->format), hSize) - zds->lhSize) + ZSTD_blockHeaderSize; /* remaining header bytes + next block header */
1565
1953
  }
1566
1954
  assert(ip != NULL);
1567
- memcpy(zds->headerBuffer + zds->lhSize, ip, toLoad); zds->lhSize = hSize; ip += toLoad;
1955
+ ZSTD_memcpy(zds->headerBuffer + zds->lhSize, ip, toLoad); zds->lhSize = hSize; ip += toLoad;
1568
1956
  break;
1569
1957
  } }
1570
1958
 
1571
1959
  /* check for single-pass mode opportunity */
1572
- if (zds->fParams.frameContentSize && zds->fParams.windowSize /* skippable frame if == 0 */
1960
+ if (zds->fParams.frameContentSize != ZSTD_CONTENTSIZE_UNKNOWN
1961
+ && zds->fParams.frameType != ZSTD_skippableFrame
1573
1962
  && (U64)(size_t)(oend-op) >= zds->fParams.frameContentSize) {
1574
- size_t const cSize = ZSTD_findFrameCompressedSize(istart, iend-istart);
1963
+ size_t const cSize = ZSTD_findFrameCompressedSize(istart, (size_t)(iend-istart));
1575
1964
  if (cSize <= (size_t)(iend-istart)) {
1576
1965
  /* shortcut : using single-pass mode */
1577
- size_t const decompressedSize = ZSTD_decompress_usingDDict(zds, op, oend-op, istart, cSize, ZSTD_getDDict(zds));
1966
+ size_t const decompressedSize = ZSTD_decompress_usingDDict(zds, op, (size_t)(oend-op), istart, cSize, ZSTD_getDDict(zds));
1578
1967
  if (ZSTD_isError(decompressedSize)) return decompressedSize;
1579
1968
  DEBUGLOG(4, "shortcut to single-pass ZSTD_decompress_usingDDict()")
1580
1969
  ip = istart + cSize;
@@ -1585,15 +1974,23 @@ size_t ZSTD_decompressStream(ZSTD_DStream* zds, ZSTD_outBuffer* output, ZSTD_inB
1585
1974
  break;
1586
1975
  } }
1587
1976
 
1977
+ /* Check output buffer is large enough for ZSTD_odm_stable. */
1978
+ if (zds->outBufferMode == ZSTD_bm_stable
1979
+ && zds->fParams.frameType != ZSTD_skippableFrame
1980
+ && zds->fParams.frameContentSize != ZSTD_CONTENTSIZE_UNKNOWN
1981
+ && (U64)(size_t)(oend-op) < zds->fParams.frameContentSize) {
1982
+ RETURN_ERROR(dstSize_tooSmall, "ZSTD_obm_stable passed but ZSTD_outBuffer is too small");
1983
+ }
1984
+
1588
1985
  /* Consume header (see ZSTDds_decodeFrameHeader) */
1589
1986
  DEBUGLOG(4, "Consume header");
1590
- FORWARD_IF_ERROR(ZSTD_decompressBegin_usingDDict(zds, ZSTD_getDDict(zds)));
1987
+ FORWARD_IF_ERROR(ZSTD_decompressBegin_usingDDict(zds, ZSTD_getDDict(zds)), "");
1591
1988
 
1592
1989
  if ((MEM_readLE32(zds->headerBuffer) & ZSTD_MAGIC_SKIPPABLE_MASK) == ZSTD_MAGIC_SKIPPABLE_START) { /* skippable frame */
1593
1990
  zds->expected = MEM_readLE32(zds->headerBuffer + ZSTD_FRAMEIDSIZE);
1594
1991
  zds->stage = ZSTDds_skipFrame;
1595
1992
  } else {
1596
- FORWARD_IF_ERROR(ZSTD_decodeFrameHeader(zds, zds->headerBuffer, zds->lhSize));
1993
+ FORWARD_IF_ERROR(ZSTD_decodeFrameHeader(zds, zds->headerBuffer, zds->lhSize), "");
1597
1994
  zds->expected = ZSTD_blockHeaderSize;
1598
1995
  zds->stage = ZSTDds_decodeBlockHeader;
1599
1996
  }
@@ -1604,40 +2001,48 @@ size_t ZSTD_decompressStream(ZSTD_DStream* zds, ZSTD_outBuffer* output, ZSTD_inB
1604
2001
  (U32)(zds->maxWindowSize >> 10) );
1605
2002
  zds->fParams.windowSize = MAX(zds->fParams.windowSize, 1U << ZSTD_WINDOWLOG_ABSOLUTEMIN);
1606
2003
  RETURN_ERROR_IF(zds->fParams.windowSize > zds->maxWindowSize,
1607
- frameParameter_windowTooLarge);
2004
+ frameParameter_windowTooLarge, "");
1608
2005
 
1609
2006
  /* Adapt buffer sizes to frame header instructions */
1610
2007
  { size_t const neededInBuffSize = MAX(zds->fParams.blockSizeMax, 4 /* frame checksum */);
1611
- size_t const neededOutBuffSize = ZSTD_decodingBufferSize_min(zds->fParams.windowSize, zds->fParams.frameContentSize);
1612
- if ((zds->inBuffSize < neededInBuffSize) || (zds->outBuffSize < neededOutBuffSize)) {
1613
- size_t const bufferSize = neededInBuffSize + neededOutBuffSize;
1614
- DEBUGLOG(4, "inBuff : from %u to %u",
1615
- (U32)zds->inBuffSize, (U32)neededInBuffSize);
1616
- DEBUGLOG(4, "outBuff : from %u to %u",
1617
- (U32)zds->outBuffSize, (U32)neededOutBuffSize);
1618
- if (zds->staticSize) { /* static DCtx */
1619
- DEBUGLOG(4, "staticSize : %u", (U32)zds->staticSize);
1620
- assert(zds->staticSize >= sizeof(ZSTD_DCtx)); /* controlled at init */
1621
- RETURN_ERROR_IF(
1622
- bufferSize > zds->staticSize - sizeof(ZSTD_DCtx),
1623
- memory_allocation);
1624
- } else {
1625
- ZSTD_free(zds->inBuff, zds->customMem);
1626
- zds->inBuffSize = 0;
1627
- zds->outBuffSize = 0;
1628
- zds->inBuff = (char*)ZSTD_malloc(bufferSize, zds->customMem);
1629
- RETURN_ERROR_IF(zds->inBuff == NULL, memory_allocation);
1630
- }
1631
- zds->inBuffSize = neededInBuffSize;
1632
- zds->outBuff = zds->inBuff + zds->inBuffSize;
1633
- zds->outBuffSize = neededOutBuffSize;
1634
- } }
2008
+ size_t const neededOutBuffSize = zds->outBufferMode == ZSTD_bm_buffered
2009
+ ? ZSTD_decodingBufferSize_min(zds->fParams.windowSize, zds->fParams.frameContentSize)
2010
+ : 0;
2011
+
2012
+ ZSTD_DCtx_updateOversizedDuration(zds, neededInBuffSize, neededOutBuffSize);
2013
+
2014
+ { int const tooSmall = (zds->inBuffSize < neededInBuffSize) || (zds->outBuffSize < neededOutBuffSize);
2015
+ int const tooLarge = ZSTD_DCtx_isOversizedTooLong(zds);
2016
+
2017
+ if (tooSmall || tooLarge) {
2018
+ size_t const bufferSize = neededInBuffSize + neededOutBuffSize;
2019
+ DEBUGLOG(4, "inBuff : from %u to %u",
2020
+ (U32)zds->inBuffSize, (U32)neededInBuffSize);
2021
+ DEBUGLOG(4, "outBuff : from %u to %u",
2022
+ (U32)zds->outBuffSize, (U32)neededOutBuffSize);
2023
+ if (zds->staticSize) { /* static DCtx */
2024
+ DEBUGLOG(4, "staticSize : %u", (U32)zds->staticSize);
2025
+ assert(zds->staticSize >= sizeof(ZSTD_DCtx)); /* controlled at init */
2026
+ RETURN_ERROR_IF(
2027
+ bufferSize > zds->staticSize - sizeof(ZSTD_DCtx),
2028
+ memory_allocation, "");
2029
+ } else {
2030
+ ZSTD_customFree(zds->inBuff, zds->customMem);
2031
+ zds->inBuffSize = 0;
2032
+ zds->outBuffSize = 0;
2033
+ zds->inBuff = (char*)ZSTD_customMalloc(bufferSize, zds->customMem);
2034
+ RETURN_ERROR_IF(zds->inBuff == NULL, memory_allocation, "");
2035
+ }
2036
+ zds->inBuffSize = neededInBuffSize;
2037
+ zds->outBuff = zds->inBuff + zds->inBuffSize;
2038
+ zds->outBuffSize = neededOutBuffSize;
2039
+ } } }
1635
2040
  zds->streamStage = zdss_read;
1636
2041
  /* fall-through */
1637
2042
 
1638
2043
  case zdss_read:
1639
2044
  DEBUGLOG(5, "stage zdss_read");
1640
- { size_t const neededInSize = ZSTD_nextSrcSizeToDecompress(zds);
2045
+ { size_t const neededInSize = ZSTD_nextSrcSizeToDecompressWithInputSize(zds, (size_t)(iend - ip));
1641
2046
  DEBUGLOG(5, "neededInSize = %u", (U32)neededInSize);
1642
2047
  if (neededInSize==0) { /* end of frame */
1643
2048
  zds->streamStage = zdss_init;
@@ -1645,15 +2050,9 @@ size_t ZSTD_decompressStream(ZSTD_DStream* zds, ZSTD_outBuffer* output, ZSTD_inB
1645
2050
  break;
1646
2051
  }
1647
2052
  if ((size_t)(iend-ip) >= neededInSize) { /* decode directly from src */
1648
- int const isSkipFrame = ZSTD_isSkipFrame(zds);
1649
- size_t const decodedSize = ZSTD_decompressContinue(zds,
1650
- zds->outBuff + zds->outStart, (isSkipFrame ? 0 : zds->outBuffSize - zds->outStart),
1651
- ip, neededInSize);
1652
- if (ZSTD_isError(decodedSize)) return decodedSize;
2053
+ FORWARD_IF_ERROR(ZSTD_decompressContinueStream(zds, &op, oend, ip, neededInSize), "");
1653
2054
  ip += neededInSize;
1654
- if (!decodedSize && !isSkipFrame) break; /* this was just a header */
1655
- zds->outEnd = zds->outStart + decodedSize;
1656
- zds->streamStage = zdss_flush;
2055
+ /* Function modifies the stage so we must break */
1657
2056
  break;
1658
2057
  } }
1659
2058
  if (ip==iend) { someMoreWork = 0; break; } /* no more input */
@@ -1665,33 +2064,29 @@ size_t ZSTD_decompressStream(ZSTD_DStream* zds, ZSTD_outBuffer* output, ZSTD_inB
1665
2064
  size_t const toLoad = neededInSize - zds->inPos;
1666
2065
  int const isSkipFrame = ZSTD_isSkipFrame(zds);
1667
2066
  size_t loadedSize;
2067
+ /* At this point we shouldn't be decompressing a block that we can stream. */
2068
+ assert(neededInSize == ZSTD_nextSrcSizeToDecompressWithInputSize(zds, iend - ip));
1668
2069
  if (isSkipFrame) {
1669
2070
  loadedSize = MIN(toLoad, (size_t)(iend-ip));
1670
2071
  } else {
1671
2072
  RETURN_ERROR_IF(toLoad > zds->inBuffSize - zds->inPos,
1672
2073
  corruption_detected,
1673
2074
  "should never happen");
1674
- loadedSize = ZSTD_limitCopy(zds->inBuff + zds->inPos, toLoad, ip, iend-ip);
2075
+ loadedSize = ZSTD_limitCopy(zds->inBuff + zds->inPos, toLoad, ip, (size_t)(iend-ip));
1675
2076
  }
1676
2077
  ip += loadedSize;
1677
2078
  zds->inPos += loadedSize;
1678
2079
  if (loadedSize < toLoad) { someMoreWork = 0; break; } /* not enough input, wait for more */
1679
2080
 
1680
2081
  /* decode loaded input */
1681
- { size_t const decodedSize = ZSTD_decompressContinue(zds,
1682
- zds->outBuff + zds->outStart, zds->outBuffSize - zds->outStart,
1683
- zds->inBuff, neededInSize);
1684
- if (ZSTD_isError(decodedSize)) return decodedSize;
1685
- zds->inPos = 0; /* input is consumed */
1686
- if (!decodedSize && !isSkipFrame) { zds->streamStage = zdss_read; break; } /* this was just a header */
1687
- zds->outEnd = zds->outStart + decodedSize;
1688
- } }
1689
- zds->streamStage = zdss_flush;
1690
- /* fall-through */
1691
-
2082
+ zds->inPos = 0; /* input is consumed */
2083
+ FORWARD_IF_ERROR(ZSTD_decompressContinueStream(zds, &op, oend, zds->inBuff, neededInSize), "");
2084
+ /* Function modifies the stage so we must break */
2085
+ break;
2086
+ }
1692
2087
  case zdss_flush:
1693
2088
  { size_t const toFlushSize = zds->outEnd - zds->outStart;
1694
- size_t const flushedSize = ZSTD_limitCopy(op, oend-op, zds->outBuff + zds->outStart, toFlushSize);
2089
+ size_t const flushedSize = ZSTD_limitCopy(op, (size_t)(oend-op), zds->outBuff + zds->outStart, toFlushSize);
1695
2090
  op += flushedSize;
1696
2091
  zds->outStart += flushedSize;
1697
2092
  if (flushedSize == toFlushSize) { /* flush completed */
@@ -1711,17 +2106,21 @@ size_t ZSTD_decompressStream(ZSTD_DStream* zds, ZSTD_outBuffer* output, ZSTD_inB
1711
2106
 
1712
2107
  default:
1713
2108
  assert(0); /* impossible */
1714
- RETURN_ERROR(GENERIC); /* some compiler require default to do something */
2109
+ RETURN_ERROR(GENERIC, "impossible to reach"); /* some compiler require default to do something */
1715
2110
  } }
1716
2111
 
1717
2112
  /* result */
1718
2113
  input->pos = (size_t)(ip - (const char*)(input->src));
1719
2114
  output->pos = (size_t)(op - (char*)(output->dst));
2115
+
2116
+ /* Update the expected output buffer for ZSTD_obm_stable. */
2117
+ zds->expectedOutBuffer = *output;
2118
+
1720
2119
  if ((ip==istart) && (op==ostart)) { /* no forward progress */
1721
2120
  zds->noForwardProgress ++;
1722
2121
  if (zds->noForwardProgress >= ZSTD_NO_FORWARD_PROGRESS_MAX) {
1723
- RETURN_ERROR_IF(op==oend, dstSize_tooSmall);
1724
- RETURN_ERROR_IF(ip==iend, srcSize_wrong);
2122
+ RETURN_ERROR_IF(op==oend, dstSize_tooSmall, "");
2123
+ RETURN_ERROR_IF(ip==iend, srcSize_wrong, "");
1725
2124
  assert(0);
1726
2125
  }
1727
2126
  } else {