2 * Copyright (c) 2016-2020, Yann Collet, Facebook, Inc.
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.
12 /* ***************************************************************
14 *****************************************************************/
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.
22 # define ZSTD_HEAPMODE 1
27 * if set to 1+, ZSTD_decompress() can decode older formats (v0.1+)
29 #ifndef ZSTD_LEGACY_SUPPORT
30 # define ZSTD_LEGACY_SUPPORT 0
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().
39 #ifndef ZSTD_MAXWINDOWSIZE_DEFAULT
40 # define ZSTD_MAXWINDOWSIZE_DEFAULT (((U32)1 << ZSTD_WINDOWLOG_LIMIT_DEFAULT) + 1)
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.
50 #ifndef ZSTD_NO_FORWARD_PROGRESS_MAX
51 # define ZSTD_NO_FORWARD_PROGRESS_MAX 16
55 /*-*******************************************************
57 *********************************************************/
58 #include <string.h> /* memcpy, memmove, memset */
59 #include "../common/cpu.h" /* bmi2 */
60 #include "../common/mem.h" /* low level memory routines */
61 #define FSE_STATIC_LINKING_ONLY
62 #include "../common/fse.h"
63 #define HUF_STATIC_LINKING_ONLY
64 #include "../common/huf.h"
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 */
70 #if defined(ZSTD_LEGACY_SUPPORT) && (ZSTD_LEGACY_SUPPORT>=1)
71 # include "../legacy/zstd_legacy.h"
75 /*-*************************************************************
77 ***************************************************************/
78 size_t ZSTD_sizeof_DCtx (const ZSTD_DCtx
* dctx
)
80 if (dctx
==NULL
) return 0; /* support sizeof NULL */
82 + ZSTD_sizeof_DDict(dctx
->ddictLocal
)
83 + dctx
->inBuffSize
+ dctx
->outBuffSize
;
86 size_t ZSTD_estimateDCtxSize(void) { return sizeof(ZSTD_DCtx
); }
89 static size_t ZSTD_startingInputLength(ZSTD_format_e format
)
91 size_t const startingInputLength
= ZSTD_FRAMEHEADERSIZE_PREFIX(format
);
92 /* only supports formats ZSTD_f_zstd1 and ZSTD_f_zstd1_magicless */
93 assert( (format
== ZSTD_f_zstd1
) || (format
== ZSTD_f_zstd1_magicless
) );
94 return startingInputLength
;
97 static void ZSTD_initDCtx_internal(ZSTD_DCtx
* dctx
)
99 dctx
->format
= ZSTD_f_zstd1
; /* ZSTD_decompressBegin() invokes ZSTD_startingInputLength() with argument dctx->format */
100 dctx
->staticSize
= 0;
101 dctx
->maxWindowSize
= ZSTD_MAXWINDOWSIZE_DEFAULT
;
103 dctx
->ddictLocal
= NULL
;
104 dctx
->dictEnd
= NULL
;
105 dctx
->ddictIsCold
= 0;
106 dctx
->dictUses
= ZSTD_dont_use
;
108 dctx
->inBuffSize
= 0;
109 dctx
->outBuffSize
= 0;
110 dctx
->streamStage
= zdss_init
;
111 dctx
->legacyContext
= NULL
;
112 dctx
->previousLegacyVersion
= 0;
113 dctx
->noForwardProgress
= 0;
114 dctx
->oversizedDuration
= 0;
115 dctx
->bmi2
= ZSTD_cpuid_bmi2(ZSTD_cpuid());
116 dctx
->outBufferMode
= ZSTD_obm_buffered
;
117 #ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
118 dctx
->dictContentEndForFuzzing
= NULL
;
122 ZSTD_DCtx
* ZSTD_initStaticDCtx(void *workspace
, size_t workspaceSize
)
124 ZSTD_DCtx
* const dctx
= (ZSTD_DCtx
*) workspace
;
126 if ((size_t)workspace
& 7) return NULL
; /* 8-aligned */
127 if (workspaceSize
< sizeof(ZSTD_DCtx
)) return NULL
; /* minimum size */
129 ZSTD_initDCtx_internal(dctx
);
130 dctx
->staticSize
= workspaceSize
;
131 dctx
->inBuff
= (char*)(dctx
+1);
135 ZSTD_DCtx
* ZSTD_createDCtx_advanced(ZSTD_customMem customMem
)
137 if (!customMem
.customAlloc
^ !customMem
.customFree
) return NULL
;
139 { ZSTD_DCtx
* const dctx
= (ZSTD_DCtx
*)ZSTD_malloc(sizeof(*dctx
), customMem
);
140 if (!dctx
) return NULL
;
141 dctx
->customMem
= customMem
;
142 ZSTD_initDCtx_internal(dctx
);
147 ZSTD_DCtx
* ZSTD_createDCtx(void)
149 DEBUGLOG(3, "ZSTD_createDCtx");
150 return ZSTD_createDCtx_advanced(ZSTD_defaultCMem
);
153 static void ZSTD_clearDict(ZSTD_DCtx
* dctx
)
155 ZSTD_freeDDict(dctx
->ddictLocal
);
156 dctx
->ddictLocal
= NULL
;
158 dctx
->dictUses
= ZSTD_dont_use
;
161 size_t ZSTD_freeDCtx(ZSTD_DCtx
* dctx
)
163 if (dctx
==NULL
) return 0; /* support free on NULL */
164 RETURN_ERROR_IF(dctx
->staticSize
, memory_allocation
, "not compatible with static DCtx");
165 { ZSTD_customMem
const cMem
= dctx
->customMem
;
166 ZSTD_clearDict(dctx
);
167 ZSTD_free(dctx
->inBuff
, cMem
);
169 #if defined(ZSTD_LEGACY_SUPPORT) && (ZSTD_LEGACY_SUPPORT >= 1)
170 if (dctx
->legacyContext
)
171 ZSTD_freeLegacyStreamContext(dctx
->legacyContext
, dctx
->previousLegacyVersion
);
173 ZSTD_free(dctx
, cMem
);
178 /* no longer useful */
179 void ZSTD_copyDCtx(ZSTD_DCtx
* dstDCtx
, const ZSTD_DCtx
* srcDCtx
)
181 size_t const toCopy
= (size_t)((char*)(&dstDCtx
->inBuff
) - (char*)dstDCtx
);
182 memcpy(dstDCtx
, srcDCtx
, toCopy
); /* no need to copy workspace */
186 /*-*************************************************************
187 * Frame header decoding
188 ***************************************************************/
191 * Tells if the content of `buffer` starts with a valid Frame Identifier.
192 * Note : Frame Identifier is 4 bytes. If `size < 4`, @return will always be 0.
193 * Note 2 : Legacy Frame Identifiers are considered valid only if Legacy Support is enabled.
194 * Note 3 : Skippable Frame Identifiers are considered valid. */
195 unsigned ZSTD_isFrame(const void* buffer
, size_t size
)
197 if (size
< ZSTD_FRAMEIDSIZE
) return 0;
198 { U32
const magic
= MEM_readLE32(buffer
);
199 if (magic
== ZSTD_MAGICNUMBER
) return 1;
200 if ((magic
& ZSTD_MAGIC_SKIPPABLE_MASK
) == ZSTD_MAGIC_SKIPPABLE_START
) return 1;
202 #if defined(ZSTD_LEGACY_SUPPORT) && (ZSTD_LEGACY_SUPPORT >= 1)
203 if (ZSTD_isLegacy(buffer
, size
)) return 1;
208 /** ZSTD_frameHeaderSize_internal() :
209 * srcSize must be large enough to reach header size fields.
210 * note : only works for formats ZSTD_f_zstd1 and ZSTD_f_zstd1_magicless.
211 * @return : size of the Frame Header
212 * or an error code, which can be tested with ZSTD_isError() */
213 static size_t ZSTD_frameHeaderSize_internal(const void* src
, size_t srcSize
, ZSTD_format_e format
)
215 size_t const minInputSize
= ZSTD_startingInputLength(format
);
216 RETURN_ERROR_IF(srcSize
< minInputSize
, srcSize_wrong
, "");
218 { BYTE
const fhd
= ((const BYTE
*)src
)[minInputSize
-1];
219 U32
const dictID
= fhd
& 3;
220 U32
const singleSegment
= (fhd
>> 5) & 1;
221 U32
const fcsId
= fhd
>> 6;
222 return minInputSize
+ !singleSegment
223 + ZSTD_did_fieldSize
[dictID
] + ZSTD_fcs_fieldSize
[fcsId
]
224 + (singleSegment
&& !fcsId
);
228 /** ZSTD_frameHeaderSize() :
229 * srcSize must be >= ZSTD_frameHeaderSize_prefix.
230 * @return : size of the Frame Header,
231 * or an error code (if srcSize is too small) */
232 size_t ZSTD_frameHeaderSize(const void* src
, size_t srcSize
)
234 return ZSTD_frameHeaderSize_internal(src
, srcSize
, ZSTD_f_zstd1
);
238 /** ZSTD_getFrameHeader_advanced() :
239 * decode Frame Header, or require larger `srcSize`.
240 * note : only works for formats ZSTD_f_zstd1 and ZSTD_f_zstd1_magicless
241 * @return : 0, `zfhPtr` is correctly filled,
242 * >0, `srcSize` is too small, value is wanted `srcSize` amount,
243 * or an error code, which can be tested using ZSTD_isError() */
244 size_t ZSTD_getFrameHeader_advanced(ZSTD_frameHeader
* zfhPtr
, const void* src
, size_t srcSize
, ZSTD_format_e format
)
246 const BYTE
* ip
= (const BYTE
*)src
;
247 size_t const minInputSize
= ZSTD_startingInputLength(format
);
249 memset(zfhPtr
, 0, sizeof(*zfhPtr
)); /* not strictly necessary, but static analyzer do not understand that zfhPtr is only going to be read only if return value is zero, since they are 2 different signals */
250 if (srcSize
< minInputSize
) return minInputSize
;
251 RETURN_ERROR_IF(src
==NULL
, GENERIC
, "invalid parameter");
253 if ( (format
!= ZSTD_f_zstd1_magicless
)
254 && (MEM_readLE32(src
) != ZSTD_MAGICNUMBER
) ) {
255 if ((MEM_readLE32(src
) & ZSTD_MAGIC_SKIPPABLE_MASK
) == ZSTD_MAGIC_SKIPPABLE_START
) {
256 /* skippable frame */
257 if (srcSize
< ZSTD_SKIPPABLEHEADERSIZE
)
258 return ZSTD_SKIPPABLEHEADERSIZE
; /* magic number + frame length */
259 memset(zfhPtr
, 0, sizeof(*zfhPtr
));
260 zfhPtr
->frameContentSize
= MEM_readLE32((const char *)src
+ ZSTD_FRAMEIDSIZE
);
261 zfhPtr
->frameType
= ZSTD_skippableFrame
;
264 RETURN_ERROR(prefix_unknown
, "");
267 /* ensure there is enough `srcSize` to fully read/decode frame header */
268 { size_t const fhsize
= ZSTD_frameHeaderSize_internal(src
, srcSize
, format
);
269 if (srcSize
< fhsize
) return fhsize
;
270 zfhPtr
->headerSize
= (U32
)fhsize
;
273 { BYTE
const fhdByte
= ip
[minInputSize
-1];
274 size_t pos
= minInputSize
;
275 U32
const dictIDSizeCode
= fhdByte
&3;
276 U32
const checksumFlag
= (fhdByte
>>2)&1;
277 U32
const singleSegment
= (fhdByte
>>5)&1;
278 U32
const fcsID
= fhdByte
>>6;
281 U64 frameContentSize
= ZSTD_CONTENTSIZE_UNKNOWN
;
282 RETURN_ERROR_IF((fhdByte
& 0x08) != 0, frameParameter_unsupported
,
283 "reserved bits, must be zero");
285 if (!singleSegment
) {
286 BYTE
const wlByte
= ip
[pos
++];
287 U32
const windowLog
= (wlByte
>> 3) + ZSTD_WINDOWLOG_ABSOLUTEMIN
;
288 RETURN_ERROR_IF(windowLog
> ZSTD_WINDOWLOG_MAX
, frameParameter_windowTooLarge
, "");
289 windowSize
= (1ULL << windowLog
);
290 windowSize
+= (windowSize
>> 3) * (wlByte
&7);
292 switch(dictIDSizeCode
)
294 default: assert(0); /* impossible */
296 case 1 : dictID
= ip
[pos
]; pos
++; break;
297 case 2 : dictID
= MEM_readLE16(ip
+pos
); pos
+=2; break;
298 case 3 : dictID
= MEM_readLE32(ip
+pos
); pos
+=4; break;
302 default: assert(0); /* impossible */
303 case 0 : if (singleSegment
) frameContentSize
= ip
[pos
]; break;
304 case 1 : frameContentSize
= MEM_readLE16(ip
+pos
)+256; break;
305 case 2 : frameContentSize
= MEM_readLE32(ip
+pos
); break;
306 case 3 : frameContentSize
= MEM_readLE64(ip
+pos
); break;
308 if (singleSegment
) windowSize
= frameContentSize
;
310 zfhPtr
->frameType
= ZSTD_frame
;
311 zfhPtr
->frameContentSize
= frameContentSize
;
312 zfhPtr
->windowSize
= windowSize
;
313 zfhPtr
->blockSizeMax
= (unsigned) MIN(windowSize
, ZSTD_BLOCKSIZE_MAX
);
314 zfhPtr
->dictID
= dictID
;
315 zfhPtr
->checksumFlag
= checksumFlag
;
320 /** ZSTD_getFrameHeader() :
321 * decode Frame Header, or require larger `srcSize`.
322 * note : this function does not consume input, it only reads it.
323 * @return : 0, `zfhPtr` is correctly filled,
324 * >0, `srcSize` is too small, value is wanted `srcSize` amount,
325 * or an error code, which can be tested using ZSTD_isError() */
326 size_t ZSTD_getFrameHeader(ZSTD_frameHeader
* zfhPtr
, const void* src
, size_t srcSize
)
328 return ZSTD_getFrameHeader_advanced(zfhPtr
, src
, srcSize
, ZSTD_f_zstd1
);
332 /** ZSTD_getFrameContentSize() :
333 * compatible with legacy mode
334 * @return : decompressed size of the single frame pointed to be `src` if known, otherwise
335 * - ZSTD_CONTENTSIZE_UNKNOWN if the size cannot be determined
336 * - ZSTD_CONTENTSIZE_ERROR if an error occurred (e.g. invalid magic number, srcSize too small) */
337 unsigned long long ZSTD_getFrameContentSize(const void *src
, size_t srcSize
)
339 #if defined(ZSTD_LEGACY_SUPPORT) && (ZSTD_LEGACY_SUPPORT >= 1)
340 if (ZSTD_isLegacy(src
, srcSize
)) {
341 unsigned long long const ret
= ZSTD_getDecompressedSize_legacy(src
, srcSize
);
342 return ret
== 0 ? ZSTD_CONTENTSIZE_UNKNOWN
: ret
;
345 { ZSTD_frameHeader zfh
;
346 if (ZSTD_getFrameHeader(&zfh
, src
, srcSize
) != 0)
347 return ZSTD_CONTENTSIZE_ERROR
;
348 if (zfh
.frameType
== ZSTD_skippableFrame
) {
351 return zfh
.frameContentSize
;
355 static size_t readSkippableFrameSize(void const* src
, size_t srcSize
)
357 size_t const skippableHeaderSize
= ZSTD_SKIPPABLEHEADERSIZE
;
360 RETURN_ERROR_IF(srcSize
< ZSTD_SKIPPABLEHEADERSIZE
, srcSize_wrong
, "");
362 sizeU32
= MEM_readLE32((BYTE
const*)src
+ ZSTD_FRAMEIDSIZE
);
363 RETURN_ERROR_IF((U32
)(sizeU32
+ ZSTD_SKIPPABLEHEADERSIZE
) < sizeU32
,
364 frameParameter_unsupported
, "");
366 size_t const skippableSize
= skippableHeaderSize
+ sizeU32
;
367 RETURN_ERROR_IF(skippableSize
> srcSize
, srcSize_wrong
, "");
368 return skippableSize
;
372 /** ZSTD_findDecompressedSize() :
373 * compatible with legacy mode
374 * `srcSize` must be the exact length of some number of ZSTD compressed and/or
376 * @return : decompressed size of the frames contained */
377 unsigned long long ZSTD_findDecompressedSize(const void* src
, size_t srcSize
)
379 unsigned long long totalDstSize
= 0;
381 while (srcSize
>= ZSTD_startingInputLength(ZSTD_f_zstd1
)) {
382 U32
const magicNumber
= MEM_readLE32(src
);
384 if ((magicNumber
& ZSTD_MAGIC_SKIPPABLE_MASK
) == ZSTD_MAGIC_SKIPPABLE_START
) {
385 size_t const skippableSize
= readSkippableFrameSize(src
, srcSize
);
386 if (ZSTD_isError(skippableSize
)) {
387 return ZSTD_CONTENTSIZE_ERROR
;
389 assert(skippableSize
<= srcSize
);
391 src
= (const BYTE
*)src
+ skippableSize
;
392 srcSize
-= skippableSize
;
396 { unsigned long long const ret
= ZSTD_getFrameContentSize(src
, srcSize
);
397 if (ret
>= ZSTD_CONTENTSIZE_ERROR
) return ret
;
399 /* check for overflow */
400 if (totalDstSize
+ ret
< totalDstSize
) return ZSTD_CONTENTSIZE_ERROR
;
403 { size_t const frameSrcSize
= ZSTD_findFrameCompressedSize(src
, srcSize
);
404 if (ZSTD_isError(frameSrcSize
)) {
405 return ZSTD_CONTENTSIZE_ERROR
;
408 src
= (const BYTE
*)src
+ frameSrcSize
;
409 srcSize
-= frameSrcSize
;
411 } /* while (srcSize >= ZSTD_frameHeaderSize_prefix) */
413 if (srcSize
) return ZSTD_CONTENTSIZE_ERROR
;
418 /** ZSTD_getDecompressedSize() :
419 * compatible with legacy mode
420 * @return : decompressed size if known, 0 otherwise
421 note : 0 can mean any of the following :
422 - frame content is empty
423 - decompressed size field is not present in frame header
424 - frame header unknown / not supported
425 - frame header not complete (`srcSize` too small) */
426 unsigned long long ZSTD_getDecompressedSize(const void* src
, size_t srcSize
)
428 unsigned long long const ret
= ZSTD_getFrameContentSize(src
, srcSize
);
429 ZSTD_STATIC_ASSERT(ZSTD_CONTENTSIZE_ERROR
< ZSTD_CONTENTSIZE_UNKNOWN
);
430 return (ret
>= ZSTD_CONTENTSIZE_ERROR
) ? 0 : ret
;
434 /** ZSTD_decodeFrameHeader() :
435 * `headerSize` must be the size provided by ZSTD_frameHeaderSize().
436 * @return : 0 if success, or an error code, which can be tested using ZSTD_isError() */
437 static size_t ZSTD_decodeFrameHeader(ZSTD_DCtx
* dctx
, const void* src
, size_t headerSize
)
439 size_t const result
= ZSTD_getFrameHeader_advanced(&(dctx
->fParams
), src
, headerSize
, dctx
->format
);
440 if (ZSTD_isError(result
)) return result
; /* invalid header */
441 RETURN_ERROR_IF(result
>0, srcSize_wrong
, "headerSize too small");
442 #ifndef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
443 /* Skip the dictID check in fuzzing mode, because it makes the search
446 RETURN_ERROR_IF(dctx
->fParams
.dictID
&& (dctx
->dictID
!= dctx
->fParams
.dictID
),
447 dictionary_wrong
, "");
449 if (dctx
->fParams
.checksumFlag
) XXH64_reset(&dctx
->xxhState
, 0);
453 static ZSTD_frameSizeInfo
ZSTD_errorFrameSizeInfo(size_t ret
)
455 ZSTD_frameSizeInfo frameSizeInfo
;
456 frameSizeInfo
.compressedSize
= ret
;
457 frameSizeInfo
.decompressedBound
= ZSTD_CONTENTSIZE_ERROR
;
458 return frameSizeInfo
;
461 static ZSTD_frameSizeInfo
ZSTD_findFrameSizeInfo(const void* src
, size_t srcSize
)
463 ZSTD_frameSizeInfo frameSizeInfo
;
464 memset(&frameSizeInfo
, 0, sizeof(ZSTD_frameSizeInfo
));
466 #if defined(ZSTD_LEGACY_SUPPORT) && (ZSTD_LEGACY_SUPPORT >= 1)
467 if (ZSTD_isLegacy(src
, srcSize
))
468 return ZSTD_findFrameSizeInfoLegacy(src
, srcSize
);
471 if ((srcSize
>= ZSTD_SKIPPABLEHEADERSIZE
)
472 && (MEM_readLE32(src
) & ZSTD_MAGIC_SKIPPABLE_MASK
) == ZSTD_MAGIC_SKIPPABLE_START
) {
473 frameSizeInfo
.compressedSize
= readSkippableFrameSize(src
, srcSize
);
474 assert(ZSTD_isError(frameSizeInfo
.compressedSize
) ||
475 frameSizeInfo
.compressedSize
<= srcSize
);
476 return frameSizeInfo
;
478 const BYTE
* ip
= (const BYTE
*)src
;
479 const BYTE
* const ipstart
= ip
;
480 size_t remainingSize
= srcSize
;
482 ZSTD_frameHeader zfh
;
484 /* Extract Frame Header */
485 { size_t const ret
= ZSTD_getFrameHeader(&zfh
, src
, srcSize
);
486 if (ZSTD_isError(ret
))
487 return ZSTD_errorFrameSizeInfo(ret
);
489 return ZSTD_errorFrameSizeInfo(ERROR(srcSize_wrong
));
492 ip
+= zfh
.headerSize
;
493 remainingSize
-= zfh
.headerSize
;
495 /* Iterate over each block */
497 blockProperties_t blockProperties
;
498 size_t const cBlockSize
= ZSTD_getcBlockSize(ip
, remainingSize
, &blockProperties
);
499 if (ZSTD_isError(cBlockSize
))
500 return ZSTD_errorFrameSizeInfo(cBlockSize
);
502 if (ZSTD_blockHeaderSize
+ cBlockSize
> remainingSize
)
503 return ZSTD_errorFrameSizeInfo(ERROR(srcSize_wrong
));
505 ip
+= ZSTD_blockHeaderSize
+ cBlockSize
;
506 remainingSize
-= ZSTD_blockHeaderSize
+ cBlockSize
;
509 if (blockProperties
.lastBlock
) break;
512 /* Final frame content checksum */
513 if (zfh
.checksumFlag
) {
514 if (remainingSize
< 4)
515 return ZSTD_errorFrameSizeInfo(ERROR(srcSize_wrong
));
519 frameSizeInfo
.compressedSize
= ip
- ipstart
;
520 frameSizeInfo
.decompressedBound
= (zfh
.frameContentSize
!= ZSTD_CONTENTSIZE_UNKNOWN
)
521 ? zfh
.frameContentSize
522 : nbBlocks
* zfh
.blockSizeMax
;
523 return frameSizeInfo
;
527 /** ZSTD_findFrameCompressedSize() :
528 * compatible with legacy mode
529 * `src` must point to the start of a ZSTD frame, ZSTD legacy frame, or skippable frame
530 * `srcSize` must be at least as large as the frame contained
531 * @return : the compressed size of the frame starting at `src` */
532 size_t ZSTD_findFrameCompressedSize(const void *src
, size_t srcSize
)
534 ZSTD_frameSizeInfo
const frameSizeInfo
= ZSTD_findFrameSizeInfo(src
, srcSize
);
535 return frameSizeInfo
.compressedSize
;
538 /** ZSTD_decompressBound() :
539 * compatible with legacy mode
540 * `src` must point to the start of a ZSTD frame or a skippeable frame
541 * `srcSize` must be at least as large as the frame contained
542 * @return : the maximum decompressed size of the compressed source
544 unsigned long long ZSTD_decompressBound(const void* src
, size_t srcSize
)
546 unsigned long long bound
= 0;
547 /* Iterate over each frame */
548 while (srcSize
> 0) {
549 ZSTD_frameSizeInfo
const frameSizeInfo
= ZSTD_findFrameSizeInfo(src
, srcSize
);
550 size_t const compressedSize
= frameSizeInfo
.compressedSize
;
551 unsigned long long const decompressedBound
= frameSizeInfo
.decompressedBound
;
552 if (ZSTD_isError(compressedSize
) || decompressedBound
== ZSTD_CONTENTSIZE_ERROR
)
553 return ZSTD_CONTENTSIZE_ERROR
;
554 assert(srcSize
>= compressedSize
);
555 src
= (const BYTE
*)src
+ compressedSize
;
556 srcSize
-= compressedSize
;
557 bound
+= decompressedBound
;
563 /*-*************************************************************
565 ***************************************************************/
567 /** ZSTD_insertBlock() :
568 * insert `src` block into `dctx` history. Useful to track uncompressed blocks. */
569 size_t ZSTD_insertBlock(ZSTD_DCtx
* dctx
, const void* blockStart
, size_t blockSize
)
571 DEBUGLOG(5, "ZSTD_insertBlock: %u bytes", (unsigned)blockSize
);
572 ZSTD_checkContinuity(dctx
, blockStart
);
573 dctx
->previousDstEnd
= (const char*)blockStart
+ blockSize
;
578 static size_t ZSTD_copyRawBlock(void* dst
, size_t dstCapacity
,
579 const void* src
, size_t srcSize
)
581 DEBUGLOG(5, "ZSTD_copyRawBlock");
583 if (srcSize
== 0) return 0;
584 RETURN_ERROR(dstBuffer_null
, "");
586 RETURN_ERROR_IF(srcSize
> dstCapacity
, dstSize_tooSmall
, "");
587 memcpy(dst
, src
, srcSize
);
591 static size_t ZSTD_setRleBlock(void* dst
, size_t dstCapacity
,
596 if (regenSize
== 0) return 0;
597 RETURN_ERROR(dstBuffer_null
, "");
599 RETURN_ERROR_IF(regenSize
> dstCapacity
, dstSize_tooSmall
, "");
600 memset(dst
, b
, regenSize
);
605 /*! ZSTD_decompressFrame() :
606 * @dctx must be properly initialized
607 * will update *srcPtr and *srcSizePtr,
608 * to make *srcPtr progress by one frame. */
609 static size_t ZSTD_decompressFrame(ZSTD_DCtx
* dctx
,
610 void* dst
, size_t dstCapacity
,
611 const void** srcPtr
, size_t *srcSizePtr
)
613 const BYTE
* ip
= (const BYTE
*)(*srcPtr
);
614 BYTE
* const ostart
= (BYTE
* const)dst
;
615 BYTE
* const oend
= dstCapacity
!= 0 ? ostart
+ dstCapacity
: ostart
;
617 size_t remainingSrcSize
= *srcSizePtr
;
619 DEBUGLOG(4, "ZSTD_decompressFrame (srcSize:%i)", (int)*srcSizePtr
);
623 remainingSrcSize
< ZSTD_FRAMEHEADERSIZE_MIN(dctx
->format
)+ZSTD_blockHeaderSize
,
627 { size_t const frameHeaderSize
= ZSTD_frameHeaderSize_internal(
628 ip
, ZSTD_FRAMEHEADERSIZE_PREFIX(dctx
->format
), dctx
->format
);
629 if (ZSTD_isError(frameHeaderSize
)) return frameHeaderSize
;
630 RETURN_ERROR_IF(remainingSrcSize
< frameHeaderSize
+ZSTD_blockHeaderSize
,
632 FORWARD_IF_ERROR( ZSTD_decodeFrameHeader(dctx
, ip
, frameHeaderSize
) , "");
633 ip
+= frameHeaderSize
; remainingSrcSize
-= frameHeaderSize
;
636 /* Loop on each block */
639 blockProperties_t blockProperties
;
640 size_t const cBlockSize
= ZSTD_getcBlockSize(ip
, remainingSrcSize
, &blockProperties
);
641 if (ZSTD_isError(cBlockSize
)) return cBlockSize
;
643 ip
+= ZSTD_blockHeaderSize
;
644 remainingSrcSize
-= ZSTD_blockHeaderSize
;
645 RETURN_ERROR_IF(cBlockSize
> remainingSrcSize
, srcSize_wrong
, "");
647 switch(blockProperties
.blockType
)
650 decodedSize
= ZSTD_decompressBlock_internal(dctx
, op
, oend
-op
, ip
, cBlockSize
, /* frame */ 1);
653 decodedSize
= ZSTD_copyRawBlock(op
, oend
-op
, ip
, cBlockSize
);
656 decodedSize
= ZSTD_setRleBlock(op
, oend
-op
, *ip
, blockProperties
.origSize
);
660 RETURN_ERROR(corruption_detected
, "invalid block type");
663 if (ZSTD_isError(decodedSize
)) return decodedSize
;
664 if (dctx
->fParams
.checksumFlag
)
665 XXH64_update(&dctx
->xxhState
, op
, decodedSize
);
666 if (decodedSize
!= 0)
670 remainingSrcSize
-= cBlockSize
;
671 if (blockProperties
.lastBlock
) break;
674 if (dctx
->fParams
.frameContentSize
!= ZSTD_CONTENTSIZE_UNKNOWN
) {
675 RETURN_ERROR_IF((U64
)(op
-ostart
) != dctx
->fParams
.frameContentSize
,
676 corruption_detected
, "");
678 if (dctx
->fParams
.checksumFlag
) { /* Frame content checksum verification */
679 U32
const checkCalc
= (U32
)XXH64_digest(&dctx
->xxhState
);
681 RETURN_ERROR_IF(remainingSrcSize
<4, checksum_wrong
, "");
682 checkRead
= MEM_readLE32(ip
);
683 RETURN_ERROR_IF(checkRead
!= checkCalc
, checksum_wrong
, "");
685 remainingSrcSize
-= 4;
688 /* Allow caller to get size read */
690 *srcSizePtr
= remainingSrcSize
;
694 static size_t ZSTD_decompressMultiFrame(ZSTD_DCtx
* dctx
,
695 void* dst
, size_t dstCapacity
,
696 const void* src
, size_t srcSize
,
697 const void* dict
, size_t dictSize
,
698 const ZSTD_DDict
* ddict
)
700 void* const dststart
= dst
;
701 int moreThan1Frame
= 0;
703 DEBUGLOG(5, "ZSTD_decompressMultiFrame");
704 assert(dict
==NULL
|| ddict
==NULL
); /* either dict or ddict set, not both */
707 dict
= ZSTD_DDict_dictContent(ddict
);
708 dictSize
= ZSTD_DDict_dictSize(ddict
);
711 while (srcSize
>= ZSTD_startingInputLength(dctx
->format
)) {
713 #if defined(ZSTD_LEGACY_SUPPORT) && (ZSTD_LEGACY_SUPPORT >= 1)
714 if (ZSTD_isLegacy(src
, srcSize
)) {
716 size_t const frameSize
= ZSTD_findFrameCompressedSizeLegacy(src
, srcSize
);
717 if (ZSTD_isError(frameSize
)) return frameSize
;
718 RETURN_ERROR_IF(dctx
->staticSize
, memory_allocation
,
719 "legacy support is not compatible with static dctx");
721 decodedSize
= ZSTD_decompressLegacy(dst
, dstCapacity
, src
, frameSize
, dict
, dictSize
);
722 if (ZSTD_isError(decodedSize
)) return decodedSize
;
724 assert(decodedSize
<=- dstCapacity
);
725 dst
= (BYTE
*)dst
+ decodedSize
;
726 dstCapacity
-= decodedSize
;
728 src
= (const BYTE
*)src
+ frameSize
;
729 srcSize
-= frameSize
;
735 { U32
const magicNumber
= MEM_readLE32(src
);
736 DEBUGLOG(4, "reading magic number %08X (expecting %08X)",
737 (unsigned)magicNumber
, ZSTD_MAGICNUMBER
);
738 if ((magicNumber
& ZSTD_MAGIC_SKIPPABLE_MASK
) == ZSTD_MAGIC_SKIPPABLE_START
) {
739 size_t const skippableSize
= readSkippableFrameSize(src
, srcSize
);
740 FORWARD_IF_ERROR(skippableSize
, "readSkippableFrameSize failed");
741 assert(skippableSize
<= srcSize
);
743 src
= (const BYTE
*)src
+ skippableSize
;
744 srcSize
-= skippableSize
;
749 /* we were called from ZSTD_decompress_usingDDict */
750 FORWARD_IF_ERROR(ZSTD_decompressBegin_usingDDict(dctx
, ddict
), "");
752 /* this will initialize correctly with no dict if dict == NULL, so
753 * use this in all cases but ddict */
754 FORWARD_IF_ERROR(ZSTD_decompressBegin_usingDict(dctx
, dict
, dictSize
), "");
756 ZSTD_checkContinuity(dctx
, dst
);
758 { const size_t res
= ZSTD_decompressFrame(dctx
, dst
, dstCapacity
,
761 (ZSTD_getErrorCode(res
) == ZSTD_error_prefix_unknown
)
762 && (moreThan1Frame
==1),
764 "at least one frame successfully completed, but following "
765 "bytes are garbage: it's more likely to be a srcSize error, "
766 "specifying more bytes than compressed size of frame(s). This "
767 "error message replaces ERROR(prefix_unknown), which would be "
768 "confusing, as the first header is actually correct. Note that "
769 "one could be unlucky, it might be a corruption error instead, "
770 "happening right at the place where we expect zstd magic "
771 "bytes. But this is _much_ less likely than a srcSize field "
773 if (ZSTD_isError(res
)) return res
;
774 assert(res
<= dstCapacity
);
776 dst
= (BYTE
*)dst
+ res
;
780 } /* while (srcSize >= ZSTD_frameHeaderSize_prefix) */
782 RETURN_ERROR_IF(srcSize
, srcSize_wrong
, "input not entirely consumed");
784 return (BYTE
*)dst
- (BYTE
*)dststart
;
787 size_t ZSTD_decompress_usingDict(ZSTD_DCtx
* dctx
,
788 void* dst
, size_t dstCapacity
,
789 const void* src
, size_t srcSize
,
790 const void* dict
, size_t dictSize
)
792 return ZSTD_decompressMultiFrame(dctx
, dst
, dstCapacity
, src
, srcSize
, dict
, dictSize
, NULL
);
796 static ZSTD_DDict
const* ZSTD_getDDict(ZSTD_DCtx
* dctx
)
798 switch (dctx
->dictUses
) {
800 assert(0 /* Impossible */);
803 ZSTD_clearDict(dctx
);
805 case ZSTD_use_indefinitely
:
808 dctx
->dictUses
= ZSTD_dont_use
;
813 size_t ZSTD_decompressDCtx(ZSTD_DCtx
* dctx
, void* dst
, size_t dstCapacity
, const void* src
, size_t srcSize
)
815 return ZSTD_decompress_usingDDict(dctx
, dst
, dstCapacity
, src
, srcSize
, ZSTD_getDDict(dctx
));
819 size_t ZSTD_decompress(void* dst
, size_t dstCapacity
, const void* src
, size_t srcSize
)
821 #if defined(ZSTD_HEAPMODE) && (ZSTD_HEAPMODE>=1)
823 ZSTD_DCtx
* const dctx
= ZSTD_createDCtx();
824 RETURN_ERROR_IF(dctx
==NULL
, memory_allocation
, "NULL pointer!");
825 regenSize
= ZSTD_decompressDCtx(dctx
, dst
, dstCapacity
, src
, srcSize
);
828 #else /* stack mode */
830 ZSTD_initDCtx_internal(&dctx
);
831 return ZSTD_decompressDCtx(&dctx
, dst
, dstCapacity
, src
, srcSize
);
836 /*-**************************************
837 * Advanced Streaming Decompression API
838 * Bufferless and synchronous
839 ****************************************/
840 size_t ZSTD_nextSrcSizeToDecompress(ZSTD_DCtx
* dctx
) { return dctx
->expected
; }
843 * Similar to ZSTD_nextSrcSizeToDecompress(), but when when a block input can be streamed,
844 * we allow taking a partial block as the input. Currently only raw uncompressed blocks can
847 * For blocks that can be streamed, this allows us to reduce the latency until we produce
848 * output, and avoid copying the input.
850 * @param inputSize - The total amount of input that the caller currently has.
852 static size_t ZSTD_nextSrcSizeToDecompressWithInputSize(ZSTD_DCtx
* dctx
, size_t inputSize
) {
853 if (!(dctx
->stage
== ZSTDds_decompressBlock
|| dctx
->stage
== ZSTDds_decompressLastBlock
))
854 return dctx
->expected
;
855 if (dctx
->bType
!= bt_raw
)
856 return dctx
->expected
;
857 return MIN(MAX(inputSize
, 1), dctx
->expected
);
860 ZSTD_nextInputType_e
ZSTD_nextInputType(ZSTD_DCtx
* dctx
) {
863 default: /* should not happen */
865 case ZSTDds_getFrameHeaderSize
:
866 case ZSTDds_decodeFrameHeader
:
867 return ZSTDnit_frameHeader
;
868 case ZSTDds_decodeBlockHeader
:
869 return ZSTDnit_blockHeader
;
870 case ZSTDds_decompressBlock
:
871 return ZSTDnit_block
;
872 case ZSTDds_decompressLastBlock
:
873 return ZSTDnit_lastBlock
;
874 case ZSTDds_checkChecksum
:
875 return ZSTDnit_checksum
;
876 case ZSTDds_decodeSkippableHeader
:
877 case ZSTDds_skipFrame
:
878 return ZSTDnit_skippableFrame
;
882 static int ZSTD_isSkipFrame(ZSTD_DCtx
* dctx
) { return dctx
->stage
== ZSTDds_skipFrame
; }
884 /** ZSTD_decompressContinue() :
885 * srcSize : must be the exact nb of bytes expected (see ZSTD_nextSrcSizeToDecompress())
886 * @return : nb of bytes generated into `dst` (necessarily <= `dstCapacity)
887 * or an error code, which can be tested using ZSTD_isError() */
888 size_t ZSTD_decompressContinue(ZSTD_DCtx
* dctx
, void* dst
, size_t dstCapacity
, const void* src
, size_t srcSize
)
890 DEBUGLOG(5, "ZSTD_decompressContinue (srcSize:%u)", (unsigned)srcSize
);
892 RETURN_ERROR_IF(srcSize
!= ZSTD_nextSrcSizeToDecompressWithInputSize(dctx
, srcSize
), srcSize_wrong
, "not allowed");
893 if (dstCapacity
) ZSTD_checkContinuity(dctx
, dst
);
897 case ZSTDds_getFrameHeaderSize
:
899 if (dctx
->format
== ZSTD_f_zstd1
) { /* allows header */
900 assert(srcSize
>= ZSTD_FRAMEIDSIZE
); /* to read skippable magic number */
901 if ((MEM_readLE32(src
) & ZSTD_MAGIC_SKIPPABLE_MASK
) == ZSTD_MAGIC_SKIPPABLE_START
) { /* skippable frame */
902 memcpy(dctx
->headerBuffer
, src
, srcSize
);
903 dctx
->expected
= ZSTD_SKIPPABLEHEADERSIZE
- srcSize
; /* remaining to load to get full skippable frame header */
904 dctx
->stage
= ZSTDds_decodeSkippableHeader
;
907 dctx
->headerSize
= ZSTD_frameHeaderSize_internal(src
, srcSize
, dctx
->format
);
908 if (ZSTD_isError(dctx
->headerSize
)) return dctx
->headerSize
;
909 memcpy(dctx
->headerBuffer
, src
, srcSize
);
910 dctx
->expected
= dctx
->headerSize
- srcSize
;
911 dctx
->stage
= ZSTDds_decodeFrameHeader
;
914 case ZSTDds_decodeFrameHeader
:
916 memcpy(dctx
->headerBuffer
+ (dctx
->headerSize
- srcSize
), src
, srcSize
);
917 FORWARD_IF_ERROR(ZSTD_decodeFrameHeader(dctx
, dctx
->headerBuffer
, dctx
->headerSize
), "");
918 dctx
->expected
= ZSTD_blockHeaderSize
;
919 dctx
->stage
= ZSTDds_decodeBlockHeader
;
922 case ZSTDds_decodeBlockHeader
:
923 { blockProperties_t bp
;
924 size_t const cBlockSize
= ZSTD_getcBlockSize(src
, ZSTD_blockHeaderSize
, &bp
);
925 if (ZSTD_isError(cBlockSize
)) return cBlockSize
;
926 RETURN_ERROR_IF(cBlockSize
> dctx
->fParams
.blockSizeMax
, corruption_detected
, "Block Size Exceeds Maximum");
927 dctx
->expected
= cBlockSize
;
928 dctx
->bType
= bp
.blockType
;
929 dctx
->rleSize
= bp
.origSize
;
931 dctx
->stage
= bp
.lastBlock
? ZSTDds_decompressLastBlock
: ZSTDds_decompressBlock
;
936 if (dctx
->fParams
.checksumFlag
) {
938 dctx
->stage
= ZSTDds_checkChecksum
;
940 dctx
->expected
= 0; /* end of frame */
941 dctx
->stage
= ZSTDds_getFrameHeaderSize
;
944 dctx
->expected
= ZSTD_blockHeaderSize
; /* jump to next header */
945 dctx
->stage
= ZSTDds_decodeBlockHeader
;
950 case ZSTDds_decompressLastBlock
:
951 case ZSTDds_decompressBlock
:
952 DEBUGLOG(5, "ZSTD_decompressContinue: case ZSTDds_decompressBlock");
957 DEBUGLOG(5, "ZSTD_decompressContinue: case bt_compressed");
958 rSize
= ZSTD_decompressBlock_internal(dctx
, dst
, dstCapacity
, src
, srcSize
, /* frame */ 1);
959 dctx
->expected
= 0; /* Streaming not supported */
962 assert(srcSize
<= dctx
->expected
);
963 rSize
= ZSTD_copyRawBlock(dst
, dstCapacity
, src
, srcSize
);
964 FORWARD_IF_ERROR(rSize
, "ZSTD_copyRawBlock failed");
965 assert(rSize
== srcSize
);
966 dctx
->expected
-= rSize
;
969 rSize
= ZSTD_setRleBlock(dst
, dstCapacity
, *(const BYTE
*)src
, dctx
->rleSize
);
970 dctx
->expected
= 0; /* Streaming not supported */
972 case bt_reserved
: /* should never happen */
974 RETURN_ERROR(corruption_detected
, "invalid block type");
976 FORWARD_IF_ERROR(rSize
, "");
977 RETURN_ERROR_IF(rSize
> dctx
->fParams
.blockSizeMax
, corruption_detected
, "Decompressed Block Size Exceeds Maximum");
978 DEBUGLOG(5, "ZSTD_decompressContinue: decoded size from block : %u", (unsigned)rSize
);
979 dctx
->decodedSize
+= rSize
;
980 if (dctx
->fParams
.checksumFlag
) XXH64_update(&dctx
->xxhState
, dst
, rSize
);
981 dctx
->previousDstEnd
= (char*)dst
+ rSize
;
983 /* Stay on the same stage until we are finished streaming the block. */
984 if (dctx
->expected
> 0) {
988 if (dctx
->stage
== ZSTDds_decompressLastBlock
) { /* end of frame */
989 DEBUGLOG(4, "ZSTD_decompressContinue: decoded size from frame : %u", (unsigned)dctx
->decodedSize
);
991 dctx
->fParams
.frameContentSize
!= ZSTD_CONTENTSIZE_UNKNOWN
992 && dctx
->decodedSize
!= dctx
->fParams
.frameContentSize
,
993 corruption_detected
, "");
994 if (dctx
->fParams
.checksumFlag
) { /* another round for frame checksum */
996 dctx
->stage
= ZSTDds_checkChecksum
;
998 dctx
->expected
= 0; /* ends here */
999 dctx
->stage
= ZSTDds_getFrameHeaderSize
;
1002 dctx
->stage
= ZSTDds_decodeBlockHeader
;
1003 dctx
->expected
= ZSTD_blockHeaderSize
;
1008 case ZSTDds_checkChecksum
:
1009 assert(srcSize
== 4); /* guaranteed by dctx->expected */
1010 { U32
const h32
= (U32
)XXH64_digest(&dctx
->xxhState
);
1011 U32
const check32
= MEM_readLE32(src
);
1012 DEBUGLOG(4, "ZSTD_decompressContinue: checksum : calculated %08X :: %08X read", (unsigned)h32
, (unsigned)check32
);
1013 RETURN_ERROR_IF(check32
!= h32
, checksum_wrong
, "");
1015 dctx
->stage
= ZSTDds_getFrameHeaderSize
;
1019 case ZSTDds_decodeSkippableHeader
:
1020 assert(src
!= NULL
);
1021 assert(srcSize
<= ZSTD_SKIPPABLEHEADERSIZE
);
1022 memcpy(dctx
->headerBuffer
+ (ZSTD_SKIPPABLEHEADERSIZE
- srcSize
), src
, srcSize
); /* complete skippable header */
1023 dctx
->expected
= MEM_readLE32(dctx
->headerBuffer
+ ZSTD_FRAMEIDSIZE
); /* note : dctx->expected can grow seriously large, beyond local buffer size */
1024 dctx
->stage
= ZSTDds_skipFrame
;
1027 case ZSTDds_skipFrame
:
1029 dctx
->stage
= ZSTDds_getFrameHeaderSize
;
1033 assert(0); /* impossible */
1034 RETURN_ERROR(GENERIC
, "impossible to reach"); /* some compiler require default to do something */
1039 static size_t ZSTD_refDictContent(ZSTD_DCtx
* dctx
, const void* dict
, size_t dictSize
)
1041 dctx
->dictEnd
= dctx
->previousDstEnd
;
1042 dctx
->virtualStart
= (const char*)dict
- ((const char*)(dctx
->previousDstEnd
) - (const char*)(dctx
->prefixStart
));
1043 dctx
->prefixStart
= dict
;
1044 dctx
->previousDstEnd
= (const char*)dict
+ dictSize
;
1045 #ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
1046 dctx
->dictContentBeginForFuzzing
= dctx
->prefixStart
;
1047 dctx
->dictContentEndForFuzzing
= dctx
->previousDstEnd
;
1052 /*! ZSTD_loadDEntropy() :
1053 * dict : must point at beginning of a valid zstd dictionary.
1054 * @return : size of entropy tables read */
1056 ZSTD_loadDEntropy(ZSTD_entropyDTables_t
* entropy
,
1057 const void* const dict
, size_t const dictSize
)
1059 const BYTE
* dictPtr
= (const BYTE
*)dict
;
1060 const BYTE
* const dictEnd
= dictPtr
+ dictSize
;
1062 RETURN_ERROR_IF(dictSize
<= 8, dictionary_corrupted
, "dict is too small");
1063 assert(MEM_readLE32(dict
) == ZSTD_MAGIC_DICTIONARY
); /* dict must be valid */
1064 dictPtr
+= 8; /* skip header = magic + dictID */
1066 ZSTD_STATIC_ASSERT(offsetof(ZSTD_entropyDTables_t
, OFTable
) == offsetof(ZSTD_entropyDTables_t
, LLTable
) + sizeof(entropy
->LLTable
));
1067 ZSTD_STATIC_ASSERT(offsetof(ZSTD_entropyDTables_t
, MLTable
) == offsetof(ZSTD_entropyDTables_t
, OFTable
) + sizeof(entropy
->OFTable
));
1068 ZSTD_STATIC_ASSERT(sizeof(entropy
->LLTable
) + sizeof(entropy
->OFTable
) + sizeof(entropy
->MLTable
) >= HUF_DECOMPRESS_WORKSPACE_SIZE
);
1069 { void* const workspace
= &entropy
->LLTable
; /* use fse tables as temporary workspace; implies fse tables are grouped together */
1070 size_t const workspaceSize
= sizeof(entropy
->LLTable
) + sizeof(entropy
->OFTable
) + sizeof(entropy
->MLTable
);
1071 #ifdef HUF_FORCE_DECOMPRESS_X1
1072 /* in minimal huffman, we always use X1 variants */
1073 size_t const hSize
= HUF_readDTableX1_wksp(entropy
->hufTable
,
1074 dictPtr
, dictEnd
- dictPtr
,
1075 workspace
, workspaceSize
);
1077 size_t const hSize
= HUF_readDTableX2_wksp(entropy
->hufTable
,
1078 dictPtr
, dictEnd
- dictPtr
,
1079 workspace
, workspaceSize
);
1081 RETURN_ERROR_IF(HUF_isError(hSize
), dictionary_corrupted
, "");
1085 { short offcodeNCount
[MaxOff
+1];
1086 unsigned offcodeMaxValue
= MaxOff
, offcodeLog
;
1087 size_t const offcodeHeaderSize
= FSE_readNCount(offcodeNCount
, &offcodeMaxValue
, &offcodeLog
, dictPtr
, dictEnd
-dictPtr
);
1088 RETURN_ERROR_IF(FSE_isError(offcodeHeaderSize
), dictionary_corrupted
, "");
1089 RETURN_ERROR_IF(offcodeMaxValue
> MaxOff
, dictionary_corrupted
, "");
1090 RETURN_ERROR_IF(offcodeLog
> OffFSELog
, dictionary_corrupted
, "");
1091 ZSTD_buildFSETable( entropy
->OFTable
,
1092 offcodeNCount
, offcodeMaxValue
,
1095 dictPtr
+= offcodeHeaderSize
;
1098 { short matchlengthNCount
[MaxML
+1];
1099 unsigned matchlengthMaxValue
= MaxML
, matchlengthLog
;
1100 size_t const matchlengthHeaderSize
= FSE_readNCount(matchlengthNCount
, &matchlengthMaxValue
, &matchlengthLog
, dictPtr
, dictEnd
-dictPtr
);
1101 RETURN_ERROR_IF(FSE_isError(matchlengthHeaderSize
), dictionary_corrupted
, "");
1102 RETURN_ERROR_IF(matchlengthMaxValue
> MaxML
, dictionary_corrupted
, "");
1103 RETURN_ERROR_IF(matchlengthLog
> MLFSELog
, dictionary_corrupted
, "");
1104 ZSTD_buildFSETable( entropy
->MLTable
,
1105 matchlengthNCount
, matchlengthMaxValue
,
1108 dictPtr
+= matchlengthHeaderSize
;
1111 { short litlengthNCount
[MaxLL
+1];
1112 unsigned litlengthMaxValue
= MaxLL
, litlengthLog
;
1113 size_t const litlengthHeaderSize
= FSE_readNCount(litlengthNCount
, &litlengthMaxValue
, &litlengthLog
, dictPtr
, dictEnd
-dictPtr
);
1114 RETURN_ERROR_IF(FSE_isError(litlengthHeaderSize
), dictionary_corrupted
, "");
1115 RETURN_ERROR_IF(litlengthMaxValue
> MaxLL
, dictionary_corrupted
, "");
1116 RETURN_ERROR_IF(litlengthLog
> LLFSELog
, dictionary_corrupted
, "");
1117 ZSTD_buildFSETable( entropy
->LLTable
,
1118 litlengthNCount
, litlengthMaxValue
,
1121 dictPtr
+= litlengthHeaderSize
;
1124 RETURN_ERROR_IF(dictPtr
+12 > dictEnd
, dictionary_corrupted
, "");
1126 size_t const dictContentSize
= (size_t)(dictEnd
- (dictPtr
+12));
1127 for (i
=0; i
<3; i
++) {
1128 U32
const rep
= MEM_readLE32(dictPtr
); dictPtr
+= 4;
1129 RETURN_ERROR_IF(rep
==0 || rep
> dictContentSize
,
1130 dictionary_corrupted
, "");
1131 entropy
->rep
[i
] = rep
;
1134 return dictPtr
- (const BYTE
*)dict
;
1137 static size_t ZSTD_decompress_insertDictionary(ZSTD_DCtx
* dctx
, const void* dict
, size_t dictSize
)
1139 if (dictSize
< 8) return ZSTD_refDictContent(dctx
, dict
, dictSize
);
1140 { U32
const magic
= MEM_readLE32(dict
);
1141 if (magic
!= ZSTD_MAGIC_DICTIONARY
) {
1142 return ZSTD_refDictContent(dctx
, dict
, dictSize
); /* pure content mode */
1144 dctx
->dictID
= MEM_readLE32((const char*)dict
+ ZSTD_FRAMEIDSIZE
);
1146 /* load entropy tables */
1147 { size_t const eSize
= ZSTD_loadDEntropy(&dctx
->entropy
, dict
, dictSize
);
1148 RETURN_ERROR_IF(ZSTD_isError(eSize
), dictionary_corrupted
, "");
1149 dict
= (const char*)dict
+ eSize
;
1152 dctx
->litEntropy
= dctx
->fseEntropy
= 1;
1154 /* reference dictionary content */
1155 return ZSTD_refDictContent(dctx
, dict
, dictSize
);
1158 size_t ZSTD_decompressBegin(ZSTD_DCtx
* dctx
)
1160 assert(dctx
!= NULL
);
1161 dctx
->expected
= ZSTD_startingInputLength(dctx
->format
); /* dctx->format must be properly set */
1162 dctx
->stage
= ZSTDds_getFrameHeaderSize
;
1163 dctx
->decodedSize
= 0;
1164 dctx
->previousDstEnd
= NULL
;
1165 dctx
->prefixStart
= NULL
;
1166 dctx
->virtualStart
= NULL
;
1167 dctx
->dictEnd
= NULL
;
1168 dctx
->entropy
.hufTable
[0] = (HUF_DTable
)((HufLog
)*0x1000001); /* cover both little and big endian */
1169 dctx
->litEntropy
= dctx
->fseEntropy
= 0;
1171 dctx
->bType
= bt_reserved
;
1172 ZSTD_STATIC_ASSERT(sizeof(dctx
->entropy
.rep
) == sizeof(repStartValue
));
1173 memcpy(dctx
->entropy
.rep
, repStartValue
, sizeof(repStartValue
)); /* initial repcodes */
1174 dctx
->LLTptr
= dctx
->entropy
.LLTable
;
1175 dctx
->MLTptr
= dctx
->entropy
.MLTable
;
1176 dctx
->OFTptr
= dctx
->entropy
.OFTable
;
1177 dctx
->HUFptr
= dctx
->entropy
.hufTable
;
1181 size_t ZSTD_decompressBegin_usingDict(ZSTD_DCtx
* dctx
, const void* dict
, size_t dictSize
)
1183 FORWARD_IF_ERROR( ZSTD_decompressBegin(dctx
) , "");
1184 if (dict
&& dictSize
)
1186 ZSTD_isError(ZSTD_decompress_insertDictionary(dctx
, dict
, dictSize
)),
1187 dictionary_corrupted
, "");
1192 /* ====== ZSTD_DDict ====== */
1194 size_t ZSTD_decompressBegin_usingDDict(ZSTD_DCtx
* dctx
, const ZSTD_DDict
* ddict
)
1196 DEBUGLOG(4, "ZSTD_decompressBegin_usingDDict");
1197 assert(dctx
!= NULL
);
1199 const char* const dictStart
= (const char*)ZSTD_DDict_dictContent(ddict
);
1200 size_t const dictSize
= ZSTD_DDict_dictSize(ddict
);
1201 const void* const dictEnd
= dictStart
+ dictSize
;
1202 dctx
->ddictIsCold
= (dctx
->dictEnd
!= dictEnd
);
1203 DEBUGLOG(4, "DDict is %s",
1204 dctx
->ddictIsCold
? "~cold~" : "hot!");
1206 FORWARD_IF_ERROR( ZSTD_decompressBegin(dctx
) , "");
1207 if (ddict
) { /* NULL ddict is equivalent to no dictionary */
1208 ZSTD_copyDDictParameters(dctx
, ddict
);
1213 /*! ZSTD_getDictID_fromDict() :
1214 * Provides the dictID stored within dictionary.
1215 * if @return == 0, the dictionary is not conformant with Zstandard specification.
1216 * It can still be loaded, but as a content-only dictionary. */
1217 unsigned ZSTD_getDictID_fromDict(const void* dict
, size_t dictSize
)
1219 if (dictSize
< 8) return 0;
1220 if (MEM_readLE32(dict
) != ZSTD_MAGIC_DICTIONARY
) return 0;
1221 return MEM_readLE32((const char*)dict
+ ZSTD_FRAMEIDSIZE
);
1224 /*! ZSTD_getDictID_fromFrame() :
1225 * Provides the dictID required to decompress frame stored within `src`.
1226 * If @return == 0, the dictID could not be decoded.
1227 * This could for one of the following reasons :
1228 * - The frame does not require a dictionary (most common case).
1229 * - The frame was built with dictID intentionally removed.
1230 * Needed dictionary is a hidden information.
1231 * Note : this use case also happens when using a non-conformant dictionary.
1232 * - `srcSize` is too small, and as a result, frame header could not be decoded.
1233 * Note : possible if `srcSize < ZSTD_FRAMEHEADERSIZE_MAX`.
1234 * - This is not a Zstandard frame.
1235 * When identifying the exact failure cause, it's possible to use
1236 * ZSTD_getFrameHeader(), which will provide a more precise error code. */
1237 unsigned ZSTD_getDictID_fromFrame(const void* src
, size_t srcSize
)
1239 ZSTD_frameHeader zfp
= { 0, 0, 0, ZSTD_frame
, 0, 0, 0 };
1240 size_t const hError
= ZSTD_getFrameHeader(&zfp
, src
, srcSize
);
1241 if (ZSTD_isError(hError
)) return 0;
1246 /*! ZSTD_decompress_usingDDict() :
1247 * Decompression using a pre-digested Dictionary
1248 * Use dictionary without significant overhead. */
1249 size_t ZSTD_decompress_usingDDict(ZSTD_DCtx
* dctx
,
1250 void* dst
, size_t dstCapacity
,
1251 const void* src
, size_t srcSize
,
1252 const ZSTD_DDict
* ddict
)
1254 /* pass content and size in case legacy frames are encountered */
1255 return ZSTD_decompressMultiFrame(dctx
, dst
, dstCapacity
, src
, srcSize
,
1261 /*=====================================
1262 * Streaming decompression
1263 *====================================*/
1265 ZSTD_DStream
* ZSTD_createDStream(void)
1267 DEBUGLOG(3, "ZSTD_createDStream");
1268 return ZSTD_createDStream_advanced(ZSTD_defaultCMem
);
1271 ZSTD_DStream
* ZSTD_initStaticDStream(void *workspace
, size_t workspaceSize
)
1273 return ZSTD_initStaticDCtx(workspace
, workspaceSize
);
1276 ZSTD_DStream
* ZSTD_createDStream_advanced(ZSTD_customMem customMem
)
1278 return ZSTD_createDCtx_advanced(customMem
);
1281 size_t ZSTD_freeDStream(ZSTD_DStream
* zds
)
1283 return ZSTD_freeDCtx(zds
);
1287 /* *** Initialization *** */
1289 size_t ZSTD_DStreamInSize(void) { return ZSTD_BLOCKSIZE_MAX
+ ZSTD_blockHeaderSize
; }
1290 size_t ZSTD_DStreamOutSize(void) { return ZSTD_BLOCKSIZE_MAX
; }
1292 size_t ZSTD_DCtx_loadDictionary_advanced(ZSTD_DCtx
* dctx
,
1293 const void* dict
, size_t dictSize
,
1294 ZSTD_dictLoadMethod_e dictLoadMethod
,
1295 ZSTD_dictContentType_e dictContentType
)
1297 RETURN_ERROR_IF(dctx
->streamStage
!= zdss_init
, stage_wrong
, "");
1298 ZSTD_clearDict(dctx
);
1299 if (dict
&& dictSize
!= 0) {
1300 dctx
->ddictLocal
= ZSTD_createDDict_advanced(dict
, dictSize
, dictLoadMethod
, dictContentType
, dctx
->customMem
);
1301 RETURN_ERROR_IF(dctx
->ddictLocal
== NULL
, memory_allocation
, "NULL pointer!");
1302 dctx
->ddict
= dctx
->ddictLocal
;
1303 dctx
->dictUses
= ZSTD_use_indefinitely
;
1308 size_t ZSTD_DCtx_loadDictionary_byReference(ZSTD_DCtx
* dctx
, const void* dict
, size_t dictSize
)
1310 return ZSTD_DCtx_loadDictionary_advanced(dctx
, dict
, dictSize
, ZSTD_dlm_byRef
, ZSTD_dct_auto
);
1313 size_t ZSTD_DCtx_loadDictionary(ZSTD_DCtx
* dctx
, const void* dict
, size_t dictSize
)
1315 return ZSTD_DCtx_loadDictionary_advanced(dctx
, dict
, dictSize
, ZSTD_dlm_byCopy
, ZSTD_dct_auto
);
1318 size_t ZSTD_DCtx_refPrefix_advanced(ZSTD_DCtx
* dctx
, const void* prefix
, size_t prefixSize
, ZSTD_dictContentType_e dictContentType
)
1320 FORWARD_IF_ERROR(ZSTD_DCtx_loadDictionary_advanced(dctx
, prefix
, prefixSize
, ZSTD_dlm_byRef
, dictContentType
), "");
1321 dctx
->dictUses
= ZSTD_use_once
;
1325 size_t ZSTD_DCtx_refPrefix(ZSTD_DCtx
* dctx
, const void* prefix
, size_t prefixSize
)
1327 return ZSTD_DCtx_refPrefix_advanced(dctx
, prefix
, prefixSize
, ZSTD_dct_rawContent
);
1331 /* ZSTD_initDStream_usingDict() :
1332 * return : expected size, aka ZSTD_startingInputLength().
1333 * this function cannot fail */
1334 size_t ZSTD_initDStream_usingDict(ZSTD_DStream
* zds
, const void* dict
, size_t dictSize
)
1336 DEBUGLOG(4, "ZSTD_initDStream_usingDict");
1337 FORWARD_IF_ERROR( ZSTD_DCtx_reset(zds
, ZSTD_reset_session_only
) , "");
1338 FORWARD_IF_ERROR( ZSTD_DCtx_loadDictionary(zds
, dict
, dictSize
) , "");
1339 return ZSTD_startingInputLength(zds
->format
);
1342 /* note : this variant can't fail */
1343 size_t ZSTD_initDStream(ZSTD_DStream
* zds
)
1345 DEBUGLOG(4, "ZSTD_initDStream");
1346 return ZSTD_initDStream_usingDDict(zds
, NULL
);
1349 /* ZSTD_initDStream_usingDDict() :
1350 * ddict will just be referenced, and must outlive decompression session
1351 * this function cannot fail */
1352 size_t ZSTD_initDStream_usingDDict(ZSTD_DStream
* dctx
, const ZSTD_DDict
* ddict
)
1354 FORWARD_IF_ERROR( ZSTD_DCtx_reset(dctx
, ZSTD_reset_session_only
) , "");
1355 FORWARD_IF_ERROR( ZSTD_DCtx_refDDict(dctx
, ddict
) , "");
1356 return ZSTD_startingInputLength(dctx
->format
);
1359 /* ZSTD_resetDStream() :
1360 * return : expected size, aka ZSTD_startingInputLength().
1361 * this function cannot fail */
1362 size_t ZSTD_resetDStream(ZSTD_DStream
* dctx
)
1364 FORWARD_IF_ERROR(ZSTD_DCtx_reset(dctx
, ZSTD_reset_session_only
), "");
1365 return ZSTD_startingInputLength(dctx
->format
);
1369 size_t ZSTD_DCtx_refDDict(ZSTD_DCtx
* dctx
, const ZSTD_DDict
* ddict
)
1371 RETURN_ERROR_IF(dctx
->streamStage
!= zdss_init
, stage_wrong
, "");
1372 ZSTD_clearDict(dctx
);
1374 dctx
->ddict
= ddict
;
1375 dctx
->dictUses
= ZSTD_use_indefinitely
;
1380 /* ZSTD_DCtx_setMaxWindowSize() :
1381 * note : no direct equivalence in ZSTD_DCtx_setParameter,
1382 * since this version sets windowSize, and the other sets windowLog */
1383 size_t ZSTD_DCtx_setMaxWindowSize(ZSTD_DCtx
* dctx
, size_t maxWindowSize
)
1385 ZSTD_bounds
const bounds
= ZSTD_dParam_getBounds(ZSTD_d_windowLogMax
);
1386 size_t const min
= (size_t)1 << bounds
.lowerBound
;
1387 size_t const max
= (size_t)1 << bounds
.upperBound
;
1388 RETURN_ERROR_IF(dctx
->streamStage
!= zdss_init
, stage_wrong
, "");
1389 RETURN_ERROR_IF(maxWindowSize
< min
, parameter_outOfBound
, "");
1390 RETURN_ERROR_IF(maxWindowSize
> max
, parameter_outOfBound
, "");
1391 dctx
->maxWindowSize
= maxWindowSize
;
1395 size_t ZSTD_DCtx_setFormat(ZSTD_DCtx
* dctx
, ZSTD_format_e format
)
1397 return ZSTD_DCtx_setParameter(dctx
, ZSTD_d_format
, format
);
1400 ZSTD_bounds
ZSTD_dParam_getBounds(ZSTD_dParameter dParam
)
1402 ZSTD_bounds bounds
= { 0, 0, 0 };
1404 case ZSTD_d_windowLogMax
:
1405 bounds
.lowerBound
= ZSTD_WINDOWLOG_ABSOLUTEMIN
;
1406 bounds
.upperBound
= ZSTD_WINDOWLOG_MAX
;
1409 bounds
.lowerBound
= (int)ZSTD_f_zstd1
;
1410 bounds
.upperBound
= (int)ZSTD_f_zstd1_magicless
;
1411 ZSTD_STATIC_ASSERT(ZSTD_f_zstd1
< ZSTD_f_zstd1_magicless
);
1413 case ZSTD_d_stableOutBuffer
:
1414 bounds
.lowerBound
= (int)ZSTD_obm_buffered
;
1415 bounds
.upperBound
= (int)ZSTD_obm_stable
;
1419 bounds
.error
= ERROR(parameter_unsupported
);
1423 /* ZSTD_dParam_withinBounds:
1424 * @return 1 if value is within dParam bounds,
1426 static int ZSTD_dParam_withinBounds(ZSTD_dParameter dParam
, int value
)
1428 ZSTD_bounds
const bounds
= ZSTD_dParam_getBounds(dParam
);
1429 if (ZSTD_isError(bounds
.error
)) return 0;
1430 if (value
< bounds
.lowerBound
) return 0;
1431 if (value
> bounds
.upperBound
) return 0;
1435 #define CHECK_DBOUNDS(p,v) { \
1436 RETURN_ERROR_IF(!ZSTD_dParam_withinBounds(p, v), parameter_outOfBound, ""); \
1439 size_t ZSTD_DCtx_setParameter(ZSTD_DCtx
* dctx
, ZSTD_dParameter dParam
, int value
)
1441 RETURN_ERROR_IF(dctx
->streamStage
!= zdss_init
, stage_wrong
, "");
1443 case ZSTD_d_windowLogMax
:
1444 if (value
== 0) value
= ZSTD_WINDOWLOG_LIMIT_DEFAULT
;
1445 CHECK_DBOUNDS(ZSTD_d_windowLogMax
, value
);
1446 dctx
->maxWindowSize
= ((size_t)1) << value
;
1449 CHECK_DBOUNDS(ZSTD_d_format
, value
);
1450 dctx
->format
= (ZSTD_format_e
)value
;
1452 case ZSTD_d_stableOutBuffer
:
1453 CHECK_DBOUNDS(ZSTD_d_stableOutBuffer
, value
);
1454 dctx
->outBufferMode
= (ZSTD_outBufferMode_e
)value
;
1458 RETURN_ERROR(parameter_unsupported
, "");
1461 size_t ZSTD_DCtx_reset(ZSTD_DCtx
* dctx
, ZSTD_ResetDirective reset
)
1463 if ( (reset
== ZSTD_reset_session_only
)
1464 || (reset
== ZSTD_reset_session_and_parameters
) ) {
1465 dctx
->streamStage
= zdss_init
;
1466 dctx
->noForwardProgress
= 0;
1468 if ( (reset
== ZSTD_reset_parameters
)
1469 || (reset
== ZSTD_reset_session_and_parameters
) ) {
1470 RETURN_ERROR_IF(dctx
->streamStage
!= zdss_init
, stage_wrong
, "");
1471 ZSTD_clearDict(dctx
);
1472 dctx
->format
= ZSTD_f_zstd1
;
1473 dctx
->maxWindowSize
= ZSTD_MAXWINDOWSIZE_DEFAULT
;
1479 size_t ZSTD_sizeof_DStream(const ZSTD_DStream
* dctx
)
1481 return ZSTD_sizeof_DCtx(dctx
);
1484 size_t ZSTD_decodingBufferSize_min(unsigned long long windowSize
, unsigned long long frameContentSize
)
1486 size_t const blockSize
= (size_t) MIN(windowSize
, ZSTD_BLOCKSIZE_MAX
);
1487 unsigned long long const neededRBSize
= windowSize
+ blockSize
+ (WILDCOPY_OVERLENGTH
* 2);
1488 unsigned long long const neededSize
= MIN(frameContentSize
, neededRBSize
);
1489 size_t const minRBSize
= (size_t) neededSize
;
1490 RETURN_ERROR_IF((unsigned long long)minRBSize
!= neededSize
,
1491 frameParameter_windowTooLarge
, "");
1495 size_t ZSTD_estimateDStreamSize(size_t windowSize
)
1497 size_t const blockSize
= MIN(windowSize
, ZSTD_BLOCKSIZE_MAX
);
1498 size_t const inBuffSize
= blockSize
; /* no block can be larger */
1499 size_t const outBuffSize
= ZSTD_decodingBufferSize_min(windowSize
, ZSTD_CONTENTSIZE_UNKNOWN
);
1500 return ZSTD_estimateDCtxSize() + inBuffSize
+ outBuffSize
;
1503 size_t ZSTD_estimateDStreamSize_fromFrame(const void* src
, size_t srcSize
)
1505 U32
const windowSizeMax
= 1U << ZSTD_WINDOWLOG_MAX
; /* note : should be user-selectable, but requires an additional parameter (or a dctx) */
1506 ZSTD_frameHeader zfh
;
1507 size_t const err
= ZSTD_getFrameHeader(&zfh
, src
, srcSize
);
1508 if (ZSTD_isError(err
)) return err
;
1509 RETURN_ERROR_IF(err
>0, srcSize_wrong
, "");
1510 RETURN_ERROR_IF(zfh
.windowSize
> windowSizeMax
,
1511 frameParameter_windowTooLarge
, "");
1512 return ZSTD_estimateDStreamSize((size_t)zfh
.windowSize
);
1516 /* ***** Decompression ***** */
1518 static int ZSTD_DCtx_isOverflow(ZSTD_DStream
* zds
, size_t const neededInBuffSize
, size_t const neededOutBuffSize
)
1520 return (zds
->inBuffSize
+ zds
->outBuffSize
) >= (neededInBuffSize
+ neededOutBuffSize
) * ZSTD_WORKSPACETOOLARGE_FACTOR
;
1523 static void ZSTD_DCtx_updateOversizedDuration(ZSTD_DStream
* zds
, size_t const neededInBuffSize
, size_t const neededOutBuffSize
)
1525 if (ZSTD_DCtx_isOverflow(zds
, neededInBuffSize
, neededOutBuffSize
))
1526 zds
->oversizedDuration
++;
1528 zds
->oversizedDuration
= 0;
1531 static int ZSTD_DCtx_isOversizedTooLong(ZSTD_DStream
* zds
)
1533 return zds
->oversizedDuration
>= ZSTD_WORKSPACETOOLARGE_MAXDURATION
;
1536 /* Checks that the output buffer hasn't changed if ZSTD_obm_stable is used. */
1537 static size_t ZSTD_checkOutBuffer(ZSTD_DStream
const* zds
, ZSTD_outBuffer
const* output
)
1539 ZSTD_outBuffer
const expect
= zds
->expectedOutBuffer
;
1540 /* No requirement when ZSTD_obm_stable is not enabled. */
1541 if (zds
->outBufferMode
!= ZSTD_obm_stable
)
1543 /* Any buffer is allowed in zdss_init, this must be the same for every other call until
1544 * the context is reset.
1546 if (zds
->streamStage
== zdss_init
)
1548 /* The buffer must match our expectation exactly. */
1549 if (expect
.dst
== output
->dst
&& expect
.pos
== output
->pos
&& expect
.size
== output
->size
)
1551 RETURN_ERROR(dstBuffer_wrong
, "ZSTD_obm_stable enabled but output differs!");
1554 /* Calls ZSTD_decompressContinue() with the right parameters for ZSTD_decompressStream()
1555 * and updates the stage and the output buffer state. This call is extracted so it can be
1556 * used both when reading directly from the ZSTD_inBuffer, and in buffered input mode.
1557 * NOTE: You must break after calling this function since the streamStage is modified.
1559 static size_t ZSTD_decompressContinueStream(
1560 ZSTD_DStream
* zds
, char** op
, char* oend
,
1561 void const* src
, size_t srcSize
) {
1562 int const isSkipFrame
= ZSTD_isSkipFrame(zds
);
1563 if (zds
->outBufferMode
== ZSTD_obm_buffered
) {
1564 size_t const dstSize
= isSkipFrame
? 0 : zds
->outBuffSize
- zds
->outStart
;
1565 size_t const decodedSize
= ZSTD_decompressContinue(zds
,
1566 zds
->outBuff
+ zds
->outStart
, dstSize
, src
, srcSize
);
1567 FORWARD_IF_ERROR(decodedSize
, "");
1568 if (!decodedSize
&& !isSkipFrame
) {
1569 zds
->streamStage
= zdss_read
;
1571 zds
->outEnd
= zds
->outStart
+ decodedSize
;
1572 zds
->streamStage
= zdss_flush
;
1575 /* Write directly into the output buffer */
1576 size_t const dstSize
= isSkipFrame
? 0 : oend
- *op
;
1577 size_t const decodedSize
= ZSTD_decompressContinue(zds
, *op
, dstSize
, src
, srcSize
);
1578 FORWARD_IF_ERROR(decodedSize
, "");
1580 /* Flushing is not needed. */
1581 zds
->streamStage
= zdss_read
;
1582 assert(*op
<= oend
);
1583 assert(zds
->outBufferMode
== ZSTD_obm_stable
);
1588 size_t ZSTD_decompressStream(ZSTD_DStream
* zds
, ZSTD_outBuffer
* output
, ZSTD_inBuffer
* input
)
1590 const char* const src
= (const char*)input
->src
;
1591 const char* const istart
= input
->pos
!= 0 ? src
+ input
->pos
: src
;
1592 const char* const iend
= input
->size
!= 0 ? src
+ input
->size
: src
;
1593 const char* ip
= istart
;
1594 char* const dst
= (char*)output
->dst
;
1595 char* const ostart
= output
->pos
!= 0 ? dst
+ output
->pos
: dst
;
1596 char* const oend
= output
->size
!= 0 ? dst
+ output
->size
: dst
;
1598 U32 someMoreWork
= 1;
1600 DEBUGLOG(5, "ZSTD_decompressStream");
1602 input
->pos
> input
->size
,
1604 "forbidden. in: pos: %u vs size: %u",
1605 (U32
)input
->pos
, (U32
)input
->size
);
1607 output
->pos
> output
->size
,
1609 "forbidden. out: pos: %u vs size: %u",
1610 (U32
)output
->pos
, (U32
)output
->size
);
1611 DEBUGLOG(5, "input size : %u", (U32
)(input
->size
- input
->pos
));
1612 FORWARD_IF_ERROR(ZSTD_checkOutBuffer(zds
, output
), "");
1614 while (someMoreWork
) {
1615 switch(zds
->streamStage
)
1618 DEBUGLOG(5, "stage zdss_init => transparent reset ");
1619 zds
->streamStage
= zdss_loadHeader
;
1620 zds
->lhSize
= zds
->inPos
= zds
->outStart
= zds
->outEnd
= 0;
1621 zds
->legacyVersion
= 0;
1622 zds
->hostageByte
= 0;
1623 zds
->expectedOutBuffer
= *output
;
1626 case zdss_loadHeader
:
1627 DEBUGLOG(5, "stage zdss_loadHeader (srcSize : %u)", (U32
)(iend
- ip
));
1628 #if defined(ZSTD_LEGACY_SUPPORT) && (ZSTD_LEGACY_SUPPORT>=1)
1629 if (zds
->legacyVersion
) {
1630 RETURN_ERROR_IF(zds
->staticSize
, memory_allocation
,
1631 "legacy support is incompatible with static dctx");
1632 { size_t const hint
= ZSTD_decompressLegacyStream(zds
->legacyContext
, zds
->legacyVersion
, output
, input
);
1633 if (hint
==0) zds
->streamStage
= zdss_init
;
1637 { size_t const hSize
= ZSTD_getFrameHeader_advanced(&zds
->fParams
, zds
->headerBuffer
, zds
->lhSize
, zds
->format
);
1638 DEBUGLOG(5, "header size : %u", (U32
)hSize
);
1639 if (ZSTD_isError(hSize
)) {
1640 #if defined(ZSTD_LEGACY_SUPPORT) && (ZSTD_LEGACY_SUPPORT>=1)
1641 U32
const legacyVersion
= ZSTD_isLegacy(istart
, iend
-istart
);
1642 if (legacyVersion
) {
1643 ZSTD_DDict
const* const ddict
= ZSTD_getDDict(zds
);
1644 const void* const dict
= ddict
? ZSTD_DDict_dictContent(ddict
) : NULL
;
1645 size_t const dictSize
= ddict
? ZSTD_DDict_dictSize(ddict
) : 0;
1646 DEBUGLOG(5, "ZSTD_decompressStream: detected legacy version v0.%u", legacyVersion
);
1647 RETURN_ERROR_IF(zds
->staticSize
, memory_allocation
,
1648 "legacy support is incompatible with static dctx");
1649 FORWARD_IF_ERROR(ZSTD_initLegacyStream(&zds
->legacyContext
,
1650 zds
->previousLegacyVersion
, legacyVersion
,
1651 dict
, dictSize
), "");
1652 zds
->legacyVersion
= zds
->previousLegacyVersion
= legacyVersion
;
1653 { size_t const hint
= ZSTD_decompressLegacyStream(zds
->legacyContext
, legacyVersion
, output
, input
);
1654 if (hint
==0) zds
->streamStage
= zdss_init
; /* or stay in stage zdss_loadHeader */
1658 return hSize
; /* error */
1660 if (hSize
!= 0) { /* need more input */
1661 size_t const toLoad
= hSize
- zds
->lhSize
; /* if hSize!=0, hSize > zds->lhSize */
1662 size_t const remainingInput
= (size_t)(iend
-ip
);
1664 if (toLoad
> remainingInput
) { /* not enough input to load full header */
1665 if (remainingInput
> 0) {
1666 memcpy(zds
->headerBuffer
+ zds
->lhSize
, ip
, remainingInput
);
1667 zds
->lhSize
+= remainingInput
;
1669 input
->pos
= input
->size
;
1670 return (MAX((size_t)ZSTD_FRAMEHEADERSIZE_MIN(zds
->format
), hSize
) - zds
->lhSize
) + ZSTD_blockHeaderSize
; /* remaining header bytes + next block header */
1673 memcpy(zds
->headerBuffer
+ zds
->lhSize
, ip
, toLoad
); zds
->lhSize
= hSize
; ip
+= toLoad
;
1677 /* check for single-pass mode opportunity */
1678 if (zds
->fParams
.frameContentSize
!= ZSTD_CONTENTSIZE_UNKNOWN
1679 && zds
->fParams
.frameType
!= ZSTD_skippableFrame
1680 && (U64
)(size_t)(oend
-op
) >= zds
->fParams
.frameContentSize
) {
1681 size_t const cSize
= ZSTD_findFrameCompressedSize(istart
, iend
-istart
);
1682 if (cSize
<= (size_t)(iend
-istart
)) {
1683 /* shortcut : using single-pass mode */
1684 size_t const decompressedSize
= ZSTD_decompress_usingDDict(zds
, op
, oend
-op
, istart
, cSize
, ZSTD_getDDict(zds
));
1685 if (ZSTD_isError(decompressedSize
)) return decompressedSize
;
1686 DEBUGLOG(4, "shortcut to single-pass ZSTD_decompress_usingDDict()")
1687 ip
= istart
+ cSize
;
1688 op
+= decompressedSize
;
1690 zds
->streamStage
= zdss_init
;
1695 /* Check output buffer is large enough for ZSTD_odm_stable. */
1696 if (zds
->outBufferMode
== ZSTD_obm_stable
1697 && zds
->fParams
.frameType
!= ZSTD_skippableFrame
1698 && zds
->fParams
.frameContentSize
!= ZSTD_CONTENTSIZE_UNKNOWN
1699 && (U64
)(size_t)(oend
-op
) < zds
->fParams
.frameContentSize
) {
1700 RETURN_ERROR(dstSize_tooSmall
, "ZSTD_obm_stable passed but ZSTD_outBuffer is too small");
1703 /* Consume header (see ZSTDds_decodeFrameHeader) */
1704 DEBUGLOG(4, "Consume header");
1705 FORWARD_IF_ERROR(ZSTD_decompressBegin_usingDDict(zds
, ZSTD_getDDict(zds
)), "");
1707 if ((MEM_readLE32(zds
->headerBuffer
) & ZSTD_MAGIC_SKIPPABLE_MASK
) == ZSTD_MAGIC_SKIPPABLE_START
) { /* skippable frame */
1708 zds
->expected
= MEM_readLE32(zds
->headerBuffer
+ ZSTD_FRAMEIDSIZE
);
1709 zds
->stage
= ZSTDds_skipFrame
;
1711 FORWARD_IF_ERROR(ZSTD_decodeFrameHeader(zds
, zds
->headerBuffer
, zds
->lhSize
), "");
1712 zds
->expected
= ZSTD_blockHeaderSize
;
1713 zds
->stage
= ZSTDds_decodeBlockHeader
;
1716 /* control buffer memory usage */
1717 DEBUGLOG(4, "Control max memory usage (%u KB <= max %u KB)",
1718 (U32
)(zds
->fParams
.windowSize
>>10),
1719 (U32
)(zds
->maxWindowSize
>> 10) );
1720 zds
->fParams
.windowSize
= MAX(zds
->fParams
.windowSize
, 1U << ZSTD_WINDOWLOG_ABSOLUTEMIN
);
1721 RETURN_ERROR_IF(zds
->fParams
.windowSize
> zds
->maxWindowSize
,
1722 frameParameter_windowTooLarge
, "");
1724 /* Adapt buffer sizes to frame header instructions */
1725 { size_t const neededInBuffSize
= MAX(zds
->fParams
.blockSizeMax
, 4 /* frame checksum */);
1726 size_t const neededOutBuffSize
= zds
->outBufferMode
== ZSTD_obm_buffered
1727 ? ZSTD_decodingBufferSize_min(zds
->fParams
.windowSize
, zds
->fParams
.frameContentSize
)
1730 ZSTD_DCtx_updateOversizedDuration(zds
, neededInBuffSize
, neededOutBuffSize
);
1732 { int const tooSmall
= (zds
->inBuffSize
< neededInBuffSize
) || (zds
->outBuffSize
< neededOutBuffSize
);
1733 int const tooLarge
= ZSTD_DCtx_isOversizedTooLong(zds
);
1735 if (tooSmall
|| tooLarge
) {
1736 size_t const bufferSize
= neededInBuffSize
+ neededOutBuffSize
;
1737 DEBUGLOG(4, "inBuff : from %u to %u",
1738 (U32
)zds
->inBuffSize
, (U32
)neededInBuffSize
);
1739 DEBUGLOG(4, "outBuff : from %u to %u",
1740 (U32
)zds
->outBuffSize
, (U32
)neededOutBuffSize
);
1741 if (zds
->staticSize
) { /* static DCtx */
1742 DEBUGLOG(4, "staticSize : %u", (U32
)zds
->staticSize
);
1743 assert(zds
->staticSize
>= sizeof(ZSTD_DCtx
)); /* controlled at init */
1745 bufferSize
> zds
->staticSize
- sizeof(ZSTD_DCtx
),
1746 memory_allocation
, "");
1748 ZSTD_free(zds
->inBuff
, zds
->customMem
);
1749 zds
->inBuffSize
= 0;
1750 zds
->outBuffSize
= 0;
1751 zds
->inBuff
= (char*)ZSTD_malloc(bufferSize
, zds
->customMem
);
1752 RETURN_ERROR_IF(zds
->inBuff
== NULL
, memory_allocation
, "");
1754 zds
->inBuffSize
= neededInBuffSize
;
1755 zds
->outBuff
= zds
->inBuff
+ zds
->inBuffSize
;
1756 zds
->outBuffSize
= neededOutBuffSize
;
1758 zds
->streamStage
= zdss_read
;
1762 DEBUGLOG(5, "stage zdss_read");
1763 { size_t const neededInSize
= ZSTD_nextSrcSizeToDecompressWithInputSize(zds
, iend
- ip
);
1764 DEBUGLOG(5, "neededInSize = %u", (U32
)neededInSize
);
1765 if (neededInSize
==0) { /* end of frame */
1766 zds
->streamStage
= zdss_init
;
1770 if ((size_t)(iend
-ip
) >= neededInSize
) { /* decode directly from src */
1771 FORWARD_IF_ERROR(ZSTD_decompressContinueStream(zds
, &op
, oend
, ip
, neededInSize
), "");
1773 /* Function modifies the stage so we must break */
1776 if (ip
==iend
) { someMoreWork
= 0; break; } /* no more input */
1777 zds
->streamStage
= zdss_load
;
1781 { size_t const neededInSize
= ZSTD_nextSrcSizeToDecompress(zds
);
1782 size_t const toLoad
= neededInSize
- zds
->inPos
;
1783 int const isSkipFrame
= ZSTD_isSkipFrame(zds
);
1785 /* At this point we shouldn't be decompressing a block that we can stream. */
1786 assert(neededInSize
== ZSTD_nextSrcSizeToDecompressWithInputSize(zds
, iend
- ip
));
1788 loadedSize
= MIN(toLoad
, (size_t)(iend
-ip
));
1790 RETURN_ERROR_IF(toLoad
> zds
->inBuffSize
- zds
->inPos
,
1791 corruption_detected
,
1792 "should never happen");
1793 loadedSize
= ZSTD_limitCopy(zds
->inBuff
+ zds
->inPos
, toLoad
, ip
, iend
-ip
);
1796 zds
->inPos
+= loadedSize
;
1797 if (loadedSize
< toLoad
) { someMoreWork
= 0; break; } /* not enough input, wait for more */
1799 /* decode loaded input */
1800 zds
->inPos
= 0; /* input is consumed */
1801 FORWARD_IF_ERROR(ZSTD_decompressContinueStream(zds
, &op
, oend
, zds
->inBuff
, neededInSize
), "");
1802 /* Function modifies the stage so we must break */
1806 { size_t const toFlushSize
= zds
->outEnd
- zds
->outStart
;
1807 size_t const flushedSize
= ZSTD_limitCopy(op
, oend
-op
, zds
->outBuff
+ zds
->outStart
, toFlushSize
);
1809 zds
->outStart
+= flushedSize
;
1810 if (flushedSize
== toFlushSize
) { /* flush completed */
1811 zds
->streamStage
= zdss_read
;
1812 if ( (zds
->outBuffSize
< zds
->fParams
.frameContentSize
)
1813 && (zds
->outStart
+ zds
->fParams
.blockSizeMax
> zds
->outBuffSize
) ) {
1814 DEBUGLOG(5, "restart filling outBuff from beginning (left:%i, needed:%u)",
1815 (int)(zds
->outBuffSize
- zds
->outStart
),
1816 (U32
)zds
->fParams
.blockSizeMax
);
1817 zds
->outStart
= zds
->outEnd
= 0;
1821 /* cannot complete flush */
1826 assert(0); /* impossible */
1827 RETURN_ERROR(GENERIC
, "impossible to reach"); /* some compiler require default to do something */
1831 input
->pos
= (size_t)(ip
- (const char*)(input
->src
));
1832 output
->pos
= (size_t)(op
- (char*)(output
->dst
));
1834 /* Update the expected output buffer for ZSTD_obm_stable. */
1835 zds
->expectedOutBuffer
= *output
;
1837 if ((ip
==istart
) && (op
==ostart
)) { /* no forward progress */
1838 zds
->noForwardProgress
++;
1839 if (zds
->noForwardProgress
>= ZSTD_NO_FORWARD_PROGRESS_MAX
) {
1840 RETURN_ERROR_IF(op
==oend
, dstSize_tooSmall
, "");
1841 RETURN_ERROR_IF(ip
==iend
, srcSize_wrong
, "");
1845 zds
->noForwardProgress
= 0;
1847 { size_t nextSrcSizeHint
= ZSTD_nextSrcSizeToDecompress(zds
);
1848 if (!nextSrcSizeHint
) { /* frame fully decoded */
1849 if (zds
->outEnd
== zds
->outStart
) { /* output fully flushed */
1850 if (zds
->hostageByte
) {
1851 if (input
->pos
>= input
->size
) {
1852 /* can't release hostage (not present) */
1853 zds
->streamStage
= zdss_read
;
1856 input
->pos
++; /* release hostage */
1857 } /* zds->hostageByte */
1859 } /* zds->outEnd == zds->outStart */
1860 if (!zds
->hostageByte
) { /* output not fully flushed; keep last byte as hostage; will be released when all output is flushed */
1861 input
->pos
--; /* note : pos > 0, otherwise, impossible to finish reading last block */
1865 } /* nextSrcSizeHint==0 */
1866 nextSrcSizeHint
+= ZSTD_blockHeaderSize
* (ZSTD_nextInputType(zds
) == ZSTDnit_block
); /* preload header of next block */
1867 assert(zds
->inPos
<= nextSrcSizeHint
);
1868 nextSrcSizeHint
-= zds
->inPos
; /* part already loaded*/
1869 return nextSrcSizeHint
;
1873 size_t ZSTD_decompressStream_simpleArgs (
1875 void* dst
, size_t dstCapacity
, size_t* dstPos
,
1876 const void* src
, size_t srcSize
, size_t* srcPos
)
1878 ZSTD_outBuffer output
= { dst
, dstCapacity
, *dstPos
};
1879 ZSTD_inBuffer input
= { src
, srcSize
, *srcPos
};
1880 /* ZSTD_compress_generic() will check validity of dstPos and srcPos */
1881 size_t const cErr
= ZSTD_decompressStream(dctx
, &output
, &input
);
1882 *dstPos
= output
.pos
;
1883 *srcPos
= input
.pos
;