The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/contrib/zstd/lib/decompress/zstd_decompress.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

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

Cache object: 0d55ae31283771a7aba6bbb14ddbc8b8


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.