18c2ecf20Sopenharmony_ci/** 28c2ecf20Sopenharmony_ci * Copyright (c) 2016-present, Yann Collet, Facebook, Inc. 38c2ecf20Sopenharmony_ci * All rights reserved. 48c2ecf20Sopenharmony_ci * 58c2ecf20Sopenharmony_ci * This source code is licensed under the BSD-style license found in the 68c2ecf20Sopenharmony_ci * LICENSE file in the root directory of https://github.com/facebook/zstd. 78c2ecf20Sopenharmony_ci * An additional grant of patent rights can be found in the PATENTS file in the 88c2ecf20Sopenharmony_ci * same directory. 98c2ecf20Sopenharmony_ci * 108c2ecf20Sopenharmony_ci * This program is free software; you can redistribute it and/or modify it under 118c2ecf20Sopenharmony_ci * the terms of the GNU General Public License version 2 as published by the 128c2ecf20Sopenharmony_ci * Free Software Foundation. This program is dual-licensed; you may select 138c2ecf20Sopenharmony_ci * either version 2 of the GNU General Public License ("GPL") or BSD license 148c2ecf20Sopenharmony_ci * ("BSD"). 158c2ecf20Sopenharmony_ci */ 168c2ecf20Sopenharmony_ci 178c2ecf20Sopenharmony_ci/* *************************************************************** 188c2ecf20Sopenharmony_ci* Tuning parameters 198c2ecf20Sopenharmony_ci*****************************************************************/ 208c2ecf20Sopenharmony_ci/*! 218c2ecf20Sopenharmony_ci* MAXWINDOWSIZE_DEFAULT : 228c2ecf20Sopenharmony_ci* maximum window size accepted by DStream, by default. 238c2ecf20Sopenharmony_ci* Frames requiring more memory will be rejected. 248c2ecf20Sopenharmony_ci*/ 258c2ecf20Sopenharmony_ci#ifndef ZSTD_MAXWINDOWSIZE_DEFAULT 268c2ecf20Sopenharmony_ci#define ZSTD_MAXWINDOWSIZE_DEFAULT ((1 << ZSTD_WINDOWLOG_MAX) + 1) /* defined within zstd.h */ 278c2ecf20Sopenharmony_ci#endif 288c2ecf20Sopenharmony_ci 298c2ecf20Sopenharmony_ci/*-******************************************************* 308c2ecf20Sopenharmony_ci* Dependencies 318c2ecf20Sopenharmony_ci*********************************************************/ 328c2ecf20Sopenharmony_ci#include "fse.h" 338c2ecf20Sopenharmony_ci#include "huf.h" 348c2ecf20Sopenharmony_ci#include "mem.h" /* low level memory routines */ 358c2ecf20Sopenharmony_ci#include "zstd_internal.h" 368c2ecf20Sopenharmony_ci#include <linux/kernel.h> 378c2ecf20Sopenharmony_ci#include <linux/module.h> 388c2ecf20Sopenharmony_ci#include <linux/string.h> /* memcpy, memmove, memset */ 398c2ecf20Sopenharmony_ci 408c2ecf20Sopenharmony_ci#define ZSTD_PREFETCH(ptr) __builtin_prefetch(ptr, 0, 0) 418c2ecf20Sopenharmony_ci 428c2ecf20Sopenharmony_ci/*-************************************* 438c2ecf20Sopenharmony_ci* Macros 448c2ecf20Sopenharmony_ci***************************************/ 458c2ecf20Sopenharmony_ci#define ZSTD_isError ERR_isError /* for inlining */ 468c2ecf20Sopenharmony_ci#define FSE_isError ERR_isError 478c2ecf20Sopenharmony_ci#define HUF_isError ERR_isError 488c2ecf20Sopenharmony_ci 498c2ecf20Sopenharmony_ci/*_******************************************************* 508c2ecf20Sopenharmony_ci* Memory operations 518c2ecf20Sopenharmony_ci**********************************************************/ 528c2ecf20Sopenharmony_cistatic void ZSTD_copy4(void *dst, const void *src) { memcpy(dst, src, 4); } 538c2ecf20Sopenharmony_ci 548c2ecf20Sopenharmony_ci/*-************************************************************* 558c2ecf20Sopenharmony_ci* Context management 568c2ecf20Sopenharmony_ci***************************************************************/ 578c2ecf20Sopenharmony_citypedef enum { 588c2ecf20Sopenharmony_ci ZSTDds_getFrameHeaderSize, 598c2ecf20Sopenharmony_ci ZSTDds_decodeFrameHeader, 608c2ecf20Sopenharmony_ci ZSTDds_decodeBlockHeader, 618c2ecf20Sopenharmony_ci ZSTDds_decompressBlock, 628c2ecf20Sopenharmony_ci ZSTDds_decompressLastBlock, 638c2ecf20Sopenharmony_ci ZSTDds_checkChecksum, 648c2ecf20Sopenharmony_ci ZSTDds_decodeSkippableHeader, 658c2ecf20Sopenharmony_ci ZSTDds_skipFrame 668c2ecf20Sopenharmony_ci} ZSTD_dStage; 678c2ecf20Sopenharmony_ci 688c2ecf20Sopenharmony_citypedef struct { 698c2ecf20Sopenharmony_ci FSE_DTable LLTable[FSE_DTABLE_SIZE_U32(LLFSELog)]; 708c2ecf20Sopenharmony_ci FSE_DTable OFTable[FSE_DTABLE_SIZE_U32(OffFSELog)]; 718c2ecf20Sopenharmony_ci FSE_DTable MLTable[FSE_DTABLE_SIZE_U32(MLFSELog)]; 728c2ecf20Sopenharmony_ci HUF_DTable hufTable[HUF_DTABLE_SIZE(HufLog)]; /* can accommodate HUF_decompress4X */ 738c2ecf20Sopenharmony_ci U64 workspace[HUF_DECOMPRESS_WORKSPACE_SIZE_U32 / 2]; 748c2ecf20Sopenharmony_ci U32 rep[ZSTD_REP_NUM]; 758c2ecf20Sopenharmony_ci} ZSTD_entropyTables_t; 768c2ecf20Sopenharmony_ci 778c2ecf20Sopenharmony_cistruct ZSTD_DCtx_s { 788c2ecf20Sopenharmony_ci const FSE_DTable *LLTptr; 798c2ecf20Sopenharmony_ci const FSE_DTable *MLTptr; 808c2ecf20Sopenharmony_ci const FSE_DTable *OFTptr; 818c2ecf20Sopenharmony_ci const HUF_DTable *HUFptr; 828c2ecf20Sopenharmony_ci ZSTD_entropyTables_t entropy; 838c2ecf20Sopenharmony_ci const void *previousDstEnd; /* detect continuity */ 848c2ecf20Sopenharmony_ci const void *base; /* start of curr segment */ 858c2ecf20Sopenharmony_ci const void *vBase; /* virtual start of previous segment if it was just before curr one */ 868c2ecf20Sopenharmony_ci const void *dictEnd; /* end of previous segment */ 878c2ecf20Sopenharmony_ci size_t expected; 888c2ecf20Sopenharmony_ci ZSTD_frameParams fParams; 898c2ecf20Sopenharmony_ci blockType_e bType; /* used in ZSTD_decompressContinue(), to transfer blockType between header decoding and block decoding stages */ 908c2ecf20Sopenharmony_ci ZSTD_dStage stage; 918c2ecf20Sopenharmony_ci U32 litEntropy; 928c2ecf20Sopenharmony_ci U32 fseEntropy; 938c2ecf20Sopenharmony_ci struct xxh64_state xxhState; 948c2ecf20Sopenharmony_ci size_t headerSize; 958c2ecf20Sopenharmony_ci U32 dictID; 968c2ecf20Sopenharmony_ci const BYTE *litPtr; 978c2ecf20Sopenharmony_ci ZSTD_customMem customMem; 988c2ecf20Sopenharmony_ci size_t litSize; 998c2ecf20Sopenharmony_ci size_t rleSize; 1008c2ecf20Sopenharmony_ci BYTE litBuffer[ZSTD_BLOCKSIZE_ABSOLUTEMAX + WILDCOPY_OVERLENGTH]; 1018c2ecf20Sopenharmony_ci BYTE headerBuffer[ZSTD_FRAMEHEADERSIZE_MAX]; 1028c2ecf20Sopenharmony_ci}; /* typedef'd to ZSTD_DCtx within "zstd.h" */ 1038c2ecf20Sopenharmony_ci 1048c2ecf20Sopenharmony_cisize_t ZSTD_DCtxWorkspaceBound(void) { return ZSTD_ALIGN(sizeof(ZSTD_stack)) + ZSTD_ALIGN(sizeof(ZSTD_DCtx)); } 1058c2ecf20Sopenharmony_ci 1068c2ecf20Sopenharmony_cisize_t ZSTD_decompressBegin(ZSTD_DCtx *dctx) 1078c2ecf20Sopenharmony_ci{ 1088c2ecf20Sopenharmony_ci dctx->expected = ZSTD_frameHeaderSize_prefix; 1098c2ecf20Sopenharmony_ci dctx->stage = ZSTDds_getFrameHeaderSize; 1108c2ecf20Sopenharmony_ci dctx->previousDstEnd = NULL; 1118c2ecf20Sopenharmony_ci dctx->base = NULL; 1128c2ecf20Sopenharmony_ci dctx->vBase = NULL; 1138c2ecf20Sopenharmony_ci dctx->dictEnd = NULL; 1148c2ecf20Sopenharmony_ci dctx->entropy.hufTable[0] = (HUF_DTable)((HufLog)*0x1000001); /* cover both little and big endian */ 1158c2ecf20Sopenharmony_ci dctx->litEntropy = dctx->fseEntropy = 0; 1168c2ecf20Sopenharmony_ci dctx->dictID = 0; 1178c2ecf20Sopenharmony_ci ZSTD_STATIC_ASSERT(sizeof(dctx->entropy.rep) == sizeof(repStartValue)); 1188c2ecf20Sopenharmony_ci memcpy(dctx->entropy.rep, repStartValue, sizeof(repStartValue)); /* initial repcodes */ 1198c2ecf20Sopenharmony_ci dctx->LLTptr = dctx->entropy.LLTable; 1208c2ecf20Sopenharmony_ci dctx->MLTptr = dctx->entropy.MLTable; 1218c2ecf20Sopenharmony_ci dctx->OFTptr = dctx->entropy.OFTable; 1228c2ecf20Sopenharmony_ci dctx->HUFptr = dctx->entropy.hufTable; 1238c2ecf20Sopenharmony_ci return 0; 1248c2ecf20Sopenharmony_ci} 1258c2ecf20Sopenharmony_ci 1268c2ecf20Sopenharmony_ciZSTD_DCtx *ZSTD_createDCtx_advanced(ZSTD_customMem customMem) 1278c2ecf20Sopenharmony_ci{ 1288c2ecf20Sopenharmony_ci ZSTD_DCtx *dctx; 1298c2ecf20Sopenharmony_ci 1308c2ecf20Sopenharmony_ci if (!customMem.customAlloc || !customMem.customFree) 1318c2ecf20Sopenharmony_ci return NULL; 1328c2ecf20Sopenharmony_ci 1338c2ecf20Sopenharmony_ci dctx = (ZSTD_DCtx *)ZSTD_malloc(sizeof(ZSTD_DCtx), customMem); 1348c2ecf20Sopenharmony_ci if (!dctx) 1358c2ecf20Sopenharmony_ci return NULL; 1368c2ecf20Sopenharmony_ci memcpy(&dctx->customMem, &customMem, sizeof(customMem)); 1378c2ecf20Sopenharmony_ci ZSTD_decompressBegin(dctx); 1388c2ecf20Sopenharmony_ci return dctx; 1398c2ecf20Sopenharmony_ci} 1408c2ecf20Sopenharmony_ci 1418c2ecf20Sopenharmony_ciZSTD_DCtx *ZSTD_initDCtx(void *workspace, size_t workspaceSize) 1428c2ecf20Sopenharmony_ci{ 1438c2ecf20Sopenharmony_ci ZSTD_customMem const stackMem = ZSTD_initStack(workspace, workspaceSize); 1448c2ecf20Sopenharmony_ci return ZSTD_createDCtx_advanced(stackMem); 1458c2ecf20Sopenharmony_ci} 1468c2ecf20Sopenharmony_ci 1478c2ecf20Sopenharmony_cisize_t ZSTD_freeDCtx(ZSTD_DCtx *dctx) 1488c2ecf20Sopenharmony_ci{ 1498c2ecf20Sopenharmony_ci if (dctx == NULL) 1508c2ecf20Sopenharmony_ci return 0; /* support free on NULL */ 1518c2ecf20Sopenharmony_ci ZSTD_free(dctx, dctx->customMem); 1528c2ecf20Sopenharmony_ci return 0; /* reserved as a potential error code in the future */ 1538c2ecf20Sopenharmony_ci} 1548c2ecf20Sopenharmony_ci 1558c2ecf20Sopenharmony_civoid ZSTD_copyDCtx(ZSTD_DCtx *dstDCtx, const ZSTD_DCtx *srcDCtx) 1568c2ecf20Sopenharmony_ci{ 1578c2ecf20Sopenharmony_ci size_t const workSpaceSize = (ZSTD_BLOCKSIZE_ABSOLUTEMAX + WILDCOPY_OVERLENGTH) + ZSTD_frameHeaderSize_max; 1588c2ecf20Sopenharmony_ci memcpy(dstDCtx, srcDCtx, sizeof(ZSTD_DCtx) - workSpaceSize); /* no need to copy workspace */ 1598c2ecf20Sopenharmony_ci} 1608c2ecf20Sopenharmony_ci 1618c2ecf20Sopenharmony_cistatic void ZSTD_refDDict(ZSTD_DCtx *dstDCtx, const ZSTD_DDict *ddict); 1628c2ecf20Sopenharmony_ci 1638c2ecf20Sopenharmony_ci/*-************************************************************* 1648c2ecf20Sopenharmony_ci* Decompression section 1658c2ecf20Sopenharmony_ci***************************************************************/ 1668c2ecf20Sopenharmony_ci 1678c2ecf20Sopenharmony_ci/*! ZSTD_isFrame() : 1688c2ecf20Sopenharmony_ci * Tells if the content of `buffer` starts with a valid Frame Identifier. 1698c2ecf20Sopenharmony_ci * Note : Frame Identifier is 4 bytes. If `size < 4`, @return will always be 0. 1708c2ecf20Sopenharmony_ci * Note 2 : Legacy Frame Identifiers are considered valid only if Legacy Support is enabled. 1718c2ecf20Sopenharmony_ci * Note 3 : Skippable Frame Identifiers are considered valid. */ 1728c2ecf20Sopenharmony_ciunsigned ZSTD_isFrame(const void *buffer, size_t size) 1738c2ecf20Sopenharmony_ci{ 1748c2ecf20Sopenharmony_ci if (size < 4) 1758c2ecf20Sopenharmony_ci return 0; 1768c2ecf20Sopenharmony_ci { 1778c2ecf20Sopenharmony_ci U32 const magic = ZSTD_readLE32(buffer); 1788c2ecf20Sopenharmony_ci if (magic == ZSTD_MAGICNUMBER) 1798c2ecf20Sopenharmony_ci return 1; 1808c2ecf20Sopenharmony_ci if ((magic & 0xFFFFFFF0U) == ZSTD_MAGIC_SKIPPABLE_START) 1818c2ecf20Sopenharmony_ci return 1; 1828c2ecf20Sopenharmony_ci } 1838c2ecf20Sopenharmony_ci return 0; 1848c2ecf20Sopenharmony_ci} 1858c2ecf20Sopenharmony_ci 1868c2ecf20Sopenharmony_ci/** ZSTD_frameHeaderSize() : 1878c2ecf20Sopenharmony_ci* srcSize must be >= ZSTD_frameHeaderSize_prefix. 1888c2ecf20Sopenharmony_ci* @return : size of the Frame Header */ 1898c2ecf20Sopenharmony_cistatic size_t ZSTD_frameHeaderSize(const void *src, size_t srcSize) 1908c2ecf20Sopenharmony_ci{ 1918c2ecf20Sopenharmony_ci if (srcSize < ZSTD_frameHeaderSize_prefix) 1928c2ecf20Sopenharmony_ci return ERROR(srcSize_wrong); 1938c2ecf20Sopenharmony_ci { 1948c2ecf20Sopenharmony_ci BYTE const fhd = ((const BYTE *)src)[4]; 1958c2ecf20Sopenharmony_ci U32 const dictID = fhd & 3; 1968c2ecf20Sopenharmony_ci U32 const singleSegment = (fhd >> 5) & 1; 1978c2ecf20Sopenharmony_ci U32 const fcsId = fhd >> 6; 1988c2ecf20Sopenharmony_ci return ZSTD_frameHeaderSize_prefix + !singleSegment + ZSTD_did_fieldSize[dictID] + ZSTD_fcs_fieldSize[fcsId] + (singleSegment && !fcsId); 1998c2ecf20Sopenharmony_ci } 2008c2ecf20Sopenharmony_ci} 2018c2ecf20Sopenharmony_ci 2028c2ecf20Sopenharmony_ci/** ZSTD_getFrameParams() : 2038c2ecf20Sopenharmony_ci* decode Frame Header, or require larger `srcSize`. 2048c2ecf20Sopenharmony_ci* @return : 0, `fparamsPtr` is correctly filled, 2058c2ecf20Sopenharmony_ci* >0, `srcSize` is too small, result is expected `srcSize`, 2068c2ecf20Sopenharmony_ci* or an error code, which can be tested using ZSTD_isError() */ 2078c2ecf20Sopenharmony_cisize_t ZSTD_getFrameParams(ZSTD_frameParams *fparamsPtr, const void *src, size_t srcSize) 2088c2ecf20Sopenharmony_ci{ 2098c2ecf20Sopenharmony_ci const BYTE *ip = (const BYTE *)src; 2108c2ecf20Sopenharmony_ci 2118c2ecf20Sopenharmony_ci if (srcSize < ZSTD_frameHeaderSize_prefix) 2128c2ecf20Sopenharmony_ci return ZSTD_frameHeaderSize_prefix; 2138c2ecf20Sopenharmony_ci if (ZSTD_readLE32(src) != ZSTD_MAGICNUMBER) { 2148c2ecf20Sopenharmony_ci if ((ZSTD_readLE32(src) & 0xFFFFFFF0U) == ZSTD_MAGIC_SKIPPABLE_START) { 2158c2ecf20Sopenharmony_ci if (srcSize < ZSTD_skippableHeaderSize) 2168c2ecf20Sopenharmony_ci return ZSTD_skippableHeaderSize; /* magic number + skippable frame length */ 2178c2ecf20Sopenharmony_ci memset(fparamsPtr, 0, sizeof(*fparamsPtr)); 2188c2ecf20Sopenharmony_ci fparamsPtr->frameContentSize = ZSTD_readLE32((const char *)src + 4); 2198c2ecf20Sopenharmony_ci fparamsPtr->windowSize = 0; /* windowSize==0 means a frame is skippable */ 2208c2ecf20Sopenharmony_ci return 0; 2218c2ecf20Sopenharmony_ci } 2228c2ecf20Sopenharmony_ci return ERROR(prefix_unknown); 2238c2ecf20Sopenharmony_ci } 2248c2ecf20Sopenharmony_ci 2258c2ecf20Sopenharmony_ci /* ensure there is enough `srcSize` to fully read/decode frame header */ 2268c2ecf20Sopenharmony_ci { 2278c2ecf20Sopenharmony_ci size_t const fhsize = ZSTD_frameHeaderSize(src, srcSize); 2288c2ecf20Sopenharmony_ci if (srcSize < fhsize) 2298c2ecf20Sopenharmony_ci return fhsize; 2308c2ecf20Sopenharmony_ci } 2318c2ecf20Sopenharmony_ci 2328c2ecf20Sopenharmony_ci { 2338c2ecf20Sopenharmony_ci BYTE const fhdByte = ip[4]; 2348c2ecf20Sopenharmony_ci size_t pos = 5; 2358c2ecf20Sopenharmony_ci U32 const dictIDSizeCode = fhdByte & 3; 2368c2ecf20Sopenharmony_ci U32 const checksumFlag = (fhdByte >> 2) & 1; 2378c2ecf20Sopenharmony_ci U32 const singleSegment = (fhdByte >> 5) & 1; 2388c2ecf20Sopenharmony_ci U32 const fcsID = fhdByte >> 6; 2398c2ecf20Sopenharmony_ci U32 const windowSizeMax = 1U << ZSTD_WINDOWLOG_MAX; 2408c2ecf20Sopenharmony_ci U32 windowSize = 0; 2418c2ecf20Sopenharmony_ci U32 dictID = 0; 2428c2ecf20Sopenharmony_ci U64 frameContentSize = 0; 2438c2ecf20Sopenharmony_ci if ((fhdByte & 0x08) != 0) 2448c2ecf20Sopenharmony_ci return ERROR(frameParameter_unsupported); /* reserved bits, which must be zero */ 2458c2ecf20Sopenharmony_ci if (!singleSegment) { 2468c2ecf20Sopenharmony_ci BYTE const wlByte = ip[pos++]; 2478c2ecf20Sopenharmony_ci U32 const windowLog = (wlByte >> 3) + ZSTD_WINDOWLOG_ABSOLUTEMIN; 2488c2ecf20Sopenharmony_ci if (windowLog > ZSTD_WINDOWLOG_MAX) 2498c2ecf20Sopenharmony_ci return ERROR(frameParameter_windowTooLarge); /* avoids issue with 1 << windowLog */ 2508c2ecf20Sopenharmony_ci windowSize = (1U << windowLog); 2518c2ecf20Sopenharmony_ci windowSize += (windowSize >> 3) * (wlByte & 7); 2528c2ecf20Sopenharmony_ci } 2538c2ecf20Sopenharmony_ci 2548c2ecf20Sopenharmony_ci switch (dictIDSizeCode) { 2558c2ecf20Sopenharmony_ci default: /* impossible */ 2568c2ecf20Sopenharmony_ci case 0: break; 2578c2ecf20Sopenharmony_ci case 1: 2588c2ecf20Sopenharmony_ci dictID = ip[pos]; 2598c2ecf20Sopenharmony_ci pos++; 2608c2ecf20Sopenharmony_ci break; 2618c2ecf20Sopenharmony_ci case 2: 2628c2ecf20Sopenharmony_ci dictID = ZSTD_readLE16(ip + pos); 2638c2ecf20Sopenharmony_ci pos += 2; 2648c2ecf20Sopenharmony_ci break; 2658c2ecf20Sopenharmony_ci case 3: 2668c2ecf20Sopenharmony_ci dictID = ZSTD_readLE32(ip + pos); 2678c2ecf20Sopenharmony_ci pos += 4; 2688c2ecf20Sopenharmony_ci break; 2698c2ecf20Sopenharmony_ci } 2708c2ecf20Sopenharmony_ci switch (fcsID) { 2718c2ecf20Sopenharmony_ci default: /* impossible */ 2728c2ecf20Sopenharmony_ci case 0: 2738c2ecf20Sopenharmony_ci if (singleSegment) 2748c2ecf20Sopenharmony_ci frameContentSize = ip[pos]; 2758c2ecf20Sopenharmony_ci break; 2768c2ecf20Sopenharmony_ci case 1: frameContentSize = ZSTD_readLE16(ip + pos) + 256; break; 2778c2ecf20Sopenharmony_ci case 2: frameContentSize = ZSTD_readLE32(ip + pos); break; 2788c2ecf20Sopenharmony_ci case 3: frameContentSize = ZSTD_readLE64(ip + pos); break; 2798c2ecf20Sopenharmony_ci } 2808c2ecf20Sopenharmony_ci if (!windowSize) 2818c2ecf20Sopenharmony_ci windowSize = (U32)frameContentSize; 2828c2ecf20Sopenharmony_ci if (windowSize > windowSizeMax) 2838c2ecf20Sopenharmony_ci return ERROR(frameParameter_windowTooLarge); 2848c2ecf20Sopenharmony_ci fparamsPtr->frameContentSize = frameContentSize; 2858c2ecf20Sopenharmony_ci fparamsPtr->windowSize = windowSize; 2868c2ecf20Sopenharmony_ci fparamsPtr->dictID = dictID; 2878c2ecf20Sopenharmony_ci fparamsPtr->checksumFlag = checksumFlag; 2888c2ecf20Sopenharmony_ci } 2898c2ecf20Sopenharmony_ci return 0; 2908c2ecf20Sopenharmony_ci} 2918c2ecf20Sopenharmony_ci 2928c2ecf20Sopenharmony_ci/** ZSTD_getFrameContentSize() : 2938c2ecf20Sopenharmony_ci* compatible with legacy mode 2948c2ecf20Sopenharmony_ci* @return : decompressed size of the single frame pointed to be `src` if known, otherwise 2958c2ecf20Sopenharmony_ci* - ZSTD_CONTENTSIZE_UNKNOWN if the size cannot be determined 2968c2ecf20Sopenharmony_ci* - ZSTD_CONTENTSIZE_ERROR if an error occurred (e.g. invalid magic number, srcSize too small) */ 2978c2ecf20Sopenharmony_ciunsigned long long ZSTD_getFrameContentSize(const void *src, size_t srcSize) 2988c2ecf20Sopenharmony_ci{ 2998c2ecf20Sopenharmony_ci { 3008c2ecf20Sopenharmony_ci ZSTD_frameParams fParams; 3018c2ecf20Sopenharmony_ci if (ZSTD_getFrameParams(&fParams, src, srcSize) != 0) 3028c2ecf20Sopenharmony_ci return ZSTD_CONTENTSIZE_ERROR; 3038c2ecf20Sopenharmony_ci if (fParams.windowSize == 0) { 3048c2ecf20Sopenharmony_ci /* Either skippable or empty frame, size == 0 either way */ 3058c2ecf20Sopenharmony_ci return 0; 3068c2ecf20Sopenharmony_ci } else if (fParams.frameContentSize != 0) { 3078c2ecf20Sopenharmony_ci return fParams.frameContentSize; 3088c2ecf20Sopenharmony_ci } else { 3098c2ecf20Sopenharmony_ci return ZSTD_CONTENTSIZE_UNKNOWN; 3108c2ecf20Sopenharmony_ci } 3118c2ecf20Sopenharmony_ci } 3128c2ecf20Sopenharmony_ci} 3138c2ecf20Sopenharmony_ci 3148c2ecf20Sopenharmony_ci/** ZSTD_findDecompressedSize() : 3158c2ecf20Sopenharmony_ci * compatible with legacy mode 3168c2ecf20Sopenharmony_ci * `srcSize` must be the exact length of some number of ZSTD compressed and/or 3178c2ecf20Sopenharmony_ci * skippable frames 3188c2ecf20Sopenharmony_ci * @return : decompressed size of the frames contained */ 3198c2ecf20Sopenharmony_ciunsigned long long ZSTD_findDecompressedSize(const void *src, size_t srcSize) 3208c2ecf20Sopenharmony_ci{ 3218c2ecf20Sopenharmony_ci { 3228c2ecf20Sopenharmony_ci unsigned long long totalDstSize = 0; 3238c2ecf20Sopenharmony_ci while (srcSize >= ZSTD_frameHeaderSize_prefix) { 3248c2ecf20Sopenharmony_ci const U32 magicNumber = ZSTD_readLE32(src); 3258c2ecf20Sopenharmony_ci 3268c2ecf20Sopenharmony_ci if ((magicNumber & 0xFFFFFFF0U) == ZSTD_MAGIC_SKIPPABLE_START) { 3278c2ecf20Sopenharmony_ci size_t skippableSize; 3288c2ecf20Sopenharmony_ci if (srcSize < ZSTD_skippableHeaderSize) 3298c2ecf20Sopenharmony_ci return ERROR(srcSize_wrong); 3308c2ecf20Sopenharmony_ci skippableSize = ZSTD_readLE32((const BYTE *)src + 4) + ZSTD_skippableHeaderSize; 3318c2ecf20Sopenharmony_ci if (srcSize < skippableSize) { 3328c2ecf20Sopenharmony_ci return ZSTD_CONTENTSIZE_ERROR; 3338c2ecf20Sopenharmony_ci } 3348c2ecf20Sopenharmony_ci 3358c2ecf20Sopenharmony_ci src = (const BYTE *)src + skippableSize; 3368c2ecf20Sopenharmony_ci srcSize -= skippableSize; 3378c2ecf20Sopenharmony_ci continue; 3388c2ecf20Sopenharmony_ci } 3398c2ecf20Sopenharmony_ci 3408c2ecf20Sopenharmony_ci { 3418c2ecf20Sopenharmony_ci unsigned long long const ret = ZSTD_getFrameContentSize(src, srcSize); 3428c2ecf20Sopenharmony_ci if (ret >= ZSTD_CONTENTSIZE_ERROR) 3438c2ecf20Sopenharmony_ci return ret; 3448c2ecf20Sopenharmony_ci 3458c2ecf20Sopenharmony_ci /* check for overflow */ 3468c2ecf20Sopenharmony_ci if (totalDstSize + ret < totalDstSize) 3478c2ecf20Sopenharmony_ci return ZSTD_CONTENTSIZE_ERROR; 3488c2ecf20Sopenharmony_ci totalDstSize += ret; 3498c2ecf20Sopenharmony_ci } 3508c2ecf20Sopenharmony_ci { 3518c2ecf20Sopenharmony_ci size_t const frameSrcSize = ZSTD_findFrameCompressedSize(src, srcSize); 3528c2ecf20Sopenharmony_ci if (ZSTD_isError(frameSrcSize)) { 3538c2ecf20Sopenharmony_ci return ZSTD_CONTENTSIZE_ERROR; 3548c2ecf20Sopenharmony_ci } 3558c2ecf20Sopenharmony_ci 3568c2ecf20Sopenharmony_ci src = (const BYTE *)src + frameSrcSize; 3578c2ecf20Sopenharmony_ci srcSize -= frameSrcSize; 3588c2ecf20Sopenharmony_ci } 3598c2ecf20Sopenharmony_ci } 3608c2ecf20Sopenharmony_ci 3618c2ecf20Sopenharmony_ci if (srcSize) { 3628c2ecf20Sopenharmony_ci return ZSTD_CONTENTSIZE_ERROR; 3638c2ecf20Sopenharmony_ci } 3648c2ecf20Sopenharmony_ci 3658c2ecf20Sopenharmony_ci return totalDstSize; 3668c2ecf20Sopenharmony_ci } 3678c2ecf20Sopenharmony_ci} 3688c2ecf20Sopenharmony_ci 3698c2ecf20Sopenharmony_ci/** ZSTD_decodeFrameHeader() : 3708c2ecf20Sopenharmony_ci* `headerSize` must be the size provided by ZSTD_frameHeaderSize(). 3718c2ecf20Sopenharmony_ci* @return : 0 if success, or an error code, which can be tested using ZSTD_isError() */ 3728c2ecf20Sopenharmony_cistatic size_t ZSTD_decodeFrameHeader(ZSTD_DCtx *dctx, const void *src, size_t headerSize) 3738c2ecf20Sopenharmony_ci{ 3748c2ecf20Sopenharmony_ci size_t const result = ZSTD_getFrameParams(&(dctx->fParams), src, headerSize); 3758c2ecf20Sopenharmony_ci if (ZSTD_isError(result)) 3768c2ecf20Sopenharmony_ci return result; /* invalid header */ 3778c2ecf20Sopenharmony_ci if (result > 0) 3788c2ecf20Sopenharmony_ci return ERROR(srcSize_wrong); /* headerSize too small */ 3798c2ecf20Sopenharmony_ci if (dctx->fParams.dictID && (dctx->dictID != dctx->fParams.dictID)) 3808c2ecf20Sopenharmony_ci return ERROR(dictionary_wrong); 3818c2ecf20Sopenharmony_ci if (dctx->fParams.checksumFlag) 3828c2ecf20Sopenharmony_ci xxh64_reset(&dctx->xxhState, 0); 3838c2ecf20Sopenharmony_ci return 0; 3848c2ecf20Sopenharmony_ci} 3858c2ecf20Sopenharmony_ci 3868c2ecf20Sopenharmony_citypedef struct { 3878c2ecf20Sopenharmony_ci blockType_e blockType; 3888c2ecf20Sopenharmony_ci U32 lastBlock; 3898c2ecf20Sopenharmony_ci U32 origSize; 3908c2ecf20Sopenharmony_ci} blockProperties_t; 3918c2ecf20Sopenharmony_ci 3928c2ecf20Sopenharmony_ci/*! ZSTD_getcBlockSize() : 3938c2ecf20Sopenharmony_ci* Provides the size of compressed block from block header `src` */ 3948c2ecf20Sopenharmony_cisize_t ZSTD_getcBlockSize(const void *src, size_t srcSize, blockProperties_t *bpPtr) 3958c2ecf20Sopenharmony_ci{ 3968c2ecf20Sopenharmony_ci if (srcSize < ZSTD_blockHeaderSize) 3978c2ecf20Sopenharmony_ci return ERROR(srcSize_wrong); 3988c2ecf20Sopenharmony_ci { 3998c2ecf20Sopenharmony_ci U32 const cBlockHeader = ZSTD_readLE24(src); 4008c2ecf20Sopenharmony_ci U32 const cSize = cBlockHeader >> 3; 4018c2ecf20Sopenharmony_ci bpPtr->lastBlock = cBlockHeader & 1; 4028c2ecf20Sopenharmony_ci bpPtr->blockType = (blockType_e)((cBlockHeader >> 1) & 3); 4038c2ecf20Sopenharmony_ci bpPtr->origSize = cSize; /* only useful for RLE */ 4048c2ecf20Sopenharmony_ci if (bpPtr->blockType == bt_rle) 4058c2ecf20Sopenharmony_ci return 1; 4068c2ecf20Sopenharmony_ci if (bpPtr->blockType == bt_reserved) 4078c2ecf20Sopenharmony_ci return ERROR(corruption_detected); 4088c2ecf20Sopenharmony_ci return cSize; 4098c2ecf20Sopenharmony_ci } 4108c2ecf20Sopenharmony_ci} 4118c2ecf20Sopenharmony_ci 4128c2ecf20Sopenharmony_cistatic size_t ZSTD_copyRawBlock(void *dst, size_t dstCapacity, const void *src, size_t srcSize) 4138c2ecf20Sopenharmony_ci{ 4148c2ecf20Sopenharmony_ci if (srcSize > dstCapacity) 4158c2ecf20Sopenharmony_ci return ERROR(dstSize_tooSmall); 4168c2ecf20Sopenharmony_ci memcpy(dst, src, srcSize); 4178c2ecf20Sopenharmony_ci return srcSize; 4188c2ecf20Sopenharmony_ci} 4198c2ecf20Sopenharmony_ci 4208c2ecf20Sopenharmony_cistatic size_t ZSTD_setRleBlock(void *dst, size_t dstCapacity, const void *src, size_t srcSize, size_t regenSize) 4218c2ecf20Sopenharmony_ci{ 4228c2ecf20Sopenharmony_ci if (srcSize != 1) 4238c2ecf20Sopenharmony_ci return ERROR(srcSize_wrong); 4248c2ecf20Sopenharmony_ci if (regenSize > dstCapacity) 4258c2ecf20Sopenharmony_ci return ERROR(dstSize_tooSmall); 4268c2ecf20Sopenharmony_ci memset(dst, *(const BYTE *)src, regenSize); 4278c2ecf20Sopenharmony_ci return regenSize; 4288c2ecf20Sopenharmony_ci} 4298c2ecf20Sopenharmony_ci 4308c2ecf20Sopenharmony_ci/*! ZSTD_decodeLiteralsBlock() : 4318c2ecf20Sopenharmony_ci @return : nb of bytes read from src (< srcSize ) */ 4328c2ecf20Sopenharmony_cisize_t ZSTD_decodeLiteralsBlock(ZSTD_DCtx *dctx, const void *src, size_t srcSize) /* note : srcSize < BLOCKSIZE */ 4338c2ecf20Sopenharmony_ci{ 4348c2ecf20Sopenharmony_ci if (srcSize < MIN_CBLOCK_SIZE) 4358c2ecf20Sopenharmony_ci return ERROR(corruption_detected); 4368c2ecf20Sopenharmony_ci 4378c2ecf20Sopenharmony_ci { 4388c2ecf20Sopenharmony_ci const BYTE *const istart = (const BYTE *)src; 4398c2ecf20Sopenharmony_ci symbolEncodingType_e const litEncType = (symbolEncodingType_e)(istart[0] & 3); 4408c2ecf20Sopenharmony_ci 4418c2ecf20Sopenharmony_ci switch (litEncType) { 4428c2ecf20Sopenharmony_ci case set_repeat: 4438c2ecf20Sopenharmony_ci if (dctx->litEntropy == 0) 4448c2ecf20Sopenharmony_ci return ERROR(dictionary_corrupted); 4458c2ecf20Sopenharmony_ci /* fall through */ 4468c2ecf20Sopenharmony_ci case set_compressed: 4478c2ecf20Sopenharmony_ci if (srcSize < 5) 4488c2ecf20Sopenharmony_ci return ERROR(corruption_detected); /* srcSize >= MIN_CBLOCK_SIZE == 3; here we need up to 5 for case 3 */ 4498c2ecf20Sopenharmony_ci { 4508c2ecf20Sopenharmony_ci size_t lhSize, litSize, litCSize; 4518c2ecf20Sopenharmony_ci U32 singleStream = 0; 4528c2ecf20Sopenharmony_ci U32 const lhlCode = (istart[0] >> 2) & 3; 4538c2ecf20Sopenharmony_ci U32 const lhc = ZSTD_readLE32(istart); 4548c2ecf20Sopenharmony_ci switch (lhlCode) { 4558c2ecf20Sopenharmony_ci case 0: 4568c2ecf20Sopenharmony_ci case 1: 4578c2ecf20Sopenharmony_ci default: /* note : default is impossible, since lhlCode into [0..3] */ 4588c2ecf20Sopenharmony_ci /* 2 - 2 - 10 - 10 */ 4598c2ecf20Sopenharmony_ci singleStream = !lhlCode; 4608c2ecf20Sopenharmony_ci lhSize = 3; 4618c2ecf20Sopenharmony_ci litSize = (lhc >> 4) & 0x3FF; 4628c2ecf20Sopenharmony_ci litCSize = (lhc >> 14) & 0x3FF; 4638c2ecf20Sopenharmony_ci break; 4648c2ecf20Sopenharmony_ci case 2: 4658c2ecf20Sopenharmony_ci /* 2 - 2 - 14 - 14 */ 4668c2ecf20Sopenharmony_ci lhSize = 4; 4678c2ecf20Sopenharmony_ci litSize = (lhc >> 4) & 0x3FFF; 4688c2ecf20Sopenharmony_ci litCSize = lhc >> 18; 4698c2ecf20Sopenharmony_ci break; 4708c2ecf20Sopenharmony_ci case 3: 4718c2ecf20Sopenharmony_ci /* 2 - 2 - 18 - 18 */ 4728c2ecf20Sopenharmony_ci lhSize = 5; 4738c2ecf20Sopenharmony_ci litSize = (lhc >> 4) & 0x3FFFF; 4748c2ecf20Sopenharmony_ci litCSize = (lhc >> 22) + (istart[4] << 10); 4758c2ecf20Sopenharmony_ci break; 4768c2ecf20Sopenharmony_ci } 4778c2ecf20Sopenharmony_ci if (litSize > ZSTD_BLOCKSIZE_ABSOLUTEMAX) 4788c2ecf20Sopenharmony_ci return ERROR(corruption_detected); 4798c2ecf20Sopenharmony_ci if (litCSize + lhSize > srcSize) 4808c2ecf20Sopenharmony_ci return ERROR(corruption_detected); 4818c2ecf20Sopenharmony_ci 4828c2ecf20Sopenharmony_ci if (HUF_isError( 4838c2ecf20Sopenharmony_ci (litEncType == set_repeat) 4848c2ecf20Sopenharmony_ci ? (singleStream ? HUF_decompress1X_usingDTable(dctx->litBuffer, litSize, istart + lhSize, litCSize, dctx->HUFptr) 4858c2ecf20Sopenharmony_ci : HUF_decompress4X_usingDTable(dctx->litBuffer, litSize, istart + lhSize, litCSize, dctx->HUFptr)) 4868c2ecf20Sopenharmony_ci : (singleStream 4878c2ecf20Sopenharmony_ci ? HUF_decompress1X2_DCtx_wksp(dctx->entropy.hufTable, dctx->litBuffer, litSize, istart + lhSize, litCSize, 4888c2ecf20Sopenharmony_ci dctx->entropy.workspace, sizeof(dctx->entropy.workspace)) 4898c2ecf20Sopenharmony_ci : HUF_decompress4X_hufOnly_wksp(dctx->entropy.hufTable, dctx->litBuffer, litSize, istart + lhSize, litCSize, 4908c2ecf20Sopenharmony_ci dctx->entropy.workspace, sizeof(dctx->entropy.workspace))))) 4918c2ecf20Sopenharmony_ci return ERROR(corruption_detected); 4928c2ecf20Sopenharmony_ci 4938c2ecf20Sopenharmony_ci dctx->litPtr = dctx->litBuffer; 4948c2ecf20Sopenharmony_ci dctx->litSize = litSize; 4958c2ecf20Sopenharmony_ci dctx->litEntropy = 1; 4968c2ecf20Sopenharmony_ci if (litEncType == set_compressed) 4978c2ecf20Sopenharmony_ci dctx->HUFptr = dctx->entropy.hufTable; 4988c2ecf20Sopenharmony_ci memset(dctx->litBuffer + dctx->litSize, 0, WILDCOPY_OVERLENGTH); 4998c2ecf20Sopenharmony_ci return litCSize + lhSize; 5008c2ecf20Sopenharmony_ci } 5018c2ecf20Sopenharmony_ci 5028c2ecf20Sopenharmony_ci case set_basic: { 5038c2ecf20Sopenharmony_ci size_t litSize, lhSize; 5048c2ecf20Sopenharmony_ci U32 const lhlCode = ((istart[0]) >> 2) & 3; 5058c2ecf20Sopenharmony_ci switch (lhlCode) { 5068c2ecf20Sopenharmony_ci case 0: 5078c2ecf20Sopenharmony_ci case 2: 5088c2ecf20Sopenharmony_ci default: /* note : default is impossible, since lhlCode into [0..3] */ 5098c2ecf20Sopenharmony_ci lhSize = 1; 5108c2ecf20Sopenharmony_ci litSize = istart[0] >> 3; 5118c2ecf20Sopenharmony_ci break; 5128c2ecf20Sopenharmony_ci case 1: 5138c2ecf20Sopenharmony_ci lhSize = 2; 5148c2ecf20Sopenharmony_ci litSize = ZSTD_readLE16(istart) >> 4; 5158c2ecf20Sopenharmony_ci break; 5168c2ecf20Sopenharmony_ci case 3: 5178c2ecf20Sopenharmony_ci lhSize = 3; 5188c2ecf20Sopenharmony_ci litSize = ZSTD_readLE24(istart) >> 4; 5198c2ecf20Sopenharmony_ci break; 5208c2ecf20Sopenharmony_ci } 5218c2ecf20Sopenharmony_ci 5228c2ecf20Sopenharmony_ci if (lhSize + litSize + WILDCOPY_OVERLENGTH > srcSize) { /* risk reading beyond src buffer with wildcopy */ 5238c2ecf20Sopenharmony_ci if (litSize + lhSize > srcSize) 5248c2ecf20Sopenharmony_ci return ERROR(corruption_detected); 5258c2ecf20Sopenharmony_ci memcpy(dctx->litBuffer, istart + lhSize, litSize); 5268c2ecf20Sopenharmony_ci dctx->litPtr = dctx->litBuffer; 5278c2ecf20Sopenharmony_ci dctx->litSize = litSize; 5288c2ecf20Sopenharmony_ci memset(dctx->litBuffer + dctx->litSize, 0, WILDCOPY_OVERLENGTH); 5298c2ecf20Sopenharmony_ci return lhSize + litSize; 5308c2ecf20Sopenharmony_ci } 5318c2ecf20Sopenharmony_ci /* direct reference into compressed stream */ 5328c2ecf20Sopenharmony_ci dctx->litPtr = istart + lhSize; 5338c2ecf20Sopenharmony_ci dctx->litSize = litSize; 5348c2ecf20Sopenharmony_ci return lhSize + litSize; 5358c2ecf20Sopenharmony_ci } 5368c2ecf20Sopenharmony_ci 5378c2ecf20Sopenharmony_ci case set_rle: { 5388c2ecf20Sopenharmony_ci U32 const lhlCode = ((istart[0]) >> 2) & 3; 5398c2ecf20Sopenharmony_ci size_t litSize, lhSize; 5408c2ecf20Sopenharmony_ci switch (lhlCode) { 5418c2ecf20Sopenharmony_ci case 0: 5428c2ecf20Sopenharmony_ci case 2: 5438c2ecf20Sopenharmony_ci default: /* note : default is impossible, since lhlCode into [0..3] */ 5448c2ecf20Sopenharmony_ci lhSize = 1; 5458c2ecf20Sopenharmony_ci litSize = istart[0] >> 3; 5468c2ecf20Sopenharmony_ci break; 5478c2ecf20Sopenharmony_ci case 1: 5488c2ecf20Sopenharmony_ci lhSize = 2; 5498c2ecf20Sopenharmony_ci litSize = ZSTD_readLE16(istart) >> 4; 5508c2ecf20Sopenharmony_ci break; 5518c2ecf20Sopenharmony_ci case 3: 5528c2ecf20Sopenharmony_ci lhSize = 3; 5538c2ecf20Sopenharmony_ci litSize = ZSTD_readLE24(istart) >> 4; 5548c2ecf20Sopenharmony_ci if (srcSize < 4) 5558c2ecf20Sopenharmony_ci return ERROR(corruption_detected); /* srcSize >= MIN_CBLOCK_SIZE == 3; here we need lhSize+1 = 4 */ 5568c2ecf20Sopenharmony_ci break; 5578c2ecf20Sopenharmony_ci } 5588c2ecf20Sopenharmony_ci if (litSize > ZSTD_BLOCKSIZE_ABSOLUTEMAX) 5598c2ecf20Sopenharmony_ci return ERROR(corruption_detected); 5608c2ecf20Sopenharmony_ci memset(dctx->litBuffer, istart[lhSize], litSize + WILDCOPY_OVERLENGTH); 5618c2ecf20Sopenharmony_ci dctx->litPtr = dctx->litBuffer; 5628c2ecf20Sopenharmony_ci dctx->litSize = litSize; 5638c2ecf20Sopenharmony_ci return lhSize + 1; 5648c2ecf20Sopenharmony_ci } 5658c2ecf20Sopenharmony_ci default: 5668c2ecf20Sopenharmony_ci return ERROR(corruption_detected); /* impossible */ 5678c2ecf20Sopenharmony_ci } 5688c2ecf20Sopenharmony_ci } 5698c2ecf20Sopenharmony_ci} 5708c2ecf20Sopenharmony_ci 5718c2ecf20Sopenharmony_citypedef union { 5728c2ecf20Sopenharmony_ci FSE_decode_t realData; 5738c2ecf20Sopenharmony_ci U32 alignedBy4; 5748c2ecf20Sopenharmony_ci} FSE_decode_t4; 5758c2ecf20Sopenharmony_ci 5768c2ecf20Sopenharmony_cistatic const FSE_decode_t4 LL_defaultDTable[(1 << LL_DEFAULTNORMLOG) + 1] = { 5778c2ecf20Sopenharmony_ci {{LL_DEFAULTNORMLOG, 1, 1}}, /* header : tableLog, fastMode, fastMode */ 5788c2ecf20Sopenharmony_ci {{0, 0, 4}}, /* 0 : base, symbol, bits */ 5798c2ecf20Sopenharmony_ci {{16, 0, 4}}, 5808c2ecf20Sopenharmony_ci {{32, 1, 5}}, 5818c2ecf20Sopenharmony_ci {{0, 3, 5}}, 5828c2ecf20Sopenharmony_ci {{0, 4, 5}}, 5838c2ecf20Sopenharmony_ci {{0, 6, 5}}, 5848c2ecf20Sopenharmony_ci {{0, 7, 5}}, 5858c2ecf20Sopenharmony_ci {{0, 9, 5}}, 5868c2ecf20Sopenharmony_ci {{0, 10, 5}}, 5878c2ecf20Sopenharmony_ci {{0, 12, 5}}, 5888c2ecf20Sopenharmony_ci {{0, 14, 6}}, 5898c2ecf20Sopenharmony_ci {{0, 16, 5}}, 5908c2ecf20Sopenharmony_ci {{0, 18, 5}}, 5918c2ecf20Sopenharmony_ci {{0, 19, 5}}, 5928c2ecf20Sopenharmony_ci {{0, 21, 5}}, 5938c2ecf20Sopenharmony_ci {{0, 22, 5}}, 5948c2ecf20Sopenharmony_ci {{0, 24, 5}}, 5958c2ecf20Sopenharmony_ci {{32, 25, 5}}, 5968c2ecf20Sopenharmony_ci {{0, 26, 5}}, 5978c2ecf20Sopenharmony_ci {{0, 27, 6}}, 5988c2ecf20Sopenharmony_ci {{0, 29, 6}}, 5998c2ecf20Sopenharmony_ci {{0, 31, 6}}, 6008c2ecf20Sopenharmony_ci {{32, 0, 4}}, 6018c2ecf20Sopenharmony_ci {{0, 1, 4}}, 6028c2ecf20Sopenharmony_ci {{0, 2, 5}}, 6038c2ecf20Sopenharmony_ci {{32, 4, 5}}, 6048c2ecf20Sopenharmony_ci {{0, 5, 5}}, 6058c2ecf20Sopenharmony_ci {{32, 7, 5}}, 6068c2ecf20Sopenharmony_ci {{0, 8, 5}}, 6078c2ecf20Sopenharmony_ci {{32, 10, 5}}, 6088c2ecf20Sopenharmony_ci {{0, 11, 5}}, 6098c2ecf20Sopenharmony_ci {{0, 13, 6}}, 6108c2ecf20Sopenharmony_ci {{32, 16, 5}}, 6118c2ecf20Sopenharmony_ci {{0, 17, 5}}, 6128c2ecf20Sopenharmony_ci {{32, 19, 5}}, 6138c2ecf20Sopenharmony_ci {{0, 20, 5}}, 6148c2ecf20Sopenharmony_ci {{32, 22, 5}}, 6158c2ecf20Sopenharmony_ci {{0, 23, 5}}, 6168c2ecf20Sopenharmony_ci {{0, 25, 4}}, 6178c2ecf20Sopenharmony_ci {{16, 25, 4}}, 6188c2ecf20Sopenharmony_ci {{32, 26, 5}}, 6198c2ecf20Sopenharmony_ci {{0, 28, 6}}, 6208c2ecf20Sopenharmony_ci {{0, 30, 6}}, 6218c2ecf20Sopenharmony_ci {{48, 0, 4}}, 6228c2ecf20Sopenharmony_ci {{16, 1, 4}}, 6238c2ecf20Sopenharmony_ci {{32, 2, 5}}, 6248c2ecf20Sopenharmony_ci {{32, 3, 5}}, 6258c2ecf20Sopenharmony_ci {{32, 5, 5}}, 6268c2ecf20Sopenharmony_ci {{32, 6, 5}}, 6278c2ecf20Sopenharmony_ci {{32, 8, 5}}, 6288c2ecf20Sopenharmony_ci {{32, 9, 5}}, 6298c2ecf20Sopenharmony_ci {{32, 11, 5}}, 6308c2ecf20Sopenharmony_ci {{32, 12, 5}}, 6318c2ecf20Sopenharmony_ci {{0, 15, 6}}, 6328c2ecf20Sopenharmony_ci {{32, 17, 5}}, 6338c2ecf20Sopenharmony_ci {{32, 18, 5}}, 6348c2ecf20Sopenharmony_ci {{32, 20, 5}}, 6358c2ecf20Sopenharmony_ci {{32, 21, 5}}, 6368c2ecf20Sopenharmony_ci {{32, 23, 5}}, 6378c2ecf20Sopenharmony_ci {{32, 24, 5}}, 6388c2ecf20Sopenharmony_ci {{0, 35, 6}}, 6398c2ecf20Sopenharmony_ci {{0, 34, 6}}, 6408c2ecf20Sopenharmony_ci {{0, 33, 6}}, 6418c2ecf20Sopenharmony_ci {{0, 32, 6}}, 6428c2ecf20Sopenharmony_ci}; /* LL_defaultDTable */ 6438c2ecf20Sopenharmony_ci 6448c2ecf20Sopenharmony_cistatic const FSE_decode_t4 ML_defaultDTable[(1 << ML_DEFAULTNORMLOG) + 1] = { 6458c2ecf20Sopenharmony_ci {{ML_DEFAULTNORMLOG, 1, 1}}, /* header : tableLog, fastMode, fastMode */ 6468c2ecf20Sopenharmony_ci {{0, 0, 6}}, /* 0 : base, symbol, bits */ 6478c2ecf20Sopenharmony_ci {{0, 1, 4}}, 6488c2ecf20Sopenharmony_ci {{32, 2, 5}}, 6498c2ecf20Sopenharmony_ci {{0, 3, 5}}, 6508c2ecf20Sopenharmony_ci {{0, 5, 5}}, 6518c2ecf20Sopenharmony_ci {{0, 6, 5}}, 6528c2ecf20Sopenharmony_ci {{0, 8, 5}}, 6538c2ecf20Sopenharmony_ci {{0, 10, 6}}, 6548c2ecf20Sopenharmony_ci {{0, 13, 6}}, 6558c2ecf20Sopenharmony_ci {{0, 16, 6}}, 6568c2ecf20Sopenharmony_ci {{0, 19, 6}}, 6578c2ecf20Sopenharmony_ci {{0, 22, 6}}, 6588c2ecf20Sopenharmony_ci {{0, 25, 6}}, 6598c2ecf20Sopenharmony_ci {{0, 28, 6}}, 6608c2ecf20Sopenharmony_ci {{0, 31, 6}}, 6618c2ecf20Sopenharmony_ci {{0, 33, 6}}, 6628c2ecf20Sopenharmony_ci {{0, 35, 6}}, 6638c2ecf20Sopenharmony_ci {{0, 37, 6}}, 6648c2ecf20Sopenharmony_ci {{0, 39, 6}}, 6658c2ecf20Sopenharmony_ci {{0, 41, 6}}, 6668c2ecf20Sopenharmony_ci {{0, 43, 6}}, 6678c2ecf20Sopenharmony_ci {{0, 45, 6}}, 6688c2ecf20Sopenharmony_ci {{16, 1, 4}}, 6698c2ecf20Sopenharmony_ci {{0, 2, 4}}, 6708c2ecf20Sopenharmony_ci {{32, 3, 5}}, 6718c2ecf20Sopenharmony_ci {{0, 4, 5}}, 6728c2ecf20Sopenharmony_ci {{32, 6, 5}}, 6738c2ecf20Sopenharmony_ci {{0, 7, 5}}, 6748c2ecf20Sopenharmony_ci {{0, 9, 6}}, 6758c2ecf20Sopenharmony_ci {{0, 12, 6}}, 6768c2ecf20Sopenharmony_ci {{0, 15, 6}}, 6778c2ecf20Sopenharmony_ci {{0, 18, 6}}, 6788c2ecf20Sopenharmony_ci {{0, 21, 6}}, 6798c2ecf20Sopenharmony_ci {{0, 24, 6}}, 6808c2ecf20Sopenharmony_ci {{0, 27, 6}}, 6818c2ecf20Sopenharmony_ci {{0, 30, 6}}, 6828c2ecf20Sopenharmony_ci {{0, 32, 6}}, 6838c2ecf20Sopenharmony_ci {{0, 34, 6}}, 6848c2ecf20Sopenharmony_ci {{0, 36, 6}}, 6858c2ecf20Sopenharmony_ci {{0, 38, 6}}, 6868c2ecf20Sopenharmony_ci {{0, 40, 6}}, 6878c2ecf20Sopenharmony_ci {{0, 42, 6}}, 6888c2ecf20Sopenharmony_ci {{0, 44, 6}}, 6898c2ecf20Sopenharmony_ci {{32, 1, 4}}, 6908c2ecf20Sopenharmony_ci {{48, 1, 4}}, 6918c2ecf20Sopenharmony_ci {{16, 2, 4}}, 6928c2ecf20Sopenharmony_ci {{32, 4, 5}}, 6938c2ecf20Sopenharmony_ci {{32, 5, 5}}, 6948c2ecf20Sopenharmony_ci {{32, 7, 5}}, 6958c2ecf20Sopenharmony_ci {{32, 8, 5}}, 6968c2ecf20Sopenharmony_ci {{0, 11, 6}}, 6978c2ecf20Sopenharmony_ci {{0, 14, 6}}, 6988c2ecf20Sopenharmony_ci {{0, 17, 6}}, 6998c2ecf20Sopenharmony_ci {{0, 20, 6}}, 7008c2ecf20Sopenharmony_ci {{0, 23, 6}}, 7018c2ecf20Sopenharmony_ci {{0, 26, 6}}, 7028c2ecf20Sopenharmony_ci {{0, 29, 6}}, 7038c2ecf20Sopenharmony_ci {{0, 52, 6}}, 7048c2ecf20Sopenharmony_ci {{0, 51, 6}}, 7058c2ecf20Sopenharmony_ci {{0, 50, 6}}, 7068c2ecf20Sopenharmony_ci {{0, 49, 6}}, 7078c2ecf20Sopenharmony_ci {{0, 48, 6}}, 7088c2ecf20Sopenharmony_ci {{0, 47, 6}}, 7098c2ecf20Sopenharmony_ci {{0, 46, 6}}, 7108c2ecf20Sopenharmony_ci}; /* ML_defaultDTable */ 7118c2ecf20Sopenharmony_ci 7128c2ecf20Sopenharmony_cistatic const FSE_decode_t4 OF_defaultDTable[(1 << OF_DEFAULTNORMLOG) + 1] = { 7138c2ecf20Sopenharmony_ci {{OF_DEFAULTNORMLOG, 1, 1}}, /* header : tableLog, fastMode, fastMode */ 7148c2ecf20Sopenharmony_ci {{0, 0, 5}}, /* 0 : base, symbol, bits */ 7158c2ecf20Sopenharmony_ci {{0, 6, 4}}, 7168c2ecf20Sopenharmony_ci {{0, 9, 5}}, 7178c2ecf20Sopenharmony_ci {{0, 15, 5}}, 7188c2ecf20Sopenharmony_ci {{0, 21, 5}}, 7198c2ecf20Sopenharmony_ci {{0, 3, 5}}, 7208c2ecf20Sopenharmony_ci {{0, 7, 4}}, 7218c2ecf20Sopenharmony_ci {{0, 12, 5}}, 7228c2ecf20Sopenharmony_ci {{0, 18, 5}}, 7238c2ecf20Sopenharmony_ci {{0, 23, 5}}, 7248c2ecf20Sopenharmony_ci {{0, 5, 5}}, 7258c2ecf20Sopenharmony_ci {{0, 8, 4}}, 7268c2ecf20Sopenharmony_ci {{0, 14, 5}}, 7278c2ecf20Sopenharmony_ci {{0, 20, 5}}, 7288c2ecf20Sopenharmony_ci {{0, 2, 5}}, 7298c2ecf20Sopenharmony_ci {{16, 7, 4}}, 7308c2ecf20Sopenharmony_ci {{0, 11, 5}}, 7318c2ecf20Sopenharmony_ci {{0, 17, 5}}, 7328c2ecf20Sopenharmony_ci {{0, 22, 5}}, 7338c2ecf20Sopenharmony_ci {{0, 4, 5}}, 7348c2ecf20Sopenharmony_ci {{16, 8, 4}}, 7358c2ecf20Sopenharmony_ci {{0, 13, 5}}, 7368c2ecf20Sopenharmony_ci {{0, 19, 5}}, 7378c2ecf20Sopenharmony_ci {{0, 1, 5}}, 7388c2ecf20Sopenharmony_ci {{16, 6, 4}}, 7398c2ecf20Sopenharmony_ci {{0, 10, 5}}, 7408c2ecf20Sopenharmony_ci {{0, 16, 5}}, 7418c2ecf20Sopenharmony_ci {{0, 28, 5}}, 7428c2ecf20Sopenharmony_ci {{0, 27, 5}}, 7438c2ecf20Sopenharmony_ci {{0, 26, 5}}, 7448c2ecf20Sopenharmony_ci {{0, 25, 5}}, 7458c2ecf20Sopenharmony_ci {{0, 24, 5}}, 7468c2ecf20Sopenharmony_ci}; /* OF_defaultDTable */ 7478c2ecf20Sopenharmony_ci 7488c2ecf20Sopenharmony_ci/*! ZSTD_buildSeqTable() : 7498c2ecf20Sopenharmony_ci @return : nb bytes read from src, 7508c2ecf20Sopenharmony_ci or an error code if it fails, testable with ZSTD_isError() 7518c2ecf20Sopenharmony_ci*/ 7528c2ecf20Sopenharmony_cistatic size_t ZSTD_buildSeqTable(FSE_DTable *DTableSpace, const FSE_DTable **DTablePtr, symbolEncodingType_e type, U32 max, U32 maxLog, const void *src, 7538c2ecf20Sopenharmony_ci size_t srcSize, const FSE_decode_t4 *defaultTable, U32 flagRepeatTable, void *workspace, size_t workspaceSize) 7548c2ecf20Sopenharmony_ci{ 7558c2ecf20Sopenharmony_ci const void *const tmpPtr = defaultTable; /* bypass strict aliasing */ 7568c2ecf20Sopenharmony_ci switch (type) { 7578c2ecf20Sopenharmony_ci case set_rle: 7588c2ecf20Sopenharmony_ci if (!srcSize) 7598c2ecf20Sopenharmony_ci return ERROR(srcSize_wrong); 7608c2ecf20Sopenharmony_ci if ((*(const BYTE *)src) > max) 7618c2ecf20Sopenharmony_ci return ERROR(corruption_detected); 7628c2ecf20Sopenharmony_ci FSE_buildDTable_rle(DTableSpace, *(const BYTE *)src); 7638c2ecf20Sopenharmony_ci *DTablePtr = DTableSpace; 7648c2ecf20Sopenharmony_ci return 1; 7658c2ecf20Sopenharmony_ci case set_basic: *DTablePtr = (const FSE_DTable *)tmpPtr; return 0; 7668c2ecf20Sopenharmony_ci case set_repeat: 7678c2ecf20Sopenharmony_ci if (!flagRepeatTable) 7688c2ecf20Sopenharmony_ci return ERROR(corruption_detected); 7698c2ecf20Sopenharmony_ci return 0; 7708c2ecf20Sopenharmony_ci default: /* impossible */ 7718c2ecf20Sopenharmony_ci case set_compressed: { 7728c2ecf20Sopenharmony_ci U32 tableLog; 7738c2ecf20Sopenharmony_ci S16 *norm = (S16 *)workspace; 7748c2ecf20Sopenharmony_ci size_t const spaceUsed32 = ALIGN(sizeof(S16) * (MaxSeq + 1), sizeof(U32)) >> 2; 7758c2ecf20Sopenharmony_ci 7768c2ecf20Sopenharmony_ci if ((spaceUsed32 << 2) > workspaceSize) 7778c2ecf20Sopenharmony_ci return ERROR(GENERIC); 7788c2ecf20Sopenharmony_ci workspace = (U32 *)workspace + spaceUsed32; 7798c2ecf20Sopenharmony_ci workspaceSize -= (spaceUsed32 << 2); 7808c2ecf20Sopenharmony_ci { 7818c2ecf20Sopenharmony_ci size_t const headerSize = FSE_readNCount(norm, &max, &tableLog, src, srcSize); 7828c2ecf20Sopenharmony_ci if (FSE_isError(headerSize)) 7838c2ecf20Sopenharmony_ci return ERROR(corruption_detected); 7848c2ecf20Sopenharmony_ci if (tableLog > maxLog) 7858c2ecf20Sopenharmony_ci return ERROR(corruption_detected); 7868c2ecf20Sopenharmony_ci FSE_buildDTable_wksp(DTableSpace, norm, max, tableLog, workspace, workspaceSize); 7878c2ecf20Sopenharmony_ci *DTablePtr = DTableSpace; 7888c2ecf20Sopenharmony_ci return headerSize; 7898c2ecf20Sopenharmony_ci } 7908c2ecf20Sopenharmony_ci } 7918c2ecf20Sopenharmony_ci } 7928c2ecf20Sopenharmony_ci} 7938c2ecf20Sopenharmony_ci 7948c2ecf20Sopenharmony_cisize_t ZSTD_decodeSeqHeaders(ZSTD_DCtx *dctx, int *nbSeqPtr, const void *src, size_t srcSize) 7958c2ecf20Sopenharmony_ci{ 7968c2ecf20Sopenharmony_ci const BYTE *const istart = (const BYTE *const)src; 7978c2ecf20Sopenharmony_ci const BYTE *const iend = istart + srcSize; 7988c2ecf20Sopenharmony_ci const BYTE *ip = istart; 7998c2ecf20Sopenharmony_ci 8008c2ecf20Sopenharmony_ci /* check */ 8018c2ecf20Sopenharmony_ci if (srcSize < MIN_SEQUENCES_SIZE) 8028c2ecf20Sopenharmony_ci return ERROR(srcSize_wrong); 8038c2ecf20Sopenharmony_ci 8048c2ecf20Sopenharmony_ci /* SeqHead */ 8058c2ecf20Sopenharmony_ci { 8068c2ecf20Sopenharmony_ci int nbSeq = *ip++; 8078c2ecf20Sopenharmony_ci if (!nbSeq) { 8088c2ecf20Sopenharmony_ci *nbSeqPtr = 0; 8098c2ecf20Sopenharmony_ci return 1; 8108c2ecf20Sopenharmony_ci } 8118c2ecf20Sopenharmony_ci if (nbSeq > 0x7F) { 8128c2ecf20Sopenharmony_ci if (nbSeq == 0xFF) { 8138c2ecf20Sopenharmony_ci if (ip + 2 > iend) 8148c2ecf20Sopenharmony_ci return ERROR(srcSize_wrong); 8158c2ecf20Sopenharmony_ci nbSeq = ZSTD_readLE16(ip) + LONGNBSEQ, ip += 2; 8168c2ecf20Sopenharmony_ci } else { 8178c2ecf20Sopenharmony_ci if (ip >= iend) 8188c2ecf20Sopenharmony_ci return ERROR(srcSize_wrong); 8198c2ecf20Sopenharmony_ci nbSeq = ((nbSeq - 0x80) << 8) + *ip++; 8208c2ecf20Sopenharmony_ci } 8218c2ecf20Sopenharmony_ci } 8228c2ecf20Sopenharmony_ci *nbSeqPtr = nbSeq; 8238c2ecf20Sopenharmony_ci } 8248c2ecf20Sopenharmony_ci 8258c2ecf20Sopenharmony_ci /* FSE table descriptors */ 8268c2ecf20Sopenharmony_ci if (ip + 4 > iend) 8278c2ecf20Sopenharmony_ci return ERROR(srcSize_wrong); /* minimum possible size */ 8288c2ecf20Sopenharmony_ci { 8298c2ecf20Sopenharmony_ci symbolEncodingType_e const LLtype = (symbolEncodingType_e)(*ip >> 6); 8308c2ecf20Sopenharmony_ci symbolEncodingType_e const OFtype = (symbolEncodingType_e)((*ip >> 4) & 3); 8318c2ecf20Sopenharmony_ci symbolEncodingType_e const MLtype = (symbolEncodingType_e)((*ip >> 2) & 3); 8328c2ecf20Sopenharmony_ci ip++; 8338c2ecf20Sopenharmony_ci 8348c2ecf20Sopenharmony_ci /* Build DTables */ 8358c2ecf20Sopenharmony_ci { 8368c2ecf20Sopenharmony_ci size_t const llhSize = ZSTD_buildSeqTable(dctx->entropy.LLTable, &dctx->LLTptr, LLtype, MaxLL, LLFSELog, ip, iend - ip, 8378c2ecf20Sopenharmony_ci LL_defaultDTable, dctx->fseEntropy, dctx->entropy.workspace, sizeof(dctx->entropy.workspace)); 8388c2ecf20Sopenharmony_ci if (ZSTD_isError(llhSize)) 8398c2ecf20Sopenharmony_ci return ERROR(corruption_detected); 8408c2ecf20Sopenharmony_ci ip += llhSize; 8418c2ecf20Sopenharmony_ci } 8428c2ecf20Sopenharmony_ci { 8438c2ecf20Sopenharmony_ci size_t const ofhSize = ZSTD_buildSeqTable(dctx->entropy.OFTable, &dctx->OFTptr, OFtype, MaxOff, OffFSELog, ip, iend - ip, 8448c2ecf20Sopenharmony_ci OF_defaultDTable, dctx->fseEntropy, dctx->entropy.workspace, sizeof(dctx->entropy.workspace)); 8458c2ecf20Sopenharmony_ci if (ZSTD_isError(ofhSize)) 8468c2ecf20Sopenharmony_ci return ERROR(corruption_detected); 8478c2ecf20Sopenharmony_ci ip += ofhSize; 8488c2ecf20Sopenharmony_ci } 8498c2ecf20Sopenharmony_ci { 8508c2ecf20Sopenharmony_ci size_t const mlhSize = ZSTD_buildSeqTable(dctx->entropy.MLTable, &dctx->MLTptr, MLtype, MaxML, MLFSELog, ip, iend - ip, 8518c2ecf20Sopenharmony_ci ML_defaultDTable, dctx->fseEntropy, dctx->entropy.workspace, sizeof(dctx->entropy.workspace)); 8528c2ecf20Sopenharmony_ci if (ZSTD_isError(mlhSize)) 8538c2ecf20Sopenharmony_ci return ERROR(corruption_detected); 8548c2ecf20Sopenharmony_ci ip += mlhSize; 8558c2ecf20Sopenharmony_ci } 8568c2ecf20Sopenharmony_ci } 8578c2ecf20Sopenharmony_ci 8588c2ecf20Sopenharmony_ci return ip - istart; 8598c2ecf20Sopenharmony_ci} 8608c2ecf20Sopenharmony_ci 8618c2ecf20Sopenharmony_citypedef struct { 8628c2ecf20Sopenharmony_ci size_t litLength; 8638c2ecf20Sopenharmony_ci size_t matchLength; 8648c2ecf20Sopenharmony_ci size_t offset; 8658c2ecf20Sopenharmony_ci const BYTE *match; 8668c2ecf20Sopenharmony_ci} seq_t; 8678c2ecf20Sopenharmony_ci 8688c2ecf20Sopenharmony_citypedef struct { 8698c2ecf20Sopenharmony_ci BIT_DStream_t DStream; 8708c2ecf20Sopenharmony_ci FSE_DState_t stateLL; 8718c2ecf20Sopenharmony_ci FSE_DState_t stateOffb; 8728c2ecf20Sopenharmony_ci FSE_DState_t stateML; 8738c2ecf20Sopenharmony_ci size_t prevOffset[ZSTD_REP_NUM]; 8748c2ecf20Sopenharmony_ci const BYTE *base; 8758c2ecf20Sopenharmony_ci size_t pos; 8768c2ecf20Sopenharmony_ci uPtrDiff gotoDict; 8778c2ecf20Sopenharmony_ci} seqState_t; 8788c2ecf20Sopenharmony_ci 8798c2ecf20Sopenharmony_ciFORCE_NOINLINE 8808c2ecf20Sopenharmony_cisize_t ZSTD_execSequenceLast7(BYTE *op, BYTE *const oend, seq_t sequence, const BYTE **litPtr, const BYTE *const litLimit, const BYTE *const base, 8818c2ecf20Sopenharmony_ci const BYTE *const vBase, const BYTE *const dictEnd) 8828c2ecf20Sopenharmony_ci{ 8838c2ecf20Sopenharmony_ci BYTE *const oLitEnd = op + sequence.litLength; 8848c2ecf20Sopenharmony_ci size_t const sequenceLength = sequence.litLength + sequence.matchLength; 8858c2ecf20Sopenharmony_ci BYTE *const oMatchEnd = op + sequenceLength; /* risk : address space overflow (32-bits) */ 8868c2ecf20Sopenharmony_ci BYTE *const oend_w = oend - WILDCOPY_OVERLENGTH; 8878c2ecf20Sopenharmony_ci const BYTE *const iLitEnd = *litPtr + sequence.litLength; 8888c2ecf20Sopenharmony_ci const BYTE *match = oLitEnd - sequence.offset; 8898c2ecf20Sopenharmony_ci 8908c2ecf20Sopenharmony_ci /* check */ 8918c2ecf20Sopenharmony_ci if (oMatchEnd > oend) 8928c2ecf20Sopenharmony_ci return ERROR(dstSize_tooSmall); /* last match must start at a minimum distance of WILDCOPY_OVERLENGTH from oend */ 8938c2ecf20Sopenharmony_ci if (iLitEnd > litLimit) 8948c2ecf20Sopenharmony_ci return ERROR(corruption_detected); /* over-read beyond lit buffer */ 8958c2ecf20Sopenharmony_ci if (oLitEnd <= oend_w) 8968c2ecf20Sopenharmony_ci return ERROR(GENERIC); /* Precondition */ 8978c2ecf20Sopenharmony_ci 8988c2ecf20Sopenharmony_ci /* copy literals */ 8998c2ecf20Sopenharmony_ci if (op < oend_w) { 9008c2ecf20Sopenharmony_ci ZSTD_wildcopy(op, *litPtr, oend_w - op); 9018c2ecf20Sopenharmony_ci *litPtr += oend_w - op; 9028c2ecf20Sopenharmony_ci op = oend_w; 9038c2ecf20Sopenharmony_ci } 9048c2ecf20Sopenharmony_ci while (op < oLitEnd) 9058c2ecf20Sopenharmony_ci *op++ = *(*litPtr)++; 9068c2ecf20Sopenharmony_ci 9078c2ecf20Sopenharmony_ci /* copy Match */ 9088c2ecf20Sopenharmony_ci if (sequence.offset > (size_t)(oLitEnd - base)) { 9098c2ecf20Sopenharmony_ci /* offset beyond prefix */ 9108c2ecf20Sopenharmony_ci if (sequence.offset > (size_t)(oLitEnd - vBase)) 9118c2ecf20Sopenharmony_ci return ERROR(corruption_detected); 9128c2ecf20Sopenharmony_ci match = dictEnd - (base - match); 9138c2ecf20Sopenharmony_ci if (match + sequence.matchLength <= dictEnd) { 9148c2ecf20Sopenharmony_ci memmove(oLitEnd, match, sequence.matchLength); 9158c2ecf20Sopenharmony_ci return sequenceLength; 9168c2ecf20Sopenharmony_ci } 9178c2ecf20Sopenharmony_ci /* span extDict & currPrefixSegment */ 9188c2ecf20Sopenharmony_ci { 9198c2ecf20Sopenharmony_ci size_t const length1 = dictEnd - match; 9208c2ecf20Sopenharmony_ci memmove(oLitEnd, match, length1); 9218c2ecf20Sopenharmony_ci op = oLitEnd + length1; 9228c2ecf20Sopenharmony_ci sequence.matchLength -= length1; 9238c2ecf20Sopenharmony_ci match = base; 9248c2ecf20Sopenharmony_ci } 9258c2ecf20Sopenharmony_ci } 9268c2ecf20Sopenharmony_ci while (op < oMatchEnd) 9278c2ecf20Sopenharmony_ci *op++ = *match++; 9288c2ecf20Sopenharmony_ci return sequenceLength; 9298c2ecf20Sopenharmony_ci} 9308c2ecf20Sopenharmony_ci 9318c2ecf20Sopenharmony_cistatic seq_t ZSTD_decodeSequence(seqState_t *seqState) 9328c2ecf20Sopenharmony_ci{ 9338c2ecf20Sopenharmony_ci seq_t seq; 9348c2ecf20Sopenharmony_ci 9358c2ecf20Sopenharmony_ci U32 const llCode = FSE_peekSymbol(&seqState->stateLL); 9368c2ecf20Sopenharmony_ci U32 const mlCode = FSE_peekSymbol(&seqState->stateML); 9378c2ecf20Sopenharmony_ci U32 const ofCode = FSE_peekSymbol(&seqState->stateOffb); /* <= maxOff, by table construction */ 9388c2ecf20Sopenharmony_ci 9398c2ecf20Sopenharmony_ci U32 const llBits = LL_bits[llCode]; 9408c2ecf20Sopenharmony_ci U32 const mlBits = ML_bits[mlCode]; 9418c2ecf20Sopenharmony_ci U32 const ofBits = ofCode; 9428c2ecf20Sopenharmony_ci U32 const totalBits = llBits + mlBits + ofBits; 9438c2ecf20Sopenharmony_ci 9448c2ecf20Sopenharmony_ci static const U32 LL_base[MaxLL + 1] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 18, 9458c2ecf20Sopenharmony_ci 20, 22, 24, 28, 32, 40, 48, 64, 0x80, 0x100, 0x200, 0x400, 0x800, 0x1000, 0x2000, 0x4000, 0x8000, 0x10000}; 9468c2ecf20Sopenharmony_ci 9478c2ecf20Sopenharmony_ci static const U32 ML_base[MaxML + 1] = {3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 9488c2ecf20Sopenharmony_ci 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 37, 39, 41, 9498c2ecf20Sopenharmony_ci 43, 47, 51, 59, 67, 83, 99, 0x83, 0x103, 0x203, 0x403, 0x803, 0x1003, 0x2003, 0x4003, 0x8003, 0x10003}; 9508c2ecf20Sopenharmony_ci 9518c2ecf20Sopenharmony_ci static const U32 OF_base[MaxOff + 1] = {0, 1, 1, 5, 0xD, 0x1D, 0x3D, 0x7D, 0xFD, 0x1FD, 9528c2ecf20Sopenharmony_ci 0x3FD, 0x7FD, 0xFFD, 0x1FFD, 0x3FFD, 0x7FFD, 0xFFFD, 0x1FFFD, 0x3FFFD, 0x7FFFD, 9538c2ecf20Sopenharmony_ci 0xFFFFD, 0x1FFFFD, 0x3FFFFD, 0x7FFFFD, 0xFFFFFD, 0x1FFFFFD, 0x3FFFFFD, 0x7FFFFFD, 0xFFFFFFD}; 9548c2ecf20Sopenharmony_ci 9558c2ecf20Sopenharmony_ci /* sequence */ 9568c2ecf20Sopenharmony_ci { 9578c2ecf20Sopenharmony_ci size_t offset; 9588c2ecf20Sopenharmony_ci if (!ofCode) 9598c2ecf20Sopenharmony_ci offset = 0; 9608c2ecf20Sopenharmony_ci else { 9618c2ecf20Sopenharmony_ci offset = OF_base[ofCode] + BIT_readBitsFast(&seqState->DStream, ofBits); /* <= (ZSTD_WINDOWLOG_MAX-1) bits */ 9628c2ecf20Sopenharmony_ci if (ZSTD_32bits()) 9638c2ecf20Sopenharmony_ci BIT_reloadDStream(&seqState->DStream); 9648c2ecf20Sopenharmony_ci } 9658c2ecf20Sopenharmony_ci 9668c2ecf20Sopenharmony_ci if (ofCode <= 1) { 9678c2ecf20Sopenharmony_ci offset += (llCode == 0); 9688c2ecf20Sopenharmony_ci if (offset) { 9698c2ecf20Sopenharmony_ci size_t temp = (offset == 3) ? seqState->prevOffset[0] - 1 : seqState->prevOffset[offset]; 9708c2ecf20Sopenharmony_ci temp += !temp; /* 0 is not valid; input is corrupted; force offset to 1 */ 9718c2ecf20Sopenharmony_ci if (offset != 1) 9728c2ecf20Sopenharmony_ci seqState->prevOffset[2] = seqState->prevOffset[1]; 9738c2ecf20Sopenharmony_ci seqState->prevOffset[1] = seqState->prevOffset[0]; 9748c2ecf20Sopenharmony_ci seqState->prevOffset[0] = offset = temp; 9758c2ecf20Sopenharmony_ci } else { 9768c2ecf20Sopenharmony_ci offset = seqState->prevOffset[0]; 9778c2ecf20Sopenharmony_ci } 9788c2ecf20Sopenharmony_ci } else { 9798c2ecf20Sopenharmony_ci seqState->prevOffset[2] = seqState->prevOffset[1]; 9808c2ecf20Sopenharmony_ci seqState->prevOffset[1] = seqState->prevOffset[0]; 9818c2ecf20Sopenharmony_ci seqState->prevOffset[0] = offset; 9828c2ecf20Sopenharmony_ci } 9838c2ecf20Sopenharmony_ci seq.offset = offset; 9848c2ecf20Sopenharmony_ci } 9858c2ecf20Sopenharmony_ci 9868c2ecf20Sopenharmony_ci seq.matchLength = ML_base[mlCode] + ((mlCode > 31) ? BIT_readBitsFast(&seqState->DStream, mlBits) : 0); /* <= 16 bits */ 9878c2ecf20Sopenharmony_ci if (ZSTD_32bits() && (mlBits + llBits > 24)) 9888c2ecf20Sopenharmony_ci BIT_reloadDStream(&seqState->DStream); 9898c2ecf20Sopenharmony_ci 9908c2ecf20Sopenharmony_ci seq.litLength = LL_base[llCode] + ((llCode > 15) ? BIT_readBitsFast(&seqState->DStream, llBits) : 0); /* <= 16 bits */ 9918c2ecf20Sopenharmony_ci if (ZSTD_32bits() || (totalBits > 64 - 7 - (LLFSELog + MLFSELog + OffFSELog))) 9928c2ecf20Sopenharmony_ci BIT_reloadDStream(&seqState->DStream); 9938c2ecf20Sopenharmony_ci 9948c2ecf20Sopenharmony_ci /* ANS state update */ 9958c2ecf20Sopenharmony_ci FSE_updateState(&seqState->stateLL, &seqState->DStream); /* <= 9 bits */ 9968c2ecf20Sopenharmony_ci FSE_updateState(&seqState->stateML, &seqState->DStream); /* <= 9 bits */ 9978c2ecf20Sopenharmony_ci if (ZSTD_32bits()) 9988c2ecf20Sopenharmony_ci BIT_reloadDStream(&seqState->DStream); /* <= 18 bits */ 9998c2ecf20Sopenharmony_ci FSE_updateState(&seqState->stateOffb, &seqState->DStream); /* <= 8 bits */ 10008c2ecf20Sopenharmony_ci 10018c2ecf20Sopenharmony_ci seq.match = NULL; 10028c2ecf20Sopenharmony_ci 10038c2ecf20Sopenharmony_ci return seq; 10048c2ecf20Sopenharmony_ci} 10058c2ecf20Sopenharmony_ci 10068c2ecf20Sopenharmony_ciFORCE_INLINE 10078c2ecf20Sopenharmony_cisize_t ZSTD_execSequence(BYTE *op, BYTE *const oend, seq_t sequence, const BYTE **litPtr, const BYTE *const litLimit, const BYTE *const base, 10088c2ecf20Sopenharmony_ci const BYTE *const vBase, const BYTE *const dictEnd) 10098c2ecf20Sopenharmony_ci{ 10108c2ecf20Sopenharmony_ci BYTE *const oLitEnd = op + sequence.litLength; 10118c2ecf20Sopenharmony_ci size_t const sequenceLength = sequence.litLength + sequence.matchLength; 10128c2ecf20Sopenharmony_ci BYTE *const oMatchEnd = op + sequenceLength; /* risk : address space overflow (32-bits) */ 10138c2ecf20Sopenharmony_ci BYTE *const oend_w = oend - WILDCOPY_OVERLENGTH; 10148c2ecf20Sopenharmony_ci const BYTE *const iLitEnd = *litPtr + sequence.litLength; 10158c2ecf20Sopenharmony_ci const BYTE *match = oLitEnd - sequence.offset; 10168c2ecf20Sopenharmony_ci 10178c2ecf20Sopenharmony_ci /* check */ 10188c2ecf20Sopenharmony_ci if (oMatchEnd > oend) 10198c2ecf20Sopenharmony_ci return ERROR(dstSize_tooSmall); /* last match must start at a minimum distance of WILDCOPY_OVERLENGTH from oend */ 10208c2ecf20Sopenharmony_ci if (iLitEnd > litLimit) 10218c2ecf20Sopenharmony_ci return ERROR(corruption_detected); /* over-read beyond lit buffer */ 10228c2ecf20Sopenharmony_ci if (oLitEnd > oend_w) 10238c2ecf20Sopenharmony_ci return ZSTD_execSequenceLast7(op, oend, sequence, litPtr, litLimit, base, vBase, dictEnd); 10248c2ecf20Sopenharmony_ci 10258c2ecf20Sopenharmony_ci /* copy Literals */ 10268c2ecf20Sopenharmony_ci ZSTD_copy8(op, *litPtr); 10278c2ecf20Sopenharmony_ci if (sequence.litLength > 8) 10288c2ecf20Sopenharmony_ci ZSTD_wildcopy(op + 8, (*litPtr) + 8, 10298c2ecf20Sopenharmony_ci sequence.litLength - 8); /* note : since oLitEnd <= oend-WILDCOPY_OVERLENGTH, no risk of overwrite beyond oend */ 10308c2ecf20Sopenharmony_ci op = oLitEnd; 10318c2ecf20Sopenharmony_ci *litPtr = iLitEnd; /* update for next sequence */ 10328c2ecf20Sopenharmony_ci 10338c2ecf20Sopenharmony_ci /* copy Match */ 10348c2ecf20Sopenharmony_ci if (sequence.offset > (size_t)(oLitEnd - base)) { 10358c2ecf20Sopenharmony_ci /* offset beyond prefix */ 10368c2ecf20Sopenharmony_ci if (sequence.offset > (size_t)(oLitEnd - vBase)) 10378c2ecf20Sopenharmony_ci return ERROR(corruption_detected); 10388c2ecf20Sopenharmony_ci match = dictEnd + (match - base); 10398c2ecf20Sopenharmony_ci if (match + sequence.matchLength <= dictEnd) { 10408c2ecf20Sopenharmony_ci memmove(oLitEnd, match, sequence.matchLength); 10418c2ecf20Sopenharmony_ci return sequenceLength; 10428c2ecf20Sopenharmony_ci } 10438c2ecf20Sopenharmony_ci /* span extDict & currPrefixSegment */ 10448c2ecf20Sopenharmony_ci { 10458c2ecf20Sopenharmony_ci size_t const length1 = dictEnd - match; 10468c2ecf20Sopenharmony_ci memmove(oLitEnd, match, length1); 10478c2ecf20Sopenharmony_ci op = oLitEnd + length1; 10488c2ecf20Sopenharmony_ci sequence.matchLength -= length1; 10498c2ecf20Sopenharmony_ci match = base; 10508c2ecf20Sopenharmony_ci if (op > oend_w || sequence.matchLength < MINMATCH) { 10518c2ecf20Sopenharmony_ci U32 i; 10528c2ecf20Sopenharmony_ci for (i = 0; i < sequence.matchLength; ++i) 10538c2ecf20Sopenharmony_ci op[i] = match[i]; 10548c2ecf20Sopenharmony_ci return sequenceLength; 10558c2ecf20Sopenharmony_ci } 10568c2ecf20Sopenharmony_ci } 10578c2ecf20Sopenharmony_ci } 10588c2ecf20Sopenharmony_ci /* Requirement: op <= oend_w && sequence.matchLength >= MINMATCH */ 10598c2ecf20Sopenharmony_ci 10608c2ecf20Sopenharmony_ci /* match within prefix */ 10618c2ecf20Sopenharmony_ci if (sequence.offset < 8) { 10628c2ecf20Sopenharmony_ci /* close range match, overlap */ 10638c2ecf20Sopenharmony_ci static const U32 dec32table[] = {0, 1, 2, 1, 4, 4, 4, 4}; /* added */ 10648c2ecf20Sopenharmony_ci static const int dec64table[] = {8, 8, 8, 7, 8, 9, 10, 11}; /* subtracted */ 10658c2ecf20Sopenharmony_ci int const sub2 = dec64table[sequence.offset]; 10668c2ecf20Sopenharmony_ci op[0] = match[0]; 10678c2ecf20Sopenharmony_ci op[1] = match[1]; 10688c2ecf20Sopenharmony_ci op[2] = match[2]; 10698c2ecf20Sopenharmony_ci op[3] = match[3]; 10708c2ecf20Sopenharmony_ci match += dec32table[sequence.offset]; 10718c2ecf20Sopenharmony_ci ZSTD_copy4(op + 4, match); 10728c2ecf20Sopenharmony_ci match -= sub2; 10738c2ecf20Sopenharmony_ci } else { 10748c2ecf20Sopenharmony_ci ZSTD_copy8(op, match); 10758c2ecf20Sopenharmony_ci } 10768c2ecf20Sopenharmony_ci op += 8; 10778c2ecf20Sopenharmony_ci match += 8; 10788c2ecf20Sopenharmony_ci 10798c2ecf20Sopenharmony_ci if (oMatchEnd > oend - (16 - MINMATCH)) { 10808c2ecf20Sopenharmony_ci if (op < oend_w) { 10818c2ecf20Sopenharmony_ci ZSTD_wildcopy(op, match, oend_w - op); 10828c2ecf20Sopenharmony_ci match += oend_w - op; 10838c2ecf20Sopenharmony_ci op = oend_w; 10848c2ecf20Sopenharmony_ci } 10858c2ecf20Sopenharmony_ci while (op < oMatchEnd) 10868c2ecf20Sopenharmony_ci *op++ = *match++; 10878c2ecf20Sopenharmony_ci } else { 10888c2ecf20Sopenharmony_ci ZSTD_wildcopy(op, match, (ptrdiff_t)sequence.matchLength - 8); /* works even if matchLength < 8 */ 10898c2ecf20Sopenharmony_ci } 10908c2ecf20Sopenharmony_ci return sequenceLength; 10918c2ecf20Sopenharmony_ci} 10928c2ecf20Sopenharmony_ci 10938c2ecf20Sopenharmony_cistatic size_t ZSTD_decompressSequences(ZSTD_DCtx *dctx, void *dst, size_t maxDstSize, const void *seqStart, size_t seqSize) 10948c2ecf20Sopenharmony_ci{ 10958c2ecf20Sopenharmony_ci const BYTE *ip = (const BYTE *)seqStart; 10968c2ecf20Sopenharmony_ci const BYTE *const iend = ip + seqSize; 10978c2ecf20Sopenharmony_ci BYTE *const ostart = (BYTE * const)dst; 10988c2ecf20Sopenharmony_ci BYTE *const oend = ostart + maxDstSize; 10998c2ecf20Sopenharmony_ci BYTE *op = ostart; 11008c2ecf20Sopenharmony_ci const BYTE *litPtr = dctx->litPtr; 11018c2ecf20Sopenharmony_ci const BYTE *const litEnd = litPtr + dctx->litSize; 11028c2ecf20Sopenharmony_ci const BYTE *const base = (const BYTE *)(dctx->base); 11038c2ecf20Sopenharmony_ci const BYTE *const vBase = (const BYTE *)(dctx->vBase); 11048c2ecf20Sopenharmony_ci const BYTE *const dictEnd = (const BYTE *)(dctx->dictEnd); 11058c2ecf20Sopenharmony_ci int nbSeq; 11068c2ecf20Sopenharmony_ci 11078c2ecf20Sopenharmony_ci /* Build Decoding Tables */ 11088c2ecf20Sopenharmony_ci { 11098c2ecf20Sopenharmony_ci size_t const seqHSize = ZSTD_decodeSeqHeaders(dctx, &nbSeq, ip, seqSize); 11108c2ecf20Sopenharmony_ci if (ZSTD_isError(seqHSize)) 11118c2ecf20Sopenharmony_ci return seqHSize; 11128c2ecf20Sopenharmony_ci ip += seqHSize; 11138c2ecf20Sopenharmony_ci } 11148c2ecf20Sopenharmony_ci 11158c2ecf20Sopenharmony_ci /* Regen sequences */ 11168c2ecf20Sopenharmony_ci if (nbSeq) { 11178c2ecf20Sopenharmony_ci seqState_t seqState; 11188c2ecf20Sopenharmony_ci dctx->fseEntropy = 1; 11198c2ecf20Sopenharmony_ci { 11208c2ecf20Sopenharmony_ci U32 i; 11218c2ecf20Sopenharmony_ci for (i = 0; i < ZSTD_REP_NUM; i++) 11228c2ecf20Sopenharmony_ci seqState.prevOffset[i] = dctx->entropy.rep[i]; 11238c2ecf20Sopenharmony_ci } 11248c2ecf20Sopenharmony_ci CHECK_E(BIT_initDStream(&seqState.DStream, ip, iend - ip), corruption_detected); 11258c2ecf20Sopenharmony_ci FSE_initDState(&seqState.stateLL, &seqState.DStream, dctx->LLTptr); 11268c2ecf20Sopenharmony_ci FSE_initDState(&seqState.stateOffb, &seqState.DStream, dctx->OFTptr); 11278c2ecf20Sopenharmony_ci FSE_initDState(&seqState.stateML, &seqState.DStream, dctx->MLTptr); 11288c2ecf20Sopenharmony_ci 11298c2ecf20Sopenharmony_ci for (; (BIT_reloadDStream(&(seqState.DStream)) <= BIT_DStream_completed) && nbSeq;) { 11308c2ecf20Sopenharmony_ci nbSeq--; 11318c2ecf20Sopenharmony_ci { 11328c2ecf20Sopenharmony_ci seq_t const sequence = ZSTD_decodeSequence(&seqState); 11338c2ecf20Sopenharmony_ci size_t const oneSeqSize = ZSTD_execSequence(op, oend, sequence, &litPtr, litEnd, base, vBase, dictEnd); 11348c2ecf20Sopenharmony_ci if (ZSTD_isError(oneSeqSize)) 11358c2ecf20Sopenharmony_ci return oneSeqSize; 11368c2ecf20Sopenharmony_ci op += oneSeqSize; 11378c2ecf20Sopenharmony_ci } 11388c2ecf20Sopenharmony_ci } 11398c2ecf20Sopenharmony_ci 11408c2ecf20Sopenharmony_ci /* check if reached exact end */ 11418c2ecf20Sopenharmony_ci if (nbSeq) 11428c2ecf20Sopenharmony_ci return ERROR(corruption_detected); 11438c2ecf20Sopenharmony_ci /* save reps for next block */ 11448c2ecf20Sopenharmony_ci { 11458c2ecf20Sopenharmony_ci U32 i; 11468c2ecf20Sopenharmony_ci for (i = 0; i < ZSTD_REP_NUM; i++) 11478c2ecf20Sopenharmony_ci dctx->entropy.rep[i] = (U32)(seqState.prevOffset[i]); 11488c2ecf20Sopenharmony_ci } 11498c2ecf20Sopenharmony_ci } 11508c2ecf20Sopenharmony_ci 11518c2ecf20Sopenharmony_ci /* last literal segment */ 11528c2ecf20Sopenharmony_ci { 11538c2ecf20Sopenharmony_ci size_t const lastLLSize = litEnd - litPtr; 11548c2ecf20Sopenharmony_ci if (lastLLSize > (size_t)(oend - op)) 11558c2ecf20Sopenharmony_ci return ERROR(dstSize_tooSmall); 11568c2ecf20Sopenharmony_ci memcpy(op, litPtr, lastLLSize); 11578c2ecf20Sopenharmony_ci op += lastLLSize; 11588c2ecf20Sopenharmony_ci } 11598c2ecf20Sopenharmony_ci 11608c2ecf20Sopenharmony_ci return op - ostart; 11618c2ecf20Sopenharmony_ci} 11628c2ecf20Sopenharmony_ci 11638c2ecf20Sopenharmony_ciFORCE_INLINE seq_t ZSTD_decodeSequenceLong_generic(seqState_t *seqState, int const longOffsets) 11648c2ecf20Sopenharmony_ci{ 11658c2ecf20Sopenharmony_ci seq_t seq; 11668c2ecf20Sopenharmony_ci 11678c2ecf20Sopenharmony_ci U32 const llCode = FSE_peekSymbol(&seqState->stateLL); 11688c2ecf20Sopenharmony_ci U32 const mlCode = FSE_peekSymbol(&seqState->stateML); 11698c2ecf20Sopenharmony_ci U32 const ofCode = FSE_peekSymbol(&seqState->stateOffb); /* <= maxOff, by table construction */ 11708c2ecf20Sopenharmony_ci 11718c2ecf20Sopenharmony_ci U32 const llBits = LL_bits[llCode]; 11728c2ecf20Sopenharmony_ci U32 const mlBits = ML_bits[mlCode]; 11738c2ecf20Sopenharmony_ci U32 const ofBits = ofCode; 11748c2ecf20Sopenharmony_ci U32 const totalBits = llBits + mlBits + ofBits; 11758c2ecf20Sopenharmony_ci 11768c2ecf20Sopenharmony_ci static const U32 LL_base[MaxLL + 1] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 18, 11778c2ecf20Sopenharmony_ci 20, 22, 24, 28, 32, 40, 48, 64, 0x80, 0x100, 0x200, 0x400, 0x800, 0x1000, 0x2000, 0x4000, 0x8000, 0x10000}; 11788c2ecf20Sopenharmony_ci 11798c2ecf20Sopenharmony_ci static const U32 ML_base[MaxML + 1] = {3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 11808c2ecf20Sopenharmony_ci 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 37, 39, 41, 11818c2ecf20Sopenharmony_ci 43, 47, 51, 59, 67, 83, 99, 0x83, 0x103, 0x203, 0x403, 0x803, 0x1003, 0x2003, 0x4003, 0x8003, 0x10003}; 11828c2ecf20Sopenharmony_ci 11838c2ecf20Sopenharmony_ci static const U32 OF_base[MaxOff + 1] = {0, 1, 1, 5, 0xD, 0x1D, 0x3D, 0x7D, 0xFD, 0x1FD, 11848c2ecf20Sopenharmony_ci 0x3FD, 0x7FD, 0xFFD, 0x1FFD, 0x3FFD, 0x7FFD, 0xFFFD, 0x1FFFD, 0x3FFFD, 0x7FFFD, 11858c2ecf20Sopenharmony_ci 0xFFFFD, 0x1FFFFD, 0x3FFFFD, 0x7FFFFD, 0xFFFFFD, 0x1FFFFFD, 0x3FFFFFD, 0x7FFFFFD, 0xFFFFFFD}; 11868c2ecf20Sopenharmony_ci 11878c2ecf20Sopenharmony_ci /* sequence */ 11888c2ecf20Sopenharmony_ci { 11898c2ecf20Sopenharmony_ci size_t offset; 11908c2ecf20Sopenharmony_ci if (!ofCode) 11918c2ecf20Sopenharmony_ci offset = 0; 11928c2ecf20Sopenharmony_ci else { 11938c2ecf20Sopenharmony_ci if (longOffsets) { 11948c2ecf20Sopenharmony_ci int const extraBits = ofBits - MIN(ofBits, STREAM_ACCUMULATOR_MIN); 11958c2ecf20Sopenharmony_ci offset = OF_base[ofCode] + (BIT_readBitsFast(&seqState->DStream, ofBits - extraBits) << extraBits); 11968c2ecf20Sopenharmony_ci if (ZSTD_32bits() || extraBits) 11978c2ecf20Sopenharmony_ci BIT_reloadDStream(&seqState->DStream); 11988c2ecf20Sopenharmony_ci if (extraBits) 11998c2ecf20Sopenharmony_ci offset += BIT_readBitsFast(&seqState->DStream, extraBits); 12008c2ecf20Sopenharmony_ci } else { 12018c2ecf20Sopenharmony_ci offset = OF_base[ofCode] + BIT_readBitsFast(&seqState->DStream, ofBits); /* <= (ZSTD_WINDOWLOG_MAX-1) bits */ 12028c2ecf20Sopenharmony_ci if (ZSTD_32bits()) 12038c2ecf20Sopenharmony_ci BIT_reloadDStream(&seqState->DStream); 12048c2ecf20Sopenharmony_ci } 12058c2ecf20Sopenharmony_ci } 12068c2ecf20Sopenharmony_ci 12078c2ecf20Sopenharmony_ci if (ofCode <= 1) { 12088c2ecf20Sopenharmony_ci offset += (llCode == 0); 12098c2ecf20Sopenharmony_ci if (offset) { 12108c2ecf20Sopenharmony_ci size_t temp = (offset == 3) ? seqState->prevOffset[0] - 1 : seqState->prevOffset[offset]; 12118c2ecf20Sopenharmony_ci temp += !temp; /* 0 is not valid; input is corrupted; force offset to 1 */ 12128c2ecf20Sopenharmony_ci if (offset != 1) 12138c2ecf20Sopenharmony_ci seqState->prevOffset[2] = seqState->prevOffset[1]; 12148c2ecf20Sopenharmony_ci seqState->prevOffset[1] = seqState->prevOffset[0]; 12158c2ecf20Sopenharmony_ci seqState->prevOffset[0] = offset = temp; 12168c2ecf20Sopenharmony_ci } else { 12178c2ecf20Sopenharmony_ci offset = seqState->prevOffset[0]; 12188c2ecf20Sopenharmony_ci } 12198c2ecf20Sopenharmony_ci } else { 12208c2ecf20Sopenharmony_ci seqState->prevOffset[2] = seqState->prevOffset[1]; 12218c2ecf20Sopenharmony_ci seqState->prevOffset[1] = seqState->prevOffset[0]; 12228c2ecf20Sopenharmony_ci seqState->prevOffset[0] = offset; 12238c2ecf20Sopenharmony_ci } 12248c2ecf20Sopenharmony_ci seq.offset = offset; 12258c2ecf20Sopenharmony_ci } 12268c2ecf20Sopenharmony_ci 12278c2ecf20Sopenharmony_ci seq.matchLength = ML_base[mlCode] + ((mlCode > 31) ? BIT_readBitsFast(&seqState->DStream, mlBits) : 0); /* <= 16 bits */ 12288c2ecf20Sopenharmony_ci if (ZSTD_32bits() && (mlBits + llBits > 24)) 12298c2ecf20Sopenharmony_ci BIT_reloadDStream(&seqState->DStream); 12308c2ecf20Sopenharmony_ci 12318c2ecf20Sopenharmony_ci seq.litLength = LL_base[llCode] + ((llCode > 15) ? BIT_readBitsFast(&seqState->DStream, llBits) : 0); /* <= 16 bits */ 12328c2ecf20Sopenharmony_ci if (ZSTD_32bits() || (totalBits > 64 - 7 - (LLFSELog + MLFSELog + OffFSELog))) 12338c2ecf20Sopenharmony_ci BIT_reloadDStream(&seqState->DStream); 12348c2ecf20Sopenharmony_ci 12358c2ecf20Sopenharmony_ci { 12368c2ecf20Sopenharmony_ci size_t const pos = seqState->pos + seq.litLength; 12378c2ecf20Sopenharmony_ci seq.match = seqState->base + pos - seq.offset; /* single memory segment */ 12388c2ecf20Sopenharmony_ci if (seq.offset > pos) 12398c2ecf20Sopenharmony_ci seq.match += seqState->gotoDict; /* separate memory segment */ 12408c2ecf20Sopenharmony_ci seqState->pos = pos + seq.matchLength; 12418c2ecf20Sopenharmony_ci } 12428c2ecf20Sopenharmony_ci 12438c2ecf20Sopenharmony_ci /* ANS state update */ 12448c2ecf20Sopenharmony_ci FSE_updateState(&seqState->stateLL, &seqState->DStream); /* <= 9 bits */ 12458c2ecf20Sopenharmony_ci FSE_updateState(&seqState->stateML, &seqState->DStream); /* <= 9 bits */ 12468c2ecf20Sopenharmony_ci if (ZSTD_32bits()) 12478c2ecf20Sopenharmony_ci BIT_reloadDStream(&seqState->DStream); /* <= 18 bits */ 12488c2ecf20Sopenharmony_ci FSE_updateState(&seqState->stateOffb, &seqState->DStream); /* <= 8 bits */ 12498c2ecf20Sopenharmony_ci 12508c2ecf20Sopenharmony_ci return seq; 12518c2ecf20Sopenharmony_ci} 12528c2ecf20Sopenharmony_ci 12538c2ecf20Sopenharmony_cistatic seq_t ZSTD_decodeSequenceLong(seqState_t *seqState, unsigned const windowSize) 12548c2ecf20Sopenharmony_ci{ 12558c2ecf20Sopenharmony_ci if (ZSTD_highbit32(windowSize) > STREAM_ACCUMULATOR_MIN) { 12568c2ecf20Sopenharmony_ci return ZSTD_decodeSequenceLong_generic(seqState, 1); 12578c2ecf20Sopenharmony_ci } else { 12588c2ecf20Sopenharmony_ci return ZSTD_decodeSequenceLong_generic(seqState, 0); 12598c2ecf20Sopenharmony_ci } 12608c2ecf20Sopenharmony_ci} 12618c2ecf20Sopenharmony_ci 12628c2ecf20Sopenharmony_ciFORCE_INLINE 12638c2ecf20Sopenharmony_cisize_t ZSTD_execSequenceLong(BYTE *op, BYTE *const oend, seq_t sequence, const BYTE **litPtr, const BYTE *const litLimit, const BYTE *const base, 12648c2ecf20Sopenharmony_ci const BYTE *const vBase, const BYTE *const dictEnd) 12658c2ecf20Sopenharmony_ci{ 12668c2ecf20Sopenharmony_ci BYTE *const oLitEnd = op + sequence.litLength; 12678c2ecf20Sopenharmony_ci size_t const sequenceLength = sequence.litLength + sequence.matchLength; 12688c2ecf20Sopenharmony_ci BYTE *const oMatchEnd = op + sequenceLength; /* risk : address space overflow (32-bits) */ 12698c2ecf20Sopenharmony_ci BYTE *const oend_w = oend - WILDCOPY_OVERLENGTH; 12708c2ecf20Sopenharmony_ci const BYTE *const iLitEnd = *litPtr + sequence.litLength; 12718c2ecf20Sopenharmony_ci const BYTE *match = sequence.match; 12728c2ecf20Sopenharmony_ci 12738c2ecf20Sopenharmony_ci /* check */ 12748c2ecf20Sopenharmony_ci if (oMatchEnd > oend) 12758c2ecf20Sopenharmony_ci return ERROR(dstSize_tooSmall); /* last match must start at a minimum distance of WILDCOPY_OVERLENGTH from oend */ 12768c2ecf20Sopenharmony_ci if (iLitEnd > litLimit) 12778c2ecf20Sopenharmony_ci return ERROR(corruption_detected); /* over-read beyond lit buffer */ 12788c2ecf20Sopenharmony_ci if (oLitEnd > oend_w) 12798c2ecf20Sopenharmony_ci return ZSTD_execSequenceLast7(op, oend, sequence, litPtr, litLimit, base, vBase, dictEnd); 12808c2ecf20Sopenharmony_ci 12818c2ecf20Sopenharmony_ci /* copy Literals */ 12828c2ecf20Sopenharmony_ci ZSTD_copy8(op, *litPtr); 12838c2ecf20Sopenharmony_ci if (sequence.litLength > 8) 12848c2ecf20Sopenharmony_ci ZSTD_wildcopy(op + 8, (*litPtr) + 8, 12858c2ecf20Sopenharmony_ci sequence.litLength - 8); /* note : since oLitEnd <= oend-WILDCOPY_OVERLENGTH, no risk of overwrite beyond oend */ 12868c2ecf20Sopenharmony_ci op = oLitEnd; 12878c2ecf20Sopenharmony_ci *litPtr = iLitEnd; /* update for next sequence */ 12888c2ecf20Sopenharmony_ci 12898c2ecf20Sopenharmony_ci /* copy Match */ 12908c2ecf20Sopenharmony_ci if (sequence.offset > (size_t)(oLitEnd - base)) { 12918c2ecf20Sopenharmony_ci /* offset beyond prefix */ 12928c2ecf20Sopenharmony_ci if (sequence.offset > (size_t)(oLitEnd - vBase)) 12938c2ecf20Sopenharmony_ci return ERROR(corruption_detected); 12948c2ecf20Sopenharmony_ci if (match + sequence.matchLength <= dictEnd) { 12958c2ecf20Sopenharmony_ci memmove(oLitEnd, match, sequence.matchLength); 12968c2ecf20Sopenharmony_ci return sequenceLength; 12978c2ecf20Sopenharmony_ci } 12988c2ecf20Sopenharmony_ci /* span extDict & currPrefixSegment */ 12998c2ecf20Sopenharmony_ci { 13008c2ecf20Sopenharmony_ci size_t const length1 = dictEnd - match; 13018c2ecf20Sopenharmony_ci memmove(oLitEnd, match, length1); 13028c2ecf20Sopenharmony_ci op = oLitEnd + length1; 13038c2ecf20Sopenharmony_ci sequence.matchLength -= length1; 13048c2ecf20Sopenharmony_ci match = base; 13058c2ecf20Sopenharmony_ci if (op > oend_w || sequence.matchLength < MINMATCH) { 13068c2ecf20Sopenharmony_ci U32 i; 13078c2ecf20Sopenharmony_ci for (i = 0; i < sequence.matchLength; ++i) 13088c2ecf20Sopenharmony_ci op[i] = match[i]; 13098c2ecf20Sopenharmony_ci return sequenceLength; 13108c2ecf20Sopenharmony_ci } 13118c2ecf20Sopenharmony_ci } 13128c2ecf20Sopenharmony_ci } 13138c2ecf20Sopenharmony_ci /* Requirement: op <= oend_w && sequence.matchLength >= MINMATCH */ 13148c2ecf20Sopenharmony_ci 13158c2ecf20Sopenharmony_ci /* match within prefix */ 13168c2ecf20Sopenharmony_ci if (sequence.offset < 8) { 13178c2ecf20Sopenharmony_ci /* close range match, overlap */ 13188c2ecf20Sopenharmony_ci static const U32 dec32table[] = {0, 1, 2, 1, 4, 4, 4, 4}; /* added */ 13198c2ecf20Sopenharmony_ci static const int dec64table[] = {8, 8, 8, 7, 8, 9, 10, 11}; /* subtracted */ 13208c2ecf20Sopenharmony_ci int const sub2 = dec64table[sequence.offset]; 13218c2ecf20Sopenharmony_ci op[0] = match[0]; 13228c2ecf20Sopenharmony_ci op[1] = match[1]; 13238c2ecf20Sopenharmony_ci op[2] = match[2]; 13248c2ecf20Sopenharmony_ci op[3] = match[3]; 13258c2ecf20Sopenharmony_ci match += dec32table[sequence.offset]; 13268c2ecf20Sopenharmony_ci ZSTD_copy4(op + 4, match); 13278c2ecf20Sopenharmony_ci match -= sub2; 13288c2ecf20Sopenharmony_ci } else { 13298c2ecf20Sopenharmony_ci ZSTD_copy8(op, match); 13308c2ecf20Sopenharmony_ci } 13318c2ecf20Sopenharmony_ci op += 8; 13328c2ecf20Sopenharmony_ci match += 8; 13338c2ecf20Sopenharmony_ci 13348c2ecf20Sopenharmony_ci if (oMatchEnd > oend - (16 - MINMATCH)) { 13358c2ecf20Sopenharmony_ci if (op < oend_w) { 13368c2ecf20Sopenharmony_ci ZSTD_wildcopy(op, match, oend_w - op); 13378c2ecf20Sopenharmony_ci match += oend_w - op; 13388c2ecf20Sopenharmony_ci op = oend_w; 13398c2ecf20Sopenharmony_ci } 13408c2ecf20Sopenharmony_ci while (op < oMatchEnd) 13418c2ecf20Sopenharmony_ci *op++ = *match++; 13428c2ecf20Sopenharmony_ci } else { 13438c2ecf20Sopenharmony_ci ZSTD_wildcopy(op, match, (ptrdiff_t)sequence.matchLength - 8); /* works even if matchLength < 8 */ 13448c2ecf20Sopenharmony_ci } 13458c2ecf20Sopenharmony_ci return sequenceLength; 13468c2ecf20Sopenharmony_ci} 13478c2ecf20Sopenharmony_ci 13488c2ecf20Sopenharmony_cistatic size_t ZSTD_decompressSequencesLong(ZSTD_DCtx *dctx, void *dst, size_t maxDstSize, const void *seqStart, size_t seqSize) 13498c2ecf20Sopenharmony_ci{ 13508c2ecf20Sopenharmony_ci const BYTE *ip = (const BYTE *)seqStart; 13518c2ecf20Sopenharmony_ci const BYTE *const iend = ip + seqSize; 13528c2ecf20Sopenharmony_ci BYTE *const ostart = (BYTE * const)dst; 13538c2ecf20Sopenharmony_ci BYTE *const oend = ostart + maxDstSize; 13548c2ecf20Sopenharmony_ci BYTE *op = ostart; 13558c2ecf20Sopenharmony_ci const BYTE *litPtr = dctx->litPtr; 13568c2ecf20Sopenharmony_ci const BYTE *const litEnd = litPtr + dctx->litSize; 13578c2ecf20Sopenharmony_ci const BYTE *const base = (const BYTE *)(dctx->base); 13588c2ecf20Sopenharmony_ci const BYTE *const vBase = (const BYTE *)(dctx->vBase); 13598c2ecf20Sopenharmony_ci const BYTE *const dictEnd = (const BYTE *)(dctx->dictEnd); 13608c2ecf20Sopenharmony_ci unsigned const windowSize = dctx->fParams.windowSize; 13618c2ecf20Sopenharmony_ci int nbSeq; 13628c2ecf20Sopenharmony_ci 13638c2ecf20Sopenharmony_ci /* Build Decoding Tables */ 13648c2ecf20Sopenharmony_ci { 13658c2ecf20Sopenharmony_ci size_t const seqHSize = ZSTD_decodeSeqHeaders(dctx, &nbSeq, ip, seqSize); 13668c2ecf20Sopenharmony_ci if (ZSTD_isError(seqHSize)) 13678c2ecf20Sopenharmony_ci return seqHSize; 13688c2ecf20Sopenharmony_ci ip += seqHSize; 13698c2ecf20Sopenharmony_ci } 13708c2ecf20Sopenharmony_ci 13718c2ecf20Sopenharmony_ci /* Regen sequences */ 13728c2ecf20Sopenharmony_ci if (nbSeq) { 13738c2ecf20Sopenharmony_ci#define STORED_SEQS 4 13748c2ecf20Sopenharmony_ci#define STOSEQ_MASK (STORED_SEQS - 1) 13758c2ecf20Sopenharmony_ci#define ADVANCED_SEQS 4 13768c2ecf20Sopenharmony_ci seq_t *sequences = (seq_t *)dctx->entropy.workspace; 13778c2ecf20Sopenharmony_ci int const seqAdvance = MIN(nbSeq, ADVANCED_SEQS); 13788c2ecf20Sopenharmony_ci seqState_t seqState; 13798c2ecf20Sopenharmony_ci int seqNb; 13808c2ecf20Sopenharmony_ci ZSTD_STATIC_ASSERT(sizeof(dctx->entropy.workspace) >= sizeof(seq_t) * STORED_SEQS); 13818c2ecf20Sopenharmony_ci dctx->fseEntropy = 1; 13828c2ecf20Sopenharmony_ci { 13838c2ecf20Sopenharmony_ci U32 i; 13848c2ecf20Sopenharmony_ci for (i = 0; i < ZSTD_REP_NUM; i++) 13858c2ecf20Sopenharmony_ci seqState.prevOffset[i] = dctx->entropy.rep[i]; 13868c2ecf20Sopenharmony_ci } 13878c2ecf20Sopenharmony_ci seqState.base = base; 13888c2ecf20Sopenharmony_ci seqState.pos = (size_t)(op - base); 13898c2ecf20Sopenharmony_ci seqState.gotoDict = (uPtrDiff)dictEnd - (uPtrDiff)base; /* cast to avoid undefined behaviour */ 13908c2ecf20Sopenharmony_ci CHECK_E(BIT_initDStream(&seqState.DStream, ip, iend - ip), corruption_detected); 13918c2ecf20Sopenharmony_ci FSE_initDState(&seqState.stateLL, &seqState.DStream, dctx->LLTptr); 13928c2ecf20Sopenharmony_ci FSE_initDState(&seqState.stateOffb, &seqState.DStream, dctx->OFTptr); 13938c2ecf20Sopenharmony_ci FSE_initDState(&seqState.stateML, &seqState.DStream, dctx->MLTptr); 13948c2ecf20Sopenharmony_ci 13958c2ecf20Sopenharmony_ci /* prepare in advance */ 13968c2ecf20Sopenharmony_ci for (seqNb = 0; (BIT_reloadDStream(&seqState.DStream) <= BIT_DStream_completed) && seqNb < seqAdvance; seqNb++) { 13978c2ecf20Sopenharmony_ci sequences[seqNb] = ZSTD_decodeSequenceLong(&seqState, windowSize); 13988c2ecf20Sopenharmony_ci } 13998c2ecf20Sopenharmony_ci if (seqNb < seqAdvance) 14008c2ecf20Sopenharmony_ci return ERROR(corruption_detected); 14018c2ecf20Sopenharmony_ci 14028c2ecf20Sopenharmony_ci /* decode and decompress */ 14038c2ecf20Sopenharmony_ci for (; (BIT_reloadDStream(&(seqState.DStream)) <= BIT_DStream_completed) && seqNb < nbSeq; seqNb++) { 14048c2ecf20Sopenharmony_ci seq_t const sequence = ZSTD_decodeSequenceLong(&seqState, windowSize); 14058c2ecf20Sopenharmony_ci size_t const oneSeqSize = 14068c2ecf20Sopenharmony_ci ZSTD_execSequenceLong(op, oend, sequences[(seqNb - ADVANCED_SEQS) & STOSEQ_MASK], &litPtr, litEnd, base, vBase, dictEnd); 14078c2ecf20Sopenharmony_ci if (ZSTD_isError(oneSeqSize)) 14088c2ecf20Sopenharmony_ci return oneSeqSize; 14098c2ecf20Sopenharmony_ci ZSTD_PREFETCH(sequence.match); 14108c2ecf20Sopenharmony_ci sequences[seqNb & STOSEQ_MASK] = sequence; 14118c2ecf20Sopenharmony_ci op += oneSeqSize; 14128c2ecf20Sopenharmony_ci } 14138c2ecf20Sopenharmony_ci if (seqNb < nbSeq) 14148c2ecf20Sopenharmony_ci return ERROR(corruption_detected); 14158c2ecf20Sopenharmony_ci 14168c2ecf20Sopenharmony_ci /* finish queue */ 14178c2ecf20Sopenharmony_ci seqNb -= seqAdvance; 14188c2ecf20Sopenharmony_ci for (; seqNb < nbSeq; seqNb++) { 14198c2ecf20Sopenharmony_ci size_t const oneSeqSize = ZSTD_execSequenceLong(op, oend, sequences[seqNb & STOSEQ_MASK], &litPtr, litEnd, base, vBase, dictEnd); 14208c2ecf20Sopenharmony_ci if (ZSTD_isError(oneSeqSize)) 14218c2ecf20Sopenharmony_ci return oneSeqSize; 14228c2ecf20Sopenharmony_ci op += oneSeqSize; 14238c2ecf20Sopenharmony_ci } 14248c2ecf20Sopenharmony_ci 14258c2ecf20Sopenharmony_ci /* save reps for next block */ 14268c2ecf20Sopenharmony_ci { 14278c2ecf20Sopenharmony_ci U32 i; 14288c2ecf20Sopenharmony_ci for (i = 0; i < ZSTD_REP_NUM; i++) 14298c2ecf20Sopenharmony_ci dctx->entropy.rep[i] = (U32)(seqState.prevOffset[i]); 14308c2ecf20Sopenharmony_ci } 14318c2ecf20Sopenharmony_ci } 14328c2ecf20Sopenharmony_ci 14338c2ecf20Sopenharmony_ci /* last literal segment */ 14348c2ecf20Sopenharmony_ci { 14358c2ecf20Sopenharmony_ci size_t const lastLLSize = litEnd - litPtr; 14368c2ecf20Sopenharmony_ci if (lastLLSize > (size_t)(oend - op)) 14378c2ecf20Sopenharmony_ci return ERROR(dstSize_tooSmall); 14388c2ecf20Sopenharmony_ci memcpy(op, litPtr, lastLLSize); 14398c2ecf20Sopenharmony_ci op += lastLLSize; 14408c2ecf20Sopenharmony_ci } 14418c2ecf20Sopenharmony_ci 14428c2ecf20Sopenharmony_ci return op - ostart; 14438c2ecf20Sopenharmony_ci} 14448c2ecf20Sopenharmony_ci 14458c2ecf20Sopenharmony_cistatic size_t ZSTD_decompressBlock_internal(ZSTD_DCtx *dctx, void *dst, size_t dstCapacity, const void *src, size_t srcSize) 14468c2ecf20Sopenharmony_ci{ /* blockType == blockCompressed */ 14478c2ecf20Sopenharmony_ci const BYTE *ip = (const BYTE *)src; 14488c2ecf20Sopenharmony_ci 14498c2ecf20Sopenharmony_ci if (srcSize >= ZSTD_BLOCKSIZE_ABSOLUTEMAX) 14508c2ecf20Sopenharmony_ci return ERROR(srcSize_wrong); 14518c2ecf20Sopenharmony_ci 14528c2ecf20Sopenharmony_ci /* Decode literals section */ 14538c2ecf20Sopenharmony_ci { 14548c2ecf20Sopenharmony_ci size_t const litCSize = ZSTD_decodeLiteralsBlock(dctx, src, srcSize); 14558c2ecf20Sopenharmony_ci if (ZSTD_isError(litCSize)) 14568c2ecf20Sopenharmony_ci return litCSize; 14578c2ecf20Sopenharmony_ci ip += litCSize; 14588c2ecf20Sopenharmony_ci srcSize -= litCSize; 14598c2ecf20Sopenharmony_ci } 14608c2ecf20Sopenharmony_ci if (sizeof(size_t) > 4) /* do not enable prefetching on 32-bits x86, as it's performance detrimental */ 14618c2ecf20Sopenharmony_ci /* likely because of register pressure */ 14628c2ecf20Sopenharmony_ci /* if that's the correct cause, then 32-bits ARM should be affected differently */ 14638c2ecf20Sopenharmony_ci /* it would be good to test this on ARM real hardware, to see if prefetch version improves speed */ 14648c2ecf20Sopenharmony_ci if (dctx->fParams.windowSize > (1 << 23)) 14658c2ecf20Sopenharmony_ci return ZSTD_decompressSequencesLong(dctx, dst, dstCapacity, ip, srcSize); 14668c2ecf20Sopenharmony_ci return ZSTD_decompressSequences(dctx, dst, dstCapacity, ip, srcSize); 14678c2ecf20Sopenharmony_ci} 14688c2ecf20Sopenharmony_ci 14698c2ecf20Sopenharmony_cistatic void ZSTD_checkContinuity(ZSTD_DCtx *dctx, const void *dst) 14708c2ecf20Sopenharmony_ci{ 14718c2ecf20Sopenharmony_ci if (dst != dctx->previousDstEnd) { /* not contiguous */ 14728c2ecf20Sopenharmony_ci dctx->dictEnd = dctx->previousDstEnd; 14738c2ecf20Sopenharmony_ci dctx->vBase = (const char *)dst - ((const char *)(dctx->previousDstEnd) - (const char *)(dctx->base)); 14748c2ecf20Sopenharmony_ci dctx->base = dst; 14758c2ecf20Sopenharmony_ci dctx->previousDstEnd = dst; 14768c2ecf20Sopenharmony_ci } 14778c2ecf20Sopenharmony_ci} 14788c2ecf20Sopenharmony_ci 14798c2ecf20Sopenharmony_cisize_t ZSTD_decompressBlock(ZSTD_DCtx *dctx, void *dst, size_t dstCapacity, const void *src, size_t srcSize) 14808c2ecf20Sopenharmony_ci{ 14818c2ecf20Sopenharmony_ci size_t dSize; 14828c2ecf20Sopenharmony_ci ZSTD_checkContinuity(dctx, dst); 14838c2ecf20Sopenharmony_ci dSize = ZSTD_decompressBlock_internal(dctx, dst, dstCapacity, src, srcSize); 14848c2ecf20Sopenharmony_ci dctx->previousDstEnd = (char *)dst + dSize; 14858c2ecf20Sopenharmony_ci return dSize; 14868c2ecf20Sopenharmony_ci} 14878c2ecf20Sopenharmony_ci 14888c2ecf20Sopenharmony_ci/** ZSTD_insertBlock() : 14898c2ecf20Sopenharmony_ci insert `src` block into `dctx` history. Useful to track uncompressed blocks. */ 14908c2ecf20Sopenharmony_cisize_t ZSTD_insertBlock(ZSTD_DCtx *dctx, const void *blockStart, size_t blockSize) 14918c2ecf20Sopenharmony_ci{ 14928c2ecf20Sopenharmony_ci ZSTD_checkContinuity(dctx, blockStart); 14938c2ecf20Sopenharmony_ci dctx->previousDstEnd = (const char *)blockStart + blockSize; 14948c2ecf20Sopenharmony_ci return blockSize; 14958c2ecf20Sopenharmony_ci} 14968c2ecf20Sopenharmony_ci 14978c2ecf20Sopenharmony_cisize_t ZSTD_generateNxBytes(void *dst, size_t dstCapacity, BYTE byte, size_t length) 14988c2ecf20Sopenharmony_ci{ 14998c2ecf20Sopenharmony_ci if (length > dstCapacity) 15008c2ecf20Sopenharmony_ci return ERROR(dstSize_tooSmall); 15018c2ecf20Sopenharmony_ci memset(dst, byte, length); 15028c2ecf20Sopenharmony_ci return length; 15038c2ecf20Sopenharmony_ci} 15048c2ecf20Sopenharmony_ci 15058c2ecf20Sopenharmony_ci/** ZSTD_findFrameCompressedSize() : 15068c2ecf20Sopenharmony_ci * compatible with legacy mode 15078c2ecf20Sopenharmony_ci * `src` must point to the start of a ZSTD frame, ZSTD legacy frame, or skippable frame 15088c2ecf20Sopenharmony_ci * `srcSize` must be at least as large as the frame contained 15098c2ecf20Sopenharmony_ci * @return : the compressed size of the frame starting at `src` */ 15108c2ecf20Sopenharmony_cisize_t ZSTD_findFrameCompressedSize(const void *src, size_t srcSize) 15118c2ecf20Sopenharmony_ci{ 15128c2ecf20Sopenharmony_ci if (srcSize >= ZSTD_skippableHeaderSize && (ZSTD_readLE32(src) & 0xFFFFFFF0U) == ZSTD_MAGIC_SKIPPABLE_START) { 15138c2ecf20Sopenharmony_ci return ZSTD_skippableHeaderSize + ZSTD_readLE32((const BYTE *)src + 4); 15148c2ecf20Sopenharmony_ci } else { 15158c2ecf20Sopenharmony_ci const BYTE *ip = (const BYTE *)src; 15168c2ecf20Sopenharmony_ci const BYTE *const ipstart = ip; 15178c2ecf20Sopenharmony_ci size_t remainingSize = srcSize; 15188c2ecf20Sopenharmony_ci ZSTD_frameParams fParams; 15198c2ecf20Sopenharmony_ci 15208c2ecf20Sopenharmony_ci size_t const headerSize = ZSTD_frameHeaderSize(ip, remainingSize); 15218c2ecf20Sopenharmony_ci if (ZSTD_isError(headerSize)) 15228c2ecf20Sopenharmony_ci return headerSize; 15238c2ecf20Sopenharmony_ci 15248c2ecf20Sopenharmony_ci /* Frame Header */ 15258c2ecf20Sopenharmony_ci { 15268c2ecf20Sopenharmony_ci size_t const ret = ZSTD_getFrameParams(&fParams, ip, remainingSize); 15278c2ecf20Sopenharmony_ci if (ZSTD_isError(ret)) 15288c2ecf20Sopenharmony_ci return ret; 15298c2ecf20Sopenharmony_ci if (ret > 0) 15308c2ecf20Sopenharmony_ci return ERROR(srcSize_wrong); 15318c2ecf20Sopenharmony_ci } 15328c2ecf20Sopenharmony_ci 15338c2ecf20Sopenharmony_ci ip += headerSize; 15348c2ecf20Sopenharmony_ci remainingSize -= headerSize; 15358c2ecf20Sopenharmony_ci 15368c2ecf20Sopenharmony_ci /* Loop on each block */ 15378c2ecf20Sopenharmony_ci while (1) { 15388c2ecf20Sopenharmony_ci blockProperties_t blockProperties; 15398c2ecf20Sopenharmony_ci size_t const cBlockSize = ZSTD_getcBlockSize(ip, remainingSize, &blockProperties); 15408c2ecf20Sopenharmony_ci if (ZSTD_isError(cBlockSize)) 15418c2ecf20Sopenharmony_ci return cBlockSize; 15428c2ecf20Sopenharmony_ci 15438c2ecf20Sopenharmony_ci if (ZSTD_blockHeaderSize + cBlockSize > remainingSize) 15448c2ecf20Sopenharmony_ci return ERROR(srcSize_wrong); 15458c2ecf20Sopenharmony_ci 15468c2ecf20Sopenharmony_ci ip += ZSTD_blockHeaderSize + cBlockSize; 15478c2ecf20Sopenharmony_ci remainingSize -= ZSTD_blockHeaderSize + cBlockSize; 15488c2ecf20Sopenharmony_ci 15498c2ecf20Sopenharmony_ci if (blockProperties.lastBlock) 15508c2ecf20Sopenharmony_ci break; 15518c2ecf20Sopenharmony_ci } 15528c2ecf20Sopenharmony_ci 15538c2ecf20Sopenharmony_ci if (fParams.checksumFlag) { /* Frame content checksum */ 15548c2ecf20Sopenharmony_ci if (remainingSize < 4) 15558c2ecf20Sopenharmony_ci return ERROR(srcSize_wrong); 15568c2ecf20Sopenharmony_ci ip += 4; 15578c2ecf20Sopenharmony_ci remainingSize -= 4; 15588c2ecf20Sopenharmony_ci } 15598c2ecf20Sopenharmony_ci 15608c2ecf20Sopenharmony_ci return ip - ipstart; 15618c2ecf20Sopenharmony_ci } 15628c2ecf20Sopenharmony_ci} 15638c2ecf20Sopenharmony_ci 15648c2ecf20Sopenharmony_ci/*! ZSTD_decompressFrame() : 15658c2ecf20Sopenharmony_ci* @dctx must be properly initialized */ 15668c2ecf20Sopenharmony_cistatic size_t ZSTD_decompressFrame(ZSTD_DCtx *dctx, void *dst, size_t dstCapacity, const void **srcPtr, size_t *srcSizePtr) 15678c2ecf20Sopenharmony_ci{ 15688c2ecf20Sopenharmony_ci const BYTE *ip = (const BYTE *)(*srcPtr); 15698c2ecf20Sopenharmony_ci BYTE *const ostart = (BYTE * const)dst; 15708c2ecf20Sopenharmony_ci BYTE *const oend = ostart + dstCapacity; 15718c2ecf20Sopenharmony_ci BYTE *op = ostart; 15728c2ecf20Sopenharmony_ci size_t remainingSize = *srcSizePtr; 15738c2ecf20Sopenharmony_ci 15748c2ecf20Sopenharmony_ci /* check */ 15758c2ecf20Sopenharmony_ci if (remainingSize < ZSTD_frameHeaderSize_min + ZSTD_blockHeaderSize) 15768c2ecf20Sopenharmony_ci return ERROR(srcSize_wrong); 15778c2ecf20Sopenharmony_ci 15788c2ecf20Sopenharmony_ci /* Frame Header */ 15798c2ecf20Sopenharmony_ci { 15808c2ecf20Sopenharmony_ci size_t const frameHeaderSize = ZSTD_frameHeaderSize(ip, ZSTD_frameHeaderSize_prefix); 15818c2ecf20Sopenharmony_ci if (ZSTD_isError(frameHeaderSize)) 15828c2ecf20Sopenharmony_ci return frameHeaderSize; 15838c2ecf20Sopenharmony_ci if (remainingSize < frameHeaderSize + ZSTD_blockHeaderSize) 15848c2ecf20Sopenharmony_ci return ERROR(srcSize_wrong); 15858c2ecf20Sopenharmony_ci CHECK_F(ZSTD_decodeFrameHeader(dctx, ip, frameHeaderSize)); 15868c2ecf20Sopenharmony_ci ip += frameHeaderSize; 15878c2ecf20Sopenharmony_ci remainingSize -= frameHeaderSize; 15888c2ecf20Sopenharmony_ci } 15898c2ecf20Sopenharmony_ci 15908c2ecf20Sopenharmony_ci /* Loop on each block */ 15918c2ecf20Sopenharmony_ci while (1) { 15928c2ecf20Sopenharmony_ci size_t decodedSize; 15938c2ecf20Sopenharmony_ci blockProperties_t blockProperties; 15948c2ecf20Sopenharmony_ci size_t const cBlockSize = ZSTD_getcBlockSize(ip, remainingSize, &blockProperties); 15958c2ecf20Sopenharmony_ci if (ZSTD_isError(cBlockSize)) 15968c2ecf20Sopenharmony_ci return cBlockSize; 15978c2ecf20Sopenharmony_ci 15988c2ecf20Sopenharmony_ci ip += ZSTD_blockHeaderSize; 15998c2ecf20Sopenharmony_ci remainingSize -= ZSTD_blockHeaderSize; 16008c2ecf20Sopenharmony_ci if (cBlockSize > remainingSize) 16018c2ecf20Sopenharmony_ci return ERROR(srcSize_wrong); 16028c2ecf20Sopenharmony_ci 16038c2ecf20Sopenharmony_ci switch (blockProperties.blockType) { 16048c2ecf20Sopenharmony_ci case bt_compressed: decodedSize = ZSTD_decompressBlock_internal(dctx, op, oend - op, ip, cBlockSize); break; 16058c2ecf20Sopenharmony_ci case bt_raw: decodedSize = ZSTD_copyRawBlock(op, oend - op, ip, cBlockSize); break; 16068c2ecf20Sopenharmony_ci case bt_rle: decodedSize = ZSTD_generateNxBytes(op, oend - op, *ip, blockProperties.origSize); break; 16078c2ecf20Sopenharmony_ci case bt_reserved: 16088c2ecf20Sopenharmony_ci default: return ERROR(corruption_detected); 16098c2ecf20Sopenharmony_ci } 16108c2ecf20Sopenharmony_ci 16118c2ecf20Sopenharmony_ci if (ZSTD_isError(decodedSize)) 16128c2ecf20Sopenharmony_ci return decodedSize; 16138c2ecf20Sopenharmony_ci if (dctx->fParams.checksumFlag) 16148c2ecf20Sopenharmony_ci xxh64_update(&dctx->xxhState, op, decodedSize); 16158c2ecf20Sopenharmony_ci op += decodedSize; 16168c2ecf20Sopenharmony_ci ip += cBlockSize; 16178c2ecf20Sopenharmony_ci remainingSize -= cBlockSize; 16188c2ecf20Sopenharmony_ci if (blockProperties.lastBlock) 16198c2ecf20Sopenharmony_ci break; 16208c2ecf20Sopenharmony_ci } 16218c2ecf20Sopenharmony_ci 16228c2ecf20Sopenharmony_ci if (dctx->fParams.checksumFlag) { /* Frame content checksum verification */ 16238c2ecf20Sopenharmony_ci U32 const checkCalc = (U32)xxh64_digest(&dctx->xxhState); 16248c2ecf20Sopenharmony_ci U32 checkRead; 16258c2ecf20Sopenharmony_ci if (remainingSize < 4) 16268c2ecf20Sopenharmony_ci return ERROR(checksum_wrong); 16278c2ecf20Sopenharmony_ci checkRead = ZSTD_readLE32(ip); 16288c2ecf20Sopenharmony_ci if (checkRead != checkCalc) 16298c2ecf20Sopenharmony_ci return ERROR(checksum_wrong); 16308c2ecf20Sopenharmony_ci ip += 4; 16318c2ecf20Sopenharmony_ci remainingSize -= 4; 16328c2ecf20Sopenharmony_ci } 16338c2ecf20Sopenharmony_ci 16348c2ecf20Sopenharmony_ci /* Allow caller to get size read */ 16358c2ecf20Sopenharmony_ci *srcPtr = ip; 16368c2ecf20Sopenharmony_ci *srcSizePtr = remainingSize; 16378c2ecf20Sopenharmony_ci return op - ostart; 16388c2ecf20Sopenharmony_ci} 16398c2ecf20Sopenharmony_ci 16408c2ecf20Sopenharmony_cistatic const void *ZSTD_DDictDictContent(const ZSTD_DDict *ddict); 16418c2ecf20Sopenharmony_cistatic size_t ZSTD_DDictDictSize(const ZSTD_DDict *ddict); 16428c2ecf20Sopenharmony_ci 16438c2ecf20Sopenharmony_cistatic size_t ZSTD_decompressMultiFrame(ZSTD_DCtx *dctx, void *dst, size_t dstCapacity, const void *src, size_t srcSize, const void *dict, size_t dictSize, 16448c2ecf20Sopenharmony_ci const ZSTD_DDict *ddict) 16458c2ecf20Sopenharmony_ci{ 16468c2ecf20Sopenharmony_ci void *const dststart = dst; 16478c2ecf20Sopenharmony_ci 16488c2ecf20Sopenharmony_ci if (ddict) { 16498c2ecf20Sopenharmony_ci if (dict) { 16508c2ecf20Sopenharmony_ci /* programmer error, these two cases should be mutually exclusive */ 16518c2ecf20Sopenharmony_ci return ERROR(GENERIC); 16528c2ecf20Sopenharmony_ci } 16538c2ecf20Sopenharmony_ci 16548c2ecf20Sopenharmony_ci dict = ZSTD_DDictDictContent(ddict); 16558c2ecf20Sopenharmony_ci dictSize = ZSTD_DDictDictSize(ddict); 16568c2ecf20Sopenharmony_ci } 16578c2ecf20Sopenharmony_ci 16588c2ecf20Sopenharmony_ci while (srcSize >= ZSTD_frameHeaderSize_prefix) { 16598c2ecf20Sopenharmony_ci U32 magicNumber; 16608c2ecf20Sopenharmony_ci 16618c2ecf20Sopenharmony_ci magicNumber = ZSTD_readLE32(src); 16628c2ecf20Sopenharmony_ci if (magicNumber != ZSTD_MAGICNUMBER) { 16638c2ecf20Sopenharmony_ci if ((magicNumber & 0xFFFFFFF0U) == ZSTD_MAGIC_SKIPPABLE_START) { 16648c2ecf20Sopenharmony_ci size_t skippableSize; 16658c2ecf20Sopenharmony_ci if (srcSize < ZSTD_skippableHeaderSize) 16668c2ecf20Sopenharmony_ci return ERROR(srcSize_wrong); 16678c2ecf20Sopenharmony_ci skippableSize = ZSTD_readLE32((const BYTE *)src + 4) + ZSTD_skippableHeaderSize; 16688c2ecf20Sopenharmony_ci if (srcSize < skippableSize) { 16698c2ecf20Sopenharmony_ci return ERROR(srcSize_wrong); 16708c2ecf20Sopenharmony_ci } 16718c2ecf20Sopenharmony_ci 16728c2ecf20Sopenharmony_ci src = (const BYTE *)src + skippableSize; 16738c2ecf20Sopenharmony_ci srcSize -= skippableSize; 16748c2ecf20Sopenharmony_ci continue; 16758c2ecf20Sopenharmony_ci } else { 16768c2ecf20Sopenharmony_ci return ERROR(prefix_unknown); 16778c2ecf20Sopenharmony_ci } 16788c2ecf20Sopenharmony_ci } 16798c2ecf20Sopenharmony_ci 16808c2ecf20Sopenharmony_ci if (ddict) { 16818c2ecf20Sopenharmony_ci /* we were called from ZSTD_decompress_usingDDict */ 16828c2ecf20Sopenharmony_ci ZSTD_refDDict(dctx, ddict); 16838c2ecf20Sopenharmony_ci } else { 16848c2ecf20Sopenharmony_ci /* this will initialize correctly with no dict if dict == NULL, so 16858c2ecf20Sopenharmony_ci * use this in all cases but ddict */ 16868c2ecf20Sopenharmony_ci CHECK_F(ZSTD_decompressBegin_usingDict(dctx, dict, dictSize)); 16878c2ecf20Sopenharmony_ci } 16888c2ecf20Sopenharmony_ci ZSTD_checkContinuity(dctx, dst); 16898c2ecf20Sopenharmony_ci 16908c2ecf20Sopenharmony_ci { 16918c2ecf20Sopenharmony_ci const size_t res = ZSTD_decompressFrame(dctx, dst, dstCapacity, &src, &srcSize); 16928c2ecf20Sopenharmony_ci if (ZSTD_isError(res)) 16938c2ecf20Sopenharmony_ci return res; 16948c2ecf20Sopenharmony_ci /* don't need to bounds check this, ZSTD_decompressFrame will have 16958c2ecf20Sopenharmony_ci * already */ 16968c2ecf20Sopenharmony_ci dst = (BYTE *)dst + res; 16978c2ecf20Sopenharmony_ci dstCapacity -= res; 16988c2ecf20Sopenharmony_ci } 16998c2ecf20Sopenharmony_ci } 17008c2ecf20Sopenharmony_ci 17018c2ecf20Sopenharmony_ci if (srcSize) 17028c2ecf20Sopenharmony_ci return ERROR(srcSize_wrong); /* input not entirely consumed */ 17038c2ecf20Sopenharmony_ci 17048c2ecf20Sopenharmony_ci return (BYTE *)dst - (BYTE *)dststart; 17058c2ecf20Sopenharmony_ci} 17068c2ecf20Sopenharmony_ci 17078c2ecf20Sopenharmony_cisize_t ZSTD_decompress_usingDict(ZSTD_DCtx *dctx, void *dst, size_t dstCapacity, const void *src, size_t srcSize, const void *dict, size_t dictSize) 17088c2ecf20Sopenharmony_ci{ 17098c2ecf20Sopenharmony_ci return ZSTD_decompressMultiFrame(dctx, dst, dstCapacity, src, srcSize, dict, dictSize, NULL); 17108c2ecf20Sopenharmony_ci} 17118c2ecf20Sopenharmony_ci 17128c2ecf20Sopenharmony_cisize_t ZSTD_decompressDCtx(ZSTD_DCtx *dctx, void *dst, size_t dstCapacity, const void *src, size_t srcSize) 17138c2ecf20Sopenharmony_ci{ 17148c2ecf20Sopenharmony_ci return ZSTD_decompress_usingDict(dctx, dst, dstCapacity, src, srcSize, NULL, 0); 17158c2ecf20Sopenharmony_ci} 17168c2ecf20Sopenharmony_ci 17178c2ecf20Sopenharmony_ci/*-************************************** 17188c2ecf20Sopenharmony_ci* Advanced Streaming Decompression API 17198c2ecf20Sopenharmony_ci* Bufferless and synchronous 17208c2ecf20Sopenharmony_ci****************************************/ 17218c2ecf20Sopenharmony_cisize_t ZSTD_nextSrcSizeToDecompress(ZSTD_DCtx *dctx) { return dctx->expected; } 17228c2ecf20Sopenharmony_ci 17238c2ecf20Sopenharmony_ciZSTD_nextInputType_e ZSTD_nextInputType(ZSTD_DCtx *dctx) 17248c2ecf20Sopenharmony_ci{ 17258c2ecf20Sopenharmony_ci switch (dctx->stage) { 17268c2ecf20Sopenharmony_ci default: /* should not happen */ 17278c2ecf20Sopenharmony_ci case ZSTDds_getFrameHeaderSize: 17288c2ecf20Sopenharmony_ci case ZSTDds_decodeFrameHeader: return ZSTDnit_frameHeader; 17298c2ecf20Sopenharmony_ci case ZSTDds_decodeBlockHeader: return ZSTDnit_blockHeader; 17308c2ecf20Sopenharmony_ci case ZSTDds_decompressBlock: return ZSTDnit_block; 17318c2ecf20Sopenharmony_ci case ZSTDds_decompressLastBlock: return ZSTDnit_lastBlock; 17328c2ecf20Sopenharmony_ci case ZSTDds_checkChecksum: return ZSTDnit_checksum; 17338c2ecf20Sopenharmony_ci case ZSTDds_decodeSkippableHeader: 17348c2ecf20Sopenharmony_ci case ZSTDds_skipFrame: return ZSTDnit_skippableFrame; 17358c2ecf20Sopenharmony_ci } 17368c2ecf20Sopenharmony_ci} 17378c2ecf20Sopenharmony_ci 17388c2ecf20Sopenharmony_ciint ZSTD_isSkipFrame(ZSTD_DCtx *dctx) { return dctx->stage == ZSTDds_skipFrame; } /* for zbuff */ 17398c2ecf20Sopenharmony_ci 17408c2ecf20Sopenharmony_ci/** ZSTD_decompressContinue() : 17418c2ecf20Sopenharmony_ci* @return : nb of bytes generated into `dst` (necessarily <= `dstCapacity) 17428c2ecf20Sopenharmony_ci* or an error code, which can be tested using ZSTD_isError() */ 17438c2ecf20Sopenharmony_cisize_t ZSTD_decompressContinue(ZSTD_DCtx *dctx, void *dst, size_t dstCapacity, const void *src, size_t srcSize) 17448c2ecf20Sopenharmony_ci{ 17458c2ecf20Sopenharmony_ci /* Sanity check */ 17468c2ecf20Sopenharmony_ci if (srcSize != dctx->expected) 17478c2ecf20Sopenharmony_ci return ERROR(srcSize_wrong); 17488c2ecf20Sopenharmony_ci if (dstCapacity) 17498c2ecf20Sopenharmony_ci ZSTD_checkContinuity(dctx, dst); 17508c2ecf20Sopenharmony_ci 17518c2ecf20Sopenharmony_ci switch (dctx->stage) { 17528c2ecf20Sopenharmony_ci case ZSTDds_getFrameHeaderSize: 17538c2ecf20Sopenharmony_ci if (srcSize != ZSTD_frameHeaderSize_prefix) 17548c2ecf20Sopenharmony_ci return ERROR(srcSize_wrong); /* impossible */ 17558c2ecf20Sopenharmony_ci if ((ZSTD_readLE32(src) & 0xFFFFFFF0U) == ZSTD_MAGIC_SKIPPABLE_START) { /* skippable frame */ 17568c2ecf20Sopenharmony_ci memcpy(dctx->headerBuffer, src, ZSTD_frameHeaderSize_prefix); 17578c2ecf20Sopenharmony_ci dctx->expected = ZSTD_skippableHeaderSize - ZSTD_frameHeaderSize_prefix; /* magic number + skippable frame length */ 17588c2ecf20Sopenharmony_ci dctx->stage = ZSTDds_decodeSkippableHeader; 17598c2ecf20Sopenharmony_ci return 0; 17608c2ecf20Sopenharmony_ci } 17618c2ecf20Sopenharmony_ci dctx->headerSize = ZSTD_frameHeaderSize(src, ZSTD_frameHeaderSize_prefix); 17628c2ecf20Sopenharmony_ci if (ZSTD_isError(dctx->headerSize)) 17638c2ecf20Sopenharmony_ci return dctx->headerSize; 17648c2ecf20Sopenharmony_ci memcpy(dctx->headerBuffer, src, ZSTD_frameHeaderSize_prefix); 17658c2ecf20Sopenharmony_ci if (dctx->headerSize > ZSTD_frameHeaderSize_prefix) { 17668c2ecf20Sopenharmony_ci dctx->expected = dctx->headerSize - ZSTD_frameHeaderSize_prefix; 17678c2ecf20Sopenharmony_ci dctx->stage = ZSTDds_decodeFrameHeader; 17688c2ecf20Sopenharmony_ci return 0; 17698c2ecf20Sopenharmony_ci } 17708c2ecf20Sopenharmony_ci dctx->expected = 0; /* not necessary to copy more */ 17718c2ecf20Sopenharmony_ci /* fall through */ 17728c2ecf20Sopenharmony_ci 17738c2ecf20Sopenharmony_ci case ZSTDds_decodeFrameHeader: 17748c2ecf20Sopenharmony_ci memcpy(dctx->headerBuffer + ZSTD_frameHeaderSize_prefix, src, dctx->expected); 17758c2ecf20Sopenharmony_ci CHECK_F(ZSTD_decodeFrameHeader(dctx, dctx->headerBuffer, dctx->headerSize)); 17768c2ecf20Sopenharmony_ci dctx->expected = ZSTD_blockHeaderSize; 17778c2ecf20Sopenharmony_ci dctx->stage = ZSTDds_decodeBlockHeader; 17788c2ecf20Sopenharmony_ci return 0; 17798c2ecf20Sopenharmony_ci 17808c2ecf20Sopenharmony_ci case ZSTDds_decodeBlockHeader: { 17818c2ecf20Sopenharmony_ci blockProperties_t bp; 17828c2ecf20Sopenharmony_ci size_t const cBlockSize = ZSTD_getcBlockSize(src, ZSTD_blockHeaderSize, &bp); 17838c2ecf20Sopenharmony_ci if (ZSTD_isError(cBlockSize)) 17848c2ecf20Sopenharmony_ci return cBlockSize; 17858c2ecf20Sopenharmony_ci dctx->expected = cBlockSize; 17868c2ecf20Sopenharmony_ci dctx->bType = bp.blockType; 17878c2ecf20Sopenharmony_ci dctx->rleSize = bp.origSize; 17888c2ecf20Sopenharmony_ci if (cBlockSize) { 17898c2ecf20Sopenharmony_ci dctx->stage = bp.lastBlock ? ZSTDds_decompressLastBlock : ZSTDds_decompressBlock; 17908c2ecf20Sopenharmony_ci return 0; 17918c2ecf20Sopenharmony_ci } 17928c2ecf20Sopenharmony_ci /* empty block */ 17938c2ecf20Sopenharmony_ci if (bp.lastBlock) { 17948c2ecf20Sopenharmony_ci if (dctx->fParams.checksumFlag) { 17958c2ecf20Sopenharmony_ci dctx->expected = 4; 17968c2ecf20Sopenharmony_ci dctx->stage = ZSTDds_checkChecksum; 17978c2ecf20Sopenharmony_ci } else { 17988c2ecf20Sopenharmony_ci dctx->expected = 0; /* end of frame */ 17998c2ecf20Sopenharmony_ci dctx->stage = ZSTDds_getFrameHeaderSize; 18008c2ecf20Sopenharmony_ci } 18018c2ecf20Sopenharmony_ci } else { 18028c2ecf20Sopenharmony_ci dctx->expected = 3; /* go directly to next header */ 18038c2ecf20Sopenharmony_ci dctx->stage = ZSTDds_decodeBlockHeader; 18048c2ecf20Sopenharmony_ci } 18058c2ecf20Sopenharmony_ci return 0; 18068c2ecf20Sopenharmony_ci } 18078c2ecf20Sopenharmony_ci case ZSTDds_decompressLastBlock: 18088c2ecf20Sopenharmony_ci case ZSTDds_decompressBlock: { 18098c2ecf20Sopenharmony_ci size_t rSize; 18108c2ecf20Sopenharmony_ci switch (dctx->bType) { 18118c2ecf20Sopenharmony_ci case bt_compressed: rSize = ZSTD_decompressBlock_internal(dctx, dst, dstCapacity, src, srcSize); break; 18128c2ecf20Sopenharmony_ci case bt_raw: rSize = ZSTD_copyRawBlock(dst, dstCapacity, src, srcSize); break; 18138c2ecf20Sopenharmony_ci case bt_rle: rSize = ZSTD_setRleBlock(dst, dstCapacity, src, srcSize, dctx->rleSize); break; 18148c2ecf20Sopenharmony_ci case bt_reserved: /* should never happen */ 18158c2ecf20Sopenharmony_ci default: return ERROR(corruption_detected); 18168c2ecf20Sopenharmony_ci } 18178c2ecf20Sopenharmony_ci if (ZSTD_isError(rSize)) 18188c2ecf20Sopenharmony_ci return rSize; 18198c2ecf20Sopenharmony_ci if (dctx->fParams.checksumFlag) 18208c2ecf20Sopenharmony_ci xxh64_update(&dctx->xxhState, dst, rSize); 18218c2ecf20Sopenharmony_ci 18228c2ecf20Sopenharmony_ci if (dctx->stage == ZSTDds_decompressLastBlock) { /* end of frame */ 18238c2ecf20Sopenharmony_ci if (dctx->fParams.checksumFlag) { /* another round for frame checksum */ 18248c2ecf20Sopenharmony_ci dctx->expected = 4; 18258c2ecf20Sopenharmony_ci dctx->stage = ZSTDds_checkChecksum; 18268c2ecf20Sopenharmony_ci } else { 18278c2ecf20Sopenharmony_ci dctx->expected = 0; /* ends here */ 18288c2ecf20Sopenharmony_ci dctx->stage = ZSTDds_getFrameHeaderSize; 18298c2ecf20Sopenharmony_ci } 18308c2ecf20Sopenharmony_ci } else { 18318c2ecf20Sopenharmony_ci dctx->stage = ZSTDds_decodeBlockHeader; 18328c2ecf20Sopenharmony_ci dctx->expected = ZSTD_blockHeaderSize; 18338c2ecf20Sopenharmony_ci dctx->previousDstEnd = (char *)dst + rSize; 18348c2ecf20Sopenharmony_ci } 18358c2ecf20Sopenharmony_ci return rSize; 18368c2ecf20Sopenharmony_ci } 18378c2ecf20Sopenharmony_ci case ZSTDds_checkChecksum: { 18388c2ecf20Sopenharmony_ci U32 const h32 = (U32)xxh64_digest(&dctx->xxhState); 18398c2ecf20Sopenharmony_ci U32 const check32 = ZSTD_readLE32(src); /* srcSize == 4, guaranteed by dctx->expected */ 18408c2ecf20Sopenharmony_ci if (check32 != h32) 18418c2ecf20Sopenharmony_ci return ERROR(checksum_wrong); 18428c2ecf20Sopenharmony_ci dctx->expected = 0; 18438c2ecf20Sopenharmony_ci dctx->stage = ZSTDds_getFrameHeaderSize; 18448c2ecf20Sopenharmony_ci return 0; 18458c2ecf20Sopenharmony_ci } 18468c2ecf20Sopenharmony_ci case ZSTDds_decodeSkippableHeader: { 18478c2ecf20Sopenharmony_ci memcpy(dctx->headerBuffer + ZSTD_frameHeaderSize_prefix, src, dctx->expected); 18488c2ecf20Sopenharmony_ci dctx->expected = ZSTD_readLE32(dctx->headerBuffer + 4); 18498c2ecf20Sopenharmony_ci dctx->stage = ZSTDds_skipFrame; 18508c2ecf20Sopenharmony_ci return 0; 18518c2ecf20Sopenharmony_ci } 18528c2ecf20Sopenharmony_ci case ZSTDds_skipFrame: { 18538c2ecf20Sopenharmony_ci dctx->expected = 0; 18548c2ecf20Sopenharmony_ci dctx->stage = ZSTDds_getFrameHeaderSize; 18558c2ecf20Sopenharmony_ci return 0; 18568c2ecf20Sopenharmony_ci } 18578c2ecf20Sopenharmony_ci default: 18588c2ecf20Sopenharmony_ci return ERROR(GENERIC); /* impossible */ 18598c2ecf20Sopenharmony_ci } 18608c2ecf20Sopenharmony_ci} 18618c2ecf20Sopenharmony_ci 18628c2ecf20Sopenharmony_cistatic size_t ZSTD_refDictContent(ZSTD_DCtx *dctx, const void *dict, size_t dictSize) 18638c2ecf20Sopenharmony_ci{ 18648c2ecf20Sopenharmony_ci dctx->dictEnd = dctx->previousDstEnd; 18658c2ecf20Sopenharmony_ci dctx->vBase = (const char *)dict - ((const char *)(dctx->previousDstEnd) - (const char *)(dctx->base)); 18668c2ecf20Sopenharmony_ci dctx->base = dict; 18678c2ecf20Sopenharmony_ci dctx->previousDstEnd = (const char *)dict + dictSize; 18688c2ecf20Sopenharmony_ci return 0; 18698c2ecf20Sopenharmony_ci} 18708c2ecf20Sopenharmony_ci 18718c2ecf20Sopenharmony_ci/* ZSTD_loadEntropy() : 18728c2ecf20Sopenharmony_ci * dict : must point at beginning of a valid zstd dictionary 18738c2ecf20Sopenharmony_ci * @return : size of entropy tables read */ 18748c2ecf20Sopenharmony_cistatic size_t ZSTD_loadEntropy(ZSTD_entropyTables_t *entropy, const void *const dict, size_t const dictSize) 18758c2ecf20Sopenharmony_ci{ 18768c2ecf20Sopenharmony_ci const BYTE *dictPtr = (const BYTE *)dict; 18778c2ecf20Sopenharmony_ci const BYTE *const dictEnd = dictPtr + dictSize; 18788c2ecf20Sopenharmony_ci 18798c2ecf20Sopenharmony_ci if (dictSize <= 8) 18808c2ecf20Sopenharmony_ci return ERROR(dictionary_corrupted); 18818c2ecf20Sopenharmony_ci dictPtr += 8; /* skip header = magic + dictID */ 18828c2ecf20Sopenharmony_ci 18838c2ecf20Sopenharmony_ci { 18848c2ecf20Sopenharmony_ci size_t const hSize = HUF_readDTableX4_wksp(entropy->hufTable, dictPtr, dictEnd - dictPtr, entropy->workspace, sizeof(entropy->workspace)); 18858c2ecf20Sopenharmony_ci if (HUF_isError(hSize)) 18868c2ecf20Sopenharmony_ci return ERROR(dictionary_corrupted); 18878c2ecf20Sopenharmony_ci dictPtr += hSize; 18888c2ecf20Sopenharmony_ci } 18898c2ecf20Sopenharmony_ci 18908c2ecf20Sopenharmony_ci { 18918c2ecf20Sopenharmony_ci short offcodeNCount[MaxOff + 1]; 18928c2ecf20Sopenharmony_ci U32 offcodeMaxValue = MaxOff, offcodeLog; 18938c2ecf20Sopenharmony_ci size_t const offcodeHeaderSize = FSE_readNCount(offcodeNCount, &offcodeMaxValue, &offcodeLog, dictPtr, dictEnd - dictPtr); 18948c2ecf20Sopenharmony_ci if (FSE_isError(offcodeHeaderSize)) 18958c2ecf20Sopenharmony_ci return ERROR(dictionary_corrupted); 18968c2ecf20Sopenharmony_ci if (offcodeLog > OffFSELog) 18978c2ecf20Sopenharmony_ci return ERROR(dictionary_corrupted); 18988c2ecf20Sopenharmony_ci CHECK_E(FSE_buildDTable_wksp(entropy->OFTable, offcodeNCount, offcodeMaxValue, offcodeLog, entropy->workspace, sizeof(entropy->workspace)), dictionary_corrupted); 18998c2ecf20Sopenharmony_ci dictPtr += offcodeHeaderSize; 19008c2ecf20Sopenharmony_ci } 19018c2ecf20Sopenharmony_ci 19028c2ecf20Sopenharmony_ci { 19038c2ecf20Sopenharmony_ci short matchlengthNCount[MaxML + 1]; 19048c2ecf20Sopenharmony_ci unsigned matchlengthMaxValue = MaxML, matchlengthLog; 19058c2ecf20Sopenharmony_ci size_t const matchlengthHeaderSize = FSE_readNCount(matchlengthNCount, &matchlengthMaxValue, &matchlengthLog, dictPtr, dictEnd - dictPtr); 19068c2ecf20Sopenharmony_ci if (FSE_isError(matchlengthHeaderSize)) 19078c2ecf20Sopenharmony_ci return ERROR(dictionary_corrupted); 19088c2ecf20Sopenharmony_ci if (matchlengthLog > MLFSELog) 19098c2ecf20Sopenharmony_ci return ERROR(dictionary_corrupted); 19108c2ecf20Sopenharmony_ci CHECK_E(FSE_buildDTable_wksp(entropy->MLTable, matchlengthNCount, matchlengthMaxValue, matchlengthLog, entropy->workspace, sizeof(entropy->workspace)), dictionary_corrupted); 19118c2ecf20Sopenharmony_ci dictPtr += matchlengthHeaderSize; 19128c2ecf20Sopenharmony_ci } 19138c2ecf20Sopenharmony_ci 19148c2ecf20Sopenharmony_ci { 19158c2ecf20Sopenharmony_ci short litlengthNCount[MaxLL + 1]; 19168c2ecf20Sopenharmony_ci unsigned litlengthMaxValue = MaxLL, litlengthLog; 19178c2ecf20Sopenharmony_ci size_t const litlengthHeaderSize = FSE_readNCount(litlengthNCount, &litlengthMaxValue, &litlengthLog, dictPtr, dictEnd - dictPtr); 19188c2ecf20Sopenharmony_ci if (FSE_isError(litlengthHeaderSize)) 19198c2ecf20Sopenharmony_ci return ERROR(dictionary_corrupted); 19208c2ecf20Sopenharmony_ci if (litlengthLog > LLFSELog) 19218c2ecf20Sopenharmony_ci return ERROR(dictionary_corrupted); 19228c2ecf20Sopenharmony_ci CHECK_E(FSE_buildDTable_wksp(entropy->LLTable, litlengthNCount, litlengthMaxValue, litlengthLog, entropy->workspace, sizeof(entropy->workspace)), dictionary_corrupted); 19238c2ecf20Sopenharmony_ci dictPtr += litlengthHeaderSize; 19248c2ecf20Sopenharmony_ci } 19258c2ecf20Sopenharmony_ci 19268c2ecf20Sopenharmony_ci if (dictPtr + 12 > dictEnd) 19278c2ecf20Sopenharmony_ci return ERROR(dictionary_corrupted); 19288c2ecf20Sopenharmony_ci { 19298c2ecf20Sopenharmony_ci int i; 19308c2ecf20Sopenharmony_ci size_t const dictContentSize = (size_t)(dictEnd - (dictPtr + 12)); 19318c2ecf20Sopenharmony_ci for (i = 0; i < 3; i++) { 19328c2ecf20Sopenharmony_ci U32 const rep = ZSTD_readLE32(dictPtr); 19338c2ecf20Sopenharmony_ci dictPtr += 4; 19348c2ecf20Sopenharmony_ci if (rep == 0 || rep >= dictContentSize) 19358c2ecf20Sopenharmony_ci return ERROR(dictionary_corrupted); 19368c2ecf20Sopenharmony_ci entropy->rep[i] = rep; 19378c2ecf20Sopenharmony_ci } 19388c2ecf20Sopenharmony_ci } 19398c2ecf20Sopenharmony_ci 19408c2ecf20Sopenharmony_ci return dictPtr - (const BYTE *)dict; 19418c2ecf20Sopenharmony_ci} 19428c2ecf20Sopenharmony_ci 19438c2ecf20Sopenharmony_cistatic size_t ZSTD_decompress_insertDictionary(ZSTD_DCtx *dctx, const void *dict, size_t dictSize) 19448c2ecf20Sopenharmony_ci{ 19458c2ecf20Sopenharmony_ci if (dictSize < 8) 19468c2ecf20Sopenharmony_ci return ZSTD_refDictContent(dctx, dict, dictSize); 19478c2ecf20Sopenharmony_ci { 19488c2ecf20Sopenharmony_ci U32 const magic = ZSTD_readLE32(dict); 19498c2ecf20Sopenharmony_ci if (magic != ZSTD_DICT_MAGIC) { 19508c2ecf20Sopenharmony_ci return ZSTD_refDictContent(dctx, dict, dictSize); /* pure content mode */ 19518c2ecf20Sopenharmony_ci } 19528c2ecf20Sopenharmony_ci } 19538c2ecf20Sopenharmony_ci dctx->dictID = ZSTD_readLE32((const char *)dict + 4); 19548c2ecf20Sopenharmony_ci 19558c2ecf20Sopenharmony_ci /* load entropy tables */ 19568c2ecf20Sopenharmony_ci { 19578c2ecf20Sopenharmony_ci size_t const eSize = ZSTD_loadEntropy(&dctx->entropy, dict, dictSize); 19588c2ecf20Sopenharmony_ci if (ZSTD_isError(eSize)) 19598c2ecf20Sopenharmony_ci return ERROR(dictionary_corrupted); 19608c2ecf20Sopenharmony_ci dict = (const char *)dict + eSize; 19618c2ecf20Sopenharmony_ci dictSize -= eSize; 19628c2ecf20Sopenharmony_ci } 19638c2ecf20Sopenharmony_ci dctx->litEntropy = dctx->fseEntropy = 1; 19648c2ecf20Sopenharmony_ci 19658c2ecf20Sopenharmony_ci /* reference dictionary content */ 19668c2ecf20Sopenharmony_ci return ZSTD_refDictContent(dctx, dict, dictSize); 19678c2ecf20Sopenharmony_ci} 19688c2ecf20Sopenharmony_ci 19698c2ecf20Sopenharmony_cisize_t ZSTD_decompressBegin_usingDict(ZSTD_DCtx *dctx, const void *dict, size_t dictSize) 19708c2ecf20Sopenharmony_ci{ 19718c2ecf20Sopenharmony_ci CHECK_F(ZSTD_decompressBegin(dctx)); 19728c2ecf20Sopenharmony_ci if (dict && dictSize) 19738c2ecf20Sopenharmony_ci CHECK_E(ZSTD_decompress_insertDictionary(dctx, dict, dictSize), dictionary_corrupted); 19748c2ecf20Sopenharmony_ci return 0; 19758c2ecf20Sopenharmony_ci} 19768c2ecf20Sopenharmony_ci 19778c2ecf20Sopenharmony_ci/* ====== ZSTD_DDict ====== */ 19788c2ecf20Sopenharmony_ci 19798c2ecf20Sopenharmony_cistruct ZSTD_DDict_s { 19808c2ecf20Sopenharmony_ci void *dictBuffer; 19818c2ecf20Sopenharmony_ci const void *dictContent; 19828c2ecf20Sopenharmony_ci size_t dictSize; 19838c2ecf20Sopenharmony_ci ZSTD_entropyTables_t entropy; 19848c2ecf20Sopenharmony_ci U32 dictID; 19858c2ecf20Sopenharmony_ci U32 entropyPresent; 19868c2ecf20Sopenharmony_ci ZSTD_customMem cMem; 19878c2ecf20Sopenharmony_ci}; /* typedef'd to ZSTD_DDict within "zstd.h" */ 19888c2ecf20Sopenharmony_ci 19898c2ecf20Sopenharmony_cisize_t ZSTD_DDictWorkspaceBound(void) { return ZSTD_ALIGN(sizeof(ZSTD_stack)) + ZSTD_ALIGN(sizeof(ZSTD_DDict)); } 19908c2ecf20Sopenharmony_ci 19918c2ecf20Sopenharmony_cistatic const void *ZSTD_DDictDictContent(const ZSTD_DDict *ddict) { return ddict->dictContent; } 19928c2ecf20Sopenharmony_ci 19938c2ecf20Sopenharmony_cistatic size_t ZSTD_DDictDictSize(const ZSTD_DDict *ddict) { return ddict->dictSize; } 19948c2ecf20Sopenharmony_ci 19958c2ecf20Sopenharmony_cistatic void ZSTD_refDDict(ZSTD_DCtx *dstDCtx, const ZSTD_DDict *ddict) 19968c2ecf20Sopenharmony_ci{ 19978c2ecf20Sopenharmony_ci ZSTD_decompressBegin(dstDCtx); /* init */ 19988c2ecf20Sopenharmony_ci if (ddict) { /* support refDDict on NULL */ 19998c2ecf20Sopenharmony_ci dstDCtx->dictID = ddict->dictID; 20008c2ecf20Sopenharmony_ci dstDCtx->base = ddict->dictContent; 20018c2ecf20Sopenharmony_ci dstDCtx->vBase = ddict->dictContent; 20028c2ecf20Sopenharmony_ci dstDCtx->dictEnd = (const BYTE *)ddict->dictContent + ddict->dictSize; 20038c2ecf20Sopenharmony_ci dstDCtx->previousDstEnd = dstDCtx->dictEnd; 20048c2ecf20Sopenharmony_ci if (ddict->entropyPresent) { 20058c2ecf20Sopenharmony_ci dstDCtx->litEntropy = 1; 20068c2ecf20Sopenharmony_ci dstDCtx->fseEntropy = 1; 20078c2ecf20Sopenharmony_ci dstDCtx->LLTptr = ddict->entropy.LLTable; 20088c2ecf20Sopenharmony_ci dstDCtx->MLTptr = ddict->entropy.MLTable; 20098c2ecf20Sopenharmony_ci dstDCtx->OFTptr = ddict->entropy.OFTable; 20108c2ecf20Sopenharmony_ci dstDCtx->HUFptr = ddict->entropy.hufTable; 20118c2ecf20Sopenharmony_ci dstDCtx->entropy.rep[0] = ddict->entropy.rep[0]; 20128c2ecf20Sopenharmony_ci dstDCtx->entropy.rep[1] = ddict->entropy.rep[1]; 20138c2ecf20Sopenharmony_ci dstDCtx->entropy.rep[2] = ddict->entropy.rep[2]; 20148c2ecf20Sopenharmony_ci } else { 20158c2ecf20Sopenharmony_ci dstDCtx->litEntropy = 0; 20168c2ecf20Sopenharmony_ci dstDCtx->fseEntropy = 0; 20178c2ecf20Sopenharmony_ci } 20188c2ecf20Sopenharmony_ci } 20198c2ecf20Sopenharmony_ci} 20208c2ecf20Sopenharmony_ci 20218c2ecf20Sopenharmony_cistatic size_t ZSTD_loadEntropy_inDDict(ZSTD_DDict *ddict) 20228c2ecf20Sopenharmony_ci{ 20238c2ecf20Sopenharmony_ci ddict->dictID = 0; 20248c2ecf20Sopenharmony_ci ddict->entropyPresent = 0; 20258c2ecf20Sopenharmony_ci if (ddict->dictSize < 8) 20268c2ecf20Sopenharmony_ci return 0; 20278c2ecf20Sopenharmony_ci { 20288c2ecf20Sopenharmony_ci U32 const magic = ZSTD_readLE32(ddict->dictContent); 20298c2ecf20Sopenharmony_ci if (magic != ZSTD_DICT_MAGIC) 20308c2ecf20Sopenharmony_ci return 0; /* pure content mode */ 20318c2ecf20Sopenharmony_ci } 20328c2ecf20Sopenharmony_ci ddict->dictID = ZSTD_readLE32((const char *)ddict->dictContent + 4); 20338c2ecf20Sopenharmony_ci 20348c2ecf20Sopenharmony_ci /* load entropy tables */ 20358c2ecf20Sopenharmony_ci CHECK_E(ZSTD_loadEntropy(&ddict->entropy, ddict->dictContent, ddict->dictSize), dictionary_corrupted); 20368c2ecf20Sopenharmony_ci ddict->entropyPresent = 1; 20378c2ecf20Sopenharmony_ci return 0; 20388c2ecf20Sopenharmony_ci} 20398c2ecf20Sopenharmony_ci 20408c2ecf20Sopenharmony_cistatic ZSTD_DDict *ZSTD_createDDict_advanced(const void *dict, size_t dictSize, unsigned byReference, ZSTD_customMem customMem) 20418c2ecf20Sopenharmony_ci{ 20428c2ecf20Sopenharmony_ci if (!customMem.customAlloc || !customMem.customFree) 20438c2ecf20Sopenharmony_ci return NULL; 20448c2ecf20Sopenharmony_ci 20458c2ecf20Sopenharmony_ci { 20468c2ecf20Sopenharmony_ci ZSTD_DDict *const ddict = (ZSTD_DDict *)ZSTD_malloc(sizeof(ZSTD_DDict), customMem); 20478c2ecf20Sopenharmony_ci if (!ddict) 20488c2ecf20Sopenharmony_ci return NULL; 20498c2ecf20Sopenharmony_ci ddict->cMem = customMem; 20508c2ecf20Sopenharmony_ci 20518c2ecf20Sopenharmony_ci if ((byReference) || (!dict) || (!dictSize)) { 20528c2ecf20Sopenharmony_ci ddict->dictBuffer = NULL; 20538c2ecf20Sopenharmony_ci ddict->dictContent = dict; 20548c2ecf20Sopenharmony_ci } else { 20558c2ecf20Sopenharmony_ci void *const internalBuffer = ZSTD_malloc(dictSize, customMem); 20568c2ecf20Sopenharmony_ci if (!internalBuffer) { 20578c2ecf20Sopenharmony_ci ZSTD_freeDDict(ddict); 20588c2ecf20Sopenharmony_ci return NULL; 20598c2ecf20Sopenharmony_ci } 20608c2ecf20Sopenharmony_ci memcpy(internalBuffer, dict, dictSize); 20618c2ecf20Sopenharmony_ci ddict->dictBuffer = internalBuffer; 20628c2ecf20Sopenharmony_ci ddict->dictContent = internalBuffer; 20638c2ecf20Sopenharmony_ci } 20648c2ecf20Sopenharmony_ci ddict->dictSize = dictSize; 20658c2ecf20Sopenharmony_ci ddict->entropy.hufTable[0] = (HUF_DTable)((HufLog)*0x1000001); /* cover both little and big endian */ 20668c2ecf20Sopenharmony_ci /* parse dictionary content */ 20678c2ecf20Sopenharmony_ci { 20688c2ecf20Sopenharmony_ci size_t const errorCode = ZSTD_loadEntropy_inDDict(ddict); 20698c2ecf20Sopenharmony_ci if (ZSTD_isError(errorCode)) { 20708c2ecf20Sopenharmony_ci ZSTD_freeDDict(ddict); 20718c2ecf20Sopenharmony_ci return NULL; 20728c2ecf20Sopenharmony_ci } 20738c2ecf20Sopenharmony_ci } 20748c2ecf20Sopenharmony_ci 20758c2ecf20Sopenharmony_ci return ddict; 20768c2ecf20Sopenharmony_ci } 20778c2ecf20Sopenharmony_ci} 20788c2ecf20Sopenharmony_ci 20798c2ecf20Sopenharmony_ci/*! ZSTD_initDDict() : 20808c2ecf20Sopenharmony_ci* Create a digested dictionary, to start decompression without startup delay. 20818c2ecf20Sopenharmony_ci* `dict` content is copied inside DDict. 20828c2ecf20Sopenharmony_ci* Consequently, `dict` can be released after `ZSTD_DDict` creation */ 20838c2ecf20Sopenharmony_ciZSTD_DDict *ZSTD_initDDict(const void *dict, size_t dictSize, void *workspace, size_t workspaceSize) 20848c2ecf20Sopenharmony_ci{ 20858c2ecf20Sopenharmony_ci ZSTD_customMem const stackMem = ZSTD_initStack(workspace, workspaceSize); 20868c2ecf20Sopenharmony_ci return ZSTD_createDDict_advanced(dict, dictSize, 1, stackMem); 20878c2ecf20Sopenharmony_ci} 20888c2ecf20Sopenharmony_ci 20898c2ecf20Sopenharmony_cisize_t ZSTD_freeDDict(ZSTD_DDict *ddict) 20908c2ecf20Sopenharmony_ci{ 20918c2ecf20Sopenharmony_ci if (ddict == NULL) 20928c2ecf20Sopenharmony_ci return 0; /* support free on NULL */ 20938c2ecf20Sopenharmony_ci { 20948c2ecf20Sopenharmony_ci ZSTD_customMem const cMem = ddict->cMem; 20958c2ecf20Sopenharmony_ci ZSTD_free(ddict->dictBuffer, cMem); 20968c2ecf20Sopenharmony_ci ZSTD_free(ddict, cMem); 20978c2ecf20Sopenharmony_ci return 0; 20988c2ecf20Sopenharmony_ci } 20998c2ecf20Sopenharmony_ci} 21008c2ecf20Sopenharmony_ci 21018c2ecf20Sopenharmony_ci/*! ZSTD_getDictID_fromDict() : 21028c2ecf20Sopenharmony_ci * Provides the dictID stored within dictionary. 21038c2ecf20Sopenharmony_ci * if @return == 0, the dictionary is not conformant with Zstandard specification. 21048c2ecf20Sopenharmony_ci * It can still be loaded, but as a content-only dictionary. */ 21058c2ecf20Sopenharmony_ciunsigned ZSTD_getDictID_fromDict(const void *dict, size_t dictSize) 21068c2ecf20Sopenharmony_ci{ 21078c2ecf20Sopenharmony_ci if (dictSize < 8) 21088c2ecf20Sopenharmony_ci return 0; 21098c2ecf20Sopenharmony_ci if (ZSTD_readLE32(dict) != ZSTD_DICT_MAGIC) 21108c2ecf20Sopenharmony_ci return 0; 21118c2ecf20Sopenharmony_ci return ZSTD_readLE32((const char *)dict + 4); 21128c2ecf20Sopenharmony_ci} 21138c2ecf20Sopenharmony_ci 21148c2ecf20Sopenharmony_ci/*! ZSTD_getDictID_fromDDict() : 21158c2ecf20Sopenharmony_ci * Provides the dictID of the dictionary loaded into `ddict`. 21168c2ecf20Sopenharmony_ci * If @return == 0, the dictionary is not conformant to Zstandard specification, or empty. 21178c2ecf20Sopenharmony_ci * Non-conformant dictionaries can still be loaded, but as content-only dictionaries. */ 21188c2ecf20Sopenharmony_ciunsigned ZSTD_getDictID_fromDDict(const ZSTD_DDict *ddict) 21198c2ecf20Sopenharmony_ci{ 21208c2ecf20Sopenharmony_ci if (ddict == NULL) 21218c2ecf20Sopenharmony_ci return 0; 21228c2ecf20Sopenharmony_ci return ZSTD_getDictID_fromDict(ddict->dictContent, ddict->dictSize); 21238c2ecf20Sopenharmony_ci} 21248c2ecf20Sopenharmony_ci 21258c2ecf20Sopenharmony_ci/*! ZSTD_getDictID_fromFrame() : 21268c2ecf20Sopenharmony_ci * Provides the dictID required to decompressed the frame stored within `src`. 21278c2ecf20Sopenharmony_ci * If @return == 0, the dictID could not be decoded. 21288c2ecf20Sopenharmony_ci * This could for one of the following reasons : 21298c2ecf20Sopenharmony_ci * - The frame does not require a dictionary to be decoded (most common case). 21308c2ecf20Sopenharmony_ci * - The frame was built with dictID intentionally removed. Whatever dictionary is necessary is a hidden information. 21318c2ecf20Sopenharmony_ci * Note : this use case also happens when using a non-conformant dictionary. 21328c2ecf20Sopenharmony_ci * - `srcSize` is too small, and as a result, the frame header could not be decoded (only possible if `srcSize < ZSTD_FRAMEHEADERSIZE_MAX`). 21338c2ecf20Sopenharmony_ci * - This is not a Zstandard frame. 21348c2ecf20Sopenharmony_ci * When identifying the exact failure cause, it's possible to used ZSTD_getFrameParams(), which will provide a more precise error code. */ 21358c2ecf20Sopenharmony_ciunsigned ZSTD_getDictID_fromFrame(const void *src, size_t srcSize) 21368c2ecf20Sopenharmony_ci{ 21378c2ecf20Sopenharmony_ci ZSTD_frameParams zfp = {0, 0, 0, 0}; 21388c2ecf20Sopenharmony_ci size_t const hError = ZSTD_getFrameParams(&zfp, src, srcSize); 21398c2ecf20Sopenharmony_ci if (ZSTD_isError(hError)) 21408c2ecf20Sopenharmony_ci return 0; 21418c2ecf20Sopenharmony_ci return zfp.dictID; 21428c2ecf20Sopenharmony_ci} 21438c2ecf20Sopenharmony_ci 21448c2ecf20Sopenharmony_ci/*! ZSTD_decompress_usingDDict() : 21458c2ecf20Sopenharmony_ci* Decompression using a pre-digested Dictionary 21468c2ecf20Sopenharmony_ci* Use dictionary without significant overhead. */ 21478c2ecf20Sopenharmony_cisize_t ZSTD_decompress_usingDDict(ZSTD_DCtx *dctx, void *dst, size_t dstCapacity, const void *src, size_t srcSize, const ZSTD_DDict *ddict) 21488c2ecf20Sopenharmony_ci{ 21498c2ecf20Sopenharmony_ci /* pass content and size in case legacy frames are encountered */ 21508c2ecf20Sopenharmony_ci return ZSTD_decompressMultiFrame(dctx, dst, dstCapacity, src, srcSize, NULL, 0, ddict); 21518c2ecf20Sopenharmony_ci} 21528c2ecf20Sopenharmony_ci 21538c2ecf20Sopenharmony_ci/*===================================== 21548c2ecf20Sopenharmony_ci* Streaming decompression 21558c2ecf20Sopenharmony_ci*====================================*/ 21568c2ecf20Sopenharmony_ci 21578c2ecf20Sopenharmony_citypedef enum { zdss_init, zdss_loadHeader, zdss_read, zdss_load, zdss_flush } ZSTD_dStreamStage; 21588c2ecf20Sopenharmony_ci 21598c2ecf20Sopenharmony_ci/* *** Resource management *** */ 21608c2ecf20Sopenharmony_cistruct ZSTD_DStream_s { 21618c2ecf20Sopenharmony_ci ZSTD_DCtx *dctx; 21628c2ecf20Sopenharmony_ci ZSTD_DDict *ddictLocal; 21638c2ecf20Sopenharmony_ci const ZSTD_DDict *ddict; 21648c2ecf20Sopenharmony_ci ZSTD_frameParams fParams; 21658c2ecf20Sopenharmony_ci ZSTD_dStreamStage stage; 21668c2ecf20Sopenharmony_ci char *inBuff; 21678c2ecf20Sopenharmony_ci size_t inBuffSize; 21688c2ecf20Sopenharmony_ci size_t inPos; 21698c2ecf20Sopenharmony_ci size_t maxWindowSize; 21708c2ecf20Sopenharmony_ci char *outBuff; 21718c2ecf20Sopenharmony_ci size_t outBuffSize; 21728c2ecf20Sopenharmony_ci size_t outStart; 21738c2ecf20Sopenharmony_ci size_t outEnd; 21748c2ecf20Sopenharmony_ci size_t blockSize; 21758c2ecf20Sopenharmony_ci BYTE headerBuffer[ZSTD_FRAMEHEADERSIZE_MAX]; /* tmp buffer to store frame header */ 21768c2ecf20Sopenharmony_ci size_t lhSize; 21778c2ecf20Sopenharmony_ci ZSTD_customMem customMem; 21788c2ecf20Sopenharmony_ci void *legacyContext; 21798c2ecf20Sopenharmony_ci U32 previousLegacyVersion; 21808c2ecf20Sopenharmony_ci U32 legacyVersion; 21818c2ecf20Sopenharmony_ci U32 hostageByte; 21828c2ecf20Sopenharmony_ci}; /* typedef'd to ZSTD_DStream within "zstd.h" */ 21838c2ecf20Sopenharmony_ci 21848c2ecf20Sopenharmony_cisize_t ZSTD_DStreamWorkspaceBound(size_t maxWindowSize) 21858c2ecf20Sopenharmony_ci{ 21868c2ecf20Sopenharmony_ci size_t const blockSize = MIN(maxWindowSize, ZSTD_BLOCKSIZE_ABSOLUTEMAX); 21878c2ecf20Sopenharmony_ci size_t const inBuffSize = blockSize; 21888c2ecf20Sopenharmony_ci size_t const outBuffSize = maxWindowSize + blockSize + WILDCOPY_OVERLENGTH * 2; 21898c2ecf20Sopenharmony_ci return ZSTD_DCtxWorkspaceBound() + ZSTD_ALIGN(sizeof(ZSTD_DStream)) + ZSTD_ALIGN(inBuffSize) + ZSTD_ALIGN(outBuffSize); 21908c2ecf20Sopenharmony_ci} 21918c2ecf20Sopenharmony_ci 21928c2ecf20Sopenharmony_cistatic ZSTD_DStream *ZSTD_createDStream_advanced(ZSTD_customMem customMem) 21938c2ecf20Sopenharmony_ci{ 21948c2ecf20Sopenharmony_ci ZSTD_DStream *zds; 21958c2ecf20Sopenharmony_ci 21968c2ecf20Sopenharmony_ci if (!customMem.customAlloc || !customMem.customFree) 21978c2ecf20Sopenharmony_ci return NULL; 21988c2ecf20Sopenharmony_ci 21998c2ecf20Sopenharmony_ci zds = (ZSTD_DStream *)ZSTD_malloc(sizeof(ZSTD_DStream), customMem); 22008c2ecf20Sopenharmony_ci if (zds == NULL) 22018c2ecf20Sopenharmony_ci return NULL; 22028c2ecf20Sopenharmony_ci memset(zds, 0, sizeof(ZSTD_DStream)); 22038c2ecf20Sopenharmony_ci memcpy(&zds->customMem, &customMem, sizeof(ZSTD_customMem)); 22048c2ecf20Sopenharmony_ci zds->dctx = ZSTD_createDCtx_advanced(customMem); 22058c2ecf20Sopenharmony_ci if (zds->dctx == NULL) { 22068c2ecf20Sopenharmony_ci ZSTD_freeDStream(zds); 22078c2ecf20Sopenharmony_ci return NULL; 22088c2ecf20Sopenharmony_ci } 22098c2ecf20Sopenharmony_ci zds->stage = zdss_init; 22108c2ecf20Sopenharmony_ci zds->maxWindowSize = ZSTD_MAXWINDOWSIZE_DEFAULT; 22118c2ecf20Sopenharmony_ci return zds; 22128c2ecf20Sopenharmony_ci} 22138c2ecf20Sopenharmony_ci 22148c2ecf20Sopenharmony_ciZSTD_DStream *ZSTD_initDStream(size_t maxWindowSize, void *workspace, size_t workspaceSize) 22158c2ecf20Sopenharmony_ci{ 22168c2ecf20Sopenharmony_ci ZSTD_customMem const stackMem = ZSTD_initStack(workspace, workspaceSize); 22178c2ecf20Sopenharmony_ci ZSTD_DStream *zds = ZSTD_createDStream_advanced(stackMem); 22188c2ecf20Sopenharmony_ci if (!zds) { 22198c2ecf20Sopenharmony_ci return NULL; 22208c2ecf20Sopenharmony_ci } 22218c2ecf20Sopenharmony_ci 22228c2ecf20Sopenharmony_ci zds->maxWindowSize = maxWindowSize; 22238c2ecf20Sopenharmony_ci zds->stage = zdss_loadHeader; 22248c2ecf20Sopenharmony_ci zds->lhSize = zds->inPos = zds->outStart = zds->outEnd = 0; 22258c2ecf20Sopenharmony_ci ZSTD_freeDDict(zds->ddictLocal); 22268c2ecf20Sopenharmony_ci zds->ddictLocal = NULL; 22278c2ecf20Sopenharmony_ci zds->ddict = zds->ddictLocal; 22288c2ecf20Sopenharmony_ci zds->legacyVersion = 0; 22298c2ecf20Sopenharmony_ci zds->hostageByte = 0; 22308c2ecf20Sopenharmony_ci 22318c2ecf20Sopenharmony_ci { 22328c2ecf20Sopenharmony_ci size_t const blockSize = MIN(zds->maxWindowSize, ZSTD_BLOCKSIZE_ABSOLUTEMAX); 22338c2ecf20Sopenharmony_ci size_t const neededOutSize = zds->maxWindowSize + blockSize + WILDCOPY_OVERLENGTH * 2; 22348c2ecf20Sopenharmony_ci 22358c2ecf20Sopenharmony_ci zds->inBuff = (char *)ZSTD_malloc(blockSize, zds->customMem); 22368c2ecf20Sopenharmony_ci zds->inBuffSize = blockSize; 22378c2ecf20Sopenharmony_ci zds->outBuff = (char *)ZSTD_malloc(neededOutSize, zds->customMem); 22388c2ecf20Sopenharmony_ci zds->outBuffSize = neededOutSize; 22398c2ecf20Sopenharmony_ci if (zds->inBuff == NULL || zds->outBuff == NULL) { 22408c2ecf20Sopenharmony_ci ZSTD_freeDStream(zds); 22418c2ecf20Sopenharmony_ci return NULL; 22428c2ecf20Sopenharmony_ci } 22438c2ecf20Sopenharmony_ci } 22448c2ecf20Sopenharmony_ci return zds; 22458c2ecf20Sopenharmony_ci} 22468c2ecf20Sopenharmony_ci 22478c2ecf20Sopenharmony_ciZSTD_DStream *ZSTD_initDStream_usingDDict(size_t maxWindowSize, const ZSTD_DDict *ddict, void *workspace, size_t workspaceSize) 22488c2ecf20Sopenharmony_ci{ 22498c2ecf20Sopenharmony_ci ZSTD_DStream *zds = ZSTD_initDStream(maxWindowSize, workspace, workspaceSize); 22508c2ecf20Sopenharmony_ci if (zds) { 22518c2ecf20Sopenharmony_ci zds->ddict = ddict; 22528c2ecf20Sopenharmony_ci } 22538c2ecf20Sopenharmony_ci return zds; 22548c2ecf20Sopenharmony_ci} 22558c2ecf20Sopenharmony_ci 22568c2ecf20Sopenharmony_cisize_t ZSTD_freeDStream(ZSTD_DStream *zds) 22578c2ecf20Sopenharmony_ci{ 22588c2ecf20Sopenharmony_ci if (zds == NULL) 22598c2ecf20Sopenharmony_ci return 0; /* support free on null */ 22608c2ecf20Sopenharmony_ci { 22618c2ecf20Sopenharmony_ci ZSTD_customMem const cMem = zds->customMem; 22628c2ecf20Sopenharmony_ci ZSTD_freeDCtx(zds->dctx); 22638c2ecf20Sopenharmony_ci zds->dctx = NULL; 22648c2ecf20Sopenharmony_ci ZSTD_freeDDict(zds->ddictLocal); 22658c2ecf20Sopenharmony_ci zds->ddictLocal = NULL; 22668c2ecf20Sopenharmony_ci ZSTD_free(zds->inBuff, cMem); 22678c2ecf20Sopenharmony_ci zds->inBuff = NULL; 22688c2ecf20Sopenharmony_ci ZSTD_free(zds->outBuff, cMem); 22698c2ecf20Sopenharmony_ci zds->outBuff = NULL; 22708c2ecf20Sopenharmony_ci ZSTD_free(zds, cMem); 22718c2ecf20Sopenharmony_ci return 0; 22728c2ecf20Sopenharmony_ci } 22738c2ecf20Sopenharmony_ci} 22748c2ecf20Sopenharmony_ci 22758c2ecf20Sopenharmony_ci/* *** Initialization *** */ 22768c2ecf20Sopenharmony_ci 22778c2ecf20Sopenharmony_cisize_t ZSTD_DStreamInSize(void) { return ZSTD_BLOCKSIZE_ABSOLUTEMAX + ZSTD_blockHeaderSize; } 22788c2ecf20Sopenharmony_cisize_t ZSTD_DStreamOutSize(void) { return ZSTD_BLOCKSIZE_ABSOLUTEMAX; } 22798c2ecf20Sopenharmony_ci 22808c2ecf20Sopenharmony_cisize_t ZSTD_resetDStream(ZSTD_DStream *zds) 22818c2ecf20Sopenharmony_ci{ 22828c2ecf20Sopenharmony_ci zds->stage = zdss_loadHeader; 22838c2ecf20Sopenharmony_ci zds->lhSize = zds->inPos = zds->outStart = zds->outEnd = 0; 22848c2ecf20Sopenharmony_ci zds->legacyVersion = 0; 22858c2ecf20Sopenharmony_ci zds->hostageByte = 0; 22868c2ecf20Sopenharmony_ci return ZSTD_frameHeaderSize_prefix; 22878c2ecf20Sopenharmony_ci} 22888c2ecf20Sopenharmony_ci 22898c2ecf20Sopenharmony_ci/* ***** Decompression ***** */ 22908c2ecf20Sopenharmony_ci 22918c2ecf20Sopenharmony_ciZSTD_STATIC size_t ZSTD_limitCopy(void *dst, size_t dstCapacity, const void *src, size_t srcSize) 22928c2ecf20Sopenharmony_ci{ 22938c2ecf20Sopenharmony_ci size_t const length = MIN(dstCapacity, srcSize); 22948c2ecf20Sopenharmony_ci memcpy(dst, src, length); 22958c2ecf20Sopenharmony_ci return length; 22968c2ecf20Sopenharmony_ci} 22978c2ecf20Sopenharmony_ci 22988c2ecf20Sopenharmony_cisize_t ZSTD_decompressStream(ZSTD_DStream *zds, ZSTD_outBuffer *output, ZSTD_inBuffer *input) 22998c2ecf20Sopenharmony_ci{ 23008c2ecf20Sopenharmony_ci const char *const istart = (const char *)(input->src) + input->pos; 23018c2ecf20Sopenharmony_ci const char *const iend = (const char *)(input->src) + input->size; 23028c2ecf20Sopenharmony_ci const char *ip = istart; 23038c2ecf20Sopenharmony_ci char *const ostart = (char *)(output->dst) + output->pos; 23048c2ecf20Sopenharmony_ci char *const oend = (char *)(output->dst) + output->size; 23058c2ecf20Sopenharmony_ci char *op = ostart; 23068c2ecf20Sopenharmony_ci U32 someMoreWork = 1; 23078c2ecf20Sopenharmony_ci 23088c2ecf20Sopenharmony_ci while (someMoreWork) { 23098c2ecf20Sopenharmony_ci switch (zds->stage) { 23108c2ecf20Sopenharmony_ci case zdss_init: 23118c2ecf20Sopenharmony_ci ZSTD_resetDStream(zds); /* transparent reset on starting decoding a new frame */ 23128c2ecf20Sopenharmony_ci /* fall through */ 23138c2ecf20Sopenharmony_ci 23148c2ecf20Sopenharmony_ci case zdss_loadHeader: { 23158c2ecf20Sopenharmony_ci size_t const hSize = ZSTD_getFrameParams(&zds->fParams, zds->headerBuffer, zds->lhSize); 23168c2ecf20Sopenharmony_ci if (ZSTD_isError(hSize)) 23178c2ecf20Sopenharmony_ci return hSize; 23188c2ecf20Sopenharmony_ci if (hSize != 0) { /* need more input */ 23198c2ecf20Sopenharmony_ci size_t const toLoad = hSize - zds->lhSize; /* if hSize!=0, hSize > zds->lhSize */ 23208c2ecf20Sopenharmony_ci if (toLoad > (size_t)(iend - ip)) { /* not enough input to load full header */ 23218c2ecf20Sopenharmony_ci memcpy(zds->headerBuffer + zds->lhSize, ip, iend - ip); 23228c2ecf20Sopenharmony_ci zds->lhSize += iend - ip; 23238c2ecf20Sopenharmony_ci input->pos = input->size; 23248c2ecf20Sopenharmony_ci return (MAX(ZSTD_frameHeaderSize_min, hSize) - zds->lhSize) + 23258c2ecf20Sopenharmony_ci ZSTD_blockHeaderSize; /* remaining header bytes + next block header */ 23268c2ecf20Sopenharmony_ci } 23278c2ecf20Sopenharmony_ci memcpy(zds->headerBuffer + zds->lhSize, ip, toLoad); 23288c2ecf20Sopenharmony_ci zds->lhSize = hSize; 23298c2ecf20Sopenharmony_ci ip += toLoad; 23308c2ecf20Sopenharmony_ci break; 23318c2ecf20Sopenharmony_ci } 23328c2ecf20Sopenharmony_ci 23338c2ecf20Sopenharmony_ci /* check for single-pass mode opportunity */ 23348c2ecf20Sopenharmony_ci if (zds->fParams.frameContentSize && zds->fParams.windowSize /* skippable frame if == 0 */ 23358c2ecf20Sopenharmony_ci && (U64)(size_t)(oend - op) >= zds->fParams.frameContentSize) { 23368c2ecf20Sopenharmony_ci size_t const cSize = ZSTD_findFrameCompressedSize(istart, iend - istart); 23378c2ecf20Sopenharmony_ci if (cSize <= (size_t)(iend - istart)) { 23388c2ecf20Sopenharmony_ci size_t const decompressedSize = ZSTD_decompress_usingDDict(zds->dctx, op, oend - op, istart, cSize, zds->ddict); 23398c2ecf20Sopenharmony_ci if (ZSTD_isError(decompressedSize)) 23408c2ecf20Sopenharmony_ci return decompressedSize; 23418c2ecf20Sopenharmony_ci ip = istart + cSize; 23428c2ecf20Sopenharmony_ci op += decompressedSize; 23438c2ecf20Sopenharmony_ci zds->dctx->expected = 0; 23448c2ecf20Sopenharmony_ci zds->stage = zdss_init; 23458c2ecf20Sopenharmony_ci someMoreWork = 0; 23468c2ecf20Sopenharmony_ci break; 23478c2ecf20Sopenharmony_ci } 23488c2ecf20Sopenharmony_ci } 23498c2ecf20Sopenharmony_ci 23508c2ecf20Sopenharmony_ci /* Consume header */ 23518c2ecf20Sopenharmony_ci ZSTD_refDDict(zds->dctx, zds->ddict); 23528c2ecf20Sopenharmony_ci { 23538c2ecf20Sopenharmony_ci size_t const h1Size = ZSTD_nextSrcSizeToDecompress(zds->dctx); /* == ZSTD_frameHeaderSize_prefix */ 23548c2ecf20Sopenharmony_ci CHECK_F(ZSTD_decompressContinue(zds->dctx, NULL, 0, zds->headerBuffer, h1Size)); 23558c2ecf20Sopenharmony_ci { 23568c2ecf20Sopenharmony_ci size_t const h2Size = ZSTD_nextSrcSizeToDecompress(zds->dctx); 23578c2ecf20Sopenharmony_ci CHECK_F(ZSTD_decompressContinue(zds->dctx, NULL, 0, zds->headerBuffer + h1Size, h2Size)); 23588c2ecf20Sopenharmony_ci } 23598c2ecf20Sopenharmony_ci } 23608c2ecf20Sopenharmony_ci 23618c2ecf20Sopenharmony_ci zds->fParams.windowSize = MAX(zds->fParams.windowSize, 1U << ZSTD_WINDOWLOG_ABSOLUTEMIN); 23628c2ecf20Sopenharmony_ci if (zds->fParams.windowSize > zds->maxWindowSize) 23638c2ecf20Sopenharmony_ci return ERROR(frameParameter_windowTooLarge); 23648c2ecf20Sopenharmony_ci 23658c2ecf20Sopenharmony_ci /* Buffers are preallocated, but double check */ 23668c2ecf20Sopenharmony_ci { 23678c2ecf20Sopenharmony_ci size_t const blockSize = MIN(zds->maxWindowSize, ZSTD_BLOCKSIZE_ABSOLUTEMAX); 23688c2ecf20Sopenharmony_ci size_t const neededOutSize = zds->maxWindowSize + blockSize + WILDCOPY_OVERLENGTH * 2; 23698c2ecf20Sopenharmony_ci if (zds->inBuffSize < blockSize) { 23708c2ecf20Sopenharmony_ci return ERROR(GENERIC); 23718c2ecf20Sopenharmony_ci } 23728c2ecf20Sopenharmony_ci if (zds->outBuffSize < neededOutSize) { 23738c2ecf20Sopenharmony_ci return ERROR(GENERIC); 23748c2ecf20Sopenharmony_ci } 23758c2ecf20Sopenharmony_ci zds->blockSize = blockSize; 23768c2ecf20Sopenharmony_ci } 23778c2ecf20Sopenharmony_ci zds->stage = zdss_read; 23788c2ecf20Sopenharmony_ci } 23798c2ecf20Sopenharmony_ci /* fall through */ 23808c2ecf20Sopenharmony_ci 23818c2ecf20Sopenharmony_ci case zdss_read: { 23828c2ecf20Sopenharmony_ci size_t const neededInSize = ZSTD_nextSrcSizeToDecompress(zds->dctx); 23838c2ecf20Sopenharmony_ci if (neededInSize == 0) { /* end of frame */ 23848c2ecf20Sopenharmony_ci zds->stage = zdss_init; 23858c2ecf20Sopenharmony_ci someMoreWork = 0; 23868c2ecf20Sopenharmony_ci break; 23878c2ecf20Sopenharmony_ci } 23888c2ecf20Sopenharmony_ci if ((size_t)(iend - ip) >= neededInSize) { /* decode directly from src */ 23898c2ecf20Sopenharmony_ci const int isSkipFrame = ZSTD_isSkipFrame(zds->dctx); 23908c2ecf20Sopenharmony_ci size_t const decodedSize = ZSTD_decompressContinue(zds->dctx, zds->outBuff + zds->outStart, 23918c2ecf20Sopenharmony_ci (isSkipFrame ? 0 : zds->outBuffSize - zds->outStart), ip, neededInSize); 23928c2ecf20Sopenharmony_ci if (ZSTD_isError(decodedSize)) 23938c2ecf20Sopenharmony_ci return decodedSize; 23948c2ecf20Sopenharmony_ci ip += neededInSize; 23958c2ecf20Sopenharmony_ci if (!decodedSize && !isSkipFrame) 23968c2ecf20Sopenharmony_ci break; /* this was just a header */ 23978c2ecf20Sopenharmony_ci zds->outEnd = zds->outStart + decodedSize; 23988c2ecf20Sopenharmony_ci zds->stage = zdss_flush; 23998c2ecf20Sopenharmony_ci break; 24008c2ecf20Sopenharmony_ci } 24018c2ecf20Sopenharmony_ci if (ip == iend) { 24028c2ecf20Sopenharmony_ci someMoreWork = 0; 24038c2ecf20Sopenharmony_ci break; 24048c2ecf20Sopenharmony_ci } /* no more input */ 24058c2ecf20Sopenharmony_ci zds->stage = zdss_load; 24068c2ecf20Sopenharmony_ci /* pass-through */ 24078c2ecf20Sopenharmony_ci } 24088c2ecf20Sopenharmony_ci /* fall through */ 24098c2ecf20Sopenharmony_ci 24108c2ecf20Sopenharmony_ci case zdss_load: { 24118c2ecf20Sopenharmony_ci size_t const neededInSize = ZSTD_nextSrcSizeToDecompress(zds->dctx); 24128c2ecf20Sopenharmony_ci size_t const toLoad = neededInSize - zds->inPos; /* should always be <= remaining space within inBuff */ 24138c2ecf20Sopenharmony_ci size_t loadedSize; 24148c2ecf20Sopenharmony_ci if (toLoad > zds->inBuffSize - zds->inPos) 24158c2ecf20Sopenharmony_ci return ERROR(corruption_detected); /* should never happen */ 24168c2ecf20Sopenharmony_ci loadedSize = ZSTD_limitCopy(zds->inBuff + zds->inPos, toLoad, ip, iend - ip); 24178c2ecf20Sopenharmony_ci ip += loadedSize; 24188c2ecf20Sopenharmony_ci zds->inPos += loadedSize; 24198c2ecf20Sopenharmony_ci if (loadedSize < toLoad) { 24208c2ecf20Sopenharmony_ci someMoreWork = 0; 24218c2ecf20Sopenharmony_ci break; 24228c2ecf20Sopenharmony_ci } /* not enough input, wait for more */ 24238c2ecf20Sopenharmony_ci 24248c2ecf20Sopenharmony_ci /* decode loaded input */ 24258c2ecf20Sopenharmony_ci { 24268c2ecf20Sopenharmony_ci const int isSkipFrame = ZSTD_isSkipFrame(zds->dctx); 24278c2ecf20Sopenharmony_ci size_t const decodedSize = ZSTD_decompressContinue(zds->dctx, zds->outBuff + zds->outStart, zds->outBuffSize - zds->outStart, 24288c2ecf20Sopenharmony_ci zds->inBuff, neededInSize); 24298c2ecf20Sopenharmony_ci if (ZSTD_isError(decodedSize)) 24308c2ecf20Sopenharmony_ci return decodedSize; 24318c2ecf20Sopenharmony_ci zds->inPos = 0; /* input is consumed */ 24328c2ecf20Sopenharmony_ci if (!decodedSize && !isSkipFrame) { 24338c2ecf20Sopenharmony_ci zds->stage = zdss_read; 24348c2ecf20Sopenharmony_ci break; 24358c2ecf20Sopenharmony_ci } /* this was just a header */ 24368c2ecf20Sopenharmony_ci zds->outEnd = zds->outStart + decodedSize; 24378c2ecf20Sopenharmony_ci zds->stage = zdss_flush; 24388c2ecf20Sopenharmony_ci /* pass-through */ 24398c2ecf20Sopenharmony_ci } 24408c2ecf20Sopenharmony_ci } 24418c2ecf20Sopenharmony_ci /* fall through */ 24428c2ecf20Sopenharmony_ci 24438c2ecf20Sopenharmony_ci case zdss_flush: { 24448c2ecf20Sopenharmony_ci size_t const toFlushSize = zds->outEnd - zds->outStart; 24458c2ecf20Sopenharmony_ci size_t const flushedSize = ZSTD_limitCopy(op, oend - op, zds->outBuff + zds->outStart, toFlushSize); 24468c2ecf20Sopenharmony_ci op += flushedSize; 24478c2ecf20Sopenharmony_ci zds->outStart += flushedSize; 24488c2ecf20Sopenharmony_ci if (flushedSize == toFlushSize) { /* flush completed */ 24498c2ecf20Sopenharmony_ci zds->stage = zdss_read; 24508c2ecf20Sopenharmony_ci if (zds->outStart + zds->blockSize > zds->outBuffSize) 24518c2ecf20Sopenharmony_ci zds->outStart = zds->outEnd = 0; 24528c2ecf20Sopenharmony_ci break; 24538c2ecf20Sopenharmony_ci } 24548c2ecf20Sopenharmony_ci /* cannot complete flush */ 24558c2ecf20Sopenharmony_ci someMoreWork = 0; 24568c2ecf20Sopenharmony_ci break; 24578c2ecf20Sopenharmony_ci } 24588c2ecf20Sopenharmony_ci default: 24598c2ecf20Sopenharmony_ci return ERROR(GENERIC); /* impossible */ 24608c2ecf20Sopenharmony_ci } 24618c2ecf20Sopenharmony_ci } 24628c2ecf20Sopenharmony_ci 24638c2ecf20Sopenharmony_ci /* result */ 24648c2ecf20Sopenharmony_ci input->pos += (size_t)(ip - istart); 24658c2ecf20Sopenharmony_ci output->pos += (size_t)(op - ostart); 24668c2ecf20Sopenharmony_ci { 24678c2ecf20Sopenharmony_ci size_t nextSrcSizeHint = ZSTD_nextSrcSizeToDecompress(zds->dctx); 24688c2ecf20Sopenharmony_ci if (!nextSrcSizeHint) { /* frame fully decoded */ 24698c2ecf20Sopenharmony_ci if (zds->outEnd == zds->outStart) { /* output fully flushed */ 24708c2ecf20Sopenharmony_ci if (zds->hostageByte) { 24718c2ecf20Sopenharmony_ci if (input->pos >= input->size) { 24728c2ecf20Sopenharmony_ci zds->stage = zdss_read; 24738c2ecf20Sopenharmony_ci return 1; 24748c2ecf20Sopenharmony_ci } /* can't release hostage (not present) */ 24758c2ecf20Sopenharmony_ci input->pos++; /* release hostage */ 24768c2ecf20Sopenharmony_ci } 24778c2ecf20Sopenharmony_ci return 0; 24788c2ecf20Sopenharmony_ci } 24798c2ecf20Sopenharmony_ci if (!zds->hostageByte) { /* output not fully flushed; keep last byte as hostage; will be released when all output is flushed */ 24808c2ecf20Sopenharmony_ci input->pos--; /* note : pos > 0, otherwise, impossible to finish reading last block */ 24818c2ecf20Sopenharmony_ci zds->hostageByte = 1; 24828c2ecf20Sopenharmony_ci } 24838c2ecf20Sopenharmony_ci return 1; 24848c2ecf20Sopenharmony_ci } 24858c2ecf20Sopenharmony_ci nextSrcSizeHint += ZSTD_blockHeaderSize * (ZSTD_nextInputType(zds->dctx) == ZSTDnit_block); /* preload header of next block */ 24868c2ecf20Sopenharmony_ci if (zds->inPos > nextSrcSizeHint) 24878c2ecf20Sopenharmony_ci return ERROR(GENERIC); /* should never happen */ 24888c2ecf20Sopenharmony_ci nextSrcSizeHint -= zds->inPos; /* already loaded*/ 24898c2ecf20Sopenharmony_ci return nextSrcSizeHint; 24908c2ecf20Sopenharmony_ci } 24918c2ecf20Sopenharmony_ci} 24928c2ecf20Sopenharmony_ci 24938c2ecf20Sopenharmony_ciEXPORT_SYMBOL(ZSTD_DCtxWorkspaceBound); 24948c2ecf20Sopenharmony_ciEXPORT_SYMBOL(ZSTD_initDCtx); 24958c2ecf20Sopenharmony_ciEXPORT_SYMBOL(ZSTD_decompressDCtx); 24968c2ecf20Sopenharmony_ciEXPORT_SYMBOL(ZSTD_decompress_usingDict); 24978c2ecf20Sopenharmony_ci 24988c2ecf20Sopenharmony_ciEXPORT_SYMBOL(ZSTD_DDictWorkspaceBound); 24998c2ecf20Sopenharmony_ciEXPORT_SYMBOL(ZSTD_initDDict); 25008c2ecf20Sopenharmony_ciEXPORT_SYMBOL(ZSTD_decompress_usingDDict); 25018c2ecf20Sopenharmony_ci 25028c2ecf20Sopenharmony_ciEXPORT_SYMBOL(ZSTD_DStreamWorkspaceBound); 25038c2ecf20Sopenharmony_ciEXPORT_SYMBOL(ZSTD_initDStream); 25048c2ecf20Sopenharmony_ciEXPORT_SYMBOL(ZSTD_initDStream_usingDDict); 25058c2ecf20Sopenharmony_ciEXPORT_SYMBOL(ZSTD_resetDStream); 25068c2ecf20Sopenharmony_ciEXPORT_SYMBOL(ZSTD_decompressStream); 25078c2ecf20Sopenharmony_ciEXPORT_SYMBOL(ZSTD_DStreamInSize); 25088c2ecf20Sopenharmony_ciEXPORT_SYMBOL(ZSTD_DStreamOutSize); 25098c2ecf20Sopenharmony_ci 25108c2ecf20Sopenharmony_ciEXPORT_SYMBOL(ZSTD_findFrameCompressedSize); 25118c2ecf20Sopenharmony_ciEXPORT_SYMBOL(ZSTD_getFrameContentSize); 25128c2ecf20Sopenharmony_ciEXPORT_SYMBOL(ZSTD_findDecompressedSize); 25138c2ecf20Sopenharmony_ci 25148c2ecf20Sopenharmony_ciEXPORT_SYMBOL(ZSTD_isFrame); 25158c2ecf20Sopenharmony_ciEXPORT_SYMBOL(ZSTD_getDictID_fromDict); 25168c2ecf20Sopenharmony_ciEXPORT_SYMBOL(ZSTD_getDictID_fromDDict); 25178c2ecf20Sopenharmony_ciEXPORT_SYMBOL(ZSTD_getDictID_fromFrame); 25188c2ecf20Sopenharmony_ci 25198c2ecf20Sopenharmony_ciEXPORT_SYMBOL(ZSTD_getFrameParams); 25208c2ecf20Sopenharmony_ciEXPORT_SYMBOL(ZSTD_decompressBegin); 25218c2ecf20Sopenharmony_ciEXPORT_SYMBOL(ZSTD_decompressBegin_usingDict); 25228c2ecf20Sopenharmony_ciEXPORT_SYMBOL(ZSTD_copyDCtx); 25238c2ecf20Sopenharmony_ciEXPORT_SYMBOL(ZSTD_nextSrcSizeToDecompress); 25248c2ecf20Sopenharmony_ciEXPORT_SYMBOL(ZSTD_decompressContinue); 25258c2ecf20Sopenharmony_ciEXPORT_SYMBOL(ZSTD_nextInputType); 25268c2ecf20Sopenharmony_ci 25278c2ecf20Sopenharmony_ciEXPORT_SYMBOL(ZSTD_decompressBlock); 25288c2ecf20Sopenharmony_ciEXPORT_SYMBOL(ZSTD_insertBlock); 25298c2ecf20Sopenharmony_ci 25308c2ecf20Sopenharmony_ciMODULE_LICENSE("Dual BSD/GPL"); 25318c2ecf20Sopenharmony_ciMODULE_DESCRIPTION("Zstd Decompressor"); 2532