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