zstdlib 0.3.0-x64-mingw32 → 0.8.0-x64-mingw32

Sign up to get free protection for your applications and to get access to all the features.
Files changed (88) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGES.md +30 -1
  3. data/README.md +2 -2
  4. data/Rakefile +1 -1
  5. data/ext/zstdlib/extconf.rb +3 -3
  6. data/ext/zstdlib/ruby/zlib-2.7/zstdlib.c +4895 -0
  7. data/ext/zstdlib/ruby/zlib-3.0/zstdlib.c +4994 -0
  8. data/ext/zstdlib/{zstd-1.4.2 → zstd-1.5.0}/lib/common/bitstream.h +59 -51
  9. data/ext/zstdlib/zstd-1.5.0/lib/common/compiler.h +289 -0
  10. data/ext/zstdlib/{zstd-1.4.2 → zstd-1.5.0}/lib/common/cpu.h +1 -3
  11. data/ext/zstdlib/zstd-1.5.0/lib/common/debug.c +24 -0
  12. data/ext/zstdlib/{zstd-1.4.2 → zstd-1.5.0}/lib/common/debug.h +22 -49
  13. data/ext/zstdlib/zstd-1.5.0/lib/common/entropy_common.c +362 -0
  14. data/ext/zstdlib/{zstd-1.4.2 → zstd-1.5.0}/lib/common/error_private.c +3 -1
  15. data/ext/zstdlib/{zstd-1.4.2 → zstd-1.5.0}/lib/common/error_private.h +8 -4
  16. data/ext/zstdlib/{zstd-1.4.2 → zstd-1.5.0}/lib/common/fse.h +50 -42
  17. data/ext/zstdlib/{zstd-1.4.2 → zstd-1.5.0}/lib/common/fse_decompress.c +149 -55
  18. data/ext/zstdlib/{zstd-1.4.2 → zstd-1.5.0}/lib/common/huf.h +43 -39
  19. data/ext/zstdlib/{zstd-1.4.2 → zstd-1.5.0}/lib/common/mem.h +69 -25
  20. data/ext/zstdlib/{zstd-1.4.2 → zstd-1.5.0}/lib/common/pool.c +30 -20
  21. data/ext/zstdlib/{zstd-1.4.2 → zstd-1.5.0}/lib/common/pool.h +3 -3
  22. data/ext/zstdlib/{zstd-1.4.2 → zstd-1.5.0}/lib/common/threading.c +51 -4
  23. data/ext/zstdlib/{zstd-1.4.2 → zstd-1.5.0}/lib/common/threading.h +36 -4
  24. data/ext/zstdlib/{zstd-1.4.2 → zstd-1.5.0}/lib/common/xxhash.c +40 -92
  25. data/ext/zstdlib/{zstd-1.4.2 → zstd-1.5.0}/lib/common/xxhash.h +12 -32
  26. data/ext/zstdlib/{zstd-1.4.2 → zstd-1.5.0}/lib/common/zstd_common.c +10 -10
  27. data/ext/zstdlib/zstd-1.5.0/lib/common/zstd_deps.h +111 -0
  28. data/ext/zstdlib/zstd-1.5.0/lib/common/zstd_internal.h +490 -0
  29. data/ext/zstdlib/zstd-1.5.0/lib/common/zstd_trace.h +154 -0
  30. data/ext/zstdlib/{zstd-1.4.2 → zstd-1.5.0}/lib/compress/fse_compress.c +47 -63
  31. data/ext/zstdlib/{zstd-1.4.2 → zstd-1.5.0}/lib/compress/hist.c +41 -63
  32. data/ext/zstdlib/{zstd-1.4.2 → zstd-1.5.0}/lib/compress/hist.h +13 -33
  33. data/ext/zstdlib/{zstd-1.4.2 → zstd-1.5.0}/lib/compress/huf_compress.c +332 -193
  34. data/ext/zstdlib/zstd-1.5.0/lib/compress/zstd_compress.c +6393 -0
  35. data/ext/zstdlib/{zstd-1.4.2 → zstd-1.5.0}/lib/compress/zstd_compress_internal.h +522 -86
  36. data/ext/zstdlib/{zstd-1.4.2 → zstd-1.5.0}/lib/compress/zstd_compress_literals.c +25 -16
  37. data/ext/zstdlib/{zstd-1.4.2 → zstd-1.5.0}/lib/compress/zstd_compress_literals.h +2 -2
  38. data/ext/zstdlib/{zstd-1.4.2 → zstd-1.5.0}/lib/compress/zstd_compress_sequences.c +50 -24
  39. data/ext/zstdlib/{zstd-1.4.2 → zstd-1.5.0}/lib/compress/zstd_compress_sequences.h +11 -4
  40. data/ext/zstdlib/zstd-1.5.0/lib/compress/zstd_compress_superblock.c +572 -0
  41. data/ext/zstdlib/zstd-1.5.0/lib/compress/zstd_compress_superblock.h +32 -0
  42. data/ext/zstdlib/zstd-1.5.0/lib/compress/zstd_cwksp.h +662 -0
  43. data/ext/zstdlib/{zstd-1.4.2 → zstd-1.5.0}/lib/compress/zstd_double_fast.c +43 -41
  44. data/ext/zstdlib/{zstd-1.4.2 → zstd-1.5.0}/lib/compress/zstd_double_fast.h +2 -2
  45. data/ext/zstdlib/{zstd-1.4.2 → zstd-1.5.0}/lib/compress/zstd_fast.c +85 -80
  46. data/ext/zstdlib/{zstd-1.4.2 → zstd-1.5.0}/lib/compress/zstd_fast.h +2 -2
  47. data/ext/zstdlib/zstd-1.5.0/lib/compress/zstd_lazy.c +2184 -0
  48. data/ext/zstdlib/zstd-1.5.0/lib/compress/zstd_lazy.h +125 -0
  49. data/ext/zstdlib/{zstd-1.4.2 → zstd-1.5.0}/lib/compress/zstd_ldm.c +333 -208
  50. data/ext/zstdlib/{zstd-1.4.2 → zstd-1.5.0}/lib/compress/zstd_ldm.h +15 -3
  51. data/ext/zstdlib/zstd-1.5.0/lib/compress/zstd_ldm_geartab.h +103 -0
  52. data/ext/zstdlib/{zstd-1.4.2 → zstd-1.5.0}/lib/compress/zstd_opt.c +228 -129
  53. data/ext/zstdlib/{zstd-1.4.2 → zstd-1.5.0}/lib/compress/zstd_opt.h +1 -1
  54. data/ext/zstdlib/{zstd-1.4.2 → zstd-1.5.0}/lib/compress/zstdmt_compress.c +151 -440
  55. data/ext/zstdlib/zstd-1.5.0/lib/compress/zstdmt_compress.h +110 -0
  56. data/ext/zstdlib/{zstd-1.4.2 → zstd-1.5.0}/lib/decompress/huf_decompress.c +395 -276
  57. data/ext/zstdlib/{zstd-1.4.2 → zstd-1.5.0}/lib/decompress/zstd_ddict.c +20 -16
  58. data/ext/zstdlib/{zstd-1.4.2 → zstd-1.5.0}/lib/decompress/zstd_ddict.h +3 -3
  59. data/ext/zstdlib/{zstd-1.4.2 → zstd-1.5.0}/lib/decompress/zstd_decompress.c +628 -231
  60. data/ext/zstdlib/{zstd-1.4.2 → zstd-1.5.0}/lib/decompress/zstd_decompress_block.c +606 -380
  61. data/ext/zstdlib/{zstd-1.4.2 → zstd-1.5.0}/lib/decompress/zstd_decompress_block.h +8 -5
  62. data/ext/zstdlib/{zstd-1.4.2 → zstd-1.5.0}/lib/decompress/zstd_decompress_internal.h +39 -9
  63. data/ext/zstdlib/zstd-1.5.0/lib/zdict.h +452 -0
  64. data/ext/zstdlib/{zstd-1.4.2 → zstd-1.5.0}/lib/zstd.h +740 -153
  65. data/ext/zstdlib/{zstd-1.4.2/lib/common → zstd-1.5.0/lib}/zstd_errors.h +3 -1
  66. data/ext/zstdlib/{zstd-1.4.2 → zstd-1.5.0}/zlibWrapper/gzclose.c +1 -1
  67. data/ext/zstdlib/{zstd-1.4.2 → zstd-1.5.0}/zlibWrapper/gzcompatibility.h +1 -1
  68. data/ext/zstdlib/{zstd-1.4.2 → zstd-1.5.0}/zlibWrapper/gzguts.h +0 -0
  69. data/ext/zstdlib/{zstd-1.4.2 → zstd-1.5.0}/zlibWrapper/gzlib.c +9 -9
  70. data/ext/zstdlib/{zstd-1.4.2 → zstd-1.5.0}/zlibWrapper/gzread.c +16 -8
  71. data/ext/zstdlib/{zstd-1.4.2 → zstd-1.5.0}/zlibWrapper/gzwrite.c +8 -8
  72. data/ext/zstdlib/{zstd-1.4.2 → zstd-1.5.0}/zlibWrapper/zstd_zlibwrapper.c +131 -45
  73. data/ext/zstdlib/{zstd-1.4.2 → zstd-1.5.0}/zlibWrapper/zstd_zlibwrapper.h +1 -1
  74. data/lib/2.2/zstdlib.so +0 -0
  75. data/lib/2.3/zstdlib.so +0 -0
  76. data/lib/2.4/zstdlib.so +0 -0
  77. data/lib/2.5/zstdlib.so +0 -0
  78. data/lib/2.6/zstdlib.so +0 -0
  79. data/lib/2.7/zstdlib.so +0 -0
  80. metadata +76 -67
  81. data/ext/zstdlib/zstd-1.4.2/lib/common/compiler.h +0 -147
  82. data/ext/zstdlib/zstd-1.4.2/lib/common/debug.c +0 -44
  83. data/ext/zstdlib/zstd-1.4.2/lib/common/entropy_common.c +0 -236
  84. data/ext/zstdlib/zstd-1.4.2/lib/common/zstd_internal.h +0 -371
  85. data/ext/zstdlib/zstd-1.4.2/lib/compress/zstd_compress.c +0 -3904
  86. data/ext/zstdlib/zstd-1.4.2/lib/compress/zstd_lazy.c +0 -1111
  87. data/ext/zstdlib/zstd-1.4.2/lib/compress/zstd_lazy.h +0 -67
  88. data/ext/zstdlib/zstd-1.4.2/lib/compress/zstdmt_compress.h +0 -192
@@ -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;
@@ -942,50 +1169,66 @@ size_t ZSTD_decompressContinue(ZSTD_DCtx* dctx, void* dst, size_t dstCapacity, c
942
1169
  case bt_compressed:
943
1170
  DEBUGLOG(5, "ZSTD_decompressContinue: case bt_compressed");
944
1171
  rSize = ZSTD_decompressBlock_internal(dctx, dst, dstCapacity, src, srcSize, /* frame */ 1);
1172
+ dctx->expected = 0; /* Streaming not supported */
945
1173
  break;
946
1174
  case bt_raw :
1175
+ assert(srcSize <= dctx->expected);
947
1176
  rSize = ZSTD_copyRawBlock(dst, dstCapacity, src, srcSize);
1177
+ FORWARD_IF_ERROR(rSize, "ZSTD_copyRawBlock failed");
1178
+ assert(rSize == srcSize);
1179
+ dctx->expected -= rSize;
948
1180
  break;
949
1181
  case bt_rle :
950
1182
  rSize = ZSTD_setRleBlock(dst, dstCapacity, *(const BYTE*)src, dctx->rleSize);
1183
+ dctx->expected = 0; /* Streaming not supported */
951
1184
  break;
952
1185
  case bt_reserved : /* should never happen */
953
1186
  default:
954
- RETURN_ERROR(corruption_detected);
1187
+ RETURN_ERROR(corruption_detected, "invalid block type");
955
1188
  }
956
- if (ZSTD_isError(rSize)) return rSize;
1189
+ FORWARD_IF_ERROR(rSize, "");
957
1190
  RETURN_ERROR_IF(rSize > dctx->fParams.blockSizeMax, corruption_detected, "Decompressed Block Size Exceeds Maximum");
958
1191
  DEBUGLOG(5, "ZSTD_decompressContinue: decoded size from block : %u", (unsigned)rSize);
959
1192
  dctx->decodedSize += rSize;
960
- 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
+ }
961
1200
 
962
1201
  if (dctx->stage == ZSTDds_decompressLastBlock) { /* end of frame */
963
1202
  DEBUGLOG(4, "ZSTD_decompressContinue: decoded size from frame : %u", (unsigned)dctx->decodedSize);
964
1203
  RETURN_ERROR_IF(
965
1204
  dctx->fParams.frameContentSize != ZSTD_CONTENTSIZE_UNKNOWN
966
1205
  && dctx->decodedSize != dctx->fParams.frameContentSize,
967
- corruption_detected);
1206
+ corruption_detected, "");
968
1207
  if (dctx->fParams.checksumFlag) { /* another round for frame checksum */
969
1208
  dctx->expected = 4;
970
1209
  dctx->stage = ZSTDds_checkChecksum;
971
1210
  } else {
1211
+ ZSTD_DCtx_trace_end(dctx, dctx->decodedSize, dctx->processedCSize, /* streaming */ 1);
972
1212
  dctx->expected = 0; /* ends here */
973
1213
  dctx->stage = ZSTDds_getFrameHeaderSize;
974
1214
  }
975
1215
  } else {
976
1216
  dctx->stage = ZSTDds_decodeBlockHeader;
977
1217
  dctx->expected = ZSTD_blockHeaderSize;
978
- dctx->previousDstEnd = (char*)dst + rSize;
979
1218
  }
980
1219
  return rSize;
981
1220
  }
982
1221
 
983
1222
  case ZSTDds_checkChecksum:
984
1223
  assert(srcSize == 4); /* guaranteed by dctx->expected */
985
- { U32 const h32 = (U32)XXH64_digest(&dctx->xxhState);
986
- U32 const check32 = MEM_readLE32(src);
987
- DEBUGLOG(4, "ZSTD_decompressContinue: checksum : calculated %08X :: %08X read", (unsigned)h32, (unsigned)check32);
988
- 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);
989
1232
  dctx->expected = 0;
990
1233
  dctx->stage = ZSTDds_getFrameHeaderSize;
991
1234
  return 0;
@@ -994,7 +1237,7 @@ size_t ZSTD_decompressContinue(ZSTD_DCtx* dctx, void* dst, size_t dstCapacity, c
994
1237
  case ZSTDds_decodeSkippableHeader:
995
1238
  assert(src != NULL);
996
1239
  assert(srcSize <= ZSTD_SKIPPABLEHEADERSIZE);
997
- memcpy(dctx->headerBuffer + (ZSTD_SKIPPABLEHEADERSIZE - srcSize), src, srcSize); /* complete skippable header */
1240
+ ZSTD_memcpy(dctx->headerBuffer + (ZSTD_SKIPPABLEHEADERSIZE - srcSize), src, srcSize); /* complete skippable header */
998
1241
  dctx->expected = MEM_readLE32(dctx->headerBuffer + ZSTD_FRAMEIDSIZE); /* note : dctx->expected can grow seriously large, beyond local buffer size */
999
1242
  dctx->stage = ZSTDds_skipFrame;
1000
1243
  return 0;
@@ -1006,7 +1249,7 @@ size_t ZSTD_decompressContinue(ZSTD_DCtx* dctx, void* dst, size_t dstCapacity, c
1006
1249
 
1007
1250
  default:
1008
1251
  assert(0); /* impossible */
1009
- RETURN_ERROR(GENERIC); /* some compiler require default to do something */
1252
+ RETURN_ERROR(GENERIC, "impossible to reach"); /* some compiler require default to do something */
1010
1253
  }
1011
1254
  }
1012
1255
 
@@ -1017,6 +1260,10 @@ static size_t ZSTD_refDictContent(ZSTD_DCtx* dctx, const void* dict, size_t dict
1017
1260
  dctx->virtualStart = (const char*)dict - ((const char*)(dctx->previousDstEnd) - (const char*)(dctx->prefixStart));
1018
1261
  dctx->prefixStart = dict;
1019
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
1020
1267
  return 0;
1021
1268
  }
1022
1269
 
@@ -1030,7 +1277,7 @@ ZSTD_loadDEntropy(ZSTD_entropyDTables_t* entropy,
1030
1277
  const BYTE* dictPtr = (const BYTE*)dict;
1031
1278
  const BYTE* const dictEnd = dictPtr + dictSize;
1032
1279
 
1033
- RETURN_ERROR_IF(dictSize <= 8, dictionary_corrupted);
1280
+ RETURN_ERROR_IF(dictSize <= 8, dictionary_corrupted, "dict is too small");
1034
1281
  assert(MEM_readLE32(dict) == ZSTD_MAGIC_DICTIONARY); /* dict must be valid */
1035
1282
  dictPtr += 8; /* skip header = magic + dictID */
1036
1283
 
@@ -1046,63 +1293,69 @@ ZSTD_loadDEntropy(ZSTD_entropyDTables_t* entropy,
1046
1293
  workspace, workspaceSize);
1047
1294
  #else
1048
1295
  size_t const hSize = HUF_readDTableX2_wksp(entropy->hufTable,
1049
- dictPtr, dictEnd - dictPtr,
1296
+ dictPtr, (size_t)(dictEnd - dictPtr),
1050
1297
  workspace, workspaceSize);
1051
1298
  #endif
1052
- RETURN_ERROR_IF(HUF_isError(hSize), dictionary_corrupted);
1299
+ RETURN_ERROR_IF(HUF_isError(hSize), dictionary_corrupted, "");
1053
1300
  dictPtr += hSize;
1054
1301
  }
1055
1302
 
1056
1303
  { short offcodeNCount[MaxOff+1];
1057
1304
  unsigned offcodeMaxValue = MaxOff, offcodeLog;
1058
- size_t const offcodeHeaderSize = FSE_readNCount(offcodeNCount, &offcodeMaxValue, &offcodeLog, dictPtr, dictEnd-dictPtr);
1059
- RETURN_ERROR_IF(FSE_isError(offcodeHeaderSize), dictionary_corrupted);
1060
- RETURN_ERROR_IF(offcodeMaxValue > MaxOff, dictionary_corrupted);
1061
- 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, "");
1062
1309
  ZSTD_buildFSETable( entropy->OFTable,
1063
1310
  offcodeNCount, offcodeMaxValue,
1064
1311
  OF_base, OF_bits,
1065
- offcodeLog);
1312
+ offcodeLog,
1313
+ entropy->workspace, sizeof(entropy->workspace),
1314
+ /* bmi2 */0);
1066
1315
  dictPtr += offcodeHeaderSize;
1067
1316
  }
1068
1317
 
1069
1318
  { short matchlengthNCount[MaxML+1];
1070
1319
  unsigned matchlengthMaxValue = MaxML, matchlengthLog;
1071
- size_t const matchlengthHeaderSize = FSE_readNCount(matchlengthNCount, &matchlengthMaxValue, &matchlengthLog, dictPtr, dictEnd-dictPtr);
1072
- RETURN_ERROR_IF(FSE_isError(matchlengthHeaderSize), dictionary_corrupted);
1073
- RETURN_ERROR_IF(matchlengthMaxValue > MaxML, dictionary_corrupted);
1074
- 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, "");
1075
1324
  ZSTD_buildFSETable( entropy->MLTable,
1076
1325
  matchlengthNCount, matchlengthMaxValue,
1077
1326
  ML_base, ML_bits,
1078
- matchlengthLog);
1327
+ matchlengthLog,
1328
+ entropy->workspace, sizeof(entropy->workspace),
1329
+ /* bmi2 */ 0);
1079
1330
  dictPtr += matchlengthHeaderSize;
1080
1331
  }
1081
1332
 
1082
1333
  { short litlengthNCount[MaxLL+1];
1083
1334
  unsigned litlengthMaxValue = MaxLL, litlengthLog;
1084
- size_t const litlengthHeaderSize = FSE_readNCount(litlengthNCount, &litlengthMaxValue, &litlengthLog, dictPtr, dictEnd-dictPtr);
1085
- RETURN_ERROR_IF(FSE_isError(litlengthHeaderSize), dictionary_corrupted);
1086
- RETURN_ERROR_IF(litlengthMaxValue > MaxLL, dictionary_corrupted);
1087
- 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, "");
1088
1339
  ZSTD_buildFSETable( entropy->LLTable,
1089
1340
  litlengthNCount, litlengthMaxValue,
1090
1341
  LL_base, LL_bits,
1091
- litlengthLog);
1342
+ litlengthLog,
1343
+ entropy->workspace, sizeof(entropy->workspace),
1344
+ /* bmi2 */ 0);
1092
1345
  dictPtr += litlengthHeaderSize;
1093
1346
  }
1094
1347
 
1095
- RETURN_ERROR_IF(dictPtr+12 > dictEnd, dictionary_corrupted);
1348
+ RETURN_ERROR_IF(dictPtr+12 > dictEnd, dictionary_corrupted, "");
1096
1349
  { int i;
1097
1350
  size_t const dictContentSize = (size_t)(dictEnd - (dictPtr+12));
1098
1351
  for (i=0; i<3; i++) {
1099
1352
  U32 const rep = MEM_readLE32(dictPtr); dictPtr += 4;
1100
- RETURN_ERROR_IF(rep==0 || rep >= dictContentSize,
1101
- dictionary_corrupted);
1353
+ RETURN_ERROR_IF(rep==0 || rep > dictContentSize,
1354
+ dictionary_corrupted, "");
1102
1355
  entropy->rep[i] = rep;
1103
1356
  } }
1104
1357
 
1105
- return dictPtr - (const BYTE*)dict;
1358
+ return (size_t)(dictPtr - (const BYTE*)dict);
1106
1359
  }
1107
1360
 
1108
1361
  static size_t ZSTD_decompress_insertDictionary(ZSTD_DCtx* dctx, const void* dict, size_t dictSize)
@@ -1116,7 +1369,7 @@ static size_t ZSTD_decompress_insertDictionary(ZSTD_DCtx* dctx, const void* dict
1116
1369
 
1117
1370
  /* load entropy tables */
1118
1371
  { size_t const eSize = ZSTD_loadDEntropy(&dctx->entropy, dict, dictSize);
1119
- RETURN_ERROR_IF(ZSTD_isError(eSize), dictionary_corrupted);
1372
+ RETURN_ERROR_IF(ZSTD_isError(eSize), dictionary_corrupted, "");
1120
1373
  dict = (const char*)dict + eSize;
1121
1374
  dictSize -= eSize;
1122
1375
  }
@@ -1129,8 +1382,12 @@ static size_t ZSTD_decompress_insertDictionary(ZSTD_DCtx* dctx, const void* dict
1129
1382
  size_t ZSTD_decompressBegin(ZSTD_DCtx* dctx)
1130
1383
  {
1131
1384
  assert(dctx != NULL);
1385
+ #if ZSTD_TRACE
1386
+ dctx->traceCtx = (ZSTD_trace_decompress_begin != NULL) ? ZSTD_trace_decompress_begin(dctx) : 0;
1387
+ #endif
1132
1388
  dctx->expected = ZSTD_startingInputLength(dctx->format); /* dctx->format must be properly set */
1133
1389
  dctx->stage = ZSTDds_getFrameHeaderSize;
1390
+ dctx->processedCSize = 0;
1134
1391
  dctx->decodedSize = 0;
1135
1392
  dctx->previousDstEnd = NULL;
1136
1393
  dctx->prefixStart = NULL;
@@ -1139,8 +1396,9 @@ size_t ZSTD_decompressBegin(ZSTD_DCtx* dctx)
1139
1396
  dctx->entropy.hufTable[0] = (HUF_DTable)((HufLog)*0x1000001); /* cover both little and big endian */
1140
1397
  dctx->litEntropy = dctx->fseEntropy = 0;
1141
1398
  dctx->dictID = 0;
1399
+ dctx->bType = bt_reserved;
1142
1400
  ZSTD_STATIC_ASSERT(sizeof(dctx->entropy.rep) == sizeof(repStartValue));
1143
- memcpy(dctx->entropy.rep, repStartValue, sizeof(repStartValue)); /* initial repcodes */
1401
+ ZSTD_memcpy(dctx->entropy.rep, repStartValue, sizeof(repStartValue)); /* initial repcodes */
1144
1402
  dctx->LLTptr = dctx->entropy.LLTable;
1145
1403
  dctx->MLTptr = dctx->entropy.MLTable;
1146
1404
  dctx->OFTptr = dctx->entropy.OFTable;
@@ -1150,11 +1408,11 @@ size_t ZSTD_decompressBegin(ZSTD_DCtx* dctx)
1150
1408
 
1151
1409
  size_t ZSTD_decompressBegin_usingDict(ZSTD_DCtx* dctx, const void* dict, size_t dictSize)
1152
1410
  {
1153
- FORWARD_IF_ERROR( ZSTD_decompressBegin(dctx) );
1411
+ FORWARD_IF_ERROR( ZSTD_decompressBegin(dctx) , "");
1154
1412
  if (dict && dictSize)
1155
1413
  RETURN_ERROR_IF(
1156
1414
  ZSTD_isError(ZSTD_decompress_insertDictionary(dctx, dict, dictSize)),
1157
- dictionary_corrupted);
1415
+ dictionary_corrupted, "");
1158
1416
  return 0;
1159
1417
  }
1160
1418
 
@@ -1173,7 +1431,7 @@ size_t ZSTD_decompressBegin_usingDDict(ZSTD_DCtx* dctx, const ZSTD_DDict* ddict)
1173
1431
  DEBUGLOG(4, "DDict is %s",
1174
1432
  dctx->ddictIsCold ? "~cold~" : "hot!");
1175
1433
  }
1176
- FORWARD_IF_ERROR( ZSTD_decompressBegin(dctx) );
1434
+ FORWARD_IF_ERROR( ZSTD_decompressBegin(dctx) , "");
1177
1435
  if (ddict) { /* NULL ddict is equivalent to no dictionary */
1178
1436
  ZSTD_copyDDictParameters(dctx, ddict);
1179
1437
  }
@@ -1264,11 +1522,11 @@ size_t ZSTD_DCtx_loadDictionary_advanced(ZSTD_DCtx* dctx,
1264
1522
  ZSTD_dictLoadMethod_e dictLoadMethod,
1265
1523
  ZSTD_dictContentType_e dictContentType)
1266
1524
  {
1267
- RETURN_ERROR_IF(dctx->streamStage != zdss_init, stage_wrong);
1525
+ RETURN_ERROR_IF(dctx->streamStage != zdss_init, stage_wrong, "");
1268
1526
  ZSTD_clearDict(dctx);
1269
- if (dict && dictSize >= 8) {
1527
+ if (dict && dictSize != 0) {
1270
1528
  dctx->ddictLocal = ZSTD_createDDict_advanced(dict, dictSize, dictLoadMethod, dictContentType, dctx->customMem);
1271
- RETURN_ERROR_IF(dctx->ddictLocal == NULL, memory_allocation);
1529
+ RETURN_ERROR_IF(dctx->ddictLocal == NULL, memory_allocation, "NULL pointer!");
1272
1530
  dctx->ddict = dctx->ddictLocal;
1273
1531
  dctx->dictUses = ZSTD_use_indefinitely;
1274
1532
  }
@@ -1287,7 +1545,7 @@ size_t ZSTD_DCtx_loadDictionary(ZSTD_DCtx* dctx, const void* dict, size_t dictSi
1287
1545
 
1288
1546
  size_t ZSTD_DCtx_refPrefix_advanced(ZSTD_DCtx* dctx, const void* prefix, size_t prefixSize, ZSTD_dictContentType_e dictContentType)
1289
1547
  {
1290
- 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), "");
1291
1549
  dctx->dictUses = ZSTD_use_once;
1292
1550
  return 0;
1293
1551
  }
@@ -1299,14 +1557,14 @@ size_t ZSTD_DCtx_refPrefix(ZSTD_DCtx* dctx, const void* prefix, size_t prefixSiz
1299
1557
 
1300
1558
 
1301
1559
  /* ZSTD_initDStream_usingDict() :
1302
- * return : expected size, aka ZSTD_FRAMEHEADERSIZE_PREFIX.
1560
+ * return : expected size, aka ZSTD_startingInputLength().
1303
1561
  * this function cannot fail */
1304
1562
  size_t ZSTD_initDStream_usingDict(ZSTD_DStream* zds, const void* dict, size_t dictSize)
1305
1563
  {
1306
1564
  DEBUGLOG(4, "ZSTD_initDStream_usingDict");
1307
- FORWARD_IF_ERROR( ZSTD_DCtx_reset(zds, ZSTD_reset_session_only) );
1308
- FORWARD_IF_ERROR( ZSTD_DCtx_loadDictionary(zds, dict, dictSize) );
1309
- 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);
1310
1568
  }
1311
1569
 
1312
1570
  /* note : this variant can't fail */
@@ -1321,28 +1579,38 @@ size_t ZSTD_initDStream(ZSTD_DStream* zds)
1321
1579
  * this function cannot fail */
1322
1580
  size_t ZSTD_initDStream_usingDDict(ZSTD_DStream* dctx, const ZSTD_DDict* ddict)
1323
1581
  {
1324
- FORWARD_IF_ERROR( ZSTD_DCtx_reset(dctx, ZSTD_reset_session_only) );
1325
- FORWARD_IF_ERROR( ZSTD_DCtx_refDDict(dctx, ddict) );
1326
- 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);
1327
1585
  }
1328
1586
 
1329
1587
  /* ZSTD_resetDStream() :
1330
- * return : expected size, aka ZSTD_FRAMEHEADERSIZE_PREFIX.
1588
+ * return : expected size, aka ZSTD_startingInputLength().
1331
1589
  * this function cannot fail */
1332
1590
  size_t ZSTD_resetDStream(ZSTD_DStream* dctx)
1333
1591
  {
1334
- FORWARD_IF_ERROR(ZSTD_DCtx_reset(dctx, ZSTD_reset_session_only));
1335
- return ZSTD_FRAMEHEADERSIZE_PREFIX;
1592
+ FORWARD_IF_ERROR(ZSTD_DCtx_reset(dctx, ZSTD_reset_session_only), "");
1593
+ return ZSTD_startingInputLength(dctx->format);
1336
1594
  }
1337
1595
 
1338
1596
 
1339
1597
  size_t ZSTD_DCtx_refDDict(ZSTD_DCtx* dctx, const ZSTD_DDict* ddict)
1340
1598
  {
1341
- RETURN_ERROR_IF(dctx->streamStage != zdss_init, stage_wrong);
1599
+ RETURN_ERROR_IF(dctx->streamStage != zdss_init, stage_wrong, "");
1342
1600
  ZSTD_clearDict(dctx);
1343
1601
  if (ddict) {
1344
1602
  dctx->ddict = ddict;
1345
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
+ }
1346
1614
  }
1347
1615
  return 0;
1348
1616
  }
@@ -1355,16 +1623,16 @@ size_t ZSTD_DCtx_setMaxWindowSize(ZSTD_DCtx* dctx, size_t maxWindowSize)
1355
1623
  ZSTD_bounds const bounds = ZSTD_dParam_getBounds(ZSTD_d_windowLogMax);
1356
1624
  size_t const min = (size_t)1 << bounds.lowerBound;
1357
1625
  size_t const max = (size_t)1 << bounds.upperBound;
1358
- RETURN_ERROR_IF(dctx->streamStage != zdss_init, stage_wrong);
1359
- RETURN_ERROR_IF(maxWindowSize < min, parameter_outOfBound);
1360
- 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, "");
1361
1629
  dctx->maxWindowSize = maxWindowSize;
1362
1630
  return 0;
1363
1631
  }
1364
1632
 
1365
1633
  size_t ZSTD_DCtx_setFormat(ZSTD_DCtx* dctx, ZSTD_format_e format)
1366
1634
  {
1367
- return ZSTD_DCtx_setParameter(dctx, ZSTD_d_format, format);
1635
+ return ZSTD_DCtx_setParameter(dctx, ZSTD_d_format, (int)format);
1368
1636
  }
1369
1637
 
1370
1638
  ZSTD_bounds ZSTD_dParam_getBounds(ZSTD_dParameter dParam)
@@ -1380,6 +1648,18 @@ ZSTD_bounds ZSTD_dParam_getBounds(ZSTD_dParameter dParam)
1380
1648
  bounds.upperBound = (int)ZSTD_f_zstd1_magicless;
1381
1649
  ZSTD_STATIC_ASSERT(ZSTD_f_zstd1 < ZSTD_f_zstd1_magicless);
1382
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;
1383
1663
  default:;
1384
1664
  }
1385
1665
  bounds.error = ERROR(parameter_unsupported);
@@ -1399,12 +1679,35 @@ static int ZSTD_dParam_withinBounds(ZSTD_dParameter dParam, int value)
1399
1679
  }
1400
1680
 
1401
1681
  #define CHECK_DBOUNDS(p,v) { \
1402
- 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, "");
1403
1706
  }
1404
1707
 
1405
1708
  size_t ZSTD_DCtx_setParameter(ZSTD_DCtx* dctx, ZSTD_dParameter dParam, int value)
1406
1709
  {
1407
- RETURN_ERROR_IF(dctx->streamStage != zdss_init, stage_wrong);
1710
+ RETURN_ERROR_IF(dctx->streamStage != zdss_init, stage_wrong, "");
1408
1711
  switch(dParam) {
1409
1712
  case ZSTD_d_windowLogMax:
1410
1713
  if (value == 0) value = ZSTD_WINDOWLOG_LIMIT_DEFAULT;
@@ -1415,9 +1718,24 @@ size_t ZSTD_DCtx_setParameter(ZSTD_DCtx* dctx, ZSTD_dParameter dParam, int value
1415
1718
  CHECK_DBOUNDS(ZSTD_d_format, value);
1416
1719
  dctx->format = (ZSTD_format_e)value;
1417
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;
1418
1736
  default:;
1419
1737
  }
1420
- RETURN_ERROR(parameter_unsupported);
1738
+ RETURN_ERROR(parameter_unsupported, "");
1421
1739
  }
1422
1740
 
1423
1741
  size_t ZSTD_DCtx_reset(ZSTD_DCtx* dctx, ZSTD_ResetDirective reset)
@@ -1429,10 +1747,9 @@ size_t ZSTD_DCtx_reset(ZSTD_DCtx* dctx, ZSTD_ResetDirective reset)
1429
1747
  }
1430
1748
  if ( (reset == ZSTD_reset_parameters)
1431
1749
  || (reset == ZSTD_reset_session_and_parameters) ) {
1432
- RETURN_ERROR_IF(dctx->streamStage != zdss_init, stage_wrong);
1750
+ RETURN_ERROR_IF(dctx->streamStage != zdss_init, stage_wrong, "");
1433
1751
  ZSTD_clearDict(dctx);
1434
- dctx->format = ZSTD_f_zstd1;
1435
- dctx->maxWindowSize = ZSTD_MAXWINDOWSIZE_DEFAULT;
1752
+ ZSTD_DCtx_resetParameters(dctx);
1436
1753
  }
1437
1754
  return 0;
1438
1755
  }
@@ -1450,7 +1767,7 @@ size_t ZSTD_decodingBufferSize_min(unsigned long long windowSize, unsigned long
1450
1767
  unsigned long long const neededSize = MIN(frameContentSize, neededRBSize);
1451
1768
  size_t const minRBSize = (size_t) neededSize;
1452
1769
  RETURN_ERROR_IF((unsigned long long)minRBSize != neededSize,
1453
- frameParameter_windowTooLarge);
1770
+ frameParameter_windowTooLarge, "");
1454
1771
  return minRBSize;
1455
1772
  }
1456
1773
 
@@ -1468,30 +1785,94 @@ size_t ZSTD_estimateDStreamSize_fromFrame(const void* src, size_t srcSize)
1468
1785
  ZSTD_frameHeader zfh;
1469
1786
  size_t const err = ZSTD_getFrameHeader(&zfh, src, srcSize);
1470
1787
  if (ZSTD_isError(err)) return err;
1471
- RETURN_ERROR_IF(err>0, srcSize_wrong);
1788
+ RETURN_ERROR_IF(err>0, srcSize_wrong, "");
1472
1789
  RETURN_ERROR_IF(zfh.windowSize > windowSizeMax,
1473
- frameParameter_windowTooLarge);
1790
+ frameParameter_windowTooLarge, "");
1474
1791
  return ZSTD_estimateDStreamSize((size_t)zfh.windowSize);
1475
1792
  }
1476
1793
 
1477
1794
 
1478
1795
  /* ***** Decompression ***** */
1479
1796
 
1480
- 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)
1481
1811
  {
1482
- size_t const length = MIN(dstCapacity, srcSize);
1483
- memcpy(dst, src, length);
1484
- 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!");
1485
1831
  }
1486
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
+ }
1487
1866
 
1488
1867
  size_t ZSTD_decompressStream(ZSTD_DStream* zds, ZSTD_outBuffer* output, ZSTD_inBuffer* input)
1489
1868
  {
1490
- const char* const istart = (const char*)(input->src) + input->pos;
1491
- 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;
1492
1872
  const char* ip = istart;
1493
- char* const ostart = (char*)(output->dst) + output->pos;
1494
- 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;
1495
1876
  char* op = ostart;
1496
1877
  U32 someMoreWork = 1;
1497
1878
 
@@ -1507,6 +1888,7 @@ size_t ZSTD_decompressStream(ZSTD_DStream* zds, ZSTD_outBuffer* output, ZSTD_inB
1507
1888
  "forbidden. out: pos: %u vs size: %u",
1508
1889
  (U32)output->pos, (U32)output->size);
1509
1890
  DEBUGLOG(5, "input size : %u", (U32)(input->size - input->pos));
1891
+ FORWARD_IF_ERROR(ZSTD_checkOutBuffer(zds, output), "");
1510
1892
 
1511
1893
  while (someMoreWork) {
1512
1894
  switch(zds->streamStage)
@@ -1517,6 +1899,7 @@ size_t ZSTD_decompressStream(ZSTD_DStream* zds, ZSTD_outBuffer* output, ZSTD_inB
1517
1899
  zds->lhSize = zds->inPos = zds->outStart = zds->outEnd = 0;
1518
1900
  zds->legacyVersion = 0;
1519
1901
  zds->hostageByte = 0;
1902
+ zds->expectedOutBuffer = *output;
1520
1903
  /* fall-through */
1521
1904
 
1522
1905
  case zdss_loadHeader :
@@ -1531,6 +1914,9 @@ size_t ZSTD_decompressStream(ZSTD_DStream* zds, ZSTD_outBuffer* output, ZSTD_inB
1531
1914
  } }
1532
1915
  #endif
1533
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
+ }
1534
1920
  DEBUGLOG(5, "header size : %u", (U32)hSize);
1535
1921
  if (ZSTD_isError(hSize)) {
1536
1922
  #if defined(ZSTD_LEGACY_SUPPORT) && (ZSTD_LEGACY_SUPPORT>=1)
@@ -1544,7 +1930,7 @@ size_t ZSTD_decompressStream(ZSTD_DStream* zds, ZSTD_outBuffer* output, ZSTD_inB
1544
1930
  "legacy support is incompatible with static dctx");
1545
1931
  FORWARD_IF_ERROR(ZSTD_initLegacyStream(&zds->legacyContext,
1546
1932
  zds->previousLegacyVersion, legacyVersion,
1547
- dict, dictSize));
1933
+ dict, dictSize), "");
1548
1934
  zds->legacyVersion = zds->previousLegacyVersion = legacyVersion;
1549
1935
  { size_t const hint = ZSTD_decompressLegacyStream(zds->legacyContext, legacyVersion, output, input);
1550
1936
  if (hint==0) zds->streamStage = zdss_init; /* or stay in stage zdss_loadHeader */
@@ -1559,24 +1945,25 @@ size_t ZSTD_decompressStream(ZSTD_DStream* zds, ZSTD_outBuffer* output, ZSTD_inB
1559
1945
  assert(iend >= ip);
1560
1946
  if (toLoad > remainingInput) { /* not enough input to load full header */
1561
1947
  if (remainingInput > 0) {
1562
- memcpy(zds->headerBuffer + zds->lhSize, ip, remainingInput);
1948
+ ZSTD_memcpy(zds->headerBuffer + zds->lhSize, ip, remainingInput);
1563
1949
  zds->lhSize += remainingInput;
1564
1950
  }
1565
1951
  input->pos = input->size;
1566
- 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 */
1567
1953
  }
1568
1954
  assert(ip != NULL);
1569
- 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;
1570
1956
  break;
1571
1957
  } }
1572
1958
 
1573
1959
  /* check for single-pass mode opportunity */
1574
- 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
1575
1962
  && (U64)(size_t)(oend-op) >= zds->fParams.frameContentSize) {
1576
- size_t const cSize = ZSTD_findFrameCompressedSize(istart, iend-istart);
1963
+ size_t const cSize = ZSTD_findFrameCompressedSize(istart, (size_t)(iend-istart));
1577
1964
  if (cSize <= (size_t)(iend-istart)) {
1578
1965
  /* shortcut : using single-pass mode */
1579
- 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));
1580
1967
  if (ZSTD_isError(decompressedSize)) return decompressedSize;
1581
1968
  DEBUGLOG(4, "shortcut to single-pass ZSTD_decompress_usingDDict()")
1582
1969
  ip = istart + cSize;
@@ -1587,15 +1974,23 @@ size_t ZSTD_decompressStream(ZSTD_DStream* zds, ZSTD_outBuffer* output, ZSTD_inB
1587
1974
  break;
1588
1975
  } }
1589
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
+
1590
1985
  /* Consume header (see ZSTDds_decodeFrameHeader) */
1591
1986
  DEBUGLOG(4, "Consume header");
1592
- FORWARD_IF_ERROR(ZSTD_decompressBegin_usingDDict(zds, ZSTD_getDDict(zds)));
1987
+ FORWARD_IF_ERROR(ZSTD_decompressBegin_usingDDict(zds, ZSTD_getDDict(zds)), "");
1593
1988
 
1594
1989
  if ((MEM_readLE32(zds->headerBuffer) & ZSTD_MAGIC_SKIPPABLE_MASK) == ZSTD_MAGIC_SKIPPABLE_START) { /* skippable frame */
1595
1990
  zds->expected = MEM_readLE32(zds->headerBuffer + ZSTD_FRAMEIDSIZE);
1596
1991
  zds->stage = ZSTDds_skipFrame;
1597
1992
  } else {
1598
- FORWARD_IF_ERROR(ZSTD_decodeFrameHeader(zds, zds->headerBuffer, zds->lhSize));
1993
+ FORWARD_IF_ERROR(ZSTD_decodeFrameHeader(zds, zds->headerBuffer, zds->lhSize), "");
1599
1994
  zds->expected = ZSTD_blockHeaderSize;
1600
1995
  zds->stage = ZSTDds_decodeBlockHeader;
1601
1996
  }
@@ -1606,40 +2001,48 @@ size_t ZSTD_decompressStream(ZSTD_DStream* zds, ZSTD_outBuffer* output, ZSTD_inB
1606
2001
  (U32)(zds->maxWindowSize >> 10) );
1607
2002
  zds->fParams.windowSize = MAX(zds->fParams.windowSize, 1U << ZSTD_WINDOWLOG_ABSOLUTEMIN);
1608
2003
  RETURN_ERROR_IF(zds->fParams.windowSize > zds->maxWindowSize,
1609
- frameParameter_windowTooLarge);
2004
+ frameParameter_windowTooLarge, "");
1610
2005
 
1611
2006
  /* Adapt buffer sizes to frame header instructions */
1612
2007
  { size_t const neededInBuffSize = MAX(zds->fParams.blockSizeMax, 4 /* frame checksum */);
1613
- size_t const neededOutBuffSize = ZSTD_decodingBufferSize_min(zds->fParams.windowSize, zds->fParams.frameContentSize);
1614
- if ((zds->inBuffSize < neededInBuffSize) || (zds->outBuffSize < neededOutBuffSize)) {
1615
- size_t const bufferSize = neededInBuffSize + neededOutBuffSize;
1616
- DEBUGLOG(4, "inBuff : from %u to %u",
1617
- (U32)zds->inBuffSize, (U32)neededInBuffSize);
1618
- DEBUGLOG(4, "outBuff : from %u to %u",
1619
- (U32)zds->outBuffSize, (U32)neededOutBuffSize);
1620
- if (zds->staticSize) { /* static DCtx */
1621
- DEBUGLOG(4, "staticSize : %u", (U32)zds->staticSize);
1622
- assert(zds->staticSize >= sizeof(ZSTD_DCtx)); /* controlled at init */
1623
- RETURN_ERROR_IF(
1624
- bufferSize > zds->staticSize - sizeof(ZSTD_DCtx),
1625
- memory_allocation);
1626
- } else {
1627
- ZSTD_free(zds->inBuff, zds->customMem);
1628
- zds->inBuffSize = 0;
1629
- zds->outBuffSize = 0;
1630
- zds->inBuff = (char*)ZSTD_malloc(bufferSize, zds->customMem);
1631
- RETURN_ERROR_IF(zds->inBuff == NULL, memory_allocation);
1632
- }
1633
- zds->inBuffSize = neededInBuffSize;
1634
- zds->outBuff = zds->inBuff + zds->inBuffSize;
1635
- zds->outBuffSize = neededOutBuffSize;
1636
- } }
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
+ } } }
1637
2040
  zds->streamStage = zdss_read;
1638
2041
  /* fall-through */
1639
2042
 
1640
2043
  case zdss_read:
1641
2044
  DEBUGLOG(5, "stage zdss_read");
1642
- { size_t const neededInSize = ZSTD_nextSrcSizeToDecompress(zds);
2045
+ { size_t const neededInSize = ZSTD_nextSrcSizeToDecompressWithInputSize(zds, (size_t)(iend - ip));
1643
2046
  DEBUGLOG(5, "neededInSize = %u", (U32)neededInSize);
1644
2047
  if (neededInSize==0) { /* end of frame */
1645
2048
  zds->streamStage = zdss_init;
@@ -1647,15 +2050,9 @@ size_t ZSTD_decompressStream(ZSTD_DStream* zds, ZSTD_outBuffer* output, ZSTD_inB
1647
2050
  break;
1648
2051
  }
1649
2052
  if ((size_t)(iend-ip) >= neededInSize) { /* decode directly from src */
1650
- int const isSkipFrame = ZSTD_isSkipFrame(zds);
1651
- size_t const decodedSize = ZSTD_decompressContinue(zds,
1652
- zds->outBuff + zds->outStart, (isSkipFrame ? 0 : zds->outBuffSize - zds->outStart),
1653
- ip, neededInSize);
1654
- if (ZSTD_isError(decodedSize)) return decodedSize;
2053
+ FORWARD_IF_ERROR(ZSTD_decompressContinueStream(zds, &op, oend, ip, neededInSize), "");
1655
2054
  ip += neededInSize;
1656
- if (!decodedSize && !isSkipFrame) break; /* this was just a header */
1657
- zds->outEnd = zds->outStart + decodedSize;
1658
- zds->streamStage = zdss_flush;
2055
+ /* Function modifies the stage so we must break */
1659
2056
  break;
1660
2057
  } }
1661
2058
  if (ip==iend) { someMoreWork = 0; break; } /* no more input */
@@ -1667,33 +2064,29 @@ size_t ZSTD_decompressStream(ZSTD_DStream* zds, ZSTD_outBuffer* output, ZSTD_inB
1667
2064
  size_t const toLoad = neededInSize - zds->inPos;
1668
2065
  int const isSkipFrame = ZSTD_isSkipFrame(zds);
1669
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));
1670
2069
  if (isSkipFrame) {
1671
2070
  loadedSize = MIN(toLoad, (size_t)(iend-ip));
1672
2071
  } else {
1673
2072
  RETURN_ERROR_IF(toLoad > zds->inBuffSize - zds->inPos,
1674
2073
  corruption_detected,
1675
2074
  "should never happen");
1676
- 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));
1677
2076
  }
1678
2077
  ip += loadedSize;
1679
2078
  zds->inPos += loadedSize;
1680
2079
  if (loadedSize < toLoad) { someMoreWork = 0; break; } /* not enough input, wait for more */
1681
2080
 
1682
2081
  /* decode loaded input */
1683
- { size_t const decodedSize = ZSTD_decompressContinue(zds,
1684
- zds->outBuff + zds->outStart, zds->outBuffSize - zds->outStart,
1685
- zds->inBuff, neededInSize);
1686
- if (ZSTD_isError(decodedSize)) return decodedSize;
1687
- zds->inPos = 0; /* input is consumed */
1688
- if (!decodedSize && !isSkipFrame) { zds->streamStage = zdss_read; break; } /* this was just a header */
1689
- zds->outEnd = zds->outStart + decodedSize;
1690
- } }
1691
- zds->streamStage = zdss_flush;
1692
- /* fall-through */
1693
-
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
+ }
1694
2087
  case zdss_flush:
1695
2088
  { size_t const toFlushSize = zds->outEnd - zds->outStart;
1696
- 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);
1697
2090
  op += flushedSize;
1698
2091
  zds->outStart += flushedSize;
1699
2092
  if (flushedSize == toFlushSize) { /* flush completed */
@@ -1713,17 +2106,21 @@ size_t ZSTD_decompressStream(ZSTD_DStream* zds, ZSTD_outBuffer* output, ZSTD_inB
1713
2106
 
1714
2107
  default:
1715
2108
  assert(0); /* impossible */
1716
- RETURN_ERROR(GENERIC); /* some compiler require default to do something */
2109
+ RETURN_ERROR(GENERIC, "impossible to reach"); /* some compiler require default to do something */
1717
2110
  } }
1718
2111
 
1719
2112
  /* result */
1720
2113
  input->pos = (size_t)(ip - (const char*)(input->src));
1721
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
+
1722
2119
  if ((ip==istart) && (op==ostart)) { /* no forward progress */
1723
2120
  zds->noForwardProgress ++;
1724
2121
  if (zds->noForwardProgress >= ZSTD_NO_FORWARD_PROGRESS_MAX) {
1725
- RETURN_ERROR_IF(op==oend, dstSize_tooSmall);
1726
- RETURN_ERROR_IF(ip==iend, srcSize_wrong);
2122
+ RETURN_ERROR_IF(op==oend, dstSize_tooSmall, "");
2123
+ RETURN_ERROR_IF(ip==iend, srcSize_wrong, "");
1727
2124
  assert(0);
1728
2125
  }
1729
2126
  } else {