1 /*
2 * Copyright (c) Yann Collet, Facebook, Inc.
3 * All rights reserved.
4 *
5 * This source code is licensed under both the BSD-style license (found in the
6 * LICENSE file in the root directory of this source tree) and the GPLv2 (found
7 * in the COPYING file in the root directory of this source tree).
8 * You may select, at your option, one of the above-listed licenses.
9 */
10
11
12 /* ***************************************************************
13 * Tuning parameters
14 *****************************************************************/
15 /*!
16 * HEAPMODE :
17 * Select how default decompression function ZSTD_decompress() allocates its context,
18 * on stack (0), or into heap (1, default; requires malloc()).
19 * Note that functions with explicit context such as ZSTD_decompressDCtx() are unaffected.
20 */
21 #ifndef ZSTD_HEAPMODE
22 # define ZSTD_HEAPMODE 1
23 #endif
24
25 /*!
26 * LEGACY_SUPPORT :
27 * if set to 1+, ZSTD_decompress() can decode older formats (v0.1+)
28 */
29 #ifndef ZSTD_LEGACY_SUPPORT
30 # define ZSTD_LEGACY_SUPPORT 0
31 #endif
32
33 /*!
34 * MAXWINDOWSIZE_DEFAULT :
35 * maximum window size accepted by DStream __by default__.
36 * Frames requiring more memory will be rejected.
37 * It's possible to set a different limit using ZSTD_DCtx_setMaxWindowSize().
38 */
39 #ifndef ZSTD_MAXWINDOWSIZE_DEFAULT
40 # define ZSTD_MAXWINDOWSIZE_DEFAULT (((U32)1 << ZSTD_WINDOWLOG_LIMIT_DEFAULT) + 1)
41 #endif
42
43 /*!
44 * NO_FORWARD_PROGRESS_MAX :
45 * maximum allowed nb of calls to ZSTD_decompressStream()
46 * without any forward progress
47 * (defined as: no byte read from input, and no byte flushed to output)
48 * before triggering an error.
49 */
50 #ifndef ZSTD_NO_FORWARD_PROGRESS_MAX
51 # define ZSTD_NO_FORWARD_PROGRESS_MAX 16
52 #endif
53
54
55 /*-*******************************************************
56 * Dependencies
57 *********************************************************/
58 #include "../common/zstd_deps.h" /* ZSTD_memcpy, ZSTD_memmove, ZSTD_memset */
59 #include "../common/mem.h" /* low level memory routines */
60 #define FSE_STATIC_LINKING_ONLY
61 #include "../common/fse.h"
62 #define HUF_STATIC_LINKING_ONLY
63 #include "../common/huf.h"
64 #include "../common/xxhash.h" /* XXH64_reset, XXH64_update, XXH64_digest, XXH64 */
65 #include "../common/zstd_internal.h" /* blockProperties_t */
66 #include "zstd_decompress_internal.h" /* ZSTD_DCtx */
67 #include "zstd_ddict.h" /* ZSTD_DDictDictContent */
68 #include "zstd_decompress_block.h" /* ZSTD_decompressBlock_internal */
69
70 #if defined(ZSTD_LEGACY_SUPPORT) && (ZSTD_LEGACY_SUPPORT>=1)
71 # include "../legacy/zstd_legacy.h"
72 #endif
73
74
75
76 /*************************************
77 * Multiple DDicts Hashset internals *
78 *************************************/
79
80 #define DDICT_HASHSET_MAX_LOAD_FACTOR_COUNT_MULT 4
81 #define DDICT_HASHSET_MAX_LOAD_FACTOR_SIZE_MULT 3 /* These two constants represent SIZE_MULT/COUNT_MULT load factor without using a float.
82 * Currently, that means a 0.75 load factor.
83 * So, if count * COUNT_MULT / size * SIZE_MULT != 0, then we've exceeded
84 * the load factor of the ddict hash set.
85 */
86
87 #define DDICT_HASHSET_TABLE_BASE_SIZE 64
88 #define DDICT_HASHSET_RESIZE_FACTOR 2
89
90 /* Hash function to determine starting position of dict insertion within the table
91 * Returns an index between [0, hashSet->ddictPtrTableSize]
92 */
ZSTD_DDictHashSet_getIndex(const ZSTD_DDictHashSet * hashSet,U32 dictID)93 static size_t ZSTD_DDictHashSet_getIndex(const ZSTD_DDictHashSet* hashSet, U32 dictID) {
94 const U64 hash = XXH64(&dictID, sizeof(U32), 0);
95 /* DDict ptr table size is a multiple of 2, use size - 1 as mask to get index within [0, hashSet->ddictPtrTableSize) */
96 return hash & (hashSet->ddictPtrTableSize - 1);
97 }
98
99 /* Adds DDict to a hashset without resizing it.
100 * If inserting a DDict with a dictID that already exists in the set, replaces the one in the set.
101 * Returns 0 if successful, or a zstd error code if something went wrong.
102 */
ZSTD_DDictHashSet_emplaceDDict(ZSTD_DDictHashSet * hashSet,const ZSTD_DDict * ddict)103 static size_t ZSTD_DDictHashSet_emplaceDDict(ZSTD_DDictHashSet* hashSet, const ZSTD_DDict* ddict) {
104 const U32 dictID = ZSTD_getDictID_fromDDict(ddict);
105 size_t idx = ZSTD_DDictHashSet_getIndex(hashSet, dictID);
106 const size_t idxRangeMask = hashSet->ddictPtrTableSize - 1;
107 RETURN_ERROR_IF(hashSet->ddictPtrCount == hashSet->ddictPtrTableSize, GENERIC, "Hash set is full!");
108 DEBUGLOG(4, "Hashed index: for dictID: %u is %zu", dictID, idx);
109 while (hashSet->ddictPtrTable[idx] != NULL) {
110 /* Replace existing ddict if inserting ddict with same dictID */
111 if (ZSTD_getDictID_fromDDict(hashSet->ddictPtrTable[idx]) == dictID) {
112 DEBUGLOG(4, "DictID already exists, replacing rather than adding");
113 hashSet->ddictPtrTable[idx] = ddict;
114 return 0;
115 }
116 idx &= idxRangeMask;
117 idx++;
118 }
119 DEBUGLOG(4, "Final idx after probing for dictID %u is: %zu", dictID, idx);
120 hashSet->ddictPtrTable[idx] = ddict;
121 hashSet->ddictPtrCount++;
122 return 0;
123 }
124
125 /* Expands hash table by factor of DDICT_HASHSET_RESIZE_FACTOR and
126 * rehashes all values, allocates new table, frees old table.
127 * Returns 0 on success, otherwise a zstd error code.
128 */
ZSTD_DDictHashSet_expand(ZSTD_DDictHashSet * hashSet,ZSTD_customMem customMem)129 static size_t ZSTD_DDictHashSet_expand(ZSTD_DDictHashSet* hashSet, ZSTD_customMem customMem) {
130 size_t newTableSize = hashSet->ddictPtrTableSize * DDICT_HASHSET_RESIZE_FACTOR;
131 const ZSTD_DDict** newTable = (const ZSTD_DDict**)ZSTD_customCalloc(sizeof(ZSTD_DDict*) * newTableSize, customMem);
132 const ZSTD_DDict** oldTable = hashSet->ddictPtrTable;
133 size_t oldTableSize = hashSet->ddictPtrTableSize;
134 size_t i;
135
136 DEBUGLOG(4, "Expanding DDict hash table! Old size: %zu new size: %zu", oldTableSize, newTableSize);
137 RETURN_ERROR_IF(!newTable, memory_allocation, "Expanded hashset allocation failed!");
138 hashSet->ddictPtrTable = newTable;
139 hashSet->ddictPtrTableSize = newTableSize;
140 hashSet->ddictPtrCount = 0;
141 for (i = 0; i < oldTableSize; ++i) {
142 if (oldTable[i] != NULL) {
143 FORWARD_IF_ERROR(ZSTD_DDictHashSet_emplaceDDict(hashSet, oldTable[i]), "");
144 }
145 }
146 ZSTD_customFree((void*)oldTable, customMem);
147 DEBUGLOG(4, "Finished re-hash");
148 return 0;
149 }
150
151 /* Fetches a DDict with the given dictID
152 * Returns the ZSTD_DDict* with the requested dictID. If it doesn't exist, then returns NULL.
153 */
ZSTD_DDictHashSet_getDDict(ZSTD_DDictHashSet * hashSet,U32 dictID)154 static const ZSTD_DDict* ZSTD_DDictHashSet_getDDict(ZSTD_DDictHashSet* hashSet, U32 dictID) {
155 size_t idx = ZSTD_DDictHashSet_getIndex(hashSet, dictID);
156 const size_t idxRangeMask = hashSet->ddictPtrTableSize - 1;
157 DEBUGLOG(4, "Hashed index: for dictID: %u is %zu", dictID, idx);
158 for (;;) {
159 size_t currDictID = ZSTD_getDictID_fromDDict(hashSet->ddictPtrTable[idx]);
160 if (currDictID == dictID || currDictID == 0) {
161 /* currDictID == 0 implies a NULL ddict entry */
162 break;
163 } else {
164 idx &= idxRangeMask; /* Goes to start of table when we reach the end */
165 idx++;
166 }
167 }
168 DEBUGLOG(4, "Final idx after probing for dictID %u is: %zu", dictID, idx);
169 return hashSet->ddictPtrTable[idx];
170 }
171
172 /* Allocates space for and returns a ddict hash set
173 * The hash set's ZSTD_DDict* table has all values automatically set to NULL to begin with.
174 * Returns NULL if allocation failed.
175 */
ZSTD_createDDictHashSet(ZSTD_customMem customMem)176 static ZSTD_DDictHashSet* ZSTD_createDDictHashSet(ZSTD_customMem customMem) {
177 ZSTD_DDictHashSet* ret = (ZSTD_DDictHashSet*)ZSTD_customMalloc(sizeof(ZSTD_DDictHashSet), customMem);
178 DEBUGLOG(4, "Allocating new hash set");
179 if (!ret)
180 return NULL;
181 ret->ddictPtrTable = (const ZSTD_DDict**)ZSTD_customCalloc(DDICT_HASHSET_TABLE_BASE_SIZE * sizeof(ZSTD_DDict*), customMem);
182 if (!ret->ddictPtrTable) {
183 ZSTD_customFree(ret, customMem);
184 return NULL;
185 }
186 ret->ddictPtrTableSize = DDICT_HASHSET_TABLE_BASE_SIZE;
187 ret->ddictPtrCount = 0;
188 return ret;
189 }
190
191 /* Frees the table of ZSTD_DDict* within a hashset, then frees the hashset itself.
192 * Note: The ZSTD_DDict* within the table are NOT freed.
193 */
ZSTD_freeDDictHashSet(ZSTD_DDictHashSet * hashSet,ZSTD_customMem customMem)194 static void ZSTD_freeDDictHashSet(ZSTD_DDictHashSet* hashSet, ZSTD_customMem customMem) {
195 DEBUGLOG(4, "Freeing ddict hash set");
196 if (hashSet && hashSet->ddictPtrTable) {
197 ZSTD_customFree((void*)hashSet->ddictPtrTable, customMem);
198 }
199 if (hashSet) {
200 ZSTD_customFree(hashSet, customMem);
201 }
202 }
203
204 /* Public function: Adds a DDict into the ZSTD_DDictHashSet, possibly triggering a resize of the hash set.
205 * Returns 0 on success, or a ZSTD error.
206 */
ZSTD_DDictHashSet_addDDict(ZSTD_DDictHashSet * hashSet,const ZSTD_DDict * ddict,ZSTD_customMem customMem)207 static size_t ZSTD_DDictHashSet_addDDict(ZSTD_DDictHashSet* hashSet, const ZSTD_DDict* ddict, ZSTD_customMem customMem) {
208 DEBUGLOG(4, "Adding dict ID: %u to hashset with - Count: %zu Tablesize: %zu", ZSTD_getDictID_fromDDict(ddict), hashSet->ddictPtrCount, hashSet->ddictPtrTableSize);
209 if (hashSet->ddictPtrCount * DDICT_HASHSET_MAX_LOAD_FACTOR_COUNT_MULT / hashSet->ddictPtrTableSize * DDICT_HASHSET_MAX_LOAD_FACTOR_SIZE_MULT != 0) {
210 FORWARD_IF_ERROR(ZSTD_DDictHashSet_expand(hashSet, customMem), "");
211 }
212 FORWARD_IF_ERROR(ZSTD_DDictHashSet_emplaceDDict(hashSet, ddict), "");
213 return 0;
214 }
215
216 /*-*************************************************************
217 * Context management
218 ***************************************************************/
ZSTD_sizeof_DCtx(const ZSTD_DCtx * dctx)219 size_t ZSTD_sizeof_DCtx (const ZSTD_DCtx* dctx)
220 {
221 if (dctx==NULL) return 0; /* support sizeof NULL */
222 return sizeof(*dctx)
223 + ZSTD_sizeof_DDict(dctx->ddictLocal)
224 + dctx->inBuffSize + dctx->outBuffSize;
225 }
226
ZSTD_estimateDCtxSize(void)227 size_t ZSTD_estimateDCtxSize(void) { return sizeof(ZSTD_DCtx); }
228
229
ZSTD_startingInputLength(ZSTD_format_e format)230 static size_t ZSTD_startingInputLength(ZSTD_format_e format)
231 {
232 size_t const startingInputLength = ZSTD_FRAMEHEADERSIZE_PREFIX(format);
233 /* only supports formats ZSTD_f_zstd1 and ZSTD_f_zstd1_magicless */
234 assert( (format == ZSTD_f_zstd1) || (format == ZSTD_f_zstd1_magicless) );
235 return startingInputLength;
236 }
237
ZSTD_DCtx_resetParameters(ZSTD_DCtx * dctx)238 static void ZSTD_DCtx_resetParameters(ZSTD_DCtx* dctx)
239 {
240 assert(dctx->streamStage == zdss_init);
241 dctx->format = ZSTD_f_zstd1;
242 dctx->maxWindowSize = ZSTD_MAXWINDOWSIZE_DEFAULT;
243 dctx->outBufferMode = ZSTD_bm_buffered;
244 dctx->forceIgnoreChecksum = ZSTD_d_validateChecksum;
245 dctx->refMultipleDDicts = ZSTD_rmd_refSingleDDict;
246 }
247
ZSTD_initDCtx_internal(ZSTD_DCtx * dctx)248 static void ZSTD_initDCtx_internal(ZSTD_DCtx* dctx)
249 {
250 dctx->staticSize = 0;
251 dctx->ddict = NULL;
252 dctx->ddictLocal = NULL;
253 dctx->dictEnd = NULL;
254 dctx->ddictIsCold = 0;
255 dctx->dictUses = ZSTD_dont_use;
256 dctx->inBuff = NULL;
257 dctx->inBuffSize = 0;
258 dctx->outBuffSize = 0;
259 dctx->streamStage = zdss_init;
260 #if defined(ZSTD_LEGACY_SUPPORT) && (ZSTD_LEGACY_SUPPORT>=1)
261 dctx->legacyContext = NULL;
262 dctx->previousLegacyVersion = 0;
263 #endif
264 dctx->noForwardProgress = 0;
265 dctx->oversizedDuration = 0;
266 #if DYNAMIC_BMI2
267 dctx->bmi2 = ZSTD_cpuSupportsBmi2();
268 #endif
269 dctx->ddictSet = NULL;
270 ZSTD_DCtx_resetParameters(dctx);
271 #ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
272 dctx->dictContentEndForFuzzing = NULL;
273 #endif
274 }
275
ZSTD_initStaticDCtx(void * workspace,size_t workspaceSize)276 ZSTD_DCtx* ZSTD_initStaticDCtx(void *workspace, size_t workspaceSize)
277 {
278 ZSTD_DCtx* const dctx = (ZSTD_DCtx*) workspace;
279
280 if ((size_t)workspace & 7) return NULL; /* 8-aligned */
281 if (workspaceSize < sizeof(ZSTD_DCtx)) return NULL; /* minimum size */
282
283 ZSTD_initDCtx_internal(dctx);
284 dctx->staticSize = workspaceSize;
285 dctx->inBuff = (char*)(dctx+1);
286 return dctx;
287 }
288
ZSTD_createDCtx_internal(ZSTD_customMem customMem)289 static ZSTD_DCtx* ZSTD_createDCtx_internal(ZSTD_customMem customMem) {
290 if ((!customMem.customAlloc) ^ (!customMem.customFree)) return NULL;
291
292 { ZSTD_DCtx* const dctx = (ZSTD_DCtx*)ZSTD_customMalloc(sizeof(*dctx), customMem);
293 if (!dctx) return NULL;
294 dctx->customMem = customMem;
295 ZSTD_initDCtx_internal(dctx);
296 return dctx;
297 }
298 }
299
ZSTD_createDCtx_advanced(ZSTD_customMem customMem)300 ZSTD_DCtx* ZSTD_createDCtx_advanced(ZSTD_customMem customMem)
301 {
302 return ZSTD_createDCtx_internal(customMem);
303 }
304
ZSTD_createDCtx(void)305 ZSTD_DCtx* ZSTD_createDCtx(void)
306 {
307 DEBUGLOG(3, "ZSTD_createDCtx");
308 return ZSTD_createDCtx_internal(ZSTD_defaultCMem);
309 }
310
ZSTD_clearDict(ZSTD_DCtx * dctx)311 static void ZSTD_clearDict(ZSTD_DCtx* dctx)
312 {
313 ZSTD_freeDDict(dctx->ddictLocal);
314 dctx->ddictLocal = NULL;
315 dctx->ddict = NULL;
316 dctx->dictUses = ZSTD_dont_use;
317 }
318
ZSTD_freeDCtx(ZSTD_DCtx * dctx)319 size_t ZSTD_freeDCtx(ZSTD_DCtx* dctx)
320 {
321 if (dctx==NULL) return 0; /* support free on NULL */
322 RETURN_ERROR_IF(dctx->staticSize, memory_allocation, "not compatible with static DCtx");
323 { ZSTD_customMem const cMem = dctx->customMem;
324 ZSTD_clearDict(dctx);
325 ZSTD_customFree(dctx->inBuff, cMem);
326 dctx->inBuff = NULL;
327 #if defined(ZSTD_LEGACY_SUPPORT) && (ZSTD_LEGACY_SUPPORT >= 1)
328 if (dctx->legacyContext)
329 ZSTD_freeLegacyStreamContext(dctx->legacyContext, dctx->previousLegacyVersion);
330 #endif
331 if (dctx->ddictSet) {
332 ZSTD_freeDDictHashSet(dctx->ddictSet, cMem);
333 dctx->ddictSet = NULL;
334 }
335 ZSTD_customFree(dctx, cMem);
336 return 0;
337 }
338 }
339
340 /* no longer useful */
ZSTD_copyDCtx(ZSTD_DCtx * dstDCtx,const ZSTD_DCtx * srcDCtx)341 void ZSTD_copyDCtx(ZSTD_DCtx* dstDCtx, const ZSTD_DCtx* srcDCtx)
342 {
343 size_t const toCopy = (size_t)((char*)(&dstDCtx->inBuff) - (char*)dstDCtx);
344 ZSTD_memcpy(dstDCtx, srcDCtx, toCopy); /* no need to copy workspace */
345 }
346
347 /* Given a dctx with a digested frame params, re-selects the correct ZSTD_DDict based on
348 * the requested dict ID from the frame. If there exists a reference to the correct ZSTD_DDict, then
349 * accordingly sets the ddict to be used to decompress the frame.
350 *
351 * If no DDict is found, then no action is taken, and the ZSTD_DCtx::ddict remains as-is.
352 *
353 * ZSTD_d_refMultipleDDicts must be enabled for this function to be called.
354 */
ZSTD_DCtx_selectFrameDDict(ZSTD_DCtx * dctx)355 static void ZSTD_DCtx_selectFrameDDict(ZSTD_DCtx* dctx) {
356 assert(dctx->refMultipleDDicts && dctx->ddictSet);
357 DEBUGLOG(4, "Adjusting DDict based on requested dict ID from frame");
358 if (dctx->ddict) {
359 const ZSTD_DDict* frameDDict = ZSTD_DDictHashSet_getDDict(dctx->ddictSet, dctx->fParams.dictID);
360 if (frameDDict) {
361 DEBUGLOG(4, "DDict found!");
362 ZSTD_clearDict(dctx);
363 dctx->dictID = dctx->fParams.dictID;
364 dctx->ddict = frameDDict;
365 dctx->dictUses = ZSTD_use_indefinitely;
366 }
367 }
368 }
369
370
371 /*-*************************************************************
372 * Frame header decoding
373 ***************************************************************/
374
375 /*! ZSTD_isFrame() :
376 * Tells if the content of `buffer` starts with a valid Frame Identifier.
377 * Note : Frame Identifier is 4 bytes. If `size < 4`, @return will always be 0.
378 * Note 2 : Legacy Frame Identifiers are considered valid only if Legacy Support is enabled.
379 * Note 3 : Skippable Frame Identifiers are considered valid. */
ZSTD_isFrame(const void * buffer,size_t size)380 unsigned ZSTD_isFrame(const void* buffer, size_t size)
381 {
382 if (size < ZSTD_FRAMEIDSIZE) return 0;
383 { U32 const magic = MEM_readLE32(buffer);
384 if (magic == ZSTD_MAGICNUMBER) return 1;
385 if ((magic & ZSTD_MAGIC_SKIPPABLE_MASK) == ZSTD_MAGIC_SKIPPABLE_START) return 1;
386 }
387 #if defined(ZSTD_LEGACY_SUPPORT) && (ZSTD_LEGACY_SUPPORT >= 1)
388 if (ZSTD_isLegacy(buffer, size)) return 1;
389 #endif
390 return 0;
391 }
392
393 /*! ZSTD_isSkippableFrame() :
394 * Tells if the content of `buffer` starts with a valid Frame Identifier for a skippable frame.
395 * Note : Frame Identifier is 4 bytes. If `size < 4`, @return will always be 0.
396 */
ZSTD_isSkippableFrame(const void * buffer,size_t size)397 unsigned ZSTD_isSkippableFrame(const void* buffer, size_t size)
398 {
399 if (size < ZSTD_FRAMEIDSIZE) return 0;
400 { U32 const magic = MEM_readLE32(buffer);
401 if ((magic & ZSTD_MAGIC_SKIPPABLE_MASK) == ZSTD_MAGIC_SKIPPABLE_START) return 1;
402 }
403 return 0;
404 }
405
406 /** ZSTD_frameHeaderSize_internal() :
407 * srcSize must be large enough to reach header size fields.
408 * note : only works for formats ZSTD_f_zstd1 and ZSTD_f_zstd1_magicless.
409 * @return : size of the Frame Header
410 * or an error code, which can be tested with ZSTD_isError() */
ZSTD_frameHeaderSize_internal(const void * src,size_t srcSize,ZSTD_format_e format)411 static size_t ZSTD_frameHeaderSize_internal(const void* src, size_t srcSize, ZSTD_format_e format)
412 {
413 size_t const minInputSize = ZSTD_startingInputLength(format);
414 RETURN_ERROR_IF(srcSize < minInputSize, srcSize_wrong, "");
415
416 { BYTE const fhd = ((const BYTE*)src)[minInputSize-1];
417 U32 const dictID= fhd & 3;
418 U32 const singleSegment = (fhd >> 5) & 1;
419 U32 const fcsId = fhd >> 6;
420 return minInputSize + !singleSegment
421 + ZSTD_did_fieldSize[dictID] + ZSTD_fcs_fieldSize[fcsId]
422 + (singleSegment && !fcsId);
423 }
424 }
425
426 /** ZSTD_frameHeaderSize() :
427 * srcSize must be >= ZSTD_frameHeaderSize_prefix.
428 * @return : size of the Frame Header,
429 * or an error code (if srcSize is too small) */
ZSTD_frameHeaderSize(const void * src,size_t srcSize)430 size_t ZSTD_frameHeaderSize(const void* src, size_t srcSize)
431 {
432 return ZSTD_frameHeaderSize_internal(src, srcSize, ZSTD_f_zstd1);
433 }
434
435
436 /** ZSTD_getFrameHeader_advanced() :
437 * decode Frame Header, or require larger `srcSize`.
438 * note : only works for formats ZSTD_f_zstd1 and ZSTD_f_zstd1_magicless
439 * @return : 0, `zfhPtr` is correctly filled,
440 * >0, `srcSize` is too small, value is wanted `srcSize` amount,
441 * or an error code, which can be tested using ZSTD_isError() */
ZSTD_getFrameHeader_advanced(ZSTD_frameHeader * zfhPtr,const void * src,size_t srcSize,ZSTD_format_e format)442 size_t ZSTD_getFrameHeader_advanced(ZSTD_frameHeader* zfhPtr, const void* src, size_t srcSize, ZSTD_format_e format)
443 {
444 const BYTE* ip = (const BYTE*)src;
445 size_t const minInputSize = ZSTD_startingInputLength(format);
446
447 ZSTD_memset(zfhPtr, 0, sizeof(*zfhPtr)); /* not strictly necessary, but static analyzer do not understand that zfhPtr is only going to be read only if return value is zero, since they are 2 different signals */
448 if (srcSize < minInputSize) return minInputSize;
449 RETURN_ERROR_IF(src==NULL, GENERIC, "invalid parameter");
450
451 if ( (format != ZSTD_f_zstd1_magicless)
452 && (MEM_readLE32(src) != ZSTD_MAGICNUMBER) ) {
453 if ((MEM_readLE32(src) & ZSTD_MAGIC_SKIPPABLE_MASK) == ZSTD_MAGIC_SKIPPABLE_START) {
454 /* skippable frame */
455 if (srcSize < ZSTD_SKIPPABLEHEADERSIZE)
456 return ZSTD_SKIPPABLEHEADERSIZE; /* magic number + frame length */
457 ZSTD_memset(zfhPtr, 0, sizeof(*zfhPtr));
458 zfhPtr->frameContentSize = MEM_readLE32((const char *)src + ZSTD_FRAMEIDSIZE);
459 zfhPtr->frameType = ZSTD_skippableFrame;
460 return 0;
461 }
462 RETURN_ERROR(prefix_unknown, "");
463 }
464
465 /* ensure there is enough `srcSize` to fully read/decode frame header */
466 { size_t const fhsize = ZSTD_frameHeaderSize_internal(src, srcSize, format);
467 if (srcSize < fhsize) return fhsize;
468 zfhPtr->headerSize = (U32)fhsize;
469 }
470
471 { BYTE const fhdByte = ip[minInputSize-1];
472 size_t pos = minInputSize;
473 U32 const dictIDSizeCode = fhdByte&3;
474 U32 const checksumFlag = (fhdByte>>2)&1;
475 U32 const singleSegment = (fhdByte>>5)&1;
476 U32 const fcsID = fhdByte>>6;
477 U64 windowSize = 0;
478 U32 dictID = 0;
479 U64 frameContentSize = ZSTD_CONTENTSIZE_UNKNOWN;
480 RETURN_ERROR_IF((fhdByte & 0x08) != 0, frameParameter_unsupported,
481 "reserved bits, must be zero");
482
483 if (!singleSegment) {
484 BYTE const wlByte = ip[pos++];
485 U32 const windowLog = (wlByte >> 3) + ZSTD_WINDOWLOG_ABSOLUTEMIN;
486 RETURN_ERROR_IF(windowLog > ZSTD_WINDOWLOG_MAX, frameParameter_windowTooLarge, "");
487 windowSize = (1ULL << windowLog);
488 windowSize += (windowSize >> 3) * (wlByte&7);
489 }
490 switch(dictIDSizeCode)
491 {
492 default:
493 assert(0); /* impossible */
494 ZSTD_FALLTHROUGH;
495 case 0 : break;
496 case 1 : dictID = ip[pos]; pos++; break;
497 case 2 : dictID = MEM_readLE16(ip+pos); pos+=2; break;
498 case 3 : dictID = MEM_readLE32(ip+pos); pos+=4; break;
499 }
500 switch(fcsID)
501 {
502 default:
503 assert(0); /* impossible */
504 ZSTD_FALLTHROUGH;
505 case 0 : if (singleSegment) frameContentSize = ip[pos]; break;
506 case 1 : frameContentSize = MEM_readLE16(ip+pos)+256; break;
507 case 2 : frameContentSize = MEM_readLE32(ip+pos); break;
508 case 3 : frameContentSize = MEM_readLE64(ip+pos); break;
509 }
510 if (singleSegment) windowSize = frameContentSize;
511
512 zfhPtr->frameType = ZSTD_frame;
513 zfhPtr->frameContentSize = frameContentSize;
514 zfhPtr->windowSize = windowSize;
515 zfhPtr->blockSizeMax = (unsigned) MIN(windowSize, ZSTD_BLOCKSIZE_MAX);
516 zfhPtr->dictID = dictID;
517 zfhPtr->checksumFlag = checksumFlag;
518 }
519 return 0;
520 }
521
522 /** ZSTD_getFrameHeader() :
523 * decode Frame Header, or require larger `srcSize`.
524 * note : this function does not consume input, it only reads it.
525 * @return : 0, `zfhPtr` is correctly filled,
526 * >0, `srcSize` is too small, value is wanted `srcSize` amount,
527 * or an error code, which can be tested using ZSTD_isError() */
ZSTD_getFrameHeader(ZSTD_frameHeader * zfhPtr,const void * src,size_t srcSize)528 size_t ZSTD_getFrameHeader(ZSTD_frameHeader* zfhPtr, const void* src, size_t srcSize)
529 {
530 return ZSTD_getFrameHeader_advanced(zfhPtr, src, srcSize, ZSTD_f_zstd1);
531 }
532
533 /** ZSTD_getFrameContentSize() :
534 * compatible with legacy mode
535 * @return : decompressed size of the single frame pointed to be `src` if known, otherwise
536 * - ZSTD_CONTENTSIZE_UNKNOWN if the size cannot be determined
537 * - ZSTD_CONTENTSIZE_ERROR if an error occurred (e.g. invalid magic number, srcSize too small) */
ZSTD_getFrameContentSize(const void * src,size_t srcSize)538 unsigned long long ZSTD_getFrameContentSize(const void *src, size_t srcSize)
539 {
540 #if defined(ZSTD_LEGACY_SUPPORT) && (ZSTD_LEGACY_SUPPORT >= 1)
541 if (ZSTD_isLegacy(src, srcSize)) {
542 unsigned long long const ret = ZSTD_getDecompressedSize_legacy(src, srcSize);
543 return ret == 0 ? ZSTD_CONTENTSIZE_UNKNOWN : ret;
544 }
545 #endif
546 { ZSTD_frameHeader zfh;
547 if (ZSTD_getFrameHeader(&zfh, src, srcSize) != 0)
548 return ZSTD_CONTENTSIZE_ERROR;
549 if (zfh.frameType == ZSTD_skippableFrame) {
550 return 0;
551 } else {
552 return zfh.frameContentSize;
553 } }
554 }
555
readSkippableFrameSize(void const * src,size_t srcSize)556 static size_t readSkippableFrameSize(void const* src, size_t srcSize)
557 {
558 size_t const skippableHeaderSize = ZSTD_SKIPPABLEHEADERSIZE;
559 U32 sizeU32;
560
561 RETURN_ERROR_IF(srcSize < ZSTD_SKIPPABLEHEADERSIZE, srcSize_wrong, "");
562
563 sizeU32 = MEM_readLE32((BYTE const*)src + ZSTD_FRAMEIDSIZE);
564 RETURN_ERROR_IF((U32)(sizeU32 + ZSTD_SKIPPABLEHEADERSIZE) < sizeU32,
565 frameParameter_unsupported, "");
566 {
567 size_t const skippableSize = skippableHeaderSize + sizeU32;
568 RETURN_ERROR_IF(skippableSize > srcSize, srcSize_wrong, "");
569 return skippableSize;
570 }
571 }
572
573 /*! ZSTD_readSkippableFrame() :
574 * Retrieves a zstd skippable frame containing data given by src, and writes it to dst buffer.
575 *
576 * The parameter magicVariant will receive the magicVariant that was supplied when the frame was written,
577 * i.e. magicNumber - ZSTD_MAGIC_SKIPPABLE_START. This can be NULL if the caller is not interested
578 * in the magicVariant.
579 *
580 * Returns an error if destination buffer is not large enough, or if the frame is not skippable.
581 *
582 * @return : number of bytes written or a ZSTD error.
583 */
ZSTD_readSkippableFrame(void * dst,size_t dstCapacity,unsigned * magicVariant,const void * src,size_t srcSize)584 ZSTDLIB_API size_t ZSTD_readSkippableFrame(void* dst, size_t dstCapacity, unsigned* magicVariant,
585 const void* src, size_t srcSize)
586 {
587 U32 const magicNumber = MEM_readLE32(src);
588 size_t skippableFrameSize = readSkippableFrameSize(src, srcSize);
589 size_t skippableContentSize = skippableFrameSize - ZSTD_SKIPPABLEHEADERSIZE;
590
591 /* check input validity */
592 RETURN_ERROR_IF(!ZSTD_isSkippableFrame(src, srcSize), frameParameter_unsupported, "");
593 RETURN_ERROR_IF(skippableFrameSize < ZSTD_SKIPPABLEHEADERSIZE || skippableFrameSize > srcSize, srcSize_wrong, "");
594 RETURN_ERROR_IF(skippableContentSize > dstCapacity, dstSize_tooSmall, "");
595
596 /* deliver payload */
597 if (skippableContentSize > 0 && dst != NULL)
598 ZSTD_memcpy(dst, (const BYTE *)src + ZSTD_SKIPPABLEHEADERSIZE, skippableContentSize);
599 if (magicVariant != NULL)
600 *magicVariant = magicNumber - ZSTD_MAGIC_SKIPPABLE_START;
601 return skippableContentSize;
602 }
603
604 /** ZSTD_findDecompressedSize() :
605 * compatible with legacy mode
606 * `srcSize` must be the exact length of some number of ZSTD compressed and/or
607 * skippable frames
608 * @return : decompressed size of the frames contained */
ZSTD_findDecompressedSize(const void * src,size_t srcSize)609 unsigned long long ZSTD_findDecompressedSize(const void* src, size_t srcSize)
610 {
611 unsigned long long totalDstSize = 0;
612
613 while (srcSize >= ZSTD_startingInputLength(ZSTD_f_zstd1)) {
614 U32 const magicNumber = MEM_readLE32(src);
615
616 if ((magicNumber & ZSTD_MAGIC_SKIPPABLE_MASK) == ZSTD_MAGIC_SKIPPABLE_START) {
617 size_t const skippableSize = readSkippableFrameSize(src, srcSize);
618 if (ZSTD_isError(skippableSize)) {
619 return ZSTD_CONTENTSIZE_ERROR;
620 }
621 assert(skippableSize <= srcSize);
622
623 src = (const BYTE *)src + skippableSize;
624 srcSize -= skippableSize;
625 continue;
626 }
627
628 { unsigned long long const ret = ZSTD_getFrameContentSize(src, srcSize);
629 if (ret >= ZSTD_CONTENTSIZE_ERROR) return ret;
630
631 /* check for overflow */
632 if (totalDstSize + ret < totalDstSize) return ZSTD_CONTENTSIZE_ERROR;
633 totalDstSize += ret;
634 }
635 { size_t const frameSrcSize = ZSTD_findFrameCompressedSize(src, srcSize);
636 if (ZSTD_isError(frameSrcSize)) {
637 return ZSTD_CONTENTSIZE_ERROR;
638 }
639
640 src = (const BYTE *)src + frameSrcSize;
641 srcSize -= frameSrcSize;
642 }
643 } /* while (srcSize >= ZSTD_frameHeaderSize_prefix) */
644
645 if (srcSize) return ZSTD_CONTENTSIZE_ERROR;
646
647 return totalDstSize;
648 }
649
650 /** ZSTD_getDecompressedSize() :
651 * compatible with legacy mode
652 * @return : decompressed size if known, 0 otherwise
653 note : 0 can mean any of the following :
654 - frame content is empty
655 - decompressed size field is not present in frame header
656 - frame header unknown / not supported
657 - frame header not complete (`srcSize` too small) */
ZSTD_getDecompressedSize(const void * src,size_t srcSize)658 unsigned long long ZSTD_getDecompressedSize(const void* src, size_t srcSize)
659 {
660 unsigned long long const ret = ZSTD_getFrameContentSize(src, srcSize);
661 ZSTD_STATIC_ASSERT(ZSTD_CONTENTSIZE_ERROR < ZSTD_CONTENTSIZE_UNKNOWN);
662 return (ret >= ZSTD_CONTENTSIZE_ERROR) ? 0 : ret;
663 }
664
665
666 /** ZSTD_decodeFrameHeader() :
667 * `headerSize` must be the size provided by ZSTD_frameHeaderSize().
668 * If multiple DDict references are enabled, also will choose the correct DDict to use.
669 * @return : 0 if success, or an error code, which can be tested using ZSTD_isError() */
ZSTD_decodeFrameHeader(ZSTD_DCtx * dctx,const void * src,size_t headerSize)670 static size_t ZSTD_decodeFrameHeader(ZSTD_DCtx* dctx, const void* src, size_t headerSize)
671 {
672 size_t const result = ZSTD_getFrameHeader_advanced(&(dctx->fParams), src, headerSize, dctx->format);
673 if (ZSTD_isError(result)) return result; /* invalid header */
674 RETURN_ERROR_IF(result>0, srcSize_wrong, "headerSize too small");
675
676 /* Reference DDict requested by frame if dctx references multiple ddicts */
677 if (dctx->refMultipleDDicts == ZSTD_rmd_refMultipleDDicts && dctx->ddictSet) {
678 ZSTD_DCtx_selectFrameDDict(dctx);
679 }
680
681 #ifndef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
682 /* Skip the dictID check in fuzzing mode, because it makes the search
683 * harder.
684 */
685 RETURN_ERROR_IF(dctx->fParams.dictID && (dctx->dictID != dctx->fParams.dictID),
686 dictionary_wrong, "");
687 #endif
688 dctx->validateChecksum = (dctx->fParams.checksumFlag && !dctx->forceIgnoreChecksum) ? 1 : 0;
689 if (dctx->validateChecksum) XXH64_reset(&dctx->xxhState, 0);
690 dctx->processedCSize += headerSize;
691 return 0;
692 }
693
ZSTD_errorFrameSizeInfo(size_t ret)694 static ZSTD_frameSizeInfo ZSTD_errorFrameSizeInfo(size_t ret)
695 {
696 ZSTD_frameSizeInfo frameSizeInfo;
697 frameSizeInfo.compressedSize = ret;
698 frameSizeInfo.decompressedBound = ZSTD_CONTENTSIZE_ERROR;
699 return frameSizeInfo;
700 }
701
ZSTD_findFrameSizeInfo(const void * src,size_t srcSize)702 static ZSTD_frameSizeInfo ZSTD_findFrameSizeInfo(const void* src, size_t srcSize)
703 {
704 ZSTD_frameSizeInfo frameSizeInfo;
705 ZSTD_memset(&frameSizeInfo, 0, sizeof(ZSTD_frameSizeInfo));
706
707 #if defined(ZSTD_LEGACY_SUPPORT) && (ZSTD_LEGACY_SUPPORT >= 1)
708 if (ZSTD_isLegacy(src, srcSize))
709 return ZSTD_findFrameSizeInfoLegacy(src, srcSize);
710 #endif
711
712 if ((srcSize >= ZSTD_SKIPPABLEHEADERSIZE)
713 && (MEM_readLE32(src) & ZSTD_MAGIC_SKIPPABLE_MASK) == ZSTD_MAGIC_SKIPPABLE_START) {
714 frameSizeInfo.compressedSize = readSkippableFrameSize(src, srcSize);
715 assert(ZSTD_isError(frameSizeInfo.compressedSize) ||
716 frameSizeInfo.compressedSize <= srcSize);
717 return frameSizeInfo;
718 } else {
719 const BYTE* ip = (const BYTE*)src;
720 const BYTE* const ipstart = ip;
721 size_t remainingSize = srcSize;
722 size_t nbBlocks = 0;
723 ZSTD_frameHeader zfh;
724
725 /* Extract Frame Header */
726 { size_t const ret = ZSTD_getFrameHeader(&zfh, src, srcSize);
727 if (ZSTD_isError(ret))
728 return ZSTD_errorFrameSizeInfo(ret);
729 if (ret > 0)
730 return ZSTD_errorFrameSizeInfo(ERROR(srcSize_wrong));
731 }
732
733 ip += zfh.headerSize;
734 remainingSize -= zfh.headerSize;
735
736 /* Iterate over each block */
737 while (1) {
738 blockProperties_t blockProperties;
739 size_t const cBlockSize = ZSTD_getcBlockSize(ip, remainingSize, &blockProperties);
740 if (ZSTD_isError(cBlockSize))
741 return ZSTD_errorFrameSizeInfo(cBlockSize);
742
743 if (ZSTD_blockHeaderSize + cBlockSize > remainingSize)
744 return ZSTD_errorFrameSizeInfo(ERROR(srcSize_wrong));
745
746 ip += ZSTD_blockHeaderSize + cBlockSize;
747 remainingSize -= ZSTD_blockHeaderSize + cBlockSize;
748 nbBlocks++;
749
750 if (blockProperties.lastBlock) break;
751 }
752
753 /* Final frame content checksum */
754 if (zfh.checksumFlag) {
755 if (remainingSize < 4)
756 return ZSTD_errorFrameSizeInfo(ERROR(srcSize_wrong));
757 ip += 4;
758 }
759
760 frameSizeInfo.compressedSize = (size_t)(ip - ipstart);
761 frameSizeInfo.decompressedBound = (zfh.frameContentSize != ZSTD_CONTENTSIZE_UNKNOWN)
762 ? zfh.frameContentSize
763 : nbBlocks * zfh.blockSizeMax;
764 return frameSizeInfo;
765 }
766 }
767
768 /** ZSTD_findFrameCompressedSize() :
769 * compatible with legacy mode
770 * `src` must point to the start of a ZSTD frame, ZSTD legacy frame, or skippable frame
771 * `srcSize` must be at least as large as the frame contained
772 * @return : the compressed size of the frame starting at `src` */
ZSTD_findFrameCompressedSize(const void * src,size_t srcSize)773 size_t ZSTD_findFrameCompressedSize(const void *src, size_t srcSize)
774 {
775 ZSTD_frameSizeInfo const frameSizeInfo = ZSTD_findFrameSizeInfo(src, srcSize);
776 return frameSizeInfo.compressedSize;
777 }
778
779 /** ZSTD_decompressBound() :
780 * compatible with legacy mode
781 * `src` must point to the start of a ZSTD frame or a skippeable frame
782 * `srcSize` must be at least as large as the frame contained
783 * @return : the maximum decompressed size of the compressed source
784 */
ZSTD_decompressBound(const void * src,size_t srcSize)785 unsigned long long ZSTD_decompressBound(const void* src, size_t srcSize)
786 {
787 unsigned long long bound = 0;
788 /* Iterate over each frame */
789 while (srcSize > 0) {
790 ZSTD_frameSizeInfo const frameSizeInfo = ZSTD_findFrameSizeInfo(src, srcSize);
791 size_t const compressedSize = frameSizeInfo.compressedSize;
792 unsigned long long const decompressedBound = frameSizeInfo.decompressedBound;
793 if (ZSTD_isError(compressedSize) || decompressedBound == ZSTD_CONTENTSIZE_ERROR)
794 return ZSTD_CONTENTSIZE_ERROR;
795 assert(srcSize >= compressedSize);
796 src = (const BYTE*)src + compressedSize;
797 srcSize -= compressedSize;
798 bound += decompressedBound;
799 }
800 return bound;
801 }
802
803
804 /*-*************************************************************
805 * Frame decoding
806 ***************************************************************/
807
808 /** ZSTD_insertBlock() :
809 * insert `src` block into `dctx` history. Useful to track uncompressed blocks. */
ZSTD_insertBlock(ZSTD_DCtx * dctx,const void * blockStart,size_t blockSize)810 size_t ZSTD_insertBlock(ZSTD_DCtx* dctx, const void* blockStart, size_t blockSize)
811 {
812 DEBUGLOG(5, "ZSTD_insertBlock: %u bytes", (unsigned)blockSize);
813 ZSTD_checkContinuity(dctx, blockStart, blockSize);
814 dctx->previousDstEnd = (const char*)blockStart + blockSize;
815 return blockSize;
816 }
817
818
ZSTD_copyRawBlock(void * dst,size_t dstCapacity,const void * src,size_t srcSize)819 static size_t ZSTD_copyRawBlock(void* dst, size_t dstCapacity,
820 const void* src, size_t srcSize)
821 {
822 DEBUGLOG(5, "ZSTD_copyRawBlock");
823 RETURN_ERROR_IF(srcSize > dstCapacity, dstSize_tooSmall, "");
824 if (dst == NULL) {
825 if (srcSize == 0) return 0;
826 RETURN_ERROR(dstBuffer_null, "");
827 }
828 ZSTD_memcpy(dst, src, srcSize);
829 return srcSize;
830 }
831
ZSTD_setRleBlock(void * dst,size_t dstCapacity,BYTE b,size_t regenSize)832 static size_t ZSTD_setRleBlock(void* dst, size_t dstCapacity,
833 BYTE b,
834 size_t regenSize)
835 {
836 RETURN_ERROR_IF(regenSize > dstCapacity, dstSize_tooSmall, "");
837 if (dst == NULL) {
838 if (regenSize == 0) return 0;
839 RETURN_ERROR(dstBuffer_null, "");
840 }
841 ZSTD_memset(dst, b, regenSize);
842 return regenSize;
843 }
844
ZSTD_DCtx_trace_end(ZSTD_DCtx const * dctx,U64 uncompressedSize,U64 compressedSize,unsigned streaming)845 static void ZSTD_DCtx_trace_end(ZSTD_DCtx const* dctx, U64 uncompressedSize, U64 compressedSize, unsigned streaming)
846 {
847 #if ZSTD_TRACE
848 if (dctx->traceCtx && ZSTD_trace_decompress_end != NULL) {
849 ZSTD_Trace trace;
850 ZSTD_memset(&trace, 0, sizeof(trace));
851 trace.version = ZSTD_VERSION_NUMBER;
852 trace.streaming = streaming;
853 if (dctx->ddict) {
854 trace.dictionaryID = ZSTD_getDictID_fromDDict(dctx->ddict);
855 trace.dictionarySize = ZSTD_DDict_dictSize(dctx->ddict);
856 trace.dictionaryIsCold = dctx->ddictIsCold;
857 }
858 trace.uncompressedSize = (size_t)uncompressedSize;
859 trace.compressedSize = (size_t)compressedSize;
860 trace.dctx = dctx;
861 ZSTD_trace_decompress_end(dctx->traceCtx, &trace);
862 }
863 #else
864 (void)dctx;
865 (void)uncompressedSize;
866 (void)compressedSize;
867 (void)streaming;
868 #endif
869 }
870
871
872 /*! ZSTD_decompressFrame() :
873 * @dctx must be properly initialized
874 * will update *srcPtr and *srcSizePtr,
875 * to make *srcPtr progress by one frame. */
ZSTD_decompressFrame(ZSTD_DCtx * dctx,void * dst,size_t dstCapacity,const void ** srcPtr,size_t * srcSizePtr)876 static size_t ZSTD_decompressFrame(ZSTD_DCtx* dctx,
877 void* dst, size_t dstCapacity,
878 const void** srcPtr, size_t *srcSizePtr)
879 {
880 const BYTE* const istart = (const BYTE*)(*srcPtr);
881 const BYTE* ip = istart;
882 BYTE* const ostart = (BYTE*)dst;
883 BYTE* const oend = dstCapacity != 0 ? ostart + dstCapacity : ostart;
884 BYTE* op = ostart;
885 size_t remainingSrcSize = *srcSizePtr;
886
887 DEBUGLOG(4, "ZSTD_decompressFrame (srcSize:%i)", (int)*srcSizePtr);
888
889 /* check */
890 RETURN_ERROR_IF(
891 remainingSrcSize < ZSTD_FRAMEHEADERSIZE_MIN(dctx->format)+ZSTD_blockHeaderSize,
892 srcSize_wrong, "");
893
894 /* Frame Header */
895 { size_t const frameHeaderSize = ZSTD_frameHeaderSize_internal(
896 ip, ZSTD_FRAMEHEADERSIZE_PREFIX(dctx->format), dctx->format);
897 if (ZSTD_isError(frameHeaderSize)) return frameHeaderSize;
898 RETURN_ERROR_IF(remainingSrcSize < frameHeaderSize+ZSTD_blockHeaderSize,
899 srcSize_wrong, "");
900 FORWARD_IF_ERROR( ZSTD_decodeFrameHeader(dctx, ip, frameHeaderSize) , "");
901 ip += frameHeaderSize; remainingSrcSize -= frameHeaderSize;
902 }
903
904 /* Loop on each block */
905 while (1) {
906 size_t decodedSize;
907 blockProperties_t blockProperties;
908 size_t const cBlockSize = ZSTD_getcBlockSize(ip, remainingSrcSize, &blockProperties);
909 if (ZSTD_isError(cBlockSize)) return cBlockSize;
910
911 ip += ZSTD_blockHeaderSize;
912 remainingSrcSize -= ZSTD_blockHeaderSize;
913 RETURN_ERROR_IF(cBlockSize > remainingSrcSize, srcSize_wrong, "");
914
915 switch(blockProperties.blockType)
916 {
917 case bt_compressed:
918 decodedSize = ZSTD_decompressBlock_internal(dctx, op, (size_t)(oend-op), ip, cBlockSize, /* frame */ 1, not_streaming);
919 break;
920 case bt_raw :
921 decodedSize = ZSTD_copyRawBlock(op, (size_t)(oend-op), ip, cBlockSize);
922 break;
923 case bt_rle :
924 decodedSize = ZSTD_setRleBlock(op, (size_t)(oend-op), *ip, blockProperties.origSize);
925 break;
926 case bt_reserved :
927 default:
928 RETURN_ERROR(corruption_detected, "invalid block type");
929 }
930
931 if (ZSTD_isError(decodedSize)) return decodedSize;
932 if (dctx->validateChecksum)
933 XXH64_update(&dctx->xxhState, op, decodedSize);
934 if (decodedSize != 0)
935 op += decodedSize;
936 assert(ip != NULL);
937 ip += cBlockSize;
938 remainingSrcSize -= cBlockSize;
939 if (blockProperties.lastBlock) break;
940 }
941
942 if (dctx->fParams.frameContentSize != ZSTD_CONTENTSIZE_UNKNOWN) {
943 RETURN_ERROR_IF((U64)(op-ostart) != dctx->fParams.frameContentSize,
944 corruption_detected, "");
945 }
946 if (dctx->fParams.checksumFlag) { /* Frame content checksum verification */
947 RETURN_ERROR_IF(remainingSrcSize<4, checksum_wrong, "");
948 if (!dctx->forceIgnoreChecksum) {
949 U32 const checkCalc = (U32)XXH64_digest(&dctx->xxhState);
950 U32 checkRead;
951 checkRead = MEM_readLE32(ip);
952 RETURN_ERROR_IF(checkRead != checkCalc, checksum_wrong, "");
953 }
954 ip += 4;
955 remainingSrcSize -= 4;
956 }
957 ZSTD_DCtx_trace_end(dctx, (U64)(op-ostart), (U64)(ip-istart), /* streaming */ 0);
958 /* Allow caller to get size read */
959 *srcPtr = ip;
960 *srcSizePtr = remainingSrcSize;
961 return (size_t)(op-ostart);
962 }
963
ZSTD_decompressMultiFrame(ZSTD_DCtx * dctx,void * dst,size_t dstCapacity,const void * src,size_t srcSize,const void * dict,size_t dictSize,const ZSTD_DDict * ddict)964 static size_t ZSTD_decompressMultiFrame(ZSTD_DCtx* dctx,
965 void* dst, size_t dstCapacity,
966 const void* src, size_t srcSize,
967 const void* dict, size_t dictSize,
968 const ZSTD_DDict* ddict)
969 {
970 void* const dststart = dst;
971 int moreThan1Frame = 0;
972
973 DEBUGLOG(5, "ZSTD_decompressMultiFrame");
974 assert(dict==NULL || ddict==NULL); /* either dict or ddict set, not both */
975
976 if (ddict) {
977 dict = ZSTD_DDict_dictContent(ddict);
978 dictSize = ZSTD_DDict_dictSize(ddict);
979 }
980
981 while (srcSize >= ZSTD_startingInputLength(dctx->format)) {
982
983 #if defined(ZSTD_LEGACY_SUPPORT) && (ZSTD_LEGACY_SUPPORT >= 1)
984 if (ZSTD_isLegacy(src, srcSize)) {
985 size_t decodedSize;
986 size_t const frameSize = ZSTD_findFrameCompressedSizeLegacy(src, srcSize);
987 if (ZSTD_isError(frameSize)) return frameSize;
988 RETURN_ERROR_IF(dctx->staticSize, memory_allocation,
989 "legacy support is not compatible with static dctx");
990
991 decodedSize = ZSTD_decompressLegacy(dst, dstCapacity, src, frameSize, dict, dictSize);
992 if (ZSTD_isError(decodedSize)) return decodedSize;
993
994 assert(decodedSize <= dstCapacity);
995 dst = (BYTE*)dst + decodedSize;
996 dstCapacity -= decodedSize;
997
998 src = (const BYTE*)src + frameSize;
999 srcSize -= frameSize;
1000
1001 continue;
1002 }
1003 #endif
1004
1005 { U32 const magicNumber = MEM_readLE32(src);
1006 DEBUGLOG(4, "reading magic number %08X (expecting %08X)",
1007 (unsigned)magicNumber, ZSTD_MAGICNUMBER);
1008 if ((magicNumber & ZSTD_MAGIC_SKIPPABLE_MASK) == ZSTD_MAGIC_SKIPPABLE_START) {
1009 size_t const skippableSize = readSkippableFrameSize(src, srcSize);
1010 FORWARD_IF_ERROR(skippableSize, "readSkippableFrameSize failed");
1011 assert(skippableSize <= srcSize);
1012
1013 src = (const BYTE *)src + skippableSize;
1014 srcSize -= skippableSize;
1015 continue;
1016 } }
1017
1018 if (ddict) {
1019 /* we were called from ZSTD_decompress_usingDDict */
1020 FORWARD_IF_ERROR(ZSTD_decompressBegin_usingDDict(dctx, ddict), "");
1021 } else {
1022 /* this will initialize correctly with no dict if dict == NULL, so
1023 * use this in all cases but ddict */
1024 FORWARD_IF_ERROR(ZSTD_decompressBegin_usingDict(dctx, dict, dictSize), "");
1025 }
1026 ZSTD_checkContinuity(dctx, dst, dstCapacity);
1027
1028 { const size_t res = ZSTD_decompressFrame(dctx, dst, dstCapacity,
1029 &src, &srcSize);
1030 RETURN_ERROR_IF(
1031 (ZSTD_getErrorCode(res) == ZSTD_error_prefix_unknown)
1032 && (moreThan1Frame==1),
1033 srcSize_wrong,
1034 "At least one frame successfully completed, "
1035 "but following bytes are garbage: "
1036 "it's more likely to be a srcSize error, "
1037 "specifying more input bytes than size of frame(s). "
1038 "Note: one could be unlucky, it might be a corruption error instead, "
1039 "happening right at the place where we expect zstd magic bytes. "
1040 "But this is _much_ less likely than a srcSize field error.");
1041 if (ZSTD_isError(res)) return res;
1042 assert(res <= dstCapacity);
1043 if (res != 0)
1044 dst = (BYTE*)dst + res;
1045 dstCapacity -= res;
1046 }
1047 moreThan1Frame = 1;
1048 } /* while (srcSize >= ZSTD_frameHeaderSize_prefix) */
1049
1050 RETURN_ERROR_IF(srcSize, srcSize_wrong, "input not entirely consumed");
1051
1052 return (size_t)((BYTE*)dst - (BYTE*)dststart);
1053 }
1054
ZSTD_decompress_usingDict(ZSTD_DCtx * dctx,void * dst,size_t dstCapacity,const void * src,size_t srcSize,const void * dict,size_t dictSize)1055 size_t ZSTD_decompress_usingDict(ZSTD_DCtx* dctx,
1056 void* dst, size_t dstCapacity,
1057 const void* src, size_t srcSize,
1058 const void* dict, size_t dictSize)
1059 {
1060 return ZSTD_decompressMultiFrame(dctx, dst, dstCapacity, src, srcSize, dict, dictSize, NULL);
1061 }
1062
1063
ZSTD_getDDict(ZSTD_DCtx * dctx)1064 static ZSTD_DDict const* ZSTD_getDDict(ZSTD_DCtx* dctx)
1065 {
1066 switch (dctx->dictUses) {
1067 default:
1068 assert(0 /* Impossible */);
1069 ZSTD_FALLTHROUGH;
1070 case ZSTD_dont_use:
1071 ZSTD_clearDict(dctx);
1072 return NULL;
1073 case ZSTD_use_indefinitely:
1074 return dctx->ddict;
1075 case ZSTD_use_once:
1076 dctx->dictUses = ZSTD_dont_use;
1077 return dctx->ddict;
1078 }
1079 }
1080
ZSTD_decompressDCtx(ZSTD_DCtx * dctx,void * dst,size_t dstCapacity,const void * src,size_t srcSize)1081 size_t ZSTD_decompressDCtx(ZSTD_DCtx* dctx, void* dst, size_t dstCapacity, const void* src, size_t srcSize)
1082 {
1083 return ZSTD_decompress_usingDDict(dctx, dst, dstCapacity, src, srcSize, ZSTD_getDDict(dctx));
1084 }
1085
1086
ZSTD_decompress(void * dst,size_t dstCapacity,const void * src,size_t srcSize)1087 size_t ZSTD_decompress(void* dst, size_t dstCapacity, const void* src, size_t srcSize)
1088 {
1089 #if defined(ZSTD_HEAPMODE) && (ZSTD_HEAPMODE>=1)
1090 size_t regenSize;
1091 ZSTD_DCtx* const dctx = ZSTD_createDCtx_internal(ZSTD_defaultCMem);
1092 RETURN_ERROR_IF(dctx==NULL, memory_allocation, "NULL pointer!");
1093 regenSize = ZSTD_decompressDCtx(dctx, dst, dstCapacity, src, srcSize);
1094 ZSTD_freeDCtx(dctx);
1095 return regenSize;
1096 #else /* stack mode */
1097 ZSTD_DCtx dctx;
1098 ZSTD_initDCtx_internal(&dctx);
1099 return ZSTD_decompressDCtx(&dctx, dst, dstCapacity, src, srcSize);
1100 #endif
1101 }
1102
1103
1104 /*-**************************************
1105 * Advanced Streaming Decompression API
1106 * Bufferless and synchronous
1107 ****************************************/
ZSTD_nextSrcSizeToDecompress(ZSTD_DCtx * dctx)1108 size_t ZSTD_nextSrcSizeToDecompress(ZSTD_DCtx* dctx) { return dctx->expected; }
1109
1110 /**
1111 * Similar to ZSTD_nextSrcSizeToDecompress(), but when when a block input can be streamed,
1112 * we allow taking a partial block as the input. Currently only raw uncompressed blocks can
1113 * be streamed.
1114 *
1115 * For blocks that can be streamed, this allows us to reduce the latency until we produce
1116 * output, and avoid copying the input.
1117 *
1118 * @param inputSize - The total amount of input that the caller currently has.
1119 */
ZSTD_nextSrcSizeToDecompressWithInputSize(ZSTD_DCtx * dctx,size_t inputSize)1120 static size_t ZSTD_nextSrcSizeToDecompressWithInputSize(ZSTD_DCtx* dctx, size_t inputSize) {
1121 if (!(dctx->stage == ZSTDds_decompressBlock || dctx->stage == ZSTDds_decompressLastBlock))
1122 return dctx->expected;
1123 if (dctx->bType != bt_raw)
1124 return dctx->expected;
1125 return BOUNDED(1, inputSize, dctx->expected);
1126 }
1127
ZSTD_nextInputType(ZSTD_DCtx * dctx)1128 ZSTD_nextInputType_e ZSTD_nextInputType(ZSTD_DCtx* dctx) {
1129 switch(dctx->stage)
1130 {
1131 default: /* should not happen */
1132 assert(0);
1133 ZSTD_FALLTHROUGH;
1134 case ZSTDds_getFrameHeaderSize:
1135 ZSTD_FALLTHROUGH;
1136 case ZSTDds_decodeFrameHeader:
1137 return ZSTDnit_frameHeader;
1138 case ZSTDds_decodeBlockHeader:
1139 return ZSTDnit_blockHeader;
1140 case ZSTDds_decompressBlock:
1141 return ZSTDnit_block;
1142 case ZSTDds_decompressLastBlock:
1143 return ZSTDnit_lastBlock;
1144 case ZSTDds_checkChecksum:
1145 return ZSTDnit_checksum;
1146 case ZSTDds_decodeSkippableHeader:
1147 ZSTD_FALLTHROUGH;
1148 case ZSTDds_skipFrame:
1149 return ZSTDnit_skippableFrame;
1150 }
1151 }
1152
ZSTD_isSkipFrame(ZSTD_DCtx * dctx)1153 static int ZSTD_isSkipFrame(ZSTD_DCtx* dctx) { return dctx->stage == ZSTDds_skipFrame; }
1154
1155 /** ZSTD_decompressContinue() :
1156 * srcSize : must be the exact nb of bytes expected (see ZSTD_nextSrcSizeToDecompress())
1157 * @return : nb of bytes generated into `dst` (necessarily <= `dstCapacity)
1158 * or an error code, which can be tested using ZSTD_isError() */
ZSTD_decompressContinue(ZSTD_DCtx * dctx,void * dst,size_t dstCapacity,const void * src,size_t srcSize)1159 size_t ZSTD_decompressContinue(ZSTD_DCtx* dctx, void* dst, size_t dstCapacity, const void* src, size_t srcSize)
1160 {
1161 DEBUGLOG(5, "ZSTD_decompressContinue (srcSize:%u)", (unsigned)srcSize);
1162 /* Sanity check */
1163 RETURN_ERROR_IF(srcSize != ZSTD_nextSrcSizeToDecompressWithInputSize(dctx, srcSize), srcSize_wrong, "not allowed");
1164 ZSTD_checkContinuity(dctx, dst, dstCapacity);
1165
1166 dctx->processedCSize += srcSize;
1167
1168 switch (dctx->stage)
1169 {
1170 case ZSTDds_getFrameHeaderSize :
1171 assert(src != NULL);
1172 if (dctx->format == ZSTD_f_zstd1) { /* allows header */
1173 assert(srcSize >= ZSTD_FRAMEIDSIZE); /* to read skippable magic number */
1174 if ((MEM_readLE32(src) & ZSTD_MAGIC_SKIPPABLE_MASK) == ZSTD_MAGIC_SKIPPABLE_START) { /* skippable frame */
1175 ZSTD_memcpy(dctx->headerBuffer, src, srcSize);
1176 dctx->expected = ZSTD_SKIPPABLEHEADERSIZE - srcSize; /* remaining to load to get full skippable frame header */
1177 dctx->stage = ZSTDds_decodeSkippableHeader;
1178 return 0;
1179 } }
1180 dctx->headerSize = ZSTD_frameHeaderSize_internal(src, srcSize, dctx->format);
1181 if (ZSTD_isError(dctx->headerSize)) return dctx->headerSize;
1182 ZSTD_memcpy(dctx->headerBuffer, src, srcSize);
1183 dctx->expected = dctx->headerSize - srcSize;
1184 dctx->stage = ZSTDds_decodeFrameHeader;
1185 return 0;
1186
1187 case ZSTDds_decodeFrameHeader:
1188 assert(src != NULL);
1189 ZSTD_memcpy(dctx->headerBuffer + (dctx->headerSize - srcSize), src, srcSize);
1190 FORWARD_IF_ERROR(ZSTD_decodeFrameHeader(dctx, dctx->headerBuffer, dctx->headerSize), "");
1191 dctx->expected = ZSTD_blockHeaderSize;
1192 dctx->stage = ZSTDds_decodeBlockHeader;
1193 return 0;
1194
1195 case ZSTDds_decodeBlockHeader:
1196 { blockProperties_t bp;
1197 size_t const cBlockSize = ZSTD_getcBlockSize(src, ZSTD_blockHeaderSize, &bp);
1198 if (ZSTD_isError(cBlockSize)) return cBlockSize;
1199 RETURN_ERROR_IF(cBlockSize > dctx->fParams.blockSizeMax, corruption_detected, "Block Size Exceeds Maximum");
1200 dctx->expected = cBlockSize;
1201 dctx->bType = bp.blockType;
1202 dctx->rleSize = bp.origSize;
1203 if (cBlockSize) {
1204 dctx->stage = bp.lastBlock ? ZSTDds_decompressLastBlock : ZSTDds_decompressBlock;
1205 return 0;
1206 }
1207 /* empty block */
1208 if (bp.lastBlock) {
1209 if (dctx->fParams.checksumFlag) {
1210 dctx->expected = 4;
1211 dctx->stage = ZSTDds_checkChecksum;
1212 } else {
1213 dctx->expected = 0; /* end of frame */
1214 dctx->stage = ZSTDds_getFrameHeaderSize;
1215 }
1216 } else {
1217 dctx->expected = ZSTD_blockHeaderSize; /* jump to next header */
1218 dctx->stage = ZSTDds_decodeBlockHeader;
1219 }
1220 return 0;
1221 }
1222
1223 case ZSTDds_decompressLastBlock:
1224 case ZSTDds_decompressBlock:
1225 DEBUGLOG(5, "ZSTD_decompressContinue: case ZSTDds_decompressBlock");
1226 { size_t rSize;
1227 switch(dctx->bType)
1228 {
1229 case bt_compressed:
1230 DEBUGLOG(5, "ZSTD_decompressContinue: case bt_compressed");
1231 rSize = ZSTD_decompressBlock_internal(dctx, dst, dstCapacity, src, srcSize, /* frame */ 1, is_streaming);
1232 dctx->expected = 0; /* Streaming not supported */
1233 break;
1234 case bt_raw :
1235 assert(srcSize <= dctx->expected);
1236 rSize = ZSTD_copyRawBlock(dst, dstCapacity, src, srcSize);
1237 FORWARD_IF_ERROR(rSize, "ZSTD_copyRawBlock failed");
1238 assert(rSize == srcSize);
1239 dctx->expected -= rSize;
1240 break;
1241 case bt_rle :
1242 rSize = ZSTD_setRleBlock(dst, dstCapacity, *(const BYTE*)src, dctx->rleSize);
1243 dctx->expected = 0; /* Streaming not supported */
1244 break;
1245 case bt_reserved : /* should never happen */
1246 default:
1247 RETURN_ERROR(corruption_detected, "invalid block type");
1248 }
1249 FORWARD_IF_ERROR(rSize, "");
1250 RETURN_ERROR_IF(rSize > dctx->fParams.blockSizeMax, corruption_detected, "Decompressed Block Size Exceeds Maximum");
1251 DEBUGLOG(5, "ZSTD_decompressContinue: decoded size from block : %u", (unsigned)rSize);
1252 dctx->decodedSize += rSize;
1253 if (dctx->validateChecksum) XXH64_update(&dctx->xxhState, dst, rSize);
1254 dctx->previousDstEnd = (char*)dst + rSize;
1255
1256 /* Stay on the same stage until we are finished streaming the block. */
1257 if (dctx->expected > 0) {
1258 return rSize;
1259 }
1260
1261 if (dctx->stage == ZSTDds_decompressLastBlock) { /* end of frame */
1262 DEBUGLOG(4, "ZSTD_decompressContinue: decoded size from frame : %u", (unsigned)dctx->decodedSize);
1263 RETURN_ERROR_IF(
1264 dctx->fParams.frameContentSize != ZSTD_CONTENTSIZE_UNKNOWN
1265 && dctx->decodedSize != dctx->fParams.frameContentSize,
1266 corruption_detected, "");
1267 if (dctx->fParams.checksumFlag) { /* another round for frame checksum */
1268 dctx->expected = 4;
1269 dctx->stage = ZSTDds_checkChecksum;
1270 } else {
1271 ZSTD_DCtx_trace_end(dctx, dctx->decodedSize, dctx->processedCSize, /* streaming */ 1);
1272 dctx->expected = 0; /* ends here */
1273 dctx->stage = ZSTDds_getFrameHeaderSize;
1274 }
1275 } else {
1276 dctx->stage = ZSTDds_decodeBlockHeader;
1277 dctx->expected = ZSTD_blockHeaderSize;
1278 }
1279 return rSize;
1280 }
1281
1282 case ZSTDds_checkChecksum:
1283 assert(srcSize == 4); /* guaranteed by dctx->expected */
1284 {
1285 if (dctx->validateChecksum) {
1286 U32 const h32 = (U32)XXH64_digest(&dctx->xxhState);
1287 U32 const check32 = MEM_readLE32(src);
1288 DEBUGLOG(4, "ZSTD_decompressContinue: checksum : calculated %08X :: %08X read", (unsigned)h32, (unsigned)check32);
1289 RETURN_ERROR_IF(check32 != h32, checksum_wrong, "");
1290 }
1291 ZSTD_DCtx_trace_end(dctx, dctx->decodedSize, dctx->processedCSize, /* streaming */ 1);
1292 dctx->expected = 0;
1293 dctx->stage = ZSTDds_getFrameHeaderSize;
1294 return 0;
1295 }
1296
1297 case ZSTDds_decodeSkippableHeader:
1298 assert(src != NULL);
1299 assert(srcSize <= ZSTD_SKIPPABLEHEADERSIZE);
1300 ZSTD_memcpy(dctx->headerBuffer + (ZSTD_SKIPPABLEHEADERSIZE - srcSize), src, srcSize); /* complete skippable header */
1301 dctx->expected = MEM_readLE32(dctx->headerBuffer + ZSTD_FRAMEIDSIZE); /* note : dctx->expected can grow seriously large, beyond local buffer size */
1302 dctx->stage = ZSTDds_skipFrame;
1303 return 0;
1304
1305 case ZSTDds_skipFrame:
1306 dctx->expected = 0;
1307 dctx->stage = ZSTDds_getFrameHeaderSize;
1308 return 0;
1309
1310 default:
1311 assert(0); /* impossible */
1312 RETURN_ERROR(GENERIC, "impossible to reach"); /* some compiler require default to do something */
1313 }
1314 }
1315
1316
ZSTD_refDictContent(ZSTD_DCtx * dctx,const void * dict,size_t dictSize)1317 static size_t ZSTD_refDictContent(ZSTD_DCtx* dctx, const void* dict, size_t dictSize)
1318 {
1319 dctx->dictEnd = dctx->previousDstEnd;
1320 dctx->virtualStart = (const char*)dict - ((const char*)(dctx->previousDstEnd) - (const char*)(dctx->prefixStart));
1321 dctx->prefixStart = dict;
1322 dctx->previousDstEnd = (const char*)dict + dictSize;
1323 #ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
1324 dctx->dictContentBeginForFuzzing = dctx->prefixStart;
1325 dctx->dictContentEndForFuzzing = dctx->previousDstEnd;
1326 #endif
1327 return 0;
1328 }
1329
1330 /*! ZSTD_loadDEntropy() :
1331 * dict : must point at beginning of a valid zstd dictionary.
1332 * @return : size of entropy tables read */
1333 size_t
ZSTD_loadDEntropy(ZSTD_entropyDTables_t * entropy,const void * const dict,size_t const dictSize)1334 ZSTD_loadDEntropy(ZSTD_entropyDTables_t* entropy,
1335 const void* const dict, size_t const dictSize)
1336 {
1337 const BYTE* dictPtr = (const BYTE*)dict;
1338 const BYTE* const dictEnd = dictPtr + dictSize;
1339
1340 RETURN_ERROR_IF(dictSize <= 8, dictionary_corrupted, "dict is too small");
1341 assert(MEM_readLE32(dict) == ZSTD_MAGIC_DICTIONARY); /* dict must be valid */
1342 dictPtr += 8; /* skip header = magic + dictID */
1343
1344 ZSTD_STATIC_ASSERT(offsetof(ZSTD_entropyDTables_t, OFTable) == offsetof(ZSTD_entropyDTables_t, LLTable) + sizeof(entropy->LLTable));
1345 ZSTD_STATIC_ASSERT(offsetof(ZSTD_entropyDTables_t, MLTable) == offsetof(ZSTD_entropyDTables_t, OFTable) + sizeof(entropy->OFTable));
1346 ZSTD_STATIC_ASSERT(sizeof(entropy->LLTable) + sizeof(entropy->OFTable) + sizeof(entropy->MLTable) >= HUF_DECOMPRESS_WORKSPACE_SIZE);
1347 { void* const workspace = &entropy->LLTable; /* use fse tables as temporary workspace; implies fse tables are grouped together */
1348 size_t const workspaceSize = sizeof(entropy->LLTable) + sizeof(entropy->OFTable) + sizeof(entropy->MLTable);
1349 #ifdef HUF_FORCE_DECOMPRESS_X1
1350 /* in minimal huffman, we always use X1 variants */
1351 size_t const hSize = HUF_readDTableX1_wksp(entropy->hufTable,
1352 dictPtr, dictEnd - dictPtr,
1353 workspace, workspaceSize);
1354 #else
1355 size_t const hSize = HUF_readDTableX2_wksp(entropy->hufTable,
1356 dictPtr, (size_t)(dictEnd - dictPtr),
1357 workspace, workspaceSize);
1358 #endif
1359 RETURN_ERROR_IF(HUF_isError(hSize), dictionary_corrupted, "");
1360 dictPtr += hSize;
1361 }
1362
1363 { short offcodeNCount[MaxOff+1];
1364 unsigned offcodeMaxValue = MaxOff, offcodeLog;
1365 size_t const offcodeHeaderSize = FSE_readNCount(offcodeNCount, &offcodeMaxValue, &offcodeLog, dictPtr, (size_t)(dictEnd-dictPtr));
1366 RETURN_ERROR_IF(FSE_isError(offcodeHeaderSize), dictionary_corrupted, "");
1367 RETURN_ERROR_IF(offcodeMaxValue > MaxOff, dictionary_corrupted, "");
1368 RETURN_ERROR_IF(offcodeLog > OffFSELog, dictionary_corrupted, "");
1369 ZSTD_buildFSETable( entropy->OFTable,
1370 offcodeNCount, offcodeMaxValue,
1371 OF_base, OF_bits,
1372 offcodeLog,
1373 entropy->workspace, sizeof(entropy->workspace),
1374 /* bmi2 */0);
1375 dictPtr += offcodeHeaderSize;
1376 }
1377
1378 { short matchlengthNCount[MaxML+1];
1379 unsigned matchlengthMaxValue = MaxML, matchlengthLog;
1380 size_t const matchlengthHeaderSize = FSE_readNCount(matchlengthNCount, &matchlengthMaxValue, &matchlengthLog, dictPtr, (size_t)(dictEnd-dictPtr));
1381 RETURN_ERROR_IF(FSE_isError(matchlengthHeaderSize), dictionary_corrupted, "");
1382 RETURN_ERROR_IF(matchlengthMaxValue > MaxML, dictionary_corrupted, "");
1383 RETURN_ERROR_IF(matchlengthLog > MLFSELog, dictionary_corrupted, "");
1384 ZSTD_buildFSETable( entropy->MLTable,
1385 matchlengthNCount, matchlengthMaxValue,
1386 ML_base, ML_bits,
1387 matchlengthLog,
1388 entropy->workspace, sizeof(entropy->workspace),
1389 /* bmi2 */ 0);
1390 dictPtr += matchlengthHeaderSize;
1391 }
1392
1393 { short litlengthNCount[MaxLL+1];
1394 unsigned litlengthMaxValue = MaxLL, litlengthLog;
1395 size_t const litlengthHeaderSize = FSE_readNCount(litlengthNCount, &litlengthMaxValue, &litlengthLog, dictPtr, (size_t)(dictEnd-dictPtr));
1396 RETURN_ERROR_IF(FSE_isError(litlengthHeaderSize), dictionary_corrupted, "");
1397 RETURN_ERROR_IF(litlengthMaxValue > MaxLL, dictionary_corrupted, "");
1398 RETURN_ERROR_IF(litlengthLog > LLFSELog, dictionary_corrupted, "");
1399 ZSTD_buildFSETable( entropy->LLTable,
1400 litlengthNCount, litlengthMaxValue,
1401 LL_base, LL_bits,
1402 litlengthLog,
1403 entropy->workspace, sizeof(entropy->workspace),
1404 /* bmi2 */ 0);
1405 dictPtr += litlengthHeaderSize;
1406 }
1407
1408 RETURN_ERROR_IF(dictPtr+12 > dictEnd, dictionary_corrupted, "");
1409 { int i;
1410 size_t const dictContentSize = (size_t)(dictEnd - (dictPtr+12));
1411 for (i=0; i<3; i++) {
1412 U32 const rep = MEM_readLE32(dictPtr); dictPtr += 4;
1413 RETURN_ERROR_IF(rep==0 || rep > dictContentSize,
1414 dictionary_corrupted, "");
1415 entropy->rep[i] = rep;
1416 } }
1417
1418 return (size_t)(dictPtr - (const BYTE*)dict);
1419 }
1420
ZSTD_decompress_insertDictionary(ZSTD_DCtx * dctx,const void * dict,size_t dictSize)1421 static size_t ZSTD_decompress_insertDictionary(ZSTD_DCtx* dctx, const void* dict, size_t dictSize)
1422 {
1423 if (dictSize < 8) return ZSTD_refDictContent(dctx, dict, dictSize);
1424 { U32 const magic = MEM_readLE32(dict);
1425 if (magic != ZSTD_MAGIC_DICTIONARY) {
1426 return ZSTD_refDictContent(dctx, dict, dictSize); /* pure content mode */
1427 } }
1428 dctx->dictID = MEM_readLE32((const char*)dict + ZSTD_FRAMEIDSIZE);
1429
1430 /* load entropy tables */
1431 { size_t const eSize = ZSTD_loadDEntropy(&dctx->entropy, dict, dictSize);
1432 RETURN_ERROR_IF(ZSTD_isError(eSize), dictionary_corrupted, "");
1433 dict = (const char*)dict + eSize;
1434 dictSize -= eSize;
1435 }
1436 dctx->litEntropy = dctx->fseEntropy = 1;
1437
1438 /* reference dictionary content */
1439 return ZSTD_refDictContent(dctx, dict, dictSize);
1440 }
1441
ZSTD_decompressBegin(ZSTD_DCtx * dctx)1442 size_t ZSTD_decompressBegin(ZSTD_DCtx* dctx)
1443 {
1444 assert(dctx != NULL);
1445 #if ZSTD_TRACE
1446 dctx->traceCtx = (ZSTD_trace_decompress_begin != NULL) ? ZSTD_trace_decompress_begin(dctx) : 0;
1447 #endif
1448 dctx->expected = ZSTD_startingInputLength(dctx->format); /* dctx->format must be properly set */
1449 dctx->stage = ZSTDds_getFrameHeaderSize;
1450 dctx->processedCSize = 0;
1451 dctx->decodedSize = 0;
1452 dctx->previousDstEnd = NULL;
1453 dctx->prefixStart = NULL;
1454 dctx->virtualStart = NULL;
1455 dctx->dictEnd = NULL;
1456 dctx->entropy.hufTable[0] = (HUF_DTable)((HufLog)*0x1000001); /* cover both little and big endian */
1457 dctx->litEntropy = dctx->fseEntropy = 0;
1458 dctx->dictID = 0;
1459 dctx->bType = bt_reserved;
1460 ZSTD_STATIC_ASSERT(sizeof(dctx->entropy.rep) == sizeof(repStartValue));
1461 ZSTD_memcpy(dctx->entropy.rep, repStartValue, sizeof(repStartValue)); /* initial repcodes */
1462 dctx->LLTptr = dctx->entropy.LLTable;
1463 dctx->MLTptr = dctx->entropy.MLTable;
1464 dctx->OFTptr = dctx->entropy.OFTable;
1465 dctx->HUFptr = dctx->entropy.hufTable;
1466 return 0;
1467 }
1468
ZSTD_decompressBegin_usingDict(ZSTD_DCtx * dctx,const void * dict,size_t dictSize)1469 size_t ZSTD_decompressBegin_usingDict(ZSTD_DCtx* dctx, const void* dict, size_t dictSize)
1470 {
1471 FORWARD_IF_ERROR( ZSTD_decompressBegin(dctx) , "");
1472 if (dict && dictSize)
1473 RETURN_ERROR_IF(
1474 ZSTD_isError(ZSTD_decompress_insertDictionary(dctx, dict, dictSize)),
1475 dictionary_corrupted, "");
1476 return 0;
1477 }
1478
1479
1480 /* ====== ZSTD_DDict ====== */
1481
ZSTD_decompressBegin_usingDDict(ZSTD_DCtx * dctx,const ZSTD_DDict * ddict)1482 size_t ZSTD_decompressBegin_usingDDict(ZSTD_DCtx* dctx, const ZSTD_DDict* ddict)
1483 {
1484 DEBUGLOG(4, "ZSTD_decompressBegin_usingDDict");
1485 assert(dctx != NULL);
1486 if (ddict) {
1487 const char* const dictStart = (const char*)ZSTD_DDict_dictContent(ddict);
1488 size_t const dictSize = ZSTD_DDict_dictSize(ddict);
1489 const void* const dictEnd = dictStart + dictSize;
1490 dctx->ddictIsCold = (dctx->dictEnd != dictEnd);
1491 DEBUGLOG(4, "DDict is %s",
1492 dctx->ddictIsCold ? "~cold~" : "hot!");
1493 }
1494 FORWARD_IF_ERROR( ZSTD_decompressBegin(dctx) , "");
1495 if (ddict) { /* NULL ddict is equivalent to no dictionary */
1496 ZSTD_copyDDictParameters(dctx, ddict);
1497 }
1498 return 0;
1499 }
1500
1501 /*! ZSTD_getDictID_fromDict() :
1502 * Provides the dictID stored within dictionary.
1503 * if @return == 0, the dictionary is not conformant with Zstandard specification.
1504 * It can still be loaded, but as a content-only dictionary. */
ZSTD_getDictID_fromDict(const void * dict,size_t dictSize)1505 unsigned ZSTD_getDictID_fromDict(const void* dict, size_t dictSize)
1506 {
1507 if (dictSize < 8) return 0;
1508 if (MEM_readLE32(dict) != ZSTD_MAGIC_DICTIONARY) return 0;
1509 return MEM_readLE32((const char*)dict + ZSTD_FRAMEIDSIZE);
1510 }
1511
1512 /*! ZSTD_getDictID_fromFrame() :
1513 * Provides the dictID required to decompress frame stored within `src`.
1514 * If @return == 0, the dictID could not be decoded.
1515 * This could for one of the following reasons :
1516 * - The frame does not require a dictionary (most common case).
1517 * - The frame was built with dictID intentionally removed.
1518 * Needed dictionary is a hidden information.
1519 * Note : this use case also happens when using a non-conformant dictionary.
1520 * - `srcSize` is too small, and as a result, frame header could not be decoded.
1521 * Note : possible if `srcSize < ZSTD_FRAMEHEADERSIZE_MAX`.
1522 * - This is not a Zstandard frame.
1523 * When identifying the exact failure cause, it's possible to use
1524 * ZSTD_getFrameHeader(), which will provide a more precise error code. */
ZSTD_getDictID_fromFrame(const void * src,size_t srcSize)1525 unsigned ZSTD_getDictID_fromFrame(const void* src, size_t srcSize)
1526 {
1527 ZSTD_frameHeader zfp = { 0, 0, 0, ZSTD_frame, 0, 0, 0 };
1528 size_t const hError = ZSTD_getFrameHeader(&zfp, src, srcSize);
1529 if (ZSTD_isError(hError)) return 0;
1530 return zfp.dictID;
1531 }
1532
1533
1534 /*! ZSTD_decompress_usingDDict() :
1535 * Decompression using a pre-digested Dictionary
1536 * Use dictionary without significant overhead. */
ZSTD_decompress_usingDDict(ZSTD_DCtx * dctx,void * dst,size_t dstCapacity,const void * src,size_t srcSize,const ZSTD_DDict * ddict)1537 size_t ZSTD_decompress_usingDDict(ZSTD_DCtx* dctx,
1538 void* dst, size_t dstCapacity,
1539 const void* src, size_t srcSize,
1540 const ZSTD_DDict* ddict)
1541 {
1542 /* pass content and size in case legacy frames are encountered */
1543 return ZSTD_decompressMultiFrame(dctx, dst, dstCapacity, src, srcSize,
1544 NULL, 0,
1545 ddict);
1546 }
1547
1548
1549 /*=====================================
1550 * Streaming decompression
1551 *====================================*/
1552
ZSTD_createDStream(void)1553 ZSTD_DStream* ZSTD_createDStream(void)
1554 {
1555 DEBUGLOG(3, "ZSTD_createDStream");
1556 return ZSTD_createDCtx_internal(ZSTD_defaultCMem);
1557 }
1558
ZSTD_initStaticDStream(void * workspace,size_t workspaceSize)1559 ZSTD_DStream* ZSTD_initStaticDStream(void *workspace, size_t workspaceSize)
1560 {
1561 return ZSTD_initStaticDCtx(workspace, workspaceSize);
1562 }
1563
ZSTD_createDStream_advanced(ZSTD_customMem customMem)1564 ZSTD_DStream* ZSTD_createDStream_advanced(ZSTD_customMem customMem)
1565 {
1566 return ZSTD_createDCtx_internal(customMem);
1567 }
1568
ZSTD_freeDStream(ZSTD_DStream * zds)1569 size_t ZSTD_freeDStream(ZSTD_DStream* zds)
1570 {
1571 return ZSTD_freeDCtx(zds);
1572 }
1573
1574
1575 /* *** Initialization *** */
1576
ZSTD_DStreamInSize(void)1577 size_t ZSTD_DStreamInSize(void) { return ZSTD_BLOCKSIZE_MAX + ZSTD_blockHeaderSize; }
ZSTD_DStreamOutSize(void)1578 size_t ZSTD_DStreamOutSize(void) { return ZSTD_BLOCKSIZE_MAX; }
1579
ZSTD_DCtx_loadDictionary_advanced(ZSTD_DCtx * dctx,const void * dict,size_t dictSize,ZSTD_dictLoadMethod_e dictLoadMethod,ZSTD_dictContentType_e dictContentType)1580 size_t ZSTD_DCtx_loadDictionary_advanced(ZSTD_DCtx* dctx,
1581 const void* dict, size_t dictSize,
1582 ZSTD_dictLoadMethod_e dictLoadMethod,
1583 ZSTD_dictContentType_e dictContentType)
1584 {
1585 RETURN_ERROR_IF(dctx->streamStage != zdss_init, stage_wrong, "");
1586 ZSTD_clearDict(dctx);
1587 if (dict && dictSize != 0) {
1588 dctx->ddictLocal = ZSTD_createDDict_advanced(dict, dictSize, dictLoadMethod, dictContentType, dctx->customMem);
1589 RETURN_ERROR_IF(dctx->ddictLocal == NULL, memory_allocation, "NULL pointer!");
1590 dctx->ddict = dctx->ddictLocal;
1591 dctx->dictUses = ZSTD_use_indefinitely;
1592 }
1593 return 0;
1594 }
1595
ZSTD_DCtx_loadDictionary_byReference(ZSTD_DCtx * dctx,const void * dict,size_t dictSize)1596 size_t ZSTD_DCtx_loadDictionary_byReference(ZSTD_DCtx* dctx, const void* dict, size_t dictSize)
1597 {
1598 return ZSTD_DCtx_loadDictionary_advanced(dctx, dict, dictSize, ZSTD_dlm_byRef, ZSTD_dct_auto);
1599 }
1600
ZSTD_DCtx_loadDictionary(ZSTD_DCtx * dctx,const void * dict,size_t dictSize)1601 size_t ZSTD_DCtx_loadDictionary(ZSTD_DCtx* dctx, const void* dict, size_t dictSize)
1602 {
1603 return ZSTD_DCtx_loadDictionary_advanced(dctx, dict, dictSize, ZSTD_dlm_byCopy, ZSTD_dct_auto);
1604 }
1605
ZSTD_DCtx_refPrefix_advanced(ZSTD_DCtx * dctx,const void * prefix,size_t prefixSize,ZSTD_dictContentType_e dictContentType)1606 size_t ZSTD_DCtx_refPrefix_advanced(ZSTD_DCtx* dctx, const void* prefix, size_t prefixSize, ZSTD_dictContentType_e dictContentType)
1607 {
1608 FORWARD_IF_ERROR(ZSTD_DCtx_loadDictionary_advanced(dctx, prefix, prefixSize, ZSTD_dlm_byRef, dictContentType), "");
1609 dctx->dictUses = ZSTD_use_once;
1610 return 0;
1611 }
1612
ZSTD_DCtx_refPrefix(ZSTD_DCtx * dctx,const void * prefix,size_t prefixSize)1613 size_t ZSTD_DCtx_refPrefix(ZSTD_DCtx* dctx, const void* prefix, size_t prefixSize)
1614 {
1615 return ZSTD_DCtx_refPrefix_advanced(dctx, prefix, prefixSize, ZSTD_dct_rawContent);
1616 }
1617
1618
1619 /* ZSTD_initDStream_usingDict() :
1620 * return : expected size, aka ZSTD_startingInputLength().
1621 * this function cannot fail */
ZSTD_initDStream_usingDict(ZSTD_DStream * zds,const void * dict,size_t dictSize)1622 size_t ZSTD_initDStream_usingDict(ZSTD_DStream* zds, const void* dict, size_t dictSize)
1623 {
1624 DEBUGLOG(4, "ZSTD_initDStream_usingDict");
1625 FORWARD_IF_ERROR( ZSTD_DCtx_reset(zds, ZSTD_reset_session_only) , "");
1626 FORWARD_IF_ERROR( ZSTD_DCtx_loadDictionary(zds, dict, dictSize) , "");
1627 return ZSTD_startingInputLength(zds->format);
1628 }
1629
1630 /* note : this variant can't fail */
ZSTD_initDStream(ZSTD_DStream * zds)1631 size_t ZSTD_initDStream(ZSTD_DStream* zds)
1632 {
1633 DEBUGLOG(4, "ZSTD_initDStream");
1634 return ZSTD_initDStream_usingDDict(zds, NULL);
1635 }
1636
1637 /* ZSTD_initDStream_usingDDict() :
1638 * ddict will just be referenced, and must outlive decompression session
1639 * this function cannot fail */
ZSTD_initDStream_usingDDict(ZSTD_DStream * dctx,const ZSTD_DDict * ddict)1640 size_t ZSTD_initDStream_usingDDict(ZSTD_DStream* dctx, const ZSTD_DDict* ddict)
1641 {
1642 FORWARD_IF_ERROR( ZSTD_DCtx_reset(dctx, ZSTD_reset_session_only) , "");
1643 FORWARD_IF_ERROR( ZSTD_DCtx_refDDict(dctx, ddict) , "");
1644 return ZSTD_startingInputLength(dctx->format);
1645 }
1646
1647 /* ZSTD_resetDStream() :
1648 * return : expected size, aka ZSTD_startingInputLength().
1649 * this function cannot fail */
ZSTD_resetDStream(ZSTD_DStream * dctx)1650 size_t ZSTD_resetDStream(ZSTD_DStream* dctx)
1651 {
1652 FORWARD_IF_ERROR(ZSTD_DCtx_reset(dctx, ZSTD_reset_session_only), "");
1653 return ZSTD_startingInputLength(dctx->format);
1654 }
1655
1656
ZSTD_DCtx_refDDict(ZSTD_DCtx * dctx,const ZSTD_DDict * ddict)1657 size_t ZSTD_DCtx_refDDict(ZSTD_DCtx* dctx, const ZSTD_DDict* ddict)
1658 {
1659 RETURN_ERROR_IF(dctx->streamStage != zdss_init, stage_wrong, "");
1660 ZSTD_clearDict(dctx);
1661 if (ddict) {
1662 dctx->ddict = ddict;
1663 dctx->dictUses = ZSTD_use_indefinitely;
1664 if (dctx->refMultipleDDicts == ZSTD_rmd_refMultipleDDicts) {
1665 if (dctx->ddictSet == NULL) {
1666 dctx->ddictSet = ZSTD_createDDictHashSet(dctx->customMem);
1667 if (!dctx->ddictSet) {
1668 RETURN_ERROR(memory_allocation, "Failed to allocate memory for hash set!");
1669 }
1670 }
1671 assert(!dctx->staticSize); /* Impossible: ddictSet cannot have been allocated if static dctx */
1672 FORWARD_IF_ERROR(ZSTD_DDictHashSet_addDDict(dctx->ddictSet, ddict, dctx->customMem), "");
1673 }
1674 }
1675 return 0;
1676 }
1677
1678 /* ZSTD_DCtx_setMaxWindowSize() :
1679 * note : no direct equivalence in ZSTD_DCtx_setParameter,
1680 * since this version sets windowSize, and the other sets windowLog */
ZSTD_DCtx_setMaxWindowSize(ZSTD_DCtx * dctx,size_t maxWindowSize)1681 size_t ZSTD_DCtx_setMaxWindowSize(ZSTD_DCtx* dctx, size_t maxWindowSize)
1682 {
1683 ZSTD_bounds const bounds = ZSTD_dParam_getBounds(ZSTD_d_windowLogMax);
1684 size_t const min = (size_t)1 << bounds.lowerBound;
1685 size_t const max = (size_t)1 << bounds.upperBound;
1686 RETURN_ERROR_IF(dctx->streamStage != zdss_init, stage_wrong, "");
1687 RETURN_ERROR_IF(maxWindowSize < min, parameter_outOfBound, "");
1688 RETURN_ERROR_IF(maxWindowSize > max, parameter_outOfBound, "");
1689 dctx->maxWindowSize = maxWindowSize;
1690 return 0;
1691 }
1692
ZSTD_DCtx_setFormat(ZSTD_DCtx * dctx,ZSTD_format_e format)1693 size_t ZSTD_DCtx_setFormat(ZSTD_DCtx* dctx, ZSTD_format_e format)
1694 {
1695 return ZSTD_DCtx_setParameter(dctx, ZSTD_d_format, (int)format);
1696 }
1697
ZSTD_dParam_getBounds(ZSTD_dParameter dParam)1698 ZSTD_bounds ZSTD_dParam_getBounds(ZSTD_dParameter dParam)
1699 {
1700 ZSTD_bounds bounds = { 0, 0, 0 };
1701 switch(dParam) {
1702 case ZSTD_d_windowLogMax:
1703 bounds.lowerBound = ZSTD_WINDOWLOG_ABSOLUTEMIN;
1704 bounds.upperBound = ZSTD_WINDOWLOG_MAX;
1705 return bounds;
1706 case ZSTD_d_format:
1707 bounds.lowerBound = (int)ZSTD_f_zstd1;
1708 bounds.upperBound = (int)ZSTD_f_zstd1_magicless;
1709 ZSTD_STATIC_ASSERT(ZSTD_f_zstd1 < ZSTD_f_zstd1_magicless);
1710 return bounds;
1711 case ZSTD_d_stableOutBuffer:
1712 bounds.lowerBound = (int)ZSTD_bm_buffered;
1713 bounds.upperBound = (int)ZSTD_bm_stable;
1714 return bounds;
1715 case ZSTD_d_forceIgnoreChecksum:
1716 bounds.lowerBound = (int)ZSTD_d_validateChecksum;
1717 bounds.upperBound = (int)ZSTD_d_ignoreChecksum;
1718 return bounds;
1719 case ZSTD_d_refMultipleDDicts:
1720 bounds.lowerBound = (int)ZSTD_rmd_refSingleDDict;
1721 bounds.upperBound = (int)ZSTD_rmd_refMultipleDDicts;
1722 return bounds;
1723 default:;
1724 }
1725 bounds.error = ERROR(parameter_unsupported);
1726 return bounds;
1727 }
1728
1729 /* ZSTD_dParam_withinBounds:
1730 * @return 1 if value is within dParam bounds,
1731 * 0 otherwise */
ZSTD_dParam_withinBounds(ZSTD_dParameter dParam,int value)1732 static int ZSTD_dParam_withinBounds(ZSTD_dParameter dParam, int value)
1733 {
1734 ZSTD_bounds const bounds = ZSTD_dParam_getBounds(dParam);
1735 if (ZSTD_isError(bounds.error)) return 0;
1736 if (value < bounds.lowerBound) return 0;
1737 if (value > bounds.upperBound) return 0;
1738 return 1;
1739 }
1740
1741 #define CHECK_DBOUNDS(p,v) { \
1742 RETURN_ERROR_IF(!ZSTD_dParam_withinBounds(p, v), parameter_outOfBound, ""); \
1743 }
1744
ZSTD_DCtx_getParameter(ZSTD_DCtx * dctx,ZSTD_dParameter param,int * value)1745 size_t ZSTD_DCtx_getParameter(ZSTD_DCtx* dctx, ZSTD_dParameter param, int* value)
1746 {
1747 switch (param) {
1748 case ZSTD_d_windowLogMax:
1749 *value = (int)ZSTD_highbit32((U32)dctx->maxWindowSize);
1750 return 0;
1751 case ZSTD_d_format:
1752 *value = (int)dctx->format;
1753 return 0;
1754 case ZSTD_d_stableOutBuffer:
1755 *value = (int)dctx->outBufferMode;
1756 return 0;
1757 case ZSTD_d_forceIgnoreChecksum:
1758 *value = (int)dctx->forceIgnoreChecksum;
1759 return 0;
1760 case ZSTD_d_refMultipleDDicts:
1761 *value = (int)dctx->refMultipleDDicts;
1762 return 0;
1763 default:;
1764 }
1765 RETURN_ERROR(parameter_unsupported, "");
1766 }
1767
ZSTD_DCtx_setParameter(ZSTD_DCtx * dctx,ZSTD_dParameter dParam,int value)1768 size_t ZSTD_DCtx_setParameter(ZSTD_DCtx* dctx, ZSTD_dParameter dParam, int value)
1769 {
1770 RETURN_ERROR_IF(dctx->streamStage != zdss_init, stage_wrong, "");
1771 switch(dParam) {
1772 case ZSTD_d_windowLogMax:
1773 if (value == 0) value = ZSTD_WINDOWLOG_LIMIT_DEFAULT;
1774 CHECK_DBOUNDS(ZSTD_d_windowLogMax, value);
1775 dctx->maxWindowSize = ((size_t)1) << value;
1776 return 0;
1777 case ZSTD_d_format:
1778 CHECK_DBOUNDS(ZSTD_d_format, value);
1779 dctx->format = (ZSTD_format_e)value;
1780 return 0;
1781 case ZSTD_d_stableOutBuffer:
1782 CHECK_DBOUNDS(ZSTD_d_stableOutBuffer, value);
1783 dctx->outBufferMode = (ZSTD_bufferMode_e)value;
1784 return 0;
1785 case ZSTD_d_forceIgnoreChecksum:
1786 CHECK_DBOUNDS(ZSTD_d_forceIgnoreChecksum, value);
1787 dctx->forceIgnoreChecksum = (ZSTD_forceIgnoreChecksum_e)value;
1788 return 0;
1789 case ZSTD_d_refMultipleDDicts:
1790 CHECK_DBOUNDS(ZSTD_d_refMultipleDDicts, value);
1791 if (dctx->staticSize != 0) {
1792 RETURN_ERROR(parameter_unsupported, "Static dctx does not support multiple DDicts!");
1793 }
1794 dctx->refMultipleDDicts = (ZSTD_refMultipleDDicts_e)value;
1795 return 0;
1796 default:;
1797 }
1798 RETURN_ERROR(parameter_unsupported, "");
1799 }
1800
ZSTD_DCtx_reset(ZSTD_DCtx * dctx,ZSTD_ResetDirective reset)1801 size_t ZSTD_DCtx_reset(ZSTD_DCtx* dctx, ZSTD_ResetDirective reset)
1802 {
1803 if ( (reset == ZSTD_reset_session_only)
1804 || (reset == ZSTD_reset_session_and_parameters) ) {
1805 dctx->streamStage = zdss_init;
1806 dctx->noForwardProgress = 0;
1807 }
1808 if ( (reset == ZSTD_reset_parameters)
1809 || (reset == ZSTD_reset_session_and_parameters) ) {
1810 RETURN_ERROR_IF(dctx->streamStage != zdss_init, stage_wrong, "");
1811 ZSTD_clearDict(dctx);
1812 ZSTD_DCtx_resetParameters(dctx);
1813 }
1814 return 0;
1815 }
1816
1817
ZSTD_sizeof_DStream(const ZSTD_DStream * dctx)1818 size_t ZSTD_sizeof_DStream(const ZSTD_DStream* dctx)
1819 {
1820 return ZSTD_sizeof_DCtx(dctx);
1821 }
1822
ZSTD_decodingBufferSize_min(unsigned long long windowSize,unsigned long long frameContentSize)1823 size_t ZSTD_decodingBufferSize_min(unsigned long long windowSize, unsigned long long frameContentSize)
1824 {
1825 size_t const blockSize = (size_t) MIN(windowSize, ZSTD_BLOCKSIZE_MAX);
1826 /* space is needed to store the litbuffer after the output of a given block without stomping the extDict of a previous run, as well as to cover both windows against wildcopy*/
1827 unsigned long long const neededRBSize = windowSize + blockSize + ZSTD_BLOCKSIZE_MAX + (WILDCOPY_OVERLENGTH * 2);
1828 unsigned long long const neededSize = MIN(frameContentSize, neededRBSize);
1829 size_t const minRBSize = (size_t) neededSize;
1830 RETURN_ERROR_IF((unsigned long long)minRBSize != neededSize,
1831 frameParameter_windowTooLarge, "");
1832 return minRBSize;
1833 }
1834
ZSTD_estimateDStreamSize(size_t windowSize)1835 size_t ZSTD_estimateDStreamSize(size_t windowSize)
1836 {
1837 size_t const blockSize = MIN(windowSize, ZSTD_BLOCKSIZE_MAX);
1838 size_t const inBuffSize = blockSize; /* no block can be larger */
1839 size_t const outBuffSize = ZSTD_decodingBufferSize_min(windowSize, ZSTD_CONTENTSIZE_UNKNOWN);
1840 return ZSTD_estimateDCtxSize() + inBuffSize + outBuffSize;
1841 }
1842
ZSTD_estimateDStreamSize_fromFrame(const void * src,size_t srcSize)1843 size_t ZSTD_estimateDStreamSize_fromFrame(const void* src, size_t srcSize)
1844 {
1845 U32 const windowSizeMax = 1U << ZSTD_WINDOWLOG_MAX; /* note : should be user-selectable, but requires an additional parameter (or a dctx) */
1846 ZSTD_frameHeader zfh;
1847 size_t const err = ZSTD_getFrameHeader(&zfh, src, srcSize);
1848 if (ZSTD_isError(err)) return err;
1849 RETURN_ERROR_IF(err>0, srcSize_wrong, "");
1850 RETURN_ERROR_IF(zfh.windowSize > windowSizeMax,
1851 frameParameter_windowTooLarge, "");
1852 return ZSTD_estimateDStreamSize((size_t)zfh.windowSize);
1853 }
1854
1855
1856 /* ***** Decompression ***** */
1857
ZSTD_DCtx_isOverflow(ZSTD_DStream * zds,size_t const neededInBuffSize,size_t const neededOutBuffSize)1858 static int ZSTD_DCtx_isOverflow(ZSTD_DStream* zds, size_t const neededInBuffSize, size_t const neededOutBuffSize)
1859 {
1860 return (zds->inBuffSize + zds->outBuffSize) >= (neededInBuffSize + neededOutBuffSize) * ZSTD_WORKSPACETOOLARGE_FACTOR;
1861 }
1862
ZSTD_DCtx_updateOversizedDuration(ZSTD_DStream * zds,size_t const neededInBuffSize,size_t const neededOutBuffSize)1863 static void ZSTD_DCtx_updateOversizedDuration(ZSTD_DStream* zds, size_t const neededInBuffSize, size_t const neededOutBuffSize)
1864 {
1865 if (ZSTD_DCtx_isOverflow(zds, neededInBuffSize, neededOutBuffSize))
1866 zds->oversizedDuration++;
1867 else
1868 zds->oversizedDuration = 0;
1869 }
1870
ZSTD_DCtx_isOversizedTooLong(ZSTD_DStream * zds)1871 static int ZSTD_DCtx_isOversizedTooLong(ZSTD_DStream* zds)
1872 {
1873 return zds->oversizedDuration >= ZSTD_WORKSPACETOOLARGE_MAXDURATION;
1874 }
1875
1876 /* Checks that the output buffer hasn't changed if ZSTD_obm_stable is used. */
ZSTD_checkOutBuffer(ZSTD_DStream const * zds,ZSTD_outBuffer const * output)1877 static size_t ZSTD_checkOutBuffer(ZSTD_DStream const* zds, ZSTD_outBuffer const* output)
1878 {
1879 ZSTD_outBuffer const expect = zds->expectedOutBuffer;
1880 /* No requirement when ZSTD_obm_stable is not enabled. */
1881 if (zds->outBufferMode != ZSTD_bm_stable)
1882 return 0;
1883 /* Any buffer is allowed in zdss_init, this must be the same for every other call until
1884 * the context is reset.
1885 */
1886 if (zds->streamStage == zdss_init)
1887 return 0;
1888 /* The buffer must match our expectation exactly. */
1889 if (expect.dst == output->dst && expect.pos == output->pos && expect.size == output->size)
1890 return 0;
1891 RETURN_ERROR(dstBuffer_wrong, "ZSTD_d_stableOutBuffer enabled but output differs!");
1892 }
1893
1894 /* Calls ZSTD_decompressContinue() with the right parameters for ZSTD_decompressStream()
1895 * and updates the stage and the output buffer state. This call is extracted so it can be
1896 * used both when reading directly from the ZSTD_inBuffer, and in buffered input mode.
1897 * NOTE: You must break after calling this function since the streamStage is modified.
1898 */
ZSTD_decompressContinueStream(ZSTD_DStream * zds,char ** op,char * oend,void const * src,size_t srcSize)1899 static size_t ZSTD_decompressContinueStream(
1900 ZSTD_DStream* zds, char** op, char* oend,
1901 void const* src, size_t srcSize) {
1902 int const isSkipFrame = ZSTD_isSkipFrame(zds);
1903 if (zds->outBufferMode == ZSTD_bm_buffered) {
1904 size_t const dstSize = isSkipFrame ? 0 : zds->outBuffSize - zds->outStart;
1905 size_t const decodedSize = ZSTD_decompressContinue(zds,
1906 zds->outBuff + zds->outStart, dstSize, src, srcSize);
1907 FORWARD_IF_ERROR(decodedSize, "");
1908 if (!decodedSize && !isSkipFrame) {
1909 zds->streamStage = zdss_read;
1910 } else {
1911 zds->outEnd = zds->outStart + decodedSize;
1912 zds->streamStage = zdss_flush;
1913 }
1914 } else {
1915 /* Write directly into the output buffer */
1916 size_t const dstSize = isSkipFrame ? 0 : (size_t)(oend - *op);
1917 size_t const decodedSize = ZSTD_decompressContinue(zds, *op, dstSize, src, srcSize);
1918 FORWARD_IF_ERROR(decodedSize, "");
1919 *op += decodedSize;
1920 /* Flushing is not needed. */
1921 zds->streamStage = zdss_read;
1922 assert(*op <= oend);
1923 assert(zds->outBufferMode == ZSTD_bm_stable);
1924 }
1925 return 0;
1926 }
1927
ZSTD_decompressStream(ZSTD_DStream * zds,ZSTD_outBuffer * output,ZSTD_inBuffer * input)1928 size_t ZSTD_decompressStream(ZSTD_DStream* zds, ZSTD_outBuffer* output, ZSTD_inBuffer* input)
1929 {
1930 const char* const src = (const char*)input->src;
1931 const char* const istart = input->pos != 0 ? src + input->pos : src;
1932 const char* const iend = input->size != 0 ? src + input->size : src;
1933 const char* ip = istart;
1934 char* const dst = (char*)output->dst;
1935 char* const ostart = output->pos != 0 ? dst + output->pos : dst;
1936 char* const oend = output->size != 0 ? dst + output->size : dst;
1937 char* op = ostart;
1938 U32 someMoreWork = 1;
1939
1940 DEBUGLOG(5, "ZSTD_decompressStream");
1941 RETURN_ERROR_IF(
1942 input->pos > input->size,
1943 srcSize_wrong,
1944 "forbidden. in: pos: %u vs size: %u",
1945 (U32)input->pos, (U32)input->size);
1946 RETURN_ERROR_IF(
1947 output->pos > output->size,
1948 dstSize_tooSmall,
1949 "forbidden. out: pos: %u vs size: %u",
1950 (U32)output->pos, (U32)output->size);
1951 DEBUGLOG(5, "input size : %u", (U32)(input->size - input->pos));
1952 FORWARD_IF_ERROR(ZSTD_checkOutBuffer(zds, output), "");
1953
1954 while (someMoreWork) {
1955 switch(zds->streamStage)
1956 {
1957 case zdss_init :
1958 DEBUGLOG(5, "stage zdss_init => transparent reset ");
1959 zds->streamStage = zdss_loadHeader;
1960 zds->lhSize = zds->inPos = zds->outStart = zds->outEnd = 0;
1961 #if defined(ZSTD_LEGACY_SUPPORT) && (ZSTD_LEGACY_SUPPORT>=1)
1962 zds->legacyVersion = 0;
1963 #endif
1964 zds->hostageByte = 0;
1965 zds->expectedOutBuffer = *output;
1966 ZSTD_FALLTHROUGH;
1967
1968 case zdss_loadHeader :
1969 DEBUGLOG(5, "stage zdss_loadHeader (srcSize : %u)", (U32)(iend - ip));
1970 #if defined(ZSTD_LEGACY_SUPPORT) && (ZSTD_LEGACY_SUPPORT>=1)
1971 if (zds->legacyVersion) {
1972 RETURN_ERROR_IF(zds->staticSize, memory_allocation,
1973 "legacy support is incompatible with static dctx");
1974 { size_t const hint = ZSTD_decompressLegacyStream(zds->legacyContext, zds->legacyVersion, output, input);
1975 if (hint==0) zds->streamStage = zdss_init;
1976 return hint;
1977 } }
1978 #endif
1979 { size_t const hSize = ZSTD_getFrameHeader_advanced(&zds->fParams, zds->headerBuffer, zds->lhSize, zds->format);
1980 if (zds->refMultipleDDicts && zds->ddictSet) {
1981 ZSTD_DCtx_selectFrameDDict(zds);
1982 }
1983 DEBUGLOG(5, "header size : %u", (U32)hSize);
1984 if (ZSTD_isError(hSize)) {
1985 #if defined(ZSTD_LEGACY_SUPPORT) && (ZSTD_LEGACY_SUPPORT>=1)
1986 U32 const legacyVersion = ZSTD_isLegacy(istart, iend-istart);
1987 if (legacyVersion) {
1988 ZSTD_DDict const* const ddict = ZSTD_getDDict(zds);
1989 const void* const dict = ddict ? ZSTD_DDict_dictContent(ddict) : NULL;
1990 size_t const dictSize = ddict ? ZSTD_DDict_dictSize(ddict) : 0;
1991 DEBUGLOG(5, "ZSTD_decompressStream: detected legacy version v0.%u", legacyVersion);
1992 RETURN_ERROR_IF(zds->staticSize, memory_allocation,
1993 "legacy support is incompatible with static dctx");
1994 FORWARD_IF_ERROR(ZSTD_initLegacyStream(&zds->legacyContext,
1995 zds->previousLegacyVersion, legacyVersion,
1996 dict, dictSize), "");
1997 zds->legacyVersion = zds->previousLegacyVersion = legacyVersion;
1998 { size_t const hint = ZSTD_decompressLegacyStream(zds->legacyContext, legacyVersion, output, input);
1999 if (hint==0) zds->streamStage = zdss_init; /* or stay in stage zdss_loadHeader */
2000 return hint;
2001 } }
2002 #endif
2003 return hSize; /* error */
2004 }
2005 if (hSize != 0) { /* need more input */
2006 size_t const toLoad = hSize - zds->lhSize; /* if hSize!=0, hSize > zds->lhSize */
2007 size_t const remainingInput = (size_t)(iend-ip);
2008 assert(iend >= ip);
2009 if (toLoad > remainingInput) { /* not enough input to load full header */
2010 if (remainingInput > 0) {
2011 ZSTD_memcpy(zds->headerBuffer + zds->lhSize, ip, remainingInput);
2012 zds->lhSize += remainingInput;
2013 }
2014 input->pos = input->size;
2015 return (MAX((size_t)ZSTD_FRAMEHEADERSIZE_MIN(zds->format), hSize) - zds->lhSize) + ZSTD_blockHeaderSize; /* remaining header bytes + next block header */
2016 }
2017 assert(ip != NULL);
2018 ZSTD_memcpy(zds->headerBuffer + zds->lhSize, ip, toLoad); zds->lhSize = hSize; ip += toLoad;
2019 break;
2020 } }
2021
2022 /* check for single-pass mode opportunity */
2023 if (zds->fParams.frameContentSize != ZSTD_CONTENTSIZE_UNKNOWN
2024 && zds->fParams.frameType != ZSTD_skippableFrame
2025 && (U64)(size_t)(oend-op) >= zds->fParams.frameContentSize) {
2026 size_t const cSize = ZSTD_findFrameCompressedSize(istart, (size_t)(iend-istart));
2027 if (cSize <= (size_t)(iend-istart)) {
2028 /* shortcut : using single-pass mode */
2029 size_t const decompressedSize = ZSTD_decompress_usingDDict(zds, op, (size_t)(oend-op), istart, cSize, ZSTD_getDDict(zds));
2030 if (ZSTD_isError(decompressedSize)) return decompressedSize;
2031 DEBUGLOG(4, "shortcut to single-pass ZSTD_decompress_usingDDict()")
2032 ip = istart + cSize;
2033 op += decompressedSize;
2034 zds->expected = 0;
2035 zds->streamStage = zdss_init;
2036 someMoreWork = 0;
2037 break;
2038 } }
2039
2040 /* Check output buffer is large enough for ZSTD_odm_stable. */
2041 if (zds->outBufferMode == ZSTD_bm_stable
2042 && zds->fParams.frameType != ZSTD_skippableFrame
2043 && zds->fParams.frameContentSize != ZSTD_CONTENTSIZE_UNKNOWN
2044 && (U64)(size_t)(oend-op) < zds->fParams.frameContentSize) {
2045 RETURN_ERROR(dstSize_tooSmall, "ZSTD_obm_stable passed but ZSTD_outBuffer is too small");
2046 }
2047
2048 /* Consume header (see ZSTDds_decodeFrameHeader) */
2049 DEBUGLOG(4, "Consume header");
2050 FORWARD_IF_ERROR(ZSTD_decompressBegin_usingDDict(zds, ZSTD_getDDict(zds)), "");
2051
2052 if ((MEM_readLE32(zds->headerBuffer) & ZSTD_MAGIC_SKIPPABLE_MASK) == ZSTD_MAGIC_SKIPPABLE_START) { /* skippable frame */
2053 zds->expected = MEM_readLE32(zds->headerBuffer + ZSTD_FRAMEIDSIZE);
2054 zds->stage = ZSTDds_skipFrame;
2055 } else {
2056 FORWARD_IF_ERROR(ZSTD_decodeFrameHeader(zds, zds->headerBuffer, zds->lhSize), "");
2057 zds->expected = ZSTD_blockHeaderSize;
2058 zds->stage = ZSTDds_decodeBlockHeader;
2059 }
2060
2061 /* control buffer memory usage */
2062 DEBUGLOG(4, "Control max memory usage (%u KB <= max %u KB)",
2063 (U32)(zds->fParams.windowSize >>10),
2064 (U32)(zds->maxWindowSize >> 10) );
2065 zds->fParams.windowSize = MAX(zds->fParams.windowSize, 1U << ZSTD_WINDOWLOG_ABSOLUTEMIN);
2066 RETURN_ERROR_IF(zds->fParams.windowSize > zds->maxWindowSize,
2067 frameParameter_windowTooLarge, "");
2068
2069 /* Adapt buffer sizes to frame header instructions */
2070 { size_t const neededInBuffSize = MAX(zds->fParams.blockSizeMax, 4 /* frame checksum */);
2071 size_t const neededOutBuffSize = zds->outBufferMode == ZSTD_bm_buffered
2072 ? ZSTD_decodingBufferSize_min(zds->fParams.windowSize, zds->fParams.frameContentSize)
2073 : 0;
2074
2075 ZSTD_DCtx_updateOversizedDuration(zds, neededInBuffSize, neededOutBuffSize);
2076
2077 { int const tooSmall = (zds->inBuffSize < neededInBuffSize) || (zds->outBuffSize < neededOutBuffSize);
2078 int const tooLarge = ZSTD_DCtx_isOversizedTooLong(zds);
2079
2080 if (tooSmall || tooLarge) {
2081 size_t const bufferSize = neededInBuffSize + neededOutBuffSize;
2082 DEBUGLOG(4, "inBuff : from %u to %u",
2083 (U32)zds->inBuffSize, (U32)neededInBuffSize);
2084 DEBUGLOG(4, "outBuff : from %u to %u",
2085 (U32)zds->outBuffSize, (U32)neededOutBuffSize);
2086 if (zds->staticSize) { /* static DCtx */
2087 DEBUGLOG(4, "staticSize : %u", (U32)zds->staticSize);
2088 assert(zds->staticSize >= sizeof(ZSTD_DCtx)); /* controlled at init */
2089 RETURN_ERROR_IF(
2090 bufferSize > zds->staticSize - sizeof(ZSTD_DCtx),
2091 memory_allocation, "");
2092 } else {
2093 ZSTD_customFree(zds->inBuff, zds->customMem);
2094 zds->inBuffSize = 0;
2095 zds->outBuffSize = 0;
2096 zds->inBuff = (char*)ZSTD_customMalloc(bufferSize, zds->customMem);
2097 RETURN_ERROR_IF(zds->inBuff == NULL, memory_allocation, "");
2098 }
2099 zds->inBuffSize = neededInBuffSize;
2100 zds->outBuff = zds->inBuff + zds->inBuffSize;
2101 zds->outBuffSize = neededOutBuffSize;
2102 } } }
2103 zds->streamStage = zdss_read;
2104 ZSTD_FALLTHROUGH;
2105
2106 case zdss_read:
2107 DEBUGLOG(5, "stage zdss_read");
2108 { size_t const neededInSize = ZSTD_nextSrcSizeToDecompressWithInputSize(zds, (size_t)(iend - ip));
2109 DEBUGLOG(5, "neededInSize = %u", (U32)neededInSize);
2110 if (neededInSize==0) { /* end of frame */
2111 zds->streamStage = zdss_init;
2112 someMoreWork = 0;
2113 break;
2114 }
2115 if ((size_t)(iend-ip) >= neededInSize) { /* decode directly from src */
2116 FORWARD_IF_ERROR(ZSTD_decompressContinueStream(zds, &op, oend, ip, neededInSize), "");
2117 ip += neededInSize;
2118 /* Function modifies the stage so we must break */
2119 break;
2120 } }
2121 if (ip==iend) { someMoreWork = 0; break; } /* no more input */
2122 zds->streamStage = zdss_load;
2123 ZSTD_FALLTHROUGH;
2124
2125 case zdss_load:
2126 { size_t const neededInSize = ZSTD_nextSrcSizeToDecompress(zds);
2127 size_t const toLoad = neededInSize - zds->inPos;
2128 int const isSkipFrame = ZSTD_isSkipFrame(zds);
2129 size_t loadedSize;
2130 /* At this point we shouldn't be decompressing a block that we can stream. */
2131 assert(neededInSize == ZSTD_nextSrcSizeToDecompressWithInputSize(zds, iend - ip));
2132 if (isSkipFrame) {
2133 loadedSize = MIN(toLoad, (size_t)(iend-ip));
2134 } else {
2135 RETURN_ERROR_IF(toLoad > zds->inBuffSize - zds->inPos,
2136 corruption_detected,
2137 "should never happen");
2138 loadedSize = ZSTD_limitCopy(zds->inBuff + zds->inPos, toLoad, ip, (size_t)(iend-ip));
2139 }
2140 ip += loadedSize;
2141 zds->inPos += loadedSize;
2142 if (loadedSize < toLoad) { someMoreWork = 0; break; } /* not enough input, wait for more */
2143
2144 /* decode loaded input */
2145 zds->inPos = 0; /* input is consumed */
2146 FORWARD_IF_ERROR(ZSTD_decompressContinueStream(zds, &op, oend, zds->inBuff, neededInSize), "");
2147 /* Function modifies the stage so we must break */
2148 break;
2149 }
2150 case zdss_flush:
2151 { size_t const toFlushSize = zds->outEnd - zds->outStart;
2152 size_t const flushedSize = ZSTD_limitCopy(op, (size_t)(oend-op), zds->outBuff + zds->outStart, toFlushSize);
2153 op += flushedSize;
2154 zds->outStart += flushedSize;
2155 if (flushedSize == toFlushSize) { /* flush completed */
2156 zds->streamStage = zdss_read;
2157 if ( (zds->outBuffSize < zds->fParams.frameContentSize)
2158 && (zds->outStart + zds->fParams.blockSizeMax > zds->outBuffSize) ) {
2159 DEBUGLOG(5, "restart filling outBuff from beginning (left:%i, needed:%u)",
2160 (int)(zds->outBuffSize - zds->outStart),
2161 (U32)zds->fParams.blockSizeMax);
2162 zds->outStart = zds->outEnd = 0;
2163 }
2164 break;
2165 } }
2166 /* cannot complete flush */
2167 someMoreWork = 0;
2168 break;
2169
2170 default:
2171 assert(0); /* impossible */
2172 RETURN_ERROR(GENERIC, "impossible to reach"); /* some compiler require default to do something */
2173 } }
2174
2175 /* result */
2176 input->pos = (size_t)(ip - (const char*)(input->src));
2177 output->pos = (size_t)(op - (char*)(output->dst));
2178
2179 /* Update the expected output buffer for ZSTD_obm_stable. */
2180 zds->expectedOutBuffer = *output;
2181
2182 if ((ip==istart) && (op==ostart)) { /* no forward progress */
2183 zds->noForwardProgress ++;
2184 if (zds->noForwardProgress >= ZSTD_NO_FORWARD_PROGRESS_MAX) {
2185 RETURN_ERROR_IF(op==oend, dstSize_tooSmall, "");
2186 RETURN_ERROR_IF(ip==iend, srcSize_wrong, "");
2187 assert(0);
2188 }
2189 } else {
2190 zds->noForwardProgress = 0;
2191 }
2192 { size_t nextSrcSizeHint = ZSTD_nextSrcSizeToDecompress(zds);
2193 if (!nextSrcSizeHint) { /* frame fully decoded */
2194 if (zds->outEnd == zds->outStart) { /* output fully flushed */
2195 if (zds->hostageByte) {
2196 if (input->pos >= input->size) {
2197 /* can't release hostage (not present) */
2198 zds->streamStage = zdss_read;
2199 return 1;
2200 }
2201 input->pos++; /* release hostage */
2202 } /* zds->hostageByte */
2203 return 0;
2204 } /* zds->outEnd == zds->outStart */
2205 if (!zds->hostageByte) { /* output not fully flushed; keep last byte as hostage; will be released when all output is flushed */
2206 input->pos--; /* note : pos > 0, otherwise, impossible to finish reading last block */
2207 zds->hostageByte=1;
2208 }
2209 return 1;
2210 } /* nextSrcSizeHint==0 */
2211 nextSrcSizeHint += ZSTD_blockHeaderSize * (ZSTD_nextInputType(zds) == ZSTDnit_block); /* preload header of next block */
2212 assert(zds->inPos <= nextSrcSizeHint);
2213 nextSrcSizeHint -= zds->inPos; /* part already loaded*/
2214 return nextSrcSizeHint;
2215 }
2216 }
2217
ZSTD_decompressStream_simpleArgs(ZSTD_DCtx * dctx,void * dst,size_t dstCapacity,size_t * dstPos,const void * src,size_t srcSize,size_t * srcPos)2218 size_t ZSTD_decompressStream_simpleArgs (
2219 ZSTD_DCtx* dctx,
2220 void* dst, size_t dstCapacity, size_t* dstPos,
2221 const void* src, size_t srcSize, size_t* srcPos)
2222 {
2223 ZSTD_outBuffer output = { dst, dstCapacity, *dstPos };
2224 ZSTD_inBuffer input = { src, srcSize, *srcPos };
2225 /* ZSTD_compress_generic() will check validity of dstPos and srcPos */
2226 size_t const cErr = ZSTD_decompressStream(dctx, &output, &input);
2227 *dstPos = output.pos;
2228 *srcPos = input.pos;
2229 return cErr;
2230 }
2231