ReactOS 0.4.15-dev-7934-g1dc8d80
zstd_decompress.c
Go to the documentation of this file.
1/*
2 * Copyright (c) 2016-2020, 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*****************************************************************/
21#ifndef ZSTD_HEAPMODE
22# define ZSTD_HEAPMODE 1
23#endif
24
29#ifndef ZSTD_LEGACY_SUPPORT
30# define ZSTD_LEGACY_SUPPORT 0
31#endif
32
39#ifndef ZSTD_MAXWINDOWSIZE_DEFAULT
40# define ZSTD_MAXWINDOWSIZE_DEFAULT (((U32)1 << ZSTD_WINDOWLOG_LIMIT_DEFAULT) + 1)
41#endif
42
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 <string.h> /* memcpy, memmove, memset */
59#include "cpu.h" /* bmi2 */
60#include "mem.h" /* low level memory routines */
61#define FSE_STATIC_LINKING_ONLY
62#include "fse.h"
63#define HUF_STATIC_LINKING_ONLY
64#include "huf.h"
65#include "zstd_internal.h" /* blockProperties_t */
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* Context management
77***************************************************************/
78size_t ZSTD_sizeof_DCtx (const ZSTD_DCtx* dctx)
79{
80 if (dctx==NULL) return 0; /* support sizeof NULL */
81 return sizeof(*dctx)
83 + dctx->inBuffSize + dctx->outBuffSize;
84}
85
86size_t ZSTD_estimateDCtxSize(void) { return sizeof(ZSTD_DCtx); }
87
88
89static size_t ZSTD_startingInputLength(ZSTD_format_e format)
90{
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;
95}
96
98{
99 dctx->format = ZSTD_f_zstd1; /* ZSTD_decompressBegin() invokes ZSTD_startingInputLength() with argument dctx->format */
100 dctx->staticSize = 0;
102 dctx->ddict = NULL;
103 dctx->ddictLocal = NULL;
104 dctx->dictEnd = NULL;
105 dctx->ddictIsCold = 0;
106 dctx->dictUses = ZSTD_dont_use;
107 dctx->inBuff = NULL;
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());
117#ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
118 dctx->dictContentEndForFuzzing = NULL;
119#endif
120}
121
122ZSTD_DCtx* ZSTD_initStaticDCtx(void *workspace, size_t workspaceSize)
123{
124 ZSTD_DCtx* const dctx = (ZSTD_DCtx*) workspace;
125
126 if ((size_t)workspace & 7) return NULL; /* 8-aligned */
127 if (workspaceSize < sizeof(ZSTD_DCtx)) return NULL; /* minimum size */
128
130 dctx->staticSize = workspaceSize;
131 dctx->inBuff = (char*)(dctx+1);
132 return dctx;
133}
134
135ZSTD_DCtx* ZSTD_createDCtx_advanced(ZSTD_customMem customMem)
136{
137 if (!customMem.customAlloc ^ !customMem.customFree) return NULL;
138
139 { ZSTD_DCtx* const dctx = (ZSTD_DCtx*)ZSTD_malloc(sizeof(*dctx), customMem);
140 if (!dctx) return NULL;
141 dctx->customMem = customMem;
143 return dctx;
144 }
145}
146
148{
149 DEBUGLOG(3, "ZSTD_createDCtx");
150 return ZSTD_createDCtx_advanced(ZSTD_defaultCMem);
151}
152
153static void ZSTD_clearDict(ZSTD_DCtx* dctx)
154{
156 dctx->ddictLocal = NULL;
157 dctx->ddict = NULL;
158 dctx->dictUses = ZSTD_dont_use;
159}
160
162{
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);
168 dctx->inBuff = NULL;
169#if defined(ZSTD_LEGACY_SUPPORT) && (ZSTD_LEGACY_SUPPORT >= 1)
170 if (dctx->legacyContext)
171 ZSTD_freeLegacyStreamContext(dctx->legacyContext, dctx->previousLegacyVersion);
172#endif
173 ZSTD_free(dctx, cMem);
174 return 0;
175 }
176}
177
178/* no longer useful */
179void ZSTD_copyDCtx(ZSTD_DCtx* dstDCtx, const ZSTD_DCtx* srcDCtx)
180{
181 size_t const toCopy = (size_t)((char*)(&dstDCtx->inBuff) - (char*)dstDCtx);
182 memcpy(dstDCtx, srcDCtx, toCopy); /* no need to copy workspace */
183}
184
185
186/*-*************************************************************
187 * Frame header decoding
188 ***************************************************************/
189
195unsigned ZSTD_isFrame(const void* buffer, size_t size)
196{
197 if (size < ZSTD_FRAMEIDSIZE) return 0;
198 { U32 const magic = MEM_readLE32(buffer);
199 if (magic == ZSTD_MAGICNUMBER) return 1;
201 }
202#if defined(ZSTD_LEGACY_SUPPORT) && (ZSTD_LEGACY_SUPPORT >= 1)
203 if (ZSTD_isLegacy(buffer, size)) return 1;
204#endif
205 return 0;
206}
207
213static size_t ZSTD_frameHeaderSize_internal(const void* src, size_t srcSize, ZSTD_format_e format)
214{
215 size_t const minInputSize = ZSTD_startingInputLength(format);
216 RETURN_ERROR_IF(srcSize < minInputSize, srcSize_wrong, "");
217
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);
225 }
226}
227
232size_t ZSTD_frameHeaderSize(const void* src, size_t srcSize)
233{
234 return ZSTD_frameHeaderSize_internal(src, srcSize, ZSTD_f_zstd1);
235}
236
237
244size_t ZSTD_getFrameHeader_advanced(ZSTD_frameHeader* zfhPtr, const void* src, size_t srcSize, ZSTD_format_e format)
245{
246 const BYTE* ip = (const BYTE*)src;
247 size_t const minInputSize = ZSTD_startingInputLength(format);
248
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");
252
253 if ( (format != ZSTD_f_zstd1_magicless)
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;
262 return 0;
263 }
264 RETURN_ERROR(prefix_unknown, "");
265 }
266
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;
271 }
272
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;
279 U64 windowSize = 0;
280 U32 dictID = 0;
281 U64 frameContentSize = ZSTD_CONTENTSIZE_UNKNOWN;
282 RETURN_ERROR_IF((fhdByte & 0x08) != 0, frameParameter_unsupported,
283 "reserved bits, must be zero");
284
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);
291 }
292 switch(dictIDSizeCode)
293 {
294 default: assert(0); /* impossible */
295 case 0 : break;
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;
299 }
300 switch(fcsID)
301 {
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;
307 }
308 if (singleSegment) windowSize = frameContentSize;
309
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;
316 }
317 return 0;
318}
319
326size_t ZSTD_getFrameHeader(ZSTD_frameHeader* zfhPtr, const void* src, size_t srcSize)
327{
328 return ZSTD_getFrameHeader_advanced(zfhPtr, src, srcSize, ZSTD_f_zstd1);
329}
330
331
337unsigned long long ZSTD_getFrameContentSize(const void *src, size_t srcSize)
338{
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;
343 }
344#endif
345 { ZSTD_frameHeader zfh;
346 if (ZSTD_getFrameHeader(&zfh, src, srcSize) != 0)
348 if (zfh.frameType == ZSTD_skippableFrame) {
349 return 0;
350 } else {
351 return zfh.frameContentSize;
352 } }
353}
354
355static size_t readSkippableFrameSize(void const* src, size_t srcSize)
356{
357 size_t const skippableHeaderSize = ZSTD_SKIPPABLEHEADERSIZE;
358 U32 sizeU32;
359
360 RETURN_ERROR_IF(srcSize < ZSTD_SKIPPABLEHEADERSIZE, srcSize_wrong, "");
361
362 sizeU32 = MEM_readLE32((BYTE const*)src + ZSTD_FRAMEIDSIZE);
363 RETURN_ERROR_IF((U32)(sizeU32 + ZSTD_SKIPPABLEHEADERSIZE) < sizeU32,
364 frameParameter_unsupported, "");
365 {
366 size_t const skippableSize = skippableHeaderSize + sizeU32;
367 RETURN_ERROR_IF(skippableSize > srcSize, srcSize_wrong, "");
368 return skippableSize;
369 }
370}
371
377unsigned long long ZSTD_findDecompressedSize(const void* src, size_t srcSize)
378{
379 unsigned long long totalDstSize = 0;
380
381 while (srcSize >= ZSTD_startingInputLength(ZSTD_f_zstd1)) {
382 U32 const magicNumber = MEM_readLE32(src);
383
385 size_t const skippableSize = readSkippableFrameSize(src, srcSize);
386 if (ZSTD_isError(skippableSize)) {
388 }
389 assert(skippableSize <= srcSize);
390
391 src = (const BYTE *)src + skippableSize;
392 srcSize -= skippableSize;
393 continue;
394 }
395
396 { unsigned long long const ret = ZSTD_getFrameContentSize(src, srcSize);
397 if (ret >= ZSTD_CONTENTSIZE_ERROR) return ret;
398
399 /* check for overflow */
400 if (totalDstSize + ret < totalDstSize) return ZSTD_CONTENTSIZE_ERROR;
401 totalDstSize += ret;
402 }
403 { size_t const frameSrcSize = ZSTD_findFrameCompressedSize(src, srcSize);
404 if (ZSTD_isError(frameSrcSize)) {
406 }
407
408 src = (const BYTE *)src + frameSrcSize;
409 srcSize -= frameSrcSize;
410 }
411 } /* while (srcSize >= ZSTD_frameHeaderSize_prefix) */
412
413 if (srcSize) return ZSTD_CONTENTSIZE_ERROR;
414
415 return totalDstSize;
416}
417
426unsigned long long ZSTD_getDecompressedSize(const void* src, size_t srcSize)
427{
428 unsigned long long const ret = ZSTD_getFrameContentSize(src, srcSize);
430 return (ret >= ZSTD_CONTENTSIZE_ERROR) ? 0 : ret;
431}
432
433
437static size_t ZSTD_decodeFrameHeader(ZSTD_DCtx* dctx, const void* src, size_t headerSize)
438{
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
444 * harder.
445 */
446 RETURN_ERROR_IF(dctx->fParams.dictID && (dctx->dictID != dctx->fParams.dictID),
447 dictionary_wrong, "");
448#endif
449 if (dctx->fParams.checksumFlag) XXH64_reset(&dctx->xxhState, 0);
450 return 0;
451}
452
454{
455 ZSTD_frameSizeInfo frameSizeInfo;
456 frameSizeInfo.compressedSize = ret;
458 return frameSizeInfo;
459}
460
461static ZSTD_frameSizeInfo ZSTD_findFrameSizeInfo(const void* src, size_t srcSize)
462{
463 ZSTD_frameSizeInfo frameSizeInfo;
464 memset(&frameSizeInfo, 0, sizeof(ZSTD_frameSizeInfo));
465
466#if defined(ZSTD_LEGACY_SUPPORT) && (ZSTD_LEGACY_SUPPORT >= 1)
467 if (ZSTD_isLegacy(src, srcSize))
468 return ZSTD_findFrameSizeInfoLegacy(src, srcSize);
469#endif
470
471 if ((srcSize >= ZSTD_SKIPPABLEHEADERSIZE)
473 frameSizeInfo.compressedSize = readSkippableFrameSize(src, srcSize);
474 assert(ZSTD_isError(frameSizeInfo.compressedSize) ||
475 frameSizeInfo.compressedSize <= srcSize);
476 return frameSizeInfo;
477 } else {
478 const BYTE* ip = (const BYTE*)src;
479 const BYTE* const ipstart = ip;
480 size_t remainingSize = srcSize;
481 size_t nbBlocks = 0;
482 ZSTD_frameHeader zfh;
483
484 /* Extract Frame Header */
485 { size_t const ret = ZSTD_getFrameHeader(&zfh, src, srcSize);
486 if (ZSTD_isError(ret))
488 if (ret > 0)
489 return ZSTD_errorFrameSizeInfo(ERROR(srcSize_wrong));
490 }
491
492 ip += zfh.headerSize;
493 remainingSize -= zfh.headerSize;
494
495 /* Iterate over each block */
496 while (1) {
497 blockProperties_t blockProperties;
498 size_t const cBlockSize = ZSTD_getcBlockSize(ip, remainingSize, &blockProperties);
499 if (ZSTD_isError(cBlockSize))
500 return ZSTD_errorFrameSizeInfo(cBlockSize);
501
502 if (ZSTD_blockHeaderSize + cBlockSize > remainingSize)
503 return ZSTD_errorFrameSizeInfo(ERROR(srcSize_wrong));
504
505 ip += ZSTD_blockHeaderSize + cBlockSize;
506 remainingSize -= ZSTD_blockHeaderSize + cBlockSize;
507 nbBlocks++;
508
509 if (blockProperties.lastBlock) break;
510 }
511
512 /* Final frame content checksum */
513 if (zfh.checksumFlag) {
514 if (remainingSize < 4)
515 return ZSTD_errorFrameSizeInfo(ERROR(srcSize_wrong));
516 ip += 4;
517 }
518
519 frameSizeInfo.compressedSize = ip - ipstart;
520 frameSizeInfo.decompressedBound = (zfh.frameContentSize != ZSTD_CONTENTSIZE_UNKNOWN)
521 ? zfh.frameContentSize
522 : nbBlocks * zfh.blockSizeMax;
523 return frameSizeInfo;
524 }
525}
526
532size_t ZSTD_findFrameCompressedSize(const void *src, size_t srcSize)
533{
534 ZSTD_frameSizeInfo const frameSizeInfo = ZSTD_findFrameSizeInfo(src, srcSize);
535 return frameSizeInfo.compressedSize;
536}
537
544unsigned long long ZSTD_decompressBound(const void* src, size_t srcSize)
545{
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)
554 assert(srcSize >= compressedSize);
555 src = (const BYTE*)src + compressedSize;
556 srcSize -= compressedSize;
557 bound += decompressedBound;
558 }
559 return bound;
560}
561
562
563/*-*************************************************************
564 * Frame decoding
565 ***************************************************************/
566
569size_t ZSTD_insertBlock(ZSTD_DCtx* dctx, const void* blockStart, size_t blockSize)
570{
571 DEBUGLOG(5, "ZSTD_insertBlock: %u bytes", (unsigned)blockSize);
572 ZSTD_checkContinuity(dctx, blockStart);
573 dctx->previousDstEnd = (const char*)blockStart + blockSize;
574 return blockSize;
575}
576
577
578static size_t ZSTD_copyRawBlock(void* dst, size_t dstCapacity,
579 const void* src, size_t srcSize)
580{
581 DEBUGLOG(5, "ZSTD_copyRawBlock");
582 if (dst == NULL) {
583 if (srcSize == 0) return 0;
584 RETURN_ERROR(dstBuffer_null, "");
585 }
586 RETURN_ERROR_IF(srcSize > dstCapacity, dstSize_tooSmall, "");
587 memcpy(dst, src, srcSize);
588 return srcSize;
589}
590
591static size_t ZSTD_setRleBlock(void* dst, size_t dstCapacity,
592 BYTE b,
593 size_t regenSize)
594{
595 if (dst == NULL) {
596 if (regenSize == 0) return 0;
597 RETURN_ERROR(dstBuffer_null, "");
598 }
599 RETURN_ERROR_IF(regenSize > dstCapacity, dstSize_tooSmall, "");
600 memset(dst, b, regenSize);
601 return regenSize;
602}
603
604
609static size_t ZSTD_decompressFrame(ZSTD_DCtx* dctx,
610 void* dst, size_t dstCapacity,
611 const void** srcPtr, size_t *srcSizePtr)
612{
613 const BYTE* ip = (const BYTE*)(*srcPtr);
614 BYTE* const ostart = (BYTE* const)dst;
615 BYTE* const oend = dstCapacity != 0 ? ostart + dstCapacity : ostart;
616 BYTE* op = ostart;
617 size_t remainingSrcSize = *srcSizePtr;
618
619 DEBUGLOG(4, "ZSTD_decompressFrame (srcSize:%i)", (int)*srcSizePtr);
620
621 /* check */
623 remainingSrcSize < ZSTD_FRAMEHEADERSIZE_MIN(dctx->format)+ZSTD_blockHeaderSize,
624 srcSize_wrong, "");
625
626 /* Frame Header */
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,
631 srcSize_wrong, "");
632 FORWARD_IF_ERROR( ZSTD_decodeFrameHeader(dctx, ip, frameHeaderSize) , "");
633 ip += frameHeaderSize; remainingSrcSize -= frameHeaderSize;
634 }
635
636 /* Loop on each block */
637 while (1) {
638 size_t decodedSize;
639 blockProperties_t blockProperties;
640 size_t const cBlockSize = ZSTD_getcBlockSize(ip, remainingSrcSize, &blockProperties);
641 if (ZSTD_isError(cBlockSize)) return cBlockSize;
642
644 remainingSrcSize -= ZSTD_blockHeaderSize;
645 RETURN_ERROR_IF(cBlockSize > remainingSrcSize, srcSize_wrong, "");
646
647 switch(blockProperties.blockType)
648 {
649 case bt_compressed:
650 decodedSize = ZSTD_decompressBlock_internal(dctx, op, oend-op, ip, cBlockSize, /* frame */ 1);
651 break;
652 case bt_raw :
653 decodedSize = ZSTD_copyRawBlock(op, oend-op, ip, cBlockSize);
654 break;
655 case bt_rle :
656 decodedSize = ZSTD_setRleBlock(op, oend-op, *ip, blockProperties.origSize);
657 break;
658 case bt_reserved :
659 default:
660 RETURN_ERROR(corruption_detected, "invalid block type");
661 }
662
663 if (ZSTD_isError(decodedSize)) return decodedSize;
664 if (dctx->fParams.checksumFlag)
665 XXH64_update(&dctx->xxhState, op, decodedSize);
666 if (decodedSize != 0)
667 op += decodedSize;
668 assert(ip != NULL);
669 ip += cBlockSize;
670 remainingSrcSize -= cBlockSize;
671 if (blockProperties.lastBlock) break;
672 }
673
674 if (dctx->fParams.frameContentSize != ZSTD_CONTENTSIZE_UNKNOWN) {
675 RETURN_ERROR_IF((U64)(op-ostart) != dctx->fParams.frameContentSize,
676 corruption_detected, "");
677 }
678 if (dctx->fParams.checksumFlag) { /* Frame content checksum verification */
679 U32 const checkCalc = (U32)XXH64_digest(&dctx->xxhState);
680 U32 checkRead;
681 RETURN_ERROR_IF(remainingSrcSize<4, checksum_wrong, "");
682 checkRead = MEM_readLE32(ip);
683 RETURN_ERROR_IF(checkRead != checkCalc, checksum_wrong, "");
684 ip += 4;
685 remainingSrcSize -= 4;
686 }
687
688 /* Allow caller to get size read */
689 *srcPtr = ip;
690 *srcSizePtr = remainingSrcSize;
691 return op-ostart;
692}
693
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)
699{
700 void* const dststart = dst;
701 int moreThan1Frame = 0;
702
703 DEBUGLOG(5, "ZSTD_decompressMultiFrame");
704 assert(dict==NULL || ddict==NULL); /* either dict or ddict set, not both */
705
706 if (ddict) {
707 dict = ZSTD_DDict_dictContent(ddict);
708 dictSize = ZSTD_DDict_dictSize(ddict);
709 }
710
711 while (srcSize >= ZSTD_startingInputLength(dctx->format)) {
712
713#if defined(ZSTD_LEGACY_SUPPORT) && (ZSTD_LEGACY_SUPPORT >= 1)
714 if (ZSTD_isLegacy(src, srcSize)) {
715 size_t decodedSize;
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");
720
721 decodedSize = ZSTD_decompressLegacy(dst, dstCapacity, src, frameSize, dict, dictSize);
722 if (ZSTD_isError(decodedSize)) return decodedSize;
723
724 assert(decodedSize <=- dstCapacity);
725 dst = (BYTE*)dst + decodedSize;
726 dstCapacity -= decodedSize;
727
728 src = (const BYTE*)src + frameSize;
729 srcSize -= frameSize;
730
731 continue;
732 }
733#endif
734
735 { U32 const magicNumber = MEM_readLE32(src);
736 DEBUGLOG(4, "reading magic number %08X (expecting %08X)",
737 (unsigned)magicNumber, ZSTD_MAGICNUMBER);
739 size_t const skippableSize = readSkippableFrameSize(src, srcSize);
740 FORWARD_IF_ERROR(skippableSize, "readSkippableFrameSize failed");
741 assert(skippableSize <= srcSize);
742
743 src = (const BYTE *)src + skippableSize;
744 srcSize -= skippableSize;
745 continue;
746 } }
747
748 if (ddict) {
749 /* we were called from ZSTD_decompress_usingDDict */
751 } else {
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), "");
755 }
757
758 { const size_t res = ZSTD_decompressFrame(dctx, dst, dstCapacity,
759 &src, &srcSize);
762 && (moreThan1Frame==1),
763 srcSize_wrong,
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 "
772 "error.");
773 if (ZSTD_isError(res)) return res;
774 assert(res <= dstCapacity);
775 if (res != 0)
776 dst = (BYTE*)dst + res;
777 dstCapacity -= res;
778 }
779 moreThan1Frame = 1;
780 } /* while (srcSize >= ZSTD_frameHeaderSize_prefix) */
781
782 RETURN_ERROR_IF(srcSize, srcSize_wrong, "input not entirely consumed");
783
784 return (BYTE*)dst - (BYTE*)dststart;
785}
786
788 void* dst, size_t dstCapacity,
789 const void* src, size_t srcSize,
790 const void* dict, size_t dictSize)
791{
792 return ZSTD_decompressMultiFrame(dctx, dst, dstCapacity, src, srcSize, dict, dictSize, NULL);
793}
794
795
797{
798 switch (dctx->dictUses) {
799 default:
800 assert(0 /* Impossible */);
801 /* fall-through */
802 case ZSTD_dont_use:
803 ZSTD_clearDict(dctx);
804 return NULL;
806 return dctx->ddict;
807 case ZSTD_use_once:
808 dctx->dictUses = ZSTD_dont_use;
809 return dctx->ddict;
810 }
811}
812
813size_t ZSTD_decompressDCtx(ZSTD_DCtx* dctx, void* dst, size_t dstCapacity, const void* src, size_t srcSize)
814{
815 return ZSTD_decompress_usingDDict(dctx, dst, dstCapacity, src, srcSize, ZSTD_getDDict(dctx));
816}
817
818
819size_t ZSTD_decompress(void* dst, size_t dstCapacity, const void* src, size_t srcSize)
820{
821#if defined(ZSTD_HEAPMODE) && (ZSTD_HEAPMODE>=1)
822 size_t regenSize;
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);
826 ZSTD_freeDCtx(dctx);
827 return regenSize;
828#else /* stack mode */
829 ZSTD_DCtx dctx;
831 return ZSTD_decompressDCtx(&dctx, dst, dstCapacity, src, srcSize);
832#endif
833}
834
835
836/*-**************************************
837* Advanced Streaming Decompression API
838* Bufferless and synchronous
839****************************************/
840size_t ZSTD_nextSrcSizeToDecompress(ZSTD_DCtx* dctx) { return dctx->expected; }
841
852static size_t ZSTD_nextSrcSizeToDecompressWithInputSize(ZSTD_DCtx* dctx, size_t inputSize) {
854 return dctx->expected;
855 if (dctx->bType != bt_raw)
856 return dctx->expected;
857 return MIN(MAX(inputSize, 1), dctx->expected);
858}
859
860ZSTD_nextInputType_e ZSTD_nextInputType(ZSTD_DCtx* dctx) {
861 switch(dctx->stage)
862 {
863 default: /* should not happen */
864 assert(0);
867 return ZSTDnit_frameHeader;
869 return ZSTDnit_blockHeader;
871 return ZSTDnit_block;
873 return ZSTDnit_lastBlock;
875 return ZSTDnit_checksum;
877 case ZSTDds_skipFrame:
878 return ZSTDnit_skippableFrame;
879 }
880}
881
882static int ZSTD_isSkipFrame(ZSTD_DCtx* dctx) { return dctx->stage == ZSTDds_skipFrame; }
883
888size_t ZSTD_decompressContinue(ZSTD_DCtx* dctx, void* dst, size_t dstCapacity, const void* src, size_t srcSize)
889{
890 DEBUGLOG(5, "ZSTD_decompressContinue (srcSize:%u)", (unsigned)srcSize);
891 /* Sanity check */
892 RETURN_ERROR_IF(srcSize != ZSTD_nextSrcSizeToDecompressWithInputSize(dctx, srcSize), srcSize_wrong, "not allowed");
893 if (dstCapacity) ZSTD_checkContinuity(dctx, dst);
894
895 switch (dctx->stage)
896 {
898 assert(src != NULL);
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 */
905 return 0;
906 } }
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;
912 return 0;
913
915 assert(src != NULL);
916 memcpy(dctx->headerBuffer + (dctx->headerSize - srcSize), src, srcSize);
920 return 0;
921
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;
930 if (cBlockSize) {
932 return 0;
933 }
934 /* empty block */
935 if (bp.lastBlock) {
936 if (dctx->fParams.checksumFlag) {
937 dctx->expected = 4;
939 } else {
940 dctx->expected = 0; /* end of frame */
942 }
943 } else {
944 dctx->expected = ZSTD_blockHeaderSize; /* jump to next header */
946 }
947 return 0;
948 }
949
952 DEBUGLOG(5, "ZSTD_decompressContinue: case ZSTDds_decompressBlock");
953 { size_t rSize;
954 switch(dctx->bType)
955 {
956 case bt_compressed:
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 */
960 break;
961 case bt_raw :
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;
967 break;
968 case bt_rle :
969 rSize = ZSTD_setRleBlock(dst, dstCapacity, *(const BYTE*)src, dctx->rleSize);
970 dctx->expected = 0; /* Streaming not supported */
971 break;
972 case bt_reserved : /* should never happen */
973 default:
974 RETURN_ERROR(corruption_detected, "invalid block type");
975 }
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;
982
983 /* Stay on the same stage until we are finished streaming the block. */
984 if (dctx->expected > 0) {
985 return rSize;
986 }
987
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 */
995 dctx->expected = 4;
997 } else {
998 dctx->expected = 0; /* ends here */
1000 }
1001 } else {
1004 }
1005 return rSize;
1006 }
1007
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, "");
1014 dctx->expected = 0;
1016 return 0;
1017 }
1018
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;
1025 return 0;
1026
1027 case ZSTDds_skipFrame:
1028 dctx->expected = 0;
1030 return 0;
1031
1032 default:
1033 assert(0); /* impossible */
1034 RETURN_ERROR(GENERIC, "impossible to reach"); /* some compiler require default to do something */
1035 }
1036}
1037
1038
1039static size_t ZSTD_refDictContent(ZSTD_DCtx* dctx, const void* dict, size_t dictSize)
1040{
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;
1048#endif
1049 return 0;
1050}
1051
1055size_t
1057 const void* const dict, size_t const dictSize)
1058{
1059 const BYTE* dictPtr = (const BYTE*)dict;
1060 const BYTE* const dictEnd = dictPtr + dictSize;
1061
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 */
1065
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);
1076#else
1077 size_t const hSize = HUF_readDTableX2_wksp(entropy->hufTable,
1078 dictPtr, dictEnd - dictPtr,
1079 workspace, workspaceSize);
1080#endif
1081 RETURN_ERROR_IF(HUF_isError(hSize), dictionary_corrupted, "");
1082 dictPtr += hSize;
1083 }
1084
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,
1094 offcodeLog);
1095 dictPtr += offcodeHeaderSize;
1096 }
1097
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,
1107 matchlengthLog);
1108 dictPtr += matchlengthHeaderSize;
1109 }
1110
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,
1120 litlengthLog);
1121 dictPtr += litlengthHeaderSize;
1122 }
1123
1124 RETURN_ERROR_IF(dictPtr+12 > dictEnd, dictionary_corrupted, "");
1125 { int i;
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;
1132 } }
1133
1134 return dictPtr - (const BYTE*)dict;
1135}
1136
1137static size_t ZSTD_decompress_insertDictionary(ZSTD_DCtx* dctx, const void* dict, size_t dictSize)
1138{
1139 if (dictSize < 8) return ZSTD_refDictContent(dctx, dict, dictSize);
1140 { U32 const magic = MEM_readLE32(dict);
1142 return ZSTD_refDictContent(dctx, dict, dictSize); /* pure content mode */
1143 } }
1144 dctx->dictID = MEM_readLE32((const char*)dict + ZSTD_FRAMEIDSIZE);
1145
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;
1150 dictSize -= eSize;
1151 }
1152 dctx->litEntropy = dctx->fseEntropy = 1;
1153
1154 /* reference dictionary content */
1155 return ZSTD_refDictContent(dctx, dict, dictSize);
1156}
1157
1159{
1160 assert(dctx != NULL);
1161 dctx->expected = ZSTD_startingInputLength(dctx->format); /* dctx->format must be properly set */
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;
1170 dctx->dictID = 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;
1178 return 0;
1179}
1180
1181size_t ZSTD_decompressBegin_usingDict(ZSTD_DCtx* dctx, const void* dict, size_t dictSize)
1182{
1184 if (dict && dictSize)
1186 ZSTD_isError(ZSTD_decompress_insertDictionary(dctx, dict, dictSize)),
1187 dictionary_corrupted, "");
1188 return 0;
1189}
1190
1191
1192/* ====== ZSTD_DDict ====== */
1193
1195{
1196 DEBUGLOG(4, "ZSTD_decompressBegin_usingDDict");
1197 assert(dctx != NULL);
1198 if (ddict) {
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!");
1205 }
1207 if (ddict) { /* NULL ddict is equivalent to no dictionary */
1208 ZSTD_copyDDictParameters(dctx, ddict);
1209 }
1210 return 0;
1211}
1212
1217unsigned ZSTD_getDictID_fromDict(const void* dict, size_t dictSize)
1218{
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);
1222}
1223
1237unsigned ZSTD_getDictID_fromFrame(const void* src, size_t srcSize)
1238{
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;
1242 return zfp.dictID;
1243}
1244
1245
1250 void* dst, size_t dstCapacity,
1251 const void* src, size_t srcSize,
1252 const ZSTD_DDict* ddict)
1253{
1254 /* pass content and size in case legacy frames are encountered */
1255 return ZSTD_decompressMultiFrame(dctx, dst, dstCapacity, src, srcSize,
1256 NULL, 0,
1257 ddict);
1258}
1259
1260
1261/*=====================================
1262* Streaming decompression
1263*====================================*/
1264
1266{
1267 DEBUGLOG(3, "ZSTD_createDStream");
1268 return ZSTD_createDStream_advanced(ZSTD_defaultCMem);
1269}
1270
1271ZSTD_DStream* ZSTD_initStaticDStream(void *workspace, size_t workspaceSize)
1272{
1273 return ZSTD_initStaticDCtx(workspace, workspaceSize);
1274}
1275
1277{
1278 return ZSTD_createDCtx_advanced(customMem);
1279}
1280
1282{
1283 return ZSTD_freeDCtx(zds);
1284}
1285
1286
1287/* *** Initialization *** */
1288
1291
1293 const void* dict, size_t dictSize,
1294 ZSTD_dictLoadMethod_e dictLoadMethod,
1295 ZSTD_dictContentType_e dictContentType)
1296{
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;
1304 }
1305 return 0;
1306}
1307
1308size_t ZSTD_DCtx_loadDictionary_byReference(ZSTD_DCtx* dctx, const void* dict, size_t dictSize)
1309{
1310 return ZSTD_DCtx_loadDictionary_advanced(dctx, dict, dictSize, ZSTD_dlm_byRef, ZSTD_dct_auto);
1311}
1312
1313size_t ZSTD_DCtx_loadDictionary(ZSTD_DCtx* dctx, const void* dict, size_t dictSize)
1314{
1315 return ZSTD_DCtx_loadDictionary_advanced(dctx, dict, dictSize, ZSTD_dlm_byCopy, ZSTD_dct_auto);
1316}
1317
1318size_t ZSTD_DCtx_refPrefix_advanced(ZSTD_DCtx* dctx, const void* prefix, size_t prefixSize, ZSTD_dictContentType_e dictContentType)
1319{
1320 FORWARD_IF_ERROR(ZSTD_DCtx_loadDictionary_advanced(dctx, prefix, prefixSize, ZSTD_dlm_byRef, dictContentType), "");
1321 dctx->dictUses = ZSTD_use_once;
1322 return 0;
1323}
1324
1325size_t ZSTD_DCtx_refPrefix(ZSTD_DCtx* dctx, const void* prefix, size_t prefixSize)
1326{
1327 return ZSTD_DCtx_refPrefix_advanced(dctx, prefix, prefixSize, ZSTD_dct_rawContent);
1328}
1329
1330
1331/* ZSTD_initDStream_usingDict() :
1332 * return : expected size, aka ZSTD_startingInputLength().
1333 * this function cannot fail */
1334size_t ZSTD_initDStream_usingDict(ZSTD_DStream* zds, const void* dict, size_t dictSize)
1335{
1336 DEBUGLOG(4, "ZSTD_initDStream_usingDict");
1338 FORWARD_IF_ERROR( ZSTD_DCtx_loadDictionary(zds, dict, dictSize) , "");
1339 return ZSTD_startingInputLength(zds->format);
1340}
1341
1342/* note : this variant can't fail */
1344{
1345 DEBUGLOG(4, "ZSTD_initDStream");
1346 return ZSTD_initDStream_usingDDict(zds, NULL);
1347}
1348
1349/* ZSTD_initDStream_usingDDict() :
1350 * ddict will just be referenced, and must outlive decompression session
1351 * this function cannot fail */
1353{
1355 FORWARD_IF_ERROR( ZSTD_DCtx_refDDict(dctx, ddict) , "");
1356 return ZSTD_startingInputLength(dctx->format);
1357}
1358
1359/* ZSTD_resetDStream() :
1360 * return : expected size, aka ZSTD_startingInputLength().
1361 * this function cannot fail */
1363{
1365 return ZSTD_startingInputLength(dctx->format);
1366}
1367
1368
1369size_t ZSTD_DCtx_refDDict(ZSTD_DCtx* dctx, const ZSTD_DDict* ddict)
1370{
1371 RETURN_ERROR_IF(dctx->streamStage != zdss_init, stage_wrong, "");
1372 ZSTD_clearDict(dctx);
1373 if (ddict) {
1374 dctx->ddict = ddict;
1376 }
1377 return 0;
1378}
1379
1380/* ZSTD_DCtx_setMaxWindowSize() :
1381 * note : no direct equivalence in ZSTD_DCtx_setParameter,
1382 * since this version sets windowSize, and the other sets windowLog */
1383size_t ZSTD_DCtx_setMaxWindowSize(ZSTD_DCtx* dctx, size_t maxWindowSize)
1384{
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;
1392 return 0;
1393}
1394
1395size_t ZSTD_DCtx_setFormat(ZSTD_DCtx* dctx, ZSTD_format_e format)
1396{
1397 return ZSTD_DCtx_setParameter(dctx, ZSTD_d_format, format);
1398}
1399
1401{
1402 ZSTD_bounds bounds = { 0, 0, 0 };
1403 switch(dParam) {
1406 bounds.upperBound = ZSTD_WINDOWLOG_MAX;
1407 return bounds;
1408 case ZSTD_d_format:
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);
1412 return bounds;
1413 case ZSTD_d_stableOutBuffer:
1415 bounds.upperBound = (int)ZSTD_obm_stable;
1416 return bounds;
1417 default:;
1418 }
1419 bounds.error = ERROR(parameter_unsupported);
1420 return bounds;
1421}
1422
1423/* ZSTD_dParam_withinBounds:
1424 * @return 1 if value is within dParam bounds,
1425 * 0 otherwise */
1427{
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;
1432 return 1;
1433}
1434
1435#define CHECK_DBOUNDS(p,v) { \
1436 RETURN_ERROR_IF(!ZSTD_dParam_withinBounds(p, v), parameter_outOfBound, ""); \
1437}
1438
1440{
1441 RETURN_ERROR_IF(dctx->streamStage != zdss_init, stage_wrong, "");
1442 switch(dParam) {
1444 if (value == 0) value = ZSTD_WINDOWLOG_LIMIT_DEFAULT;
1446 dctx->maxWindowSize = ((size_t)1) << value;
1447 return 0;
1448 case ZSTD_d_format:
1449 CHECK_DBOUNDS(ZSTD_d_format, value);
1450 dctx->format = (ZSTD_format_e)value;
1451 return 0;
1452 case ZSTD_d_stableOutBuffer:
1453 CHECK_DBOUNDS(ZSTD_d_stableOutBuffer, value);
1455 return 0;
1456 default:;
1457 }
1458 RETURN_ERROR(parameter_unsupported, "");
1459}
1460
1462{
1465 dctx->streamStage = zdss_init;
1466 dctx->noForwardProgress = 0;
1467 }
1470 RETURN_ERROR_IF(dctx->streamStage != zdss_init, stage_wrong, "");
1471 ZSTD_clearDict(dctx);
1472 dctx->format = ZSTD_f_zstd1;
1474 }
1475 return 0;
1476}
1477
1478
1480{
1481 return ZSTD_sizeof_DCtx(dctx);
1482}
1483
1484size_t ZSTD_decodingBufferSize_min(unsigned long long windowSize, unsigned long long frameContentSize)
1485{
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, "");
1492 return minRBSize;
1493}
1494
1495size_t ZSTD_estimateDStreamSize(size_t windowSize)
1496{
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;
1501}
1502
1503size_t ZSTD_estimateDStreamSize_fromFrame(const void* src, size_t srcSize)
1504{
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);
1513}
1514
1515
1516/* ***** Decompression ***** */
1517
1518static int ZSTD_DCtx_isOverflow(ZSTD_DStream* zds, size_t const neededInBuffSize, size_t const neededOutBuffSize)
1519{
1520 return (zds->inBuffSize + zds->outBuffSize) >= (neededInBuffSize + neededOutBuffSize) * ZSTD_WORKSPACETOOLARGE_FACTOR;
1521}
1522
1523static void ZSTD_DCtx_updateOversizedDuration(ZSTD_DStream* zds, size_t const neededInBuffSize, size_t const neededOutBuffSize)
1524{
1525 if (ZSTD_DCtx_isOverflow(zds, neededInBuffSize, neededOutBuffSize))
1526 zds->oversizedDuration++;
1527 else
1528 zds->oversizedDuration = 0;
1529}
1530
1532{
1534}
1535
1536/* Checks that the output buffer hasn't changed if ZSTD_obm_stable is used. */
1537static size_t ZSTD_checkOutBuffer(ZSTD_DStream const* zds, ZSTD_outBuffer const* output)
1538{
1540 /* No requirement when ZSTD_obm_stable is not enabled. */
1541 if (zds->outBufferMode != ZSTD_obm_stable)
1542 return 0;
1543 /* Any buffer is allowed in zdss_init, this must be the same for every other call until
1544 * the context is reset.
1545 */
1546 if (zds->streamStage == zdss_init)
1547 return 0;
1548 /* The buffer must match our expectation exactly. */
1549 if (expect.dst == output->dst && expect.pos == output->pos && expect.size == output->size)
1550 return 0;
1551 RETURN_ERROR(dstBuffer_wrong, "ZSTD_obm_stable enabled but output differs!");
1552}
1553
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.
1558 */
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;
1570 } else {
1571 zds->outEnd = zds->outStart + decodedSize;
1572 zds->streamStage = zdss_flush;
1573 }
1574 } else {
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, "");
1579 *op += decodedSize;
1580 /* Flushing is not needed. */
1581 zds->streamStage = zdss_read;
1582 assert(*op <= oend);
1584 }
1585 return 0;
1586}
1587
1589{
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;
1597 char* op = ostart;
1598 U32 someMoreWork = 1;
1599
1600 DEBUGLOG(5, "ZSTD_decompressStream");
1602 input->pos > input->size,
1603 srcSize_wrong,
1604 "forbidden. in: pos: %u vs size: %u",
1605 (U32)input->pos, (U32)input->size);
1607 output->pos > output->size,
1608 dstSize_tooSmall,
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), "");
1613
1614 while (someMoreWork) {
1615 switch(zds->streamStage)
1616 {
1617 case zdss_init :
1618 DEBUGLOG(5, "stage zdss_init => transparent reset ");
1620 zds->lhSize = zds->inPos = zds->outStart = zds->outEnd = 0;
1621 zds->legacyVersion = 0;
1622 zds->hostageByte = 0;
1623 zds->expectedOutBuffer = *output;
1624 /* fall-through */
1625
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;
1634 return hint;
1635 } }
1636#endif
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 */
1655 return hint;
1656 } }
1657#endif
1658 return hSize; /* error */
1659 }
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);
1663 assert(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;
1668 }
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 */
1671 }
1672 assert(ip != NULL);
1673 memcpy(zds->headerBuffer + zds->lhSize, ip, toLoad); zds->lhSize = hSize; ip += toLoad;
1674 break;
1675 } }
1676
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;
1689 zds->expected = 0;
1690 zds->streamStage = zdss_init;
1691 someMoreWork = 0;
1692 break;
1693 } }
1694
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");
1701 }
1702
1703 /* Consume header (see ZSTDds_decodeFrameHeader) */
1704 DEBUGLOG(4, "Consume header");
1706
1707 if ((MEM_readLE32(zds->headerBuffer) & ZSTD_MAGIC_SKIPPABLE_MASK) == ZSTD_MAGIC_SKIPPABLE_START) { /* skippable frame */
1709 zds->stage = ZSTDds_skipFrame;
1710 } else {
1714 }
1715
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, "");
1723
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)
1728 : 0;
1729
1730 ZSTD_DCtx_updateOversizedDuration(zds, neededInBuffSize, neededOutBuffSize);
1731
1732 { int const tooSmall = (zds->inBuffSize < neededInBuffSize) || (zds->outBuffSize < neededOutBuffSize);
1733 int const tooLarge = ZSTD_DCtx_isOversizedTooLong(zds);
1734
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, "");
1747 } else {
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, "");
1753 }
1754 zds->inBuffSize = neededInBuffSize;
1755 zds->outBuff = zds->inBuff + zds->inBuffSize;
1756 zds->outBuffSize = neededOutBuffSize;
1757 } } }
1758 zds->streamStage = zdss_read;
1759 /* fall-through */
1760
1761 case 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;
1767 someMoreWork = 0;
1768 break;
1769 }
1770 if ((size_t)(iend-ip) >= neededInSize) { /* decode directly from src */
1771 FORWARD_IF_ERROR(ZSTD_decompressContinueStream(zds, &op, oend, ip, neededInSize), "");
1772 ip += neededInSize;
1773 /* Function modifies the stage so we must break */
1774 break;
1775 } }
1776 if (ip==iend) { someMoreWork = 0; break; } /* no more input */
1777 zds->streamStage = zdss_load;
1778 /* fall-through */
1779
1780 case 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);
1784 size_t loadedSize;
1785 /* At this point we shouldn't be decompressing a block that we can stream. */
1786 assert(neededInSize == ZSTD_nextSrcSizeToDecompressWithInputSize(zds, iend - ip));
1787 if (isSkipFrame) {
1788 loadedSize = MIN(toLoad, (size_t)(iend-ip));
1789 } else {
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);
1794 }
1795 ip += loadedSize;
1796 zds->inPos += loadedSize;
1797 if (loadedSize < toLoad) { someMoreWork = 0; break; } /* not enough input, wait for more */
1798
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 */
1803 break;
1804 }
1805 case zdss_flush:
1806 { size_t const toFlushSize = zds->outEnd - zds->outStart;
1807 size_t const flushedSize = ZSTD_limitCopy(op, oend-op, zds->outBuff + zds->outStart, toFlushSize);
1808 op += flushedSize;
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;
1818 }
1819 break;
1820 } }
1821 /* cannot complete flush */
1822 someMoreWork = 0;
1823 break;
1824
1825 default:
1826 assert(0); /* impossible */
1827 RETURN_ERROR(GENERIC, "impossible to reach"); /* some compiler require default to do something */
1828 } }
1829
1830 /* result */
1831 input->pos = (size_t)(ip - (const char*)(input->src));
1832 output->pos = (size_t)(op - (char*)(output->dst));
1833
1834 /* Update the expected output buffer for ZSTD_obm_stable. */
1835 zds->expectedOutBuffer = *output;
1836
1837 if ((ip==istart) && (op==ostart)) { /* no forward progress */
1838 zds->noForwardProgress ++;
1840 RETURN_ERROR_IF(op==oend, dstSize_tooSmall, "");
1841 RETURN_ERROR_IF(ip==iend, srcSize_wrong, "");
1842 assert(0);
1843 }
1844 } else {
1845 zds->noForwardProgress = 0;
1846 }
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;
1854 return 1;
1855 }
1856 input->pos++; /* release hostage */
1857 } /* zds->hostageByte */
1858 return 0;
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 */
1862 zds->hostageByte=1;
1863 }
1864 return 1;
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;
1870 }
1871}
1872
1874 ZSTD_DCtx* dctx,
1875 void* dst, size_t dstCapacity, size_t* dstPos,
1876 const void* src, size_t srcSize, size_t* srcPos)
1877{
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;
1884 return cErr;
1885}
#define RETURN_ERROR(StatusCode)
Definition: Base.h:751
#define expect(EXPECTED, GOT)
Definition: SystemMenu.c:483
#define MIN(x, y)
Definition: rdesktop.h:171
#define MAX(x, y)
Definition: rdesktop.h:175
#define NULL
Definition: types.h:112
UINT op
Definition: effect.c:236
unsigned int(__cdecl typeof(jpeg_read_scanlines))(struct jpeg_decompress_struct *
Definition: typeof.h:31
#define assert(x)
Definition: debug.h:53
MEM_STATIC ZSTD_cpuid_t ZSTD_cpuid(void)
Definition: cpu.h:34
#define DEBUGLOG(l,...)
Definition: debug.h:106
MEM_STATIC U16 MEM_readLE16(const void *memPtr)
Definition: mem.h:314
MEM_STATIC U64 MEM_readLE64(const void *memPtr)
Definition: mem.h:362
MEM_STATIC U32 MEM_readLE32(const void *memPtr)
Definition: mem.h:346
__kernel_size_t size_t
Definition: linux.h:237
size_t FSE_readNCount(short *normalizedCounter, unsigned *maxSVPtr, unsigned *tableLogPtr, const void *headerBuffer, size_t hbSize)
#define ERROR(name)
Definition: error_private.h:53
#define FSE_isError
Definition: fse_compress.c:35
size_t bufferSize
GLint GLint GLsizei GLsizei GLsizei GLint GLenum format
Definition: gl.h:1546
GLsizeiptr size
Definition: glext.h:5919
GLboolean reset
Definition: glext.h:5666
GLuint res
Definition: glext.h:9613
GLenum src
Definition: glext.h:6340
GLuint buffer
Definition: glext.h:5915
GLboolean GLboolean GLboolean b
Definition: glext.h:6204
GLenum GLenum dst
Definition: glext.h:6340
GLenum GLenum GLenum input
Definition: glext.h:9031
GLuint64EXT * result
Definition: glext.h:11304
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
#define HUF_isError
Definition: huf_compress.c:41
size_t HUF_readDTableX1_wksp(HUF_DTable *DTable, const void *src, size_t srcSize, void *workSpace, size_t wkspSize)
size_t HUF_readDTableX2_wksp(HUF_DTable *DTable, const void *src, size_t srcSize, void *workSpace, size_t wkspSize)
#define memcpy(s1, s2, n)
Definition: mkisofs.h:878
BOOL expected
Definition: store.c:2063
static unsigned(__cdecl *hash_bstr)(bstr_t s)
#define min(a, b)
Definition: monoChain.cc:55
u32_t magic(void)
#define err(...)
#define offsetof(TYPE, MEMBER)
#define memset(x, y, z)
Definition: compat.h:39
const HUF_DTable * HUFptr
ZSTD_dStreamStage streamStage
const ZSTD_seqSymbol * MLTptr
const ZSTD_DDict * ddict
XXH64_state_t xxhState
ZSTD_customMem customMem
ZSTD_dictUses_e dictUses
const void * virtualStart
const ZSTD_seqSymbol * OFTptr
const void * prefixStart
ZSTD_entropyDTables_t entropy
ZSTD_outBuffer expectedOutBuffer
BYTE headerBuffer[ZSTD_FRAMEHEADERSIZE_MAX]
const void * previousDstEnd
ZSTD_frameHeader fParams
ZSTD_outBufferMode_e outBufferMode
const ZSTD_seqSymbol * LLTptr
int upperBound
Definition: zstd.h:422
size_t error
Definition: zstd.h:420
int lowerBound
Definition: zstd.h:421
ZSTD_seqSymbol LLTable[SEQSYMBOL_TABLE_SIZE(LLFSELog)]
ZSTD_seqSymbol MLTable[SEQSYMBOL_TABLE_SIZE(MLFSELog)]
ZSTD_seqSymbol OFTable[SEQSYMBOL_TABLE_SIZE(OffFSELog)]
HUF_DTable hufTable[HUF_DTABLE_SIZE(HufLog)]
unsigned long long decompressedBound
size_t size
Definition: zstd.h:574
size_t pos
Definition: zstd.h:575
void * dst
Definition: zstd.h:573
blockType_e blockType
Definition: dhcpd.h:62
#define max(a, b)
Definition: svc.c:63
Definition: pdh_main.c:94
DWORD hint
Definition: vfdcmd.c:88
int ret
unsigned long long U64
Definition: xxhash.c:197
XXH_PUBLIC_API XXH_errorcode XXH64_update(XXH64_state_t *state_in, const void *input, size_t len)
Definition: xxhash.c:810
XXH_PUBLIC_API XXH_errorcode XXH64_reset(XXH64_state_t *statePtr, unsigned long long seed)
Definition: xxhash.c:622
unsigned char BYTE
Definition: xxhash.c:193
unsigned int U32
Definition: xxhash.c:195
XXH_PUBLIC_API unsigned long long XXH64_digest(const XXH64_state_t *state_in)
Definition: xxhash.c:874
#define ZSTD_CONTENTSIZE_UNKNOWN
Definition: zstd.h:152
#define ZSTD_MAGICNUMBER
Definition: zstd.h:98
ZSTD_dParameter
Definition: zstd.h:513
@ ZSTD_d_windowLogMax
Definition: zstd.h:515
#define ZSTD_MAGIC_DICTIONARY
Definition: zstd.h:99
#define ZSTD_MAGIC_SKIPPABLE_MASK
Definition: zstd.h:101
ZSTDLIB_API size_t ZSTD_freeDDict(ZSTD_DDict *ddict)
Definition: zstd_ddict.c:212
struct ZSTD_DCtx_s ZSTD_DCtx
Definition: zstd.h:218
#define ZSTD_CONTENTSIZE_ERROR
Definition: zstd.h:153
ZSTD_ResetDirective
Definition: zstd.h:464
@ ZSTD_reset_session_only
Definition: zstd.h:465
@ ZSTD_reset_parameters
Definition: zstd.h:466
@ ZSTD_reset_session_and_parameters
Definition: zstd.h:467
ZSTDLIB_API size_t ZSTD_sizeof_DDict(const ZSTD_DDict *ddict)
Definition: zstd_ddict.c:230
#define ZSTD_BLOCKSIZE_MAX
Definition: zstd.h:104
#define ZSTD_MAGIC_SKIPPABLE_START
Definition: zstd.h:100
ZSTD_ErrorCode ZSTD_getErrorCode(size_t code)
Definition: zstd_common.c:45
void ZSTD_free(void *ptr, ZSTD_customMem customMem)
Definition: zstd_common.c:70
void * ZSTD_malloc(size_t size, ZSTD_customMem customMem)
Definition: zstd_common.c:56
ZSTD_DDict * ZSTD_createDDict_advanced(const void *dict, size_t dictSize, ZSTD_dictLoadMethod_e dictLoadMethod, ZSTD_dictContentType_e dictContentType, ZSTD_customMem customMem)
Definition: zstd_ddict.c:145
void ZSTD_copyDDictParameters(ZSTD_DCtx *dctx, const ZSTD_DDict *ddict)
Definition: zstd_ddict.c:58
const void * ZSTD_DDict_dictContent(const ZSTD_DDict *ddict)
Definition: zstd_ddict.c:46
size_t ZSTD_DDict_dictSize(const ZSTD_DDict *ddict)
Definition: zstd_ddict.c:52
size_t ZSTD_DCtx_loadDictionary_advanced(ZSTD_DCtx *dctx, const void *dict, size_t dictSize, ZSTD_dictLoadMethod_e dictLoadMethod, ZSTD_dictContentType_e dictContentType)
static int ZSTD_DCtx_isOverflow(ZSTD_DStream *zds, size_t const neededInBuffSize, size_t const neededOutBuffSize)
size_t ZSTD_nextSrcSizeToDecompress(ZSTD_DCtx *dctx)
size_t ZSTD_decodingBufferSize_min(unsigned long long windowSize, unsigned long long frameContentSize)
ZSTD_bounds ZSTD_dParam_getBounds(ZSTD_dParameter dParam)
static ZSTD_frameSizeInfo ZSTD_findFrameSizeInfo(const void *src, size_t srcSize)
static size_t ZSTD_refDictContent(ZSTD_DCtx *dctx, const void *dict, size_t dictSize)
static size_t 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)
#define CHECK_DBOUNDS(p, v)
size_t ZSTD_DCtx_loadDictionary_byReference(ZSTD_DCtx *dctx, const void *dict, size_t dictSize)
size_t ZSTD_decompressBegin_usingDDict(ZSTD_DCtx *dctx, const ZSTD_DDict *ddict)
ZSTD_DCtx * ZSTD_initStaticDCtx(void *workspace, size_t workspaceSize)
static ZSTD_frameSizeInfo ZSTD_errorFrameSizeInfo(size_t ret)
ZSTD_DStream * ZSTD_createDStream(void)
size_t ZSTD_DCtx_loadDictionary(ZSTD_DCtx *dctx, const void *dict, size_t dictSize)
size_t ZSTD_freeDStream(ZSTD_DStream *zds)
size_t ZSTD_estimateDStreamSize_fromFrame(const void *src, size_t srcSize)
size_t ZSTD_DCtx_refPrefix(ZSTD_DCtx *dctx, const void *prefix, size_t prefixSize)
ZSTD_nextInputType_e ZSTD_nextInputType(ZSTD_DCtx *dctx)
size_t ZSTD_decompressStream(ZSTD_DStream *zds, ZSTD_outBuffer *output, ZSTD_inBuffer *input)
static size_t ZSTD_frameHeaderSize_internal(const void *src, size_t srcSize, ZSTD_format_e format)
size_t ZSTD_decompressBegin(ZSTD_DCtx *dctx)
size_t ZSTD_estimateDCtxSize(void)
static size_t ZSTD_setRleBlock(void *dst, size_t dstCapacity, BYTE b, size_t regenSize)
ZSTD_DStream * ZSTD_createDStream_advanced(ZSTD_customMem customMem)
size_t ZSTD_freeDCtx(ZSTD_DCtx *dctx)
static size_t ZSTD_decompress_insertDictionary(ZSTD_DCtx *dctx, const void *dict, size_t dictSize)
size_t ZSTD_DCtx_reset(ZSTD_DCtx *dctx, ZSTD_ResetDirective reset)
size_t ZSTD_decompress_usingDict(ZSTD_DCtx *dctx, void *dst, size_t dstCapacity, const void *src, size_t srcSize, const void *dict, size_t dictSize)
unsigned long long ZSTD_getDecompressedSize(const void *src, size_t srcSize)
static size_t ZSTD_decodeFrameHeader(ZSTD_DCtx *dctx, const void *src, size_t headerSize)
static size_t ZSTD_decompressContinueStream(ZSTD_DStream *zds, char **op, char *oend, void const *src, size_t srcSize)
size_t ZSTD_initDStream(ZSTD_DStream *zds)
size_t ZSTD_loadDEntropy(ZSTD_entropyDTables_t *entropy, const void *const dict, size_t const dictSize)
size_t ZSTD_sizeof_DCtx(const ZSTD_DCtx *dctx)
size_t ZSTD_getFrameHeader_advanced(ZSTD_frameHeader *zfhPtr, const void *src, size_t srcSize, ZSTD_format_e format)
ZSTD_DStream * ZSTD_initStaticDStream(void *workspace, size_t workspaceSize)
static size_t readSkippableFrameSize(void const *src, size_t srcSize)
void ZSTD_copyDCtx(ZSTD_DCtx *dstDCtx, const ZSTD_DCtx *srcDCtx)
static int ZSTD_isSkipFrame(ZSTD_DCtx *dctx)
static size_t ZSTD_decompressFrame(ZSTD_DCtx *dctx, void *dst, size_t dstCapacity, const void **srcPtr, size_t *srcSizePtr)
size_t ZSTD_DCtx_refPrefix_advanced(ZSTD_DCtx *dctx, const void *prefix, size_t prefixSize, ZSTD_dictContentType_e dictContentType)
size_t ZSTD_decompressBegin_usingDict(ZSTD_DCtx *dctx, const void *dict, size_t dictSize)
static void ZSTD_DCtx_updateOversizedDuration(ZSTD_DStream *zds, size_t const neededInBuffSize, size_t const neededOutBuffSize)
static size_t ZSTD_checkOutBuffer(ZSTD_DStream const *zds, ZSTD_outBuffer const *output)
unsigned ZSTD_getDictID_fromFrame(const void *src, size_t srcSize)
static size_t ZSTD_copyRawBlock(void *dst, size_t dstCapacity, const void *src, size_t srcSize)
size_t ZSTD_resetDStream(ZSTD_DStream *dctx)
static ZSTD_DDict const * ZSTD_getDDict(ZSTD_DCtx *dctx)
static void ZSTD_clearDict(ZSTD_DCtx *dctx)
size_t ZSTD_DCtx_setFormat(ZSTD_DCtx *dctx, ZSTD_format_e format)
size_t ZSTD_DStreamOutSize(void)
size_t ZSTD_frameHeaderSize(const void *src, size_t srcSize)
size_t ZSTD_estimateDStreamSize(size_t windowSize)
unsigned long long ZSTD_getFrameContentSize(const void *src, size_t srcSize)
unsigned ZSTD_getDictID_fromDict(const void *dict, size_t dictSize)
size_t ZSTD_DCtx_refDDict(ZSTD_DCtx *dctx, const ZSTD_DDict *ddict)
static void ZSTD_initDCtx_internal(ZSTD_DCtx *dctx)
size_t ZSTD_decompress(void *dst, size_t dstCapacity, const void *src, size_t srcSize)
static int ZSTD_DCtx_isOversizedTooLong(ZSTD_DStream *zds)
static int ZSTD_dParam_withinBounds(ZSTD_dParameter dParam, int value)
unsigned long long ZSTD_findDecompressedSize(const void *src, size_t srcSize)
static size_t ZSTD_nextSrcSizeToDecompressWithInputSize(ZSTD_DCtx *dctx, size_t inputSize)
size_t ZSTD_DStreamInSize(void)
size_t ZSTD_findFrameCompressedSize(const void *src, size_t srcSize)
size_t ZSTD_initDStream_usingDDict(ZSTD_DStream *dctx, const ZSTD_DDict *ddict)
size_t ZSTD_getFrameHeader(ZSTD_frameHeader *zfhPtr, const void *src, size_t srcSize)
size_t ZSTD_initDStream_usingDict(ZSTD_DStream *zds, const void *dict, size_t dictSize)
unsigned ZSTD_isFrame(const void *buffer, size_t size)
size_t ZSTD_decompressStream_simpleArgs(ZSTD_DCtx *dctx, void *dst, size_t dstCapacity, size_t *dstPos, const void *src, size_t srcSize, size_t *srcPos)
size_t ZSTD_insertBlock(ZSTD_DCtx *dctx, const void *blockStart, size_t blockSize)
size_t ZSTD_DCtx_setParameter(ZSTD_DCtx *dctx, ZSTD_dParameter dParam, int value)
size_t ZSTD_decompressDCtx(ZSTD_DCtx *dctx, void *dst, size_t dstCapacity, const void *src, size_t srcSize)
ZSTD_DCtx * ZSTD_createDCtx(void)
unsigned long long ZSTD_decompressBound(const void *src, size_t srcSize)
size_t ZSTD_decompress_usingDDict(ZSTD_DCtx *dctx, void *dst, size_t dstCapacity, const void *src, size_t srcSize, const ZSTD_DDict *ddict)
static size_t ZSTD_startingInputLength(ZSTD_format_e format)
#define ZSTD_NO_FORWARD_PROGRESS_MAX
ZSTD_DCtx * ZSTD_createDCtx_advanced(ZSTD_customMem customMem)
size_t ZSTD_DCtx_setMaxWindowSize(ZSTD_DCtx *dctx, size_t maxWindowSize)
size_t ZSTD_decompressContinue(ZSTD_DCtx *dctx, void *dst, size_t dstCapacity, const void *src, size_t srcSize)
#define ZSTD_MAXWINDOWSIZE_DEFAULT
size_t ZSTD_sizeof_DStream(const ZSTD_DStream *dctx)
size_t ZSTD_decompressBlock_internal(ZSTD_DCtx *dctx, void *dst, size_t dstCapacity, const void *src, size_t srcSize, const int frame)
size_t ZSTD_getcBlockSize(const void *src, size_t srcSize, blockProperties_t *bpPtr)
void ZSTD_checkContinuity(ZSTD_DCtx *dctx, const void *dst)
void ZSTD_buildFSETable(ZSTD_seqSymbol *dt, const short *normalizedCounter, unsigned maxSymbolValue, const U32 *baseValue, const U32 *nbAdditionalBits, unsigned tableLog)
@ ZSTD_use_indefinitely
static const U32 ML_base[MaxML+1]
static const U32 OF_base[MaxOff+1]
@ ZSTD_obm_buffered
static const U32 OF_bits[MaxOff+1]
@ ZSTDds_getFrameHeaderSize
@ ZSTDds_skipFrame
@ ZSTDds_checkChecksum
@ ZSTDds_decodeBlockHeader
@ ZSTDds_decompressLastBlock
@ ZSTDds_decodeFrameHeader
@ ZSTDds_decompressBlock
@ ZSTDds_decodeSkippableHeader
static const U32 LL_base[MaxLL+1]
@ ZSTD_error_prefix_unknown
Definition: zstd_errors.h:55
#define ZSTD_WORKSPACETOOLARGE_MAXDURATION
#define HufLog
#define MaxLL
#define FORWARD_IF_ERROR(err,...)
static const size_t ZSTD_blockHeaderSize
#define WILDCOPY_OVERLENGTH
#define MaxML
#define ZSTD_WINDOWLOG_ABSOLUTEMIN
#define RETURN_ERROR_IF(cond, err,...)
Definition: zstd_internal.h:91
#define ZSTD_isError
Definition: zstd_internal.h:46
static const U32 ML_bits[MaxML+1]
#define MLFSELog
static const size_t ZSTD_did_fieldSize[4]
MEM_STATIC size_t ZSTD_limitCopy(void *dst, size_t dstCapacity, const void *src, size_t srcSize)
@ bt_compressed
@ bt_rle
@ bt_reserved
@ bt_raw
#define ZSTD_FRAMEIDSIZE
static const size_t ZSTD_fcs_fieldSize[4]
static const U32 repStartValue[ZSTD_REP_NUM]
static const U32 LL_bits[MaxLL+1]
#define MaxOff
#define LLFSELog
#define ZSTD_STATIC_ASSERT(c)
Definition: zstd_internal.h:45
#define OffFSELog
#define ZSTD_WORKSPACETOOLARGE_FACTOR