Path: blob/master/Utilities/cmzstd/lib/decompress/zstd_ddict.c
3158 views
/*1* Copyright (c) Meta Platforms, Inc. and affiliates.2* All rights reserved.3*4* This source code is licensed under both the BSD-style license (found in the5* LICENSE file in the root directory of this source tree) and the GPLv2 (found6* in the COPYING file in the root directory of this source tree).7* You may select, at your option, one of the above-listed licenses.8*/910/* zstd_ddict.c :11* concentrates all logic that needs to know the internals of ZSTD_DDict object */1213/*-*******************************************************14* Dependencies15*********************************************************/16#include "../common/allocations.h" /* ZSTD_customMalloc, ZSTD_customFree */17#include "../common/zstd_deps.h" /* ZSTD_memcpy, ZSTD_memmove, ZSTD_memset */18#include "../common/cpu.h" /* bmi2 */19#include "../common/mem.h" /* low level memory routines */20#define FSE_STATIC_LINKING_ONLY21#include "../common/fse.h"22#include "../common/huf.h"23#include "zstd_decompress_internal.h"24#include "zstd_ddict.h"2526#if defined(ZSTD_LEGACY_SUPPORT) && (ZSTD_LEGACY_SUPPORT>=1)27# include "../legacy/zstd_legacy.h"28#endif29303132/*-*******************************************************33* Types34*********************************************************/35struct ZSTD_DDict_s {36void* dictBuffer;37const void* dictContent;38size_t dictSize;39ZSTD_entropyDTables_t entropy;40U32 dictID;41U32 entropyPresent;42ZSTD_customMem cMem;43}; /* typedef'd to ZSTD_DDict within "zstd.h" */4445const void* ZSTD_DDict_dictContent(const ZSTD_DDict* ddict)46{47assert(ddict != NULL);48return ddict->dictContent;49}5051size_t ZSTD_DDict_dictSize(const ZSTD_DDict* ddict)52{53assert(ddict != NULL);54return ddict->dictSize;55}5657void ZSTD_copyDDictParameters(ZSTD_DCtx* dctx, const ZSTD_DDict* ddict)58{59DEBUGLOG(4, "ZSTD_copyDDictParameters");60assert(dctx != NULL);61assert(ddict != NULL);62dctx->dictID = ddict->dictID;63dctx->prefixStart = ddict->dictContent;64dctx->virtualStart = ddict->dictContent;65dctx->dictEnd = (const BYTE*)ddict->dictContent + ddict->dictSize;66dctx->previousDstEnd = dctx->dictEnd;67#ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION68dctx->dictContentBeginForFuzzing = dctx->prefixStart;69dctx->dictContentEndForFuzzing = dctx->previousDstEnd;70#endif71if (ddict->entropyPresent) {72dctx->litEntropy = 1;73dctx->fseEntropy = 1;74dctx->LLTptr = ddict->entropy.LLTable;75dctx->MLTptr = ddict->entropy.MLTable;76dctx->OFTptr = ddict->entropy.OFTable;77dctx->HUFptr = ddict->entropy.hufTable;78dctx->entropy.rep[0] = ddict->entropy.rep[0];79dctx->entropy.rep[1] = ddict->entropy.rep[1];80dctx->entropy.rep[2] = ddict->entropy.rep[2];81} else {82dctx->litEntropy = 0;83dctx->fseEntropy = 0;84}85}868788static size_t89ZSTD_loadEntropy_intoDDict(ZSTD_DDict* ddict,90ZSTD_dictContentType_e dictContentType)91{92ddict->dictID = 0;93ddict->entropyPresent = 0;94if (dictContentType == ZSTD_dct_rawContent) return 0;9596if (ddict->dictSize < 8) {97if (dictContentType == ZSTD_dct_fullDict)98return ERROR(dictionary_corrupted); /* only accept specified dictionaries */99return 0; /* pure content mode */100}101{ U32 const magic = MEM_readLE32(ddict->dictContent);102if (magic != ZSTD_MAGIC_DICTIONARY) {103if (dictContentType == ZSTD_dct_fullDict)104return ERROR(dictionary_corrupted); /* only accept specified dictionaries */105return 0; /* pure content mode */106}107}108ddict->dictID = MEM_readLE32((const char*)ddict->dictContent + ZSTD_FRAMEIDSIZE);109110/* load entropy tables */111RETURN_ERROR_IF(ZSTD_isError(ZSTD_loadDEntropy(112&ddict->entropy, ddict->dictContent, ddict->dictSize)),113dictionary_corrupted, "");114ddict->entropyPresent = 1;115return 0;116}117118119static size_t ZSTD_initDDict_internal(ZSTD_DDict* ddict,120const void* dict, size_t dictSize,121ZSTD_dictLoadMethod_e dictLoadMethod,122ZSTD_dictContentType_e dictContentType)123{124if ((dictLoadMethod == ZSTD_dlm_byRef) || (!dict) || (!dictSize)) {125ddict->dictBuffer = NULL;126ddict->dictContent = dict;127if (!dict) dictSize = 0;128} else {129void* const internalBuffer = ZSTD_customMalloc(dictSize, ddict->cMem);130ddict->dictBuffer = internalBuffer;131ddict->dictContent = internalBuffer;132if (!internalBuffer) return ERROR(memory_allocation);133ZSTD_memcpy(internalBuffer, dict, dictSize);134}135ddict->dictSize = dictSize;136ddict->entropy.hufTable[0] = (HUF_DTable)((ZSTD_HUFFDTABLE_CAPACITY_LOG)*0x1000001); /* cover both little and big endian */137138/* parse dictionary content */139FORWARD_IF_ERROR( ZSTD_loadEntropy_intoDDict(ddict, dictContentType) , "");140141return 0;142}143144ZSTD_DDict* ZSTD_createDDict_advanced(const void* dict, size_t dictSize,145ZSTD_dictLoadMethod_e dictLoadMethod,146ZSTD_dictContentType_e dictContentType,147ZSTD_customMem customMem)148{149if ((!customMem.customAlloc) ^ (!customMem.customFree)) return NULL;150151{ ZSTD_DDict* const ddict = (ZSTD_DDict*) ZSTD_customMalloc(sizeof(ZSTD_DDict), customMem);152if (ddict == NULL) return NULL;153ddict->cMem = customMem;154{ size_t const initResult = ZSTD_initDDict_internal(ddict,155dict, dictSize,156dictLoadMethod, dictContentType);157if (ZSTD_isError(initResult)) {158ZSTD_freeDDict(ddict);159return NULL;160} }161return ddict;162}163}164165/*! ZSTD_createDDict() :166* Create a digested dictionary, to start decompression without startup delay.167* `dict` content is copied inside DDict.168* Consequently, `dict` can be released after `ZSTD_DDict` creation */169ZSTD_DDict* ZSTD_createDDict(const void* dict, size_t dictSize)170{171ZSTD_customMem const allocator = { NULL, NULL, NULL };172return ZSTD_createDDict_advanced(dict, dictSize, ZSTD_dlm_byCopy, ZSTD_dct_auto, allocator);173}174175/*! ZSTD_createDDict_byReference() :176* Create a digested dictionary, to start decompression without startup delay.177* Dictionary content is simply referenced, it will be accessed during decompression.178* Warning : dictBuffer must outlive DDict (DDict must be freed before dictBuffer) */179ZSTD_DDict* ZSTD_createDDict_byReference(const void* dictBuffer, size_t dictSize)180{181ZSTD_customMem const allocator = { NULL, NULL, NULL };182return ZSTD_createDDict_advanced(dictBuffer, dictSize, ZSTD_dlm_byRef, ZSTD_dct_auto, allocator);183}184185186const ZSTD_DDict* ZSTD_initStaticDDict(187void* sBuffer, size_t sBufferSize,188const void* dict, size_t dictSize,189ZSTD_dictLoadMethod_e dictLoadMethod,190ZSTD_dictContentType_e dictContentType)191{192size_t const neededSpace = sizeof(ZSTD_DDict)193+ (dictLoadMethod == ZSTD_dlm_byRef ? 0 : dictSize);194ZSTD_DDict* const ddict = (ZSTD_DDict*)sBuffer;195assert(sBuffer != NULL);196assert(dict != NULL);197if ((size_t)sBuffer & 7) return NULL; /* 8-aligned */198if (sBufferSize < neededSpace) return NULL;199if (dictLoadMethod == ZSTD_dlm_byCopy) {200ZSTD_memcpy(ddict+1, dict, dictSize); /* local copy */201dict = ddict+1;202}203if (ZSTD_isError( ZSTD_initDDict_internal(ddict,204dict, dictSize,205ZSTD_dlm_byRef, dictContentType) ))206return NULL;207return ddict;208}209210211size_t ZSTD_freeDDict(ZSTD_DDict* ddict)212{213if (ddict==NULL) return 0; /* support free on NULL */214{ ZSTD_customMem const cMem = ddict->cMem;215ZSTD_customFree(ddict->dictBuffer, cMem);216ZSTD_customFree(ddict, cMem);217return 0;218}219}220221/*! ZSTD_estimateDDictSize() :222* Estimate amount of memory that will be needed to create a dictionary for decompression.223* Note : dictionary created by reference using ZSTD_dlm_byRef are smaller */224size_t ZSTD_estimateDDictSize(size_t dictSize, ZSTD_dictLoadMethod_e dictLoadMethod)225{226return sizeof(ZSTD_DDict) + (dictLoadMethod == ZSTD_dlm_byRef ? 0 : dictSize);227}228229size_t ZSTD_sizeof_DDict(const ZSTD_DDict* ddict)230{231if (ddict==NULL) return 0; /* support sizeof on NULL */232return sizeof(*ddict) + (ddict->dictBuffer ? ddict->dictSize : 0) ;233}234235/*! ZSTD_getDictID_fromDDict() :236* Provides the dictID of the dictionary loaded into `ddict`.237* If @return == 0, the dictionary is not conformant to Zstandard specification, or empty.238* Non-conformant dictionaries can still be loaded, but as content-only dictionaries. */239unsigned ZSTD_getDictID_fromDDict(const ZSTD_DDict* ddict)240{241if (ddict==NULL) return 0;242return ddict->dictID;243}244245246