extzstd 0.2 → 0.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/HISTORY.ja.md +13 -0
- data/README.md +17 -14
- data/contrib/zstd/{NEWS → CHANGELOG} +115 -2
- data/contrib/zstd/CODE_OF_CONDUCT.md +5 -0
- data/contrib/zstd/Makefile +99 -53
- data/contrib/zstd/README.md +59 -39
- data/contrib/zstd/TESTING.md +1 -1
- data/contrib/zstd/appveyor.yml +17 -6
- data/contrib/zstd/lib/BUCK +29 -2
- data/contrib/zstd/lib/Makefile +118 -21
- data/contrib/zstd/lib/README.md +84 -44
- data/contrib/zstd/lib/common/bitstream.h +17 -33
- data/contrib/zstd/lib/common/compiler.h +62 -8
- data/contrib/zstd/lib/common/cpu.h +215 -0
- data/contrib/zstd/lib/common/debug.c +44 -0
- data/contrib/zstd/lib/common/debug.h +134 -0
- data/contrib/zstd/lib/common/entropy_common.c +16 -1
- data/contrib/zstd/lib/common/error_private.c +7 -0
- data/contrib/zstd/lib/common/fse.h +48 -44
- data/contrib/zstd/lib/common/fse_decompress.c +3 -3
- data/contrib/zstd/lib/common/huf.h +169 -113
- data/contrib/zstd/lib/common/mem.h +20 -2
- data/contrib/zstd/lib/common/pool.c +135 -49
- data/contrib/zstd/lib/common/pool.h +40 -21
- data/contrib/zstd/lib/common/threading.c +2 -2
- data/contrib/zstd/lib/common/threading.h +12 -12
- data/contrib/zstd/lib/common/xxhash.c +3 -2
- data/contrib/zstd/lib/common/zstd_common.c +3 -6
- data/contrib/zstd/lib/common/zstd_errors.h +17 -7
- data/contrib/zstd/lib/common/zstd_internal.h +76 -48
- data/contrib/zstd/lib/compress/fse_compress.c +89 -209
- data/contrib/zstd/lib/compress/hist.c +203 -0
- data/contrib/zstd/lib/compress/hist.h +95 -0
- data/contrib/zstd/lib/compress/huf_compress.c +188 -80
- data/contrib/zstd/lib/compress/zstd_compress.c +2500 -1203
- data/contrib/zstd/lib/compress/zstd_compress_internal.h +463 -62
- data/contrib/zstd/lib/compress/zstd_double_fast.c +321 -131
- data/contrib/zstd/lib/compress/zstd_double_fast.h +13 -4
- data/contrib/zstd/lib/compress/zstd_fast.c +335 -108
- data/contrib/zstd/lib/compress/zstd_fast.h +12 -6
- data/contrib/zstd/lib/compress/zstd_lazy.c +654 -313
- data/contrib/zstd/lib/compress/zstd_lazy.h +44 -16
- data/contrib/zstd/lib/compress/zstd_ldm.c +310 -420
- data/contrib/zstd/lib/compress/zstd_ldm.h +63 -26
- data/contrib/zstd/lib/compress/zstd_opt.c +773 -325
- data/contrib/zstd/lib/compress/zstd_opt.h +31 -5
- data/contrib/zstd/lib/compress/zstdmt_compress.c +1468 -518
- data/contrib/zstd/lib/compress/zstdmt_compress.h +96 -45
- data/contrib/zstd/lib/decompress/huf_decompress.c +518 -282
- data/contrib/zstd/lib/decompress/zstd_ddict.c +240 -0
- data/contrib/zstd/lib/decompress/zstd_ddict.h +44 -0
- data/contrib/zstd/lib/decompress/zstd_decompress.c +613 -1513
- data/contrib/zstd/lib/decompress/zstd_decompress_block.c +1311 -0
- data/contrib/zstd/lib/decompress/zstd_decompress_block.h +59 -0
- data/contrib/zstd/lib/decompress/zstd_decompress_internal.h +175 -0
- data/contrib/zstd/lib/dictBuilder/cover.c +194 -113
- data/contrib/zstd/lib/dictBuilder/cover.h +112 -0
- data/contrib/zstd/lib/dictBuilder/divsufsort.c +3 -3
- data/contrib/zstd/lib/dictBuilder/fastcover.c +740 -0
- data/contrib/zstd/lib/dictBuilder/zdict.c +142 -106
- data/contrib/zstd/lib/dictBuilder/zdict.h +115 -49
- data/contrib/zstd/lib/legacy/zstd_legacy.h +44 -12
- data/contrib/zstd/lib/legacy/zstd_v01.c +41 -10
- data/contrib/zstd/lib/legacy/zstd_v01.h +12 -7
- data/contrib/zstd/lib/legacy/zstd_v02.c +37 -12
- data/contrib/zstd/lib/legacy/zstd_v02.h +12 -7
- data/contrib/zstd/lib/legacy/zstd_v03.c +38 -12
- data/contrib/zstd/lib/legacy/zstd_v03.h +12 -7
- data/contrib/zstd/lib/legacy/zstd_v04.c +55 -174
- data/contrib/zstd/lib/legacy/zstd_v04.h +12 -7
- data/contrib/zstd/lib/legacy/zstd_v05.c +59 -31
- data/contrib/zstd/lib/legacy/zstd_v05.h +12 -7
- data/contrib/zstd/lib/legacy/zstd_v06.c +48 -20
- data/contrib/zstd/lib/legacy/zstd_v06.h +10 -5
- data/contrib/zstd/lib/legacy/zstd_v07.c +62 -29
- data/contrib/zstd/lib/legacy/zstd_v07.h +10 -5
- data/contrib/zstd/lib/zstd.h +1346 -832
- data/ext/extzstd.c +27 -19
- data/ext/extzstd_stream.c +20 -4
- data/ext/zstd_compress.c +1 -0
- data/ext/zstd_decompress.c +4 -0
- data/ext/zstd_dictbuilder.c +4 -0
- data/ext/zstd_dictbuilder_fastcover.c +5 -0
- data/lib/extzstd.rb +52 -220
- data/lib/extzstd/version.rb +1 -1
- metadata +21 -7
- data/contrib/zstd/circle.yml +0 -63
|
@@ -0,0 +1,240 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Copyright (c) 2016-present, Yann Collet, Facebook, Inc.
|
|
3
|
+
* All rights reserved.
|
|
4
|
+
*
|
|
5
|
+
* This source code is licensed under both the BSD-style license (found in the
|
|
6
|
+
* LICENSE file in the root directory of this source tree) and the GPLv2 (found
|
|
7
|
+
* in the COPYING file in the root directory of this source tree).
|
|
8
|
+
* You may select, at your option, one of the above-listed licenses.
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
/* zstd_ddict.c :
|
|
12
|
+
* concentrates all logic that needs to know the internals of ZSTD_DDict object */
|
|
13
|
+
|
|
14
|
+
/*-*******************************************************
|
|
15
|
+
* Dependencies
|
|
16
|
+
*********************************************************/
|
|
17
|
+
#include <string.h> /* memcpy, memmove, memset */
|
|
18
|
+
#include "cpu.h" /* bmi2 */
|
|
19
|
+
#include "mem.h" /* low level memory routines */
|
|
20
|
+
#define FSE_STATIC_LINKING_ONLY
|
|
21
|
+
#include "fse.h"
|
|
22
|
+
#define HUF_STATIC_LINKING_ONLY
|
|
23
|
+
#include "huf.h"
|
|
24
|
+
#include "zstd_decompress_internal.h"
|
|
25
|
+
#include "zstd_ddict.h"
|
|
26
|
+
|
|
27
|
+
#if defined(ZSTD_LEGACY_SUPPORT) && (ZSTD_LEGACY_SUPPORT>=1)
|
|
28
|
+
# include "zstd_legacy.h"
|
|
29
|
+
#endif
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
/*-*******************************************************
|
|
34
|
+
* Types
|
|
35
|
+
*********************************************************/
|
|
36
|
+
struct ZSTD_DDict_s {
|
|
37
|
+
void* dictBuffer;
|
|
38
|
+
const void* dictContent;
|
|
39
|
+
size_t dictSize;
|
|
40
|
+
ZSTD_entropyDTables_t entropy;
|
|
41
|
+
U32 dictID;
|
|
42
|
+
U32 entropyPresent;
|
|
43
|
+
ZSTD_customMem cMem;
|
|
44
|
+
}; /* typedef'd to ZSTD_DDict within "zstd.h" */
|
|
45
|
+
|
|
46
|
+
const void* ZSTD_DDict_dictContent(const ZSTD_DDict* ddict)
|
|
47
|
+
{
|
|
48
|
+
assert(ddict != NULL);
|
|
49
|
+
return ddict->dictContent;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
size_t ZSTD_DDict_dictSize(const ZSTD_DDict* ddict)
|
|
53
|
+
{
|
|
54
|
+
assert(ddict != NULL);
|
|
55
|
+
return ddict->dictSize;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
void ZSTD_copyDDictParameters(ZSTD_DCtx* dctx, const ZSTD_DDict* ddict)
|
|
59
|
+
{
|
|
60
|
+
DEBUGLOG(4, "ZSTD_copyDDictParameters");
|
|
61
|
+
assert(dctx != NULL);
|
|
62
|
+
assert(ddict != NULL);
|
|
63
|
+
dctx->dictID = ddict->dictID;
|
|
64
|
+
dctx->prefixStart = ddict->dictContent;
|
|
65
|
+
dctx->virtualStart = ddict->dictContent;
|
|
66
|
+
dctx->dictEnd = (const BYTE*)ddict->dictContent + ddict->dictSize;
|
|
67
|
+
dctx->previousDstEnd = dctx->dictEnd;
|
|
68
|
+
if (ddict->entropyPresent) {
|
|
69
|
+
dctx->litEntropy = 1;
|
|
70
|
+
dctx->fseEntropy = 1;
|
|
71
|
+
dctx->LLTptr = ddict->entropy.LLTable;
|
|
72
|
+
dctx->MLTptr = ddict->entropy.MLTable;
|
|
73
|
+
dctx->OFTptr = ddict->entropy.OFTable;
|
|
74
|
+
dctx->HUFptr = ddict->entropy.hufTable;
|
|
75
|
+
dctx->entropy.rep[0] = ddict->entropy.rep[0];
|
|
76
|
+
dctx->entropy.rep[1] = ddict->entropy.rep[1];
|
|
77
|
+
dctx->entropy.rep[2] = ddict->entropy.rep[2];
|
|
78
|
+
} else {
|
|
79
|
+
dctx->litEntropy = 0;
|
|
80
|
+
dctx->fseEntropy = 0;
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
|
|
85
|
+
static size_t
|
|
86
|
+
ZSTD_loadEntropy_intoDDict(ZSTD_DDict* ddict,
|
|
87
|
+
ZSTD_dictContentType_e dictContentType)
|
|
88
|
+
{
|
|
89
|
+
ddict->dictID = 0;
|
|
90
|
+
ddict->entropyPresent = 0;
|
|
91
|
+
if (dictContentType == ZSTD_dct_rawContent) return 0;
|
|
92
|
+
|
|
93
|
+
if (ddict->dictSize < 8) {
|
|
94
|
+
if (dictContentType == ZSTD_dct_fullDict)
|
|
95
|
+
return ERROR(dictionary_corrupted); /* only accept specified dictionaries */
|
|
96
|
+
return 0; /* pure content mode */
|
|
97
|
+
}
|
|
98
|
+
{ U32 const magic = MEM_readLE32(ddict->dictContent);
|
|
99
|
+
if (magic != ZSTD_MAGIC_DICTIONARY) {
|
|
100
|
+
if (dictContentType == ZSTD_dct_fullDict)
|
|
101
|
+
return ERROR(dictionary_corrupted); /* only accept specified dictionaries */
|
|
102
|
+
return 0; /* pure content mode */
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
ddict->dictID = MEM_readLE32((const char*)ddict->dictContent + ZSTD_FRAMEIDSIZE);
|
|
106
|
+
|
|
107
|
+
/* load entropy tables */
|
|
108
|
+
RETURN_ERROR_IF(ZSTD_isError(ZSTD_loadDEntropy(
|
|
109
|
+
&ddict->entropy, ddict->dictContent, ddict->dictSize)),
|
|
110
|
+
dictionary_corrupted);
|
|
111
|
+
ddict->entropyPresent = 1;
|
|
112
|
+
return 0;
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
|
|
116
|
+
static size_t ZSTD_initDDict_internal(ZSTD_DDict* ddict,
|
|
117
|
+
const void* dict, size_t dictSize,
|
|
118
|
+
ZSTD_dictLoadMethod_e dictLoadMethod,
|
|
119
|
+
ZSTD_dictContentType_e dictContentType)
|
|
120
|
+
{
|
|
121
|
+
if ((dictLoadMethod == ZSTD_dlm_byRef) || (!dict) || (!dictSize)) {
|
|
122
|
+
ddict->dictBuffer = NULL;
|
|
123
|
+
ddict->dictContent = dict;
|
|
124
|
+
if (!dict) dictSize = 0;
|
|
125
|
+
} else {
|
|
126
|
+
void* const internalBuffer = ZSTD_malloc(dictSize, ddict->cMem);
|
|
127
|
+
ddict->dictBuffer = internalBuffer;
|
|
128
|
+
ddict->dictContent = internalBuffer;
|
|
129
|
+
if (!internalBuffer) return ERROR(memory_allocation);
|
|
130
|
+
memcpy(internalBuffer, dict, dictSize);
|
|
131
|
+
}
|
|
132
|
+
ddict->dictSize = dictSize;
|
|
133
|
+
ddict->entropy.hufTable[0] = (HUF_DTable)((HufLog)*0x1000001); /* cover both little and big endian */
|
|
134
|
+
|
|
135
|
+
/* parse dictionary content */
|
|
136
|
+
FORWARD_IF_ERROR( ZSTD_loadEntropy_intoDDict(ddict, dictContentType) );
|
|
137
|
+
|
|
138
|
+
return 0;
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
ZSTD_DDict* ZSTD_createDDict_advanced(const void* dict, size_t dictSize,
|
|
142
|
+
ZSTD_dictLoadMethod_e dictLoadMethod,
|
|
143
|
+
ZSTD_dictContentType_e dictContentType,
|
|
144
|
+
ZSTD_customMem customMem)
|
|
145
|
+
{
|
|
146
|
+
if (!customMem.customAlloc ^ !customMem.customFree) return NULL;
|
|
147
|
+
|
|
148
|
+
{ ZSTD_DDict* const ddict = (ZSTD_DDict*) ZSTD_malloc(sizeof(ZSTD_DDict), customMem);
|
|
149
|
+
if (ddict == NULL) return NULL;
|
|
150
|
+
ddict->cMem = customMem;
|
|
151
|
+
{ size_t const initResult = ZSTD_initDDict_internal(ddict,
|
|
152
|
+
dict, dictSize,
|
|
153
|
+
dictLoadMethod, dictContentType);
|
|
154
|
+
if (ZSTD_isError(initResult)) {
|
|
155
|
+
ZSTD_freeDDict(ddict);
|
|
156
|
+
return NULL;
|
|
157
|
+
} }
|
|
158
|
+
return ddict;
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
/*! ZSTD_createDDict() :
|
|
163
|
+
* Create a digested dictionary, to start decompression without startup delay.
|
|
164
|
+
* `dict` content is copied inside DDict.
|
|
165
|
+
* Consequently, `dict` can be released after `ZSTD_DDict` creation */
|
|
166
|
+
ZSTD_DDict* ZSTD_createDDict(const void* dict, size_t dictSize)
|
|
167
|
+
{
|
|
168
|
+
ZSTD_customMem const allocator = { NULL, NULL, NULL };
|
|
169
|
+
return ZSTD_createDDict_advanced(dict, dictSize, ZSTD_dlm_byCopy, ZSTD_dct_auto, allocator);
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
/*! ZSTD_createDDict_byReference() :
|
|
173
|
+
* Create a digested dictionary, to start decompression without startup delay.
|
|
174
|
+
* Dictionary content is simply referenced, it will be accessed during decompression.
|
|
175
|
+
* Warning : dictBuffer must outlive DDict (DDict must be freed before dictBuffer) */
|
|
176
|
+
ZSTD_DDict* ZSTD_createDDict_byReference(const void* dictBuffer, size_t dictSize)
|
|
177
|
+
{
|
|
178
|
+
ZSTD_customMem const allocator = { NULL, NULL, NULL };
|
|
179
|
+
return ZSTD_createDDict_advanced(dictBuffer, dictSize, ZSTD_dlm_byRef, ZSTD_dct_auto, allocator);
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
|
|
183
|
+
const ZSTD_DDict* ZSTD_initStaticDDict(
|
|
184
|
+
void* sBuffer, size_t sBufferSize,
|
|
185
|
+
const void* dict, size_t dictSize,
|
|
186
|
+
ZSTD_dictLoadMethod_e dictLoadMethod,
|
|
187
|
+
ZSTD_dictContentType_e dictContentType)
|
|
188
|
+
{
|
|
189
|
+
size_t const neededSpace = sizeof(ZSTD_DDict)
|
|
190
|
+
+ (dictLoadMethod == ZSTD_dlm_byRef ? 0 : dictSize);
|
|
191
|
+
ZSTD_DDict* const ddict = (ZSTD_DDict*)sBuffer;
|
|
192
|
+
assert(sBuffer != NULL);
|
|
193
|
+
assert(dict != NULL);
|
|
194
|
+
if ((size_t)sBuffer & 7) return NULL; /* 8-aligned */
|
|
195
|
+
if (sBufferSize < neededSpace) return NULL;
|
|
196
|
+
if (dictLoadMethod == ZSTD_dlm_byCopy) {
|
|
197
|
+
memcpy(ddict+1, dict, dictSize); /* local copy */
|
|
198
|
+
dict = ddict+1;
|
|
199
|
+
}
|
|
200
|
+
if (ZSTD_isError( ZSTD_initDDict_internal(ddict,
|
|
201
|
+
dict, dictSize,
|
|
202
|
+
ZSTD_dlm_byRef, dictContentType) ))
|
|
203
|
+
return NULL;
|
|
204
|
+
return ddict;
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
|
|
208
|
+
size_t ZSTD_freeDDict(ZSTD_DDict* ddict)
|
|
209
|
+
{
|
|
210
|
+
if (ddict==NULL) return 0; /* support free on NULL */
|
|
211
|
+
{ ZSTD_customMem const cMem = ddict->cMem;
|
|
212
|
+
ZSTD_free(ddict->dictBuffer, cMem);
|
|
213
|
+
ZSTD_free(ddict, cMem);
|
|
214
|
+
return 0;
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
/*! ZSTD_estimateDDictSize() :
|
|
219
|
+
* Estimate amount of memory that will be needed to create a dictionary for decompression.
|
|
220
|
+
* Note : dictionary created by reference using ZSTD_dlm_byRef are smaller */
|
|
221
|
+
size_t ZSTD_estimateDDictSize(size_t dictSize, ZSTD_dictLoadMethod_e dictLoadMethod)
|
|
222
|
+
{
|
|
223
|
+
return sizeof(ZSTD_DDict) + (dictLoadMethod == ZSTD_dlm_byRef ? 0 : dictSize);
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
size_t ZSTD_sizeof_DDict(const ZSTD_DDict* ddict)
|
|
227
|
+
{
|
|
228
|
+
if (ddict==NULL) return 0; /* support sizeof on NULL */
|
|
229
|
+
return sizeof(*ddict) + (ddict->dictBuffer ? ddict->dictSize : 0) ;
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
/*! ZSTD_getDictID_fromDDict() :
|
|
233
|
+
* Provides the dictID of the dictionary loaded into `ddict`.
|
|
234
|
+
* If @return == 0, the dictionary is not conformant to Zstandard specification, or empty.
|
|
235
|
+
* Non-conformant dictionaries can still be loaded, but as content-only dictionaries. */
|
|
236
|
+
unsigned ZSTD_getDictID_fromDDict(const ZSTD_DDict* ddict)
|
|
237
|
+
{
|
|
238
|
+
if (ddict==NULL) return 0;
|
|
239
|
+
return ZSTD_getDictID_fromDict(ddict->dictContent, ddict->dictSize);
|
|
240
|
+
}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Copyright (c) 2016-present, Yann Collet, Facebook, Inc.
|
|
3
|
+
* All rights reserved.
|
|
4
|
+
*
|
|
5
|
+
* This source code is licensed under both the BSD-style license (found in the
|
|
6
|
+
* LICENSE file in the root directory of this source tree) and the GPLv2 (found
|
|
7
|
+
* in the COPYING file in the root directory of this source tree).
|
|
8
|
+
* You may select, at your option, one of the above-listed licenses.
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
#ifndef ZSTD_DDICT_H
|
|
13
|
+
#define ZSTD_DDICT_H
|
|
14
|
+
|
|
15
|
+
/*-*******************************************************
|
|
16
|
+
* Dependencies
|
|
17
|
+
*********************************************************/
|
|
18
|
+
#include <stddef.h> /* size_t */
|
|
19
|
+
#include "zstd.h" /* ZSTD_DDict, and several public functions */
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
/*-*******************************************************
|
|
23
|
+
* Interface
|
|
24
|
+
*********************************************************/
|
|
25
|
+
|
|
26
|
+
/* note: several prototypes are already published in `zstd.h` :
|
|
27
|
+
* ZSTD_createDDict()
|
|
28
|
+
* ZSTD_createDDict_byReference()
|
|
29
|
+
* ZSTD_createDDict_advanced()
|
|
30
|
+
* ZSTD_freeDDict()
|
|
31
|
+
* ZSTD_initStaticDDict()
|
|
32
|
+
* ZSTD_sizeof_DDict()
|
|
33
|
+
* ZSTD_estimateDDictSize()
|
|
34
|
+
* ZSTD_getDictID_fromDict()
|
|
35
|
+
*/
|
|
36
|
+
|
|
37
|
+
const void* ZSTD_DDict_dictContent(const ZSTD_DDict* ddict);
|
|
38
|
+
size_t ZSTD_DDict_dictSize(const ZSTD_DDict* ddict);
|
|
39
|
+
|
|
40
|
+
void ZSTD_copyDDictParameters(ZSTD_DCtx* dctx, const ZSTD_DDict* ddict);
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
#endif /* ZSTD_DDICT_H */
|
|
@@ -14,8 +14,9 @@
|
|
|
14
14
|
*****************************************************************/
|
|
15
15
|
/*!
|
|
16
16
|
* HEAPMODE :
|
|
17
|
-
* Select how default decompression function ZSTD_decompress()
|
|
18
|
-
*
|
|
17
|
+
* Select how default decompression function ZSTD_decompress() allocates its context,
|
|
18
|
+
* on stack (0), or into heap (1, default; requires malloc()).
|
|
19
|
+
* Note that functions with explicit context such as ZSTD_decompressDCtx() are unaffected.
|
|
19
20
|
*/
|
|
20
21
|
#ifndef ZSTD_HEAPMODE
|
|
21
22
|
# define ZSTD_HEAPMODE 1
|
|
@@ -23,19 +24,31 @@
|
|
|
23
24
|
|
|
24
25
|
/*!
|
|
25
26
|
* LEGACY_SUPPORT :
|
|
26
|
-
* if set to 1
|
|
27
|
+
* if set to 1+, ZSTD_decompress() can decode older formats (v0.1+)
|
|
27
28
|
*/
|
|
28
29
|
#ifndef ZSTD_LEGACY_SUPPORT
|
|
29
30
|
# define ZSTD_LEGACY_SUPPORT 0
|
|
30
31
|
#endif
|
|
31
32
|
|
|
32
33
|
/*!
|
|
33
|
-
* MAXWINDOWSIZE_DEFAULT :
|
|
34
|
-
* maximum window size accepted by DStream
|
|
35
|
-
* Frames requiring more memory will be rejected.
|
|
36
|
-
|
|
34
|
+
* MAXWINDOWSIZE_DEFAULT :
|
|
35
|
+
* maximum window size accepted by DStream __by default__.
|
|
36
|
+
* Frames requiring more memory will be rejected.
|
|
37
|
+
* It's possible to set a different limit using ZSTD_DCtx_setMaxWindowSize().
|
|
38
|
+
*/
|
|
37
39
|
#ifndef ZSTD_MAXWINDOWSIZE_DEFAULT
|
|
38
|
-
# define ZSTD_MAXWINDOWSIZE_DEFAULT (((U32)1 <<
|
|
40
|
+
# define ZSTD_MAXWINDOWSIZE_DEFAULT (((U32)1 << ZSTD_WINDOWLOG_LIMIT_DEFAULT) + 1)
|
|
41
|
+
#endif
|
|
42
|
+
|
|
43
|
+
/*!
|
|
44
|
+
* NO_FORWARD_PROGRESS_MAX :
|
|
45
|
+
* maximum allowed nb of calls to ZSTD_decompressStream()
|
|
46
|
+
* without any forward progress
|
|
47
|
+
* (defined as: no byte read from input, and no byte flushed to output)
|
|
48
|
+
* before triggering an error.
|
|
49
|
+
*/
|
|
50
|
+
#ifndef ZSTD_NO_FORWARD_PROGRESS_MAX
|
|
51
|
+
# define ZSTD_NO_FORWARD_PROGRESS_MAX 16
|
|
39
52
|
#endif
|
|
40
53
|
|
|
41
54
|
|
|
@@ -43,103 +56,25 @@
|
|
|
43
56
|
* Dependencies
|
|
44
57
|
*********************************************************/
|
|
45
58
|
#include <string.h> /* memcpy, memmove, memset */
|
|
59
|
+
#include "cpu.h" /* bmi2 */
|
|
46
60
|
#include "mem.h" /* low level memory routines */
|
|
47
61
|
#define FSE_STATIC_LINKING_ONLY
|
|
48
62
|
#include "fse.h"
|
|
49
63
|
#define HUF_STATIC_LINKING_ONLY
|
|
50
64
|
#include "huf.h"
|
|
51
|
-
#include "zstd_internal.h"
|
|
65
|
+
#include "zstd_internal.h" /* blockProperties_t */
|
|
66
|
+
#include "zstd_decompress_internal.h" /* ZSTD_DCtx */
|
|
67
|
+
#include "zstd_ddict.h" /* ZSTD_DDictDictContent */
|
|
68
|
+
#include "zstd_decompress_block.h" /* ZSTD_decompressBlock_internal */
|
|
52
69
|
|
|
53
70
|
#if defined(ZSTD_LEGACY_SUPPORT) && (ZSTD_LEGACY_SUPPORT>=1)
|
|
54
71
|
# include "zstd_legacy.h"
|
|
55
72
|
#endif
|
|
56
73
|
|
|
57
74
|
|
|
58
|
-
/*-*************************************
|
|
59
|
-
* Errors
|
|
60
|
-
***************************************/
|
|
61
|
-
#define ZSTD_isError ERR_isError /* for inlining */
|
|
62
|
-
#define FSE_isError ERR_isError
|
|
63
|
-
#define HUF_isError ERR_isError
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
/*_*******************************************************
|
|
67
|
-
* Memory operations
|
|
68
|
-
**********************************************************/
|
|
69
|
-
static void ZSTD_copy4(void* dst, const void* src) { memcpy(dst, src, 4); }
|
|
70
|
-
|
|
71
|
-
|
|
72
75
|
/*-*************************************************************
|
|
73
76
|
* Context management
|
|
74
77
|
***************************************************************/
|
|
75
|
-
typedef enum { ZSTDds_getFrameHeaderSize, ZSTDds_decodeFrameHeader,
|
|
76
|
-
ZSTDds_decodeBlockHeader, ZSTDds_decompressBlock,
|
|
77
|
-
ZSTDds_decompressLastBlock, ZSTDds_checkChecksum,
|
|
78
|
-
ZSTDds_decodeSkippableHeader, ZSTDds_skipFrame } ZSTD_dStage;
|
|
79
|
-
|
|
80
|
-
typedef enum { zdss_init=0, zdss_loadHeader,
|
|
81
|
-
zdss_read, zdss_load, zdss_flush } ZSTD_dStreamStage;
|
|
82
|
-
|
|
83
|
-
typedef struct {
|
|
84
|
-
FSE_DTable LLTable[FSE_DTABLE_SIZE_U32(LLFSELog)];
|
|
85
|
-
FSE_DTable OFTable[FSE_DTABLE_SIZE_U32(OffFSELog)];
|
|
86
|
-
FSE_DTable MLTable[FSE_DTABLE_SIZE_U32(MLFSELog)];
|
|
87
|
-
HUF_DTable hufTable[HUF_DTABLE_SIZE(HufLog)]; /* can accommodate HUF_decompress4X */
|
|
88
|
-
U32 workspace[HUF_DECOMPRESS_WORKSPACE_SIZE_U32];
|
|
89
|
-
U32 rep[ZSTD_REP_NUM];
|
|
90
|
-
} ZSTD_entropyDTables_t;
|
|
91
|
-
|
|
92
|
-
struct ZSTD_DCtx_s
|
|
93
|
-
{
|
|
94
|
-
const FSE_DTable* LLTptr;
|
|
95
|
-
const FSE_DTable* MLTptr;
|
|
96
|
-
const FSE_DTable* OFTptr;
|
|
97
|
-
const HUF_DTable* HUFptr;
|
|
98
|
-
ZSTD_entropyDTables_t entropy;
|
|
99
|
-
const void* previousDstEnd; /* detect continuity */
|
|
100
|
-
const void* base; /* start of current segment */
|
|
101
|
-
const void* vBase; /* virtual start of previous segment if it was just before current one */
|
|
102
|
-
const void* dictEnd; /* end of previous segment */
|
|
103
|
-
size_t expected;
|
|
104
|
-
ZSTD_frameHeader fParams;
|
|
105
|
-
U64 decodedSize;
|
|
106
|
-
blockType_e bType; /* used in ZSTD_decompressContinue(), store blockType between block header decoding and block decompression stages */
|
|
107
|
-
ZSTD_dStage stage;
|
|
108
|
-
U32 litEntropy;
|
|
109
|
-
U32 fseEntropy;
|
|
110
|
-
XXH64_state_t xxhState;
|
|
111
|
-
size_t headerSize;
|
|
112
|
-
U32 dictID;
|
|
113
|
-
ZSTD_format_e format;
|
|
114
|
-
const BYTE* litPtr;
|
|
115
|
-
ZSTD_customMem customMem;
|
|
116
|
-
size_t litSize;
|
|
117
|
-
size_t rleSize;
|
|
118
|
-
size_t staticSize;
|
|
119
|
-
|
|
120
|
-
/* streaming */
|
|
121
|
-
ZSTD_DDict* ddictLocal;
|
|
122
|
-
const ZSTD_DDict* ddict;
|
|
123
|
-
ZSTD_dStreamStage streamStage;
|
|
124
|
-
char* inBuff;
|
|
125
|
-
size_t inBuffSize;
|
|
126
|
-
size_t inPos;
|
|
127
|
-
size_t maxWindowSize;
|
|
128
|
-
char* outBuff;
|
|
129
|
-
size_t outBuffSize;
|
|
130
|
-
size_t outStart;
|
|
131
|
-
size_t outEnd;
|
|
132
|
-
size_t lhSize;
|
|
133
|
-
void* legacyContext;
|
|
134
|
-
U32 previousLegacyVersion;
|
|
135
|
-
U32 legacyVersion;
|
|
136
|
-
U32 hostageByte;
|
|
137
|
-
|
|
138
|
-
/* workspace */
|
|
139
|
-
BYTE litBuffer[ZSTD_BLOCKSIZE_MAX + WILDCOPY_OVERLENGTH];
|
|
140
|
-
BYTE headerBuffer[ZSTD_FRAMEHEADERSIZE_MAX];
|
|
141
|
-
}; /* typedef'd to ZSTD_DCtx within "zstd.h" */
|
|
142
|
-
|
|
143
78
|
size_t ZSTD_sizeof_DCtx (const ZSTD_DCtx* dctx)
|
|
144
79
|
{
|
|
145
80
|
if (dctx==NULL) return 0; /* support sizeof NULL */
|
|
@@ -154,8 +89,8 @@ size_t ZSTD_estimateDCtxSize(void) { return sizeof(ZSTD_DCtx); }
|
|
|
154
89
|
static size_t ZSTD_startingInputLength(ZSTD_format_e format)
|
|
155
90
|
{
|
|
156
91
|
size_t const startingInputLength = (format==ZSTD_f_zstd1_magicless) ?
|
|
157
|
-
|
|
158
|
-
|
|
92
|
+
ZSTD_FRAMEHEADERSIZE_PREFIX - ZSTD_FRAMEIDSIZE :
|
|
93
|
+
ZSTD_FRAMEHEADERSIZE_PREFIX;
|
|
159
94
|
ZSTD_STATIC_ASSERT(ZSTD_FRAMEHEADERSIZE_PREFIX >= ZSTD_FRAMEIDSIZE);
|
|
160
95
|
/* only supports formats ZSTD_f_zstd1 and ZSTD_f_zstd1_magicless */
|
|
161
96
|
assert( (format == ZSTD_f_zstd1) || (format == ZSTD_f_zstd1_magicless) );
|
|
@@ -169,10 +104,17 @@ static void ZSTD_initDCtx_internal(ZSTD_DCtx* dctx)
|
|
|
169
104
|
dctx->maxWindowSize = ZSTD_MAXWINDOWSIZE_DEFAULT;
|
|
170
105
|
dctx->ddict = NULL;
|
|
171
106
|
dctx->ddictLocal = NULL;
|
|
107
|
+
dctx->dictEnd = NULL;
|
|
108
|
+
dctx->ddictIsCold = 0;
|
|
109
|
+
dctx->dictUses = ZSTD_dont_use;
|
|
172
110
|
dctx->inBuff = NULL;
|
|
173
111
|
dctx->inBuffSize = 0;
|
|
174
112
|
dctx->outBuffSize = 0;
|
|
175
113
|
dctx->streamStage = zdss_init;
|
|
114
|
+
dctx->legacyContext = NULL;
|
|
115
|
+
dctx->previousLegacyVersion = 0;
|
|
116
|
+
dctx->noForwardProgress = 0;
|
|
117
|
+
dctx->bmi2 = ZSTD_cpuid_bmi2(ZSTD_cpuid());
|
|
176
118
|
}
|
|
177
119
|
|
|
178
120
|
ZSTD_DCtx* ZSTD_initStaticDCtx(void *workspace, size_t workspaceSize)
|
|
@@ -195,8 +137,6 @@ ZSTD_DCtx* ZSTD_createDCtx_advanced(ZSTD_customMem customMem)
|
|
|
195
137
|
{ ZSTD_DCtx* const dctx = (ZSTD_DCtx*)ZSTD_malloc(sizeof(*dctx), customMem);
|
|
196
138
|
if (!dctx) return NULL;
|
|
197
139
|
dctx->customMem = customMem;
|
|
198
|
-
dctx->legacyContext = NULL;
|
|
199
|
-
dctx->previousLegacyVersion = 0;
|
|
200
140
|
ZSTD_initDCtx_internal(dctx);
|
|
201
141
|
return dctx;
|
|
202
142
|
}
|
|
@@ -204,16 +144,24 @@ ZSTD_DCtx* ZSTD_createDCtx_advanced(ZSTD_customMem customMem)
|
|
|
204
144
|
|
|
205
145
|
ZSTD_DCtx* ZSTD_createDCtx(void)
|
|
206
146
|
{
|
|
147
|
+
DEBUGLOG(3, "ZSTD_createDCtx");
|
|
207
148
|
return ZSTD_createDCtx_advanced(ZSTD_defaultCMem);
|
|
208
149
|
}
|
|
209
150
|
|
|
151
|
+
static void ZSTD_clearDict(ZSTD_DCtx* dctx)
|
|
152
|
+
{
|
|
153
|
+
ZSTD_freeDDict(dctx->ddictLocal);
|
|
154
|
+
dctx->ddictLocal = NULL;
|
|
155
|
+
dctx->ddict = NULL;
|
|
156
|
+
dctx->dictUses = ZSTD_dont_use;
|
|
157
|
+
}
|
|
158
|
+
|
|
210
159
|
size_t ZSTD_freeDCtx(ZSTD_DCtx* dctx)
|
|
211
160
|
{
|
|
212
161
|
if (dctx==NULL) return 0; /* support free on NULL */
|
|
213
|
-
|
|
162
|
+
RETURN_ERROR_IF(dctx->staticSize, memory_allocation, "not compatible with static DCtx");
|
|
214
163
|
{ ZSTD_customMem const cMem = dctx->customMem;
|
|
215
|
-
|
|
216
|
-
dctx->ddictLocal = NULL;
|
|
164
|
+
ZSTD_clearDict(dctx);
|
|
217
165
|
ZSTD_free(dctx->inBuff, cMem);
|
|
218
166
|
dctx->inBuff = NULL;
|
|
219
167
|
#if defined(ZSTD_LEGACY_SUPPORT) && (ZSTD_LEGACY_SUPPORT >= 1)
|
|
@@ -234,8 +182,8 @@ void ZSTD_copyDCtx(ZSTD_DCtx* dstDCtx, const ZSTD_DCtx* srcDCtx)
|
|
|
234
182
|
|
|
235
183
|
|
|
236
184
|
/*-*************************************************************
|
|
237
|
-
*
|
|
238
|
-
***************************************************************/
|
|
185
|
+
* Frame header decoding
|
|
186
|
+
***************************************************************/
|
|
239
187
|
|
|
240
188
|
/*! ZSTD_isFrame() :
|
|
241
189
|
* Tells if the content of `buffer` starts with a valid Frame Identifier.
|
|
@@ -244,10 +192,10 @@ void ZSTD_copyDCtx(ZSTD_DCtx* dstDCtx, const ZSTD_DCtx* srcDCtx)
|
|
|
244
192
|
* Note 3 : Skippable Frame Identifiers are considered valid. */
|
|
245
193
|
unsigned ZSTD_isFrame(const void* buffer, size_t size)
|
|
246
194
|
{
|
|
247
|
-
if (size <
|
|
195
|
+
if (size < ZSTD_FRAMEIDSIZE) return 0;
|
|
248
196
|
{ U32 const magic = MEM_readLE32(buffer);
|
|
249
197
|
if (magic == ZSTD_MAGICNUMBER) return 1;
|
|
250
|
-
if ((magic &
|
|
198
|
+
if ((magic & ZSTD_MAGIC_SKIPPABLE_MASK) == ZSTD_MAGIC_SKIPPABLE_START) return 1;
|
|
251
199
|
}
|
|
252
200
|
#if defined(ZSTD_LEGACY_SUPPORT) && (ZSTD_LEGACY_SUPPORT >= 1)
|
|
253
201
|
if (ZSTD_isLegacy(buffer, size)) return 1;
|
|
@@ -257,13 +205,13 @@ unsigned ZSTD_isFrame(const void* buffer, size_t size)
|
|
|
257
205
|
|
|
258
206
|
/** ZSTD_frameHeaderSize_internal() :
|
|
259
207
|
* srcSize must be large enough to reach header size fields.
|
|
260
|
-
* note : only works for formats ZSTD_f_zstd1 and ZSTD_f_zstd1_magicless
|
|
208
|
+
* note : only works for formats ZSTD_f_zstd1 and ZSTD_f_zstd1_magicless.
|
|
261
209
|
* @return : size of the Frame Header
|
|
262
210
|
* or an error code, which can be tested with ZSTD_isError() */
|
|
263
211
|
static size_t ZSTD_frameHeaderSize_internal(const void* src, size_t srcSize, ZSTD_format_e format)
|
|
264
212
|
{
|
|
265
213
|
size_t const minInputSize = ZSTD_startingInputLength(format);
|
|
266
|
-
|
|
214
|
+
RETURN_ERROR_IF(srcSize < minInputSize, srcSize_wrong);
|
|
267
215
|
|
|
268
216
|
{ BYTE const fhd = ((const BYTE*)src)[minInputSize-1];
|
|
269
217
|
U32 const dictID= fhd & 3;
|
|
@@ -277,38 +225,41 @@ static size_t ZSTD_frameHeaderSize_internal(const void* src, size_t srcSize, ZST
|
|
|
277
225
|
|
|
278
226
|
/** ZSTD_frameHeaderSize() :
|
|
279
227
|
* srcSize must be >= ZSTD_frameHeaderSize_prefix.
|
|
280
|
-
* @return : size of the Frame Header
|
|
228
|
+
* @return : size of the Frame Header,
|
|
229
|
+
* or an error code (if srcSize is too small) */
|
|
281
230
|
size_t ZSTD_frameHeaderSize(const void* src, size_t srcSize)
|
|
282
231
|
{
|
|
283
232
|
return ZSTD_frameHeaderSize_internal(src, srcSize, ZSTD_f_zstd1);
|
|
284
233
|
}
|
|
285
234
|
|
|
286
235
|
|
|
287
|
-
/**
|
|
236
|
+
/** ZSTD_getFrameHeader_advanced() :
|
|
288
237
|
* decode Frame Header, or require larger `srcSize`.
|
|
289
238
|
* note : only works for formats ZSTD_f_zstd1 and ZSTD_f_zstd1_magicless
|
|
290
239
|
* @return : 0, `zfhPtr` is correctly filled,
|
|
291
240
|
* >0, `srcSize` is too small, value is wanted `srcSize` amount,
|
|
292
241
|
* or an error code, which can be tested using ZSTD_isError() */
|
|
293
|
-
|
|
242
|
+
size_t ZSTD_getFrameHeader_advanced(ZSTD_frameHeader* zfhPtr, const void* src, size_t srcSize, ZSTD_format_e format)
|
|
294
243
|
{
|
|
295
244
|
const BYTE* ip = (const BYTE*)src;
|
|
296
245
|
size_t const minInputSize = ZSTD_startingInputLength(format);
|
|
297
246
|
|
|
247
|
+
memset(zfhPtr, 0, sizeof(*zfhPtr)); /* not strictly necessary, but static analyzer do not understand that zfhPtr is only going to be read only if return value is zero, since they are 2 different signals */
|
|
298
248
|
if (srcSize < minInputSize) return minInputSize;
|
|
249
|
+
RETURN_ERROR_IF(src==NULL, GENERIC, "invalid parameter");
|
|
299
250
|
|
|
300
251
|
if ( (format != ZSTD_f_zstd1_magicless)
|
|
301
252
|
&& (MEM_readLE32(src) != ZSTD_MAGICNUMBER) ) {
|
|
302
|
-
if ((MEM_readLE32(src) &
|
|
253
|
+
if ((MEM_readLE32(src) & ZSTD_MAGIC_SKIPPABLE_MASK) == ZSTD_MAGIC_SKIPPABLE_START) {
|
|
303
254
|
/* skippable frame */
|
|
304
|
-
if (srcSize <
|
|
305
|
-
return
|
|
255
|
+
if (srcSize < ZSTD_SKIPPABLEHEADERSIZE)
|
|
256
|
+
return ZSTD_SKIPPABLEHEADERSIZE; /* magic number + frame length */
|
|
306
257
|
memset(zfhPtr, 0, sizeof(*zfhPtr));
|
|
307
|
-
zfhPtr->frameContentSize = MEM_readLE32((const char *)src +
|
|
258
|
+
zfhPtr->frameContentSize = MEM_readLE32((const char *)src + ZSTD_FRAMEIDSIZE);
|
|
308
259
|
zfhPtr->frameType = ZSTD_skippableFrame;
|
|
309
260
|
return 0;
|
|
310
261
|
}
|
|
311
|
-
|
|
262
|
+
RETURN_ERROR(prefix_unknown);
|
|
312
263
|
}
|
|
313
264
|
|
|
314
265
|
/* ensure there is enough `srcSize` to fully read/decode frame header */
|
|
@@ -326,14 +277,13 @@ static size_t ZSTD_getFrameHeader_internal(ZSTD_frameHeader* zfhPtr, const void*
|
|
|
326
277
|
U64 windowSize = 0;
|
|
327
278
|
U32 dictID = 0;
|
|
328
279
|
U64 frameContentSize = ZSTD_CONTENTSIZE_UNKNOWN;
|
|
329
|
-
|
|
330
|
-
|
|
280
|
+
RETURN_ERROR_IF((fhdByte & 0x08) != 0, frameParameter_unsupported,
|
|
281
|
+
"reserved bits, must be zero");
|
|
331
282
|
|
|
332
283
|
if (!singleSegment) {
|
|
333
284
|
BYTE const wlByte = ip[pos++];
|
|
334
285
|
U32 const windowLog = (wlByte >> 3) + ZSTD_WINDOWLOG_ABSOLUTEMIN;
|
|
335
|
-
|
|
336
|
-
return ERROR(frameParameter_windowTooLarge);
|
|
286
|
+
RETURN_ERROR_IF(windowLog > ZSTD_WINDOWLOG_MAX, frameParameter_windowTooLarge);
|
|
337
287
|
windowSize = (1ULL << windowLog);
|
|
338
288
|
windowSize += (windowSize >> 3) * (wlByte&7);
|
|
339
289
|
}
|
|
@@ -373,7 +323,7 @@ static size_t ZSTD_getFrameHeader_internal(ZSTD_frameHeader* zfhPtr, const void*
|
|
|
373
323
|
* or an error code, which can be tested using ZSTD_isError() */
|
|
374
324
|
size_t ZSTD_getFrameHeader(ZSTD_frameHeader* zfhPtr, const void* src, size_t srcSize)
|
|
375
325
|
{
|
|
376
|
-
return
|
|
326
|
+
return ZSTD_getFrameHeader_advanced(zfhPtr, src, srcSize, ZSTD_f_zstd1);
|
|
377
327
|
}
|
|
378
328
|
|
|
379
329
|
|
|
@@ -400,6 +350,20 @@ unsigned long long ZSTD_getFrameContentSize(const void *src, size_t srcSize)
|
|
|
400
350
|
} }
|
|
401
351
|
}
|
|
402
352
|
|
|
353
|
+
static size_t readSkippableFrameSize(void const* src, size_t srcSize)
|
|
354
|
+
{
|
|
355
|
+
size_t const skippableHeaderSize = ZSTD_SKIPPABLEHEADERSIZE;
|
|
356
|
+
U32 sizeU32;
|
|
357
|
+
|
|
358
|
+
RETURN_ERROR_IF(srcSize < ZSTD_SKIPPABLEHEADERSIZE, srcSize_wrong);
|
|
359
|
+
|
|
360
|
+
sizeU32 = MEM_readLE32((BYTE const*)src + ZSTD_FRAMEIDSIZE);
|
|
361
|
+
RETURN_ERROR_IF((U32)(sizeU32 + ZSTD_SKIPPABLEHEADERSIZE) < sizeU32,
|
|
362
|
+
frameParameter_unsupported);
|
|
363
|
+
|
|
364
|
+
return skippableHeaderSize + sizeU32;
|
|
365
|
+
}
|
|
366
|
+
|
|
403
367
|
/** ZSTD_findDecompressedSize() :
|
|
404
368
|
* compatible with legacy mode
|
|
405
369
|
* `srcSize` must be the exact length of some number of ZSTD compressed and/or
|
|
@@ -409,15 +373,13 @@ unsigned long long ZSTD_findDecompressedSize(const void* src, size_t srcSize)
|
|
|
409
373
|
{
|
|
410
374
|
unsigned long long totalDstSize = 0;
|
|
411
375
|
|
|
412
|
-
while (srcSize >=
|
|
376
|
+
while (srcSize >= ZSTD_FRAMEHEADERSIZE_PREFIX) {
|
|
413
377
|
U32 const magicNumber = MEM_readLE32(src);
|
|
414
378
|
|
|
415
|
-
if ((magicNumber &
|
|
416
|
-
size_t skippableSize;
|
|
417
|
-
if (
|
|
418
|
-
return
|
|
419
|
-
skippableSize = MEM_readLE32((const BYTE *)src + ZSTD_frameIdSize)
|
|
420
|
-
+ ZSTD_skippableHeaderSize;
|
|
379
|
+
if ((magicNumber & ZSTD_MAGIC_SKIPPABLE_MASK) == ZSTD_MAGIC_SKIPPABLE_START) {
|
|
380
|
+
size_t const skippableSize = readSkippableFrameSize(src, srcSize);
|
|
381
|
+
if (ZSTD_isError(skippableSize))
|
|
382
|
+
return skippableSize;
|
|
421
383
|
if (srcSize < skippableSize) {
|
|
422
384
|
return ZSTD_CONTENTSIZE_ERROR;
|
|
423
385
|
}
|
|
@@ -450,9 +412,9 @@ unsigned long long ZSTD_findDecompressedSize(const void* src, size_t srcSize)
|
|
|
450
412
|
}
|
|
451
413
|
|
|
452
414
|
/** ZSTD_getDecompressedSize() :
|
|
453
|
-
*
|
|
454
|
-
*
|
|
455
|
-
|
|
415
|
+
* compatible with legacy mode
|
|
416
|
+
* @return : decompressed size if known, 0 otherwise
|
|
417
|
+
note : 0 can mean any of the following :
|
|
456
418
|
- frame content is empty
|
|
457
419
|
- decompressed size field is not present in frame header
|
|
458
420
|
- frame header unknown / not supported
|
|
@@ -466,999 +428,150 @@ unsigned long long ZSTD_getDecompressedSize(const void* src, size_t srcSize)
|
|
|
466
428
|
|
|
467
429
|
|
|
468
430
|
/** ZSTD_decodeFrameHeader() :
|
|
469
|
-
*
|
|
470
|
-
*
|
|
431
|
+
* `headerSize` must be the size provided by ZSTD_frameHeaderSize().
|
|
432
|
+
* @return : 0 if success, or an error code, which can be tested using ZSTD_isError() */
|
|
471
433
|
static size_t ZSTD_decodeFrameHeader(ZSTD_DCtx* dctx, const void* src, size_t headerSize)
|
|
472
434
|
{
|
|
473
|
-
size_t const result =
|
|
435
|
+
size_t const result = ZSTD_getFrameHeader_advanced(&(dctx->fParams), src, headerSize, dctx->format);
|
|
474
436
|
if (ZSTD_isError(result)) return result; /* invalid header */
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
437
|
+
RETURN_ERROR_IF(result>0, srcSize_wrong, "headerSize too small");
|
|
438
|
+
#ifndef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
|
|
439
|
+
/* Skip the dictID check in fuzzing mode, because it makes the search
|
|
440
|
+
* harder.
|
|
441
|
+
*/
|
|
442
|
+
RETURN_ERROR_IF(dctx->fParams.dictID && (dctx->dictID != dctx->fParams.dictID),
|
|
443
|
+
dictionary_wrong);
|
|
444
|
+
#endif
|
|
478
445
|
if (dctx->fParams.checksumFlag) XXH64_reset(&dctx->xxhState, 0);
|
|
479
446
|
return 0;
|
|
480
447
|
}
|
|
481
448
|
|
|
482
|
-
|
|
483
|
-
/*! ZSTD_getcBlockSize() :
|
|
484
|
-
* Provides the size of compressed block from block header `src` */
|
|
485
|
-
size_t ZSTD_getcBlockSize(const void* src, size_t srcSize,
|
|
486
|
-
blockProperties_t* bpPtr)
|
|
487
|
-
{
|
|
488
|
-
if (srcSize < ZSTD_blockHeaderSize) return ERROR(srcSize_wrong);
|
|
489
|
-
{ U32 const cBlockHeader = MEM_readLE24(src);
|
|
490
|
-
U32 const cSize = cBlockHeader >> 3;
|
|
491
|
-
bpPtr->lastBlock = cBlockHeader & 1;
|
|
492
|
-
bpPtr->blockType = (blockType_e)((cBlockHeader >> 1) & 3);
|
|
493
|
-
bpPtr->origSize = cSize; /* only useful for RLE */
|
|
494
|
-
if (bpPtr->blockType == bt_rle) return 1;
|
|
495
|
-
if (bpPtr->blockType == bt_reserved) return ERROR(corruption_detected);
|
|
496
|
-
return cSize;
|
|
497
|
-
}
|
|
498
|
-
}
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
static size_t ZSTD_copyRawBlock(void* dst, size_t dstCapacity,
|
|
502
|
-
const void* src, size_t srcSize)
|
|
503
|
-
{
|
|
504
|
-
if (srcSize > dstCapacity) return ERROR(dstSize_tooSmall);
|
|
505
|
-
memcpy(dst, src, srcSize);
|
|
506
|
-
return srcSize;
|
|
507
|
-
}
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
static size_t ZSTD_setRleBlock(void* dst, size_t dstCapacity,
|
|
511
|
-
const void* src, size_t srcSize,
|
|
512
|
-
size_t regenSize)
|
|
449
|
+
static ZSTD_frameSizeInfo ZSTD_errorFrameSizeInfo(size_t ret)
|
|
513
450
|
{
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
return
|
|
451
|
+
ZSTD_frameSizeInfo frameSizeInfo;
|
|
452
|
+
frameSizeInfo.compressedSize = ret;
|
|
453
|
+
frameSizeInfo.decompressedBound = ZSTD_CONTENTSIZE_ERROR;
|
|
454
|
+
return frameSizeInfo;
|
|
518
455
|
}
|
|
519
456
|
|
|
520
|
-
|
|
521
|
-
* @return : nb of bytes read from src (< srcSize )
|
|
522
|
-
* note : symbol not declared but exposed for fullbench */
|
|
523
|
-
size_t ZSTD_decodeLiteralsBlock(ZSTD_DCtx* dctx,
|
|
524
|
-
const void* src, size_t srcSize) /* note : srcSize < BLOCKSIZE */
|
|
457
|
+
static ZSTD_frameSizeInfo ZSTD_findFrameSizeInfo(const void* src, size_t srcSize)
|
|
525
458
|
{
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
{ const BYTE* const istart = (const BYTE*) src;
|
|
529
|
-
symbolEncodingType_e const litEncType = (symbolEncodingType_e)(istart[0] & 3);
|
|
459
|
+
ZSTD_frameSizeInfo frameSizeInfo;
|
|
460
|
+
memset(&frameSizeInfo, 0, sizeof(ZSTD_frameSizeInfo));
|
|
530
461
|
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
/* fall-through */
|
|
536
|
-
case set_compressed:
|
|
537
|
-
if (srcSize < 5) return ERROR(corruption_detected); /* srcSize >= MIN_CBLOCK_SIZE == 3; here we need up to 5 for case 3 */
|
|
538
|
-
{ size_t lhSize, litSize, litCSize;
|
|
539
|
-
U32 singleStream=0;
|
|
540
|
-
U32 const lhlCode = (istart[0] >> 2) & 3;
|
|
541
|
-
U32 const lhc = MEM_readLE32(istart);
|
|
542
|
-
switch(lhlCode)
|
|
543
|
-
{
|
|
544
|
-
case 0: case 1: default: /* note : default is impossible, since lhlCode into [0..3] */
|
|
545
|
-
/* 2 - 2 - 10 - 10 */
|
|
546
|
-
singleStream = !lhlCode;
|
|
547
|
-
lhSize = 3;
|
|
548
|
-
litSize = (lhc >> 4) & 0x3FF;
|
|
549
|
-
litCSize = (lhc >> 14) & 0x3FF;
|
|
550
|
-
break;
|
|
551
|
-
case 2:
|
|
552
|
-
/* 2 - 2 - 14 - 14 */
|
|
553
|
-
lhSize = 4;
|
|
554
|
-
litSize = (lhc >> 4) & 0x3FFF;
|
|
555
|
-
litCSize = lhc >> 18;
|
|
556
|
-
break;
|
|
557
|
-
case 3:
|
|
558
|
-
/* 2 - 2 - 18 - 18 */
|
|
559
|
-
lhSize = 5;
|
|
560
|
-
litSize = (lhc >> 4) & 0x3FFFF;
|
|
561
|
-
litCSize = (lhc >> 22) + (istart[4] << 10);
|
|
562
|
-
break;
|
|
563
|
-
}
|
|
564
|
-
if (litSize > ZSTD_BLOCKSIZE_MAX) return ERROR(corruption_detected);
|
|
565
|
-
if (litCSize + lhSize > srcSize) return ERROR(corruption_detected);
|
|
566
|
-
|
|
567
|
-
if (HUF_isError((litEncType==set_repeat) ?
|
|
568
|
-
( singleStream ?
|
|
569
|
-
HUF_decompress1X_usingDTable(dctx->litBuffer, litSize, istart+lhSize, litCSize, dctx->HUFptr) :
|
|
570
|
-
HUF_decompress4X_usingDTable(dctx->litBuffer, litSize, istart+lhSize, litCSize, dctx->HUFptr) ) :
|
|
571
|
-
( singleStream ?
|
|
572
|
-
HUF_decompress1X2_DCtx_wksp(dctx->entropy.hufTable, dctx->litBuffer, litSize, istart+lhSize, litCSize,
|
|
573
|
-
dctx->entropy.workspace, sizeof(dctx->entropy.workspace)) :
|
|
574
|
-
HUF_decompress4X_hufOnly_wksp(dctx->entropy.hufTable, dctx->litBuffer, litSize, istart+lhSize, litCSize,
|
|
575
|
-
dctx->entropy.workspace, sizeof(dctx->entropy.workspace)))))
|
|
576
|
-
return ERROR(corruption_detected);
|
|
577
|
-
|
|
578
|
-
dctx->litPtr = dctx->litBuffer;
|
|
579
|
-
dctx->litSize = litSize;
|
|
580
|
-
dctx->litEntropy = 1;
|
|
581
|
-
if (litEncType==set_compressed) dctx->HUFptr = dctx->entropy.hufTable;
|
|
582
|
-
memset(dctx->litBuffer + dctx->litSize, 0, WILDCOPY_OVERLENGTH);
|
|
583
|
-
return litCSize + lhSize;
|
|
584
|
-
}
|
|
585
|
-
|
|
586
|
-
case set_basic:
|
|
587
|
-
{ size_t litSize, lhSize;
|
|
588
|
-
U32 const lhlCode = ((istart[0]) >> 2) & 3;
|
|
589
|
-
switch(lhlCode)
|
|
590
|
-
{
|
|
591
|
-
case 0: case 2: default: /* note : default is impossible, since lhlCode into [0..3] */
|
|
592
|
-
lhSize = 1;
|
|
593
|
-
litSize = istart[0] >> 3;
|
|
594
|
-
break;
|
|
595
|
-
case 1:
|
|
596
|
-
lhSize = 2;
|
|
597
|
-
litSize = MEM_readLE16(istart) >> 4;
|
|
598
|
-
break;
|
|
599
|
-
case 3:
|
|
600
|
-
lhSize = 3;
|
|
601
|
-
litSize = MEM_readLE24(istart) >> 4;
|
|
602
|
-
break;
|
|
603
|
-
}
|
|
604
|
-
|
|
605
|
-
if (lhSize+litSize+WILDCOPY_OVERLENGTH > srcSize) { /* risk reading beyond src buffer with wildcopy */
|
|
606
|
-
if (litSize+lhSize > srcSize) return ERROR(corruption_detected);
|
|
607
|
-
memcpy(dctx->litBuffer, istart+lhSize, litSize);
|
|
608
|
-
dctx->litPtr = dctx->litBuffer;
|
|
609
|
-
dctx->litSize = litSize;
|
|
610
|
-
memset(dctx->litBuffer + dctx->litSize, 0, WILDCOPY_OVERLENGTH);
|
|
611
|
-
return lhSize+litSize;
|
|
612
|
-
}
|
|
613
|
-
/* direct reference into compressed stream */
|
|
614
|
-
dctx->litPtr = istart+lhSize;
|
|
615
|
-
dctx->litSize = litSize;
|
|
616
|
-
return lhSize+litSize;
|
|
617
|
-
}
|
|
618
|
-
|
|
619
|
-
case set_rle:
|
|
620
|
-
{ U32 const lhlCode = ((istart[0]) >> 2) & 3;
|
|
621
|
-
size_t litSize, lhSize;
|
|
622
|
-
switch(lhlCode)
|
|
623
|
-
{
|
|
624
|
-
case 0: case 2: default: /* note : default is impossible, since lhlCode into [0..3] */
|
|
625
|
-
lhSize = 1;
|
|
626
|
-
litSize = istart[0] >> 3;
|
|
627
|
-
break;
|
|
628
|
-
case 1:
|
|
629
|
-
lhSize = 2;
|
|
630
|
-
litSize = MEM_readLE16(istart) >> 4;
|
|
631
|
-
break;
|
|
632
|
-
case 3:
|
|
633
|
-
lhSize = 3;
|
|
634
|
-
litSize = MEM_readLE24(istart) >> 4;
|
|
635
|
-
if (srcSize<4) return ERROR(corruption_detected); /* srcSize >= MIN_CBLOCK_SIZE == 3; here we need lhSize+1 = 4 */
|
|
636
|
-
break;
|
|
637
|
-
}
|
|
638
|
-
if (litSize > ZSTD_BLOCKSIZE_MAX) return ERROR(corruption_detected);
|
|
639
|
-
memset(dctx->litBuffer, istart[lhSize], litSize + WILDCOPY_OVERLENGTH);
|
|
640
|
-
dctx->litPtr = dctx->litBuffer;
|
|
641
|
-
dctx->litSize = litSize;
|
|
642
|
-
return lhSize+1;
|
|
643
|
-
}
|
|
644
|
-
default:
|
|
645
|
-
return ERROR(corruption_detected); /* impossible */
|
|
646
|
-
}
|
|
647
|
-
}
|
|
648
|
-
}
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
typedef union {
|
|
652
|
-
FSE_decode_t realData;
|
|
653
|
-
U32 alignedBy4;
|
|
654
|
-
} FSE_decode_t4;
|
|
655
|
-
|
|
656
|
-
/* Default FSE distribution table for Literal Lengths */
|
|
657
|
-
static const FSE_decode_t4 LL_defaultDTable[(1<<LL_DEFAULTNORMLOG)+1] = {
|
|
658
|
-
{ { LL_DEFAULTNORMLOG, 1, 1 } }, /* header : tableLog, fastMode, fastMode */
|
|
659
|
-
/* base, symbol, bits */
|
|
660
|
-
{ { 0, 0, 4 } }, { { 16, 0, 4 } }, { { 32, 1, 5 } }, { { 0, 3, 5 } },
|
|
661
|
-
{ { 0, 4, 5 } }, { { 0, 6, 5 } }, { { 0, 7, 5 } }, { { 0, 9, 5 } },
|
|
662
|
-
{ { 0, 10, 5 } }, { { 0, 12, 5 } }, { { 0, 14, 6 } }, { { 0, 16, 5 } },
|
|
663
|
-
{ { 0, 18, 5 } }, { { 0, 19, 5 } }, { { 0, 21, 5 } }, { { 0, 22, 5 } },
|
|
664
|
-
{ { 0, 24, 5 } }, { { 32, 25, 5 } }, { { 0, 26, 5 } }, { { 0, 27, 6 } },
|
|
665
|
-
{ { 0, 29, 6 } }, { { 0, 31, 6 } }, { { 32, 0, 4 } }, { { 0, 1, 4 } },
|
|
666
|
-
{ { 0, 2, 5 } }, { { 32, 4, 5 } }, { { 0, 5, 5 } }, { { 32, 7, 5 } },
|
|
667
|
-
{ { 0, 8, 5 } }, { { 32, 10, 5 } }, { { 0, 11, 5 } }, { { 0, 13, 6 } },
|
|
668
|
-
{ { 32, 16, 5 } }, { { 0, 17, 5 } }, { { 32, 19, 5 } }, { { 0, 20, 5 } },
|
|
669
|
-
{ { 32, 22, 5 } }, { { 0, 23, 5 } }, { { 0, 25, 4 } }, { { 16, 25, 4 } },
|
|
670
|
-
{ { 32, 26, 5 } }, { { 0, 28, 6 } }, { { 0, 30, 6 } }, { { 48, 0, 4 } },
|
|
671
|
-
{ { 16, 1, 4 } }, { { 32, 2, 5 } }, { { 32, 3, 5 } }, { { 32, 5, 5 } },
|
|
672
|
-
{ { 32, 6, 5 } }, { { 32, 8, 5 } }, { { 32, 9, 5 } }, { { 32, 11, 5 } },
|
|
673
|
-
{ { 32, 12, 5 } }, { { 0, 15, 6 } }, { { 32, 17, 5 } }, { { 32, 18, 5 } },
|
|
674
|
-
{ { 32, 20, 5 } }, { { 32, 21, 5 } }, { { 32, 23, 5 } }, { { 32, 24, 5 } },
|
|
675
|
-
{ { 0, 35, 6 } }, { { 0, 34, 6 } }, { { 0, 33, 6 } }, { { 0, 32, 6 } },
|
|
676
|
-
}; /* LL_defaultDTable */
|
|
677
|
-
|
|
678
|
-
/* Default FSE distribution table for Match Lengths */
|
|
679
|
-
static const FSE_decode_t4 ML_defaultDTable[(1<<ML_DEFAULTNORMLOG)+1] = {
|
|
680
|
-
{ { ML_DEFAULTNORMLOG, 1, 1 } }, /* header : tableLog, fastMode, fastMode */
|
|
681
|
-
/* base, symbol, bits */
|
|
682
|
-
{ { 0, 0, 6 } }, { { 0, 1, 4 } }, { { 32, 2, 5 } }, { { 0, 3, 5 } },
|
|
683
|
-
{ { 0, 5, 5 } }, { { 0, 6, 5 } }, { { 0, 8, 5 } }, { { 0, 10, 6 } },
|
|
684
|
-
{ { 0, 13, 6 } }, { { 0, 16, 6 } }, { { 0, 19, 6 } }, { { 0, 22, 6 } },
|
|
685
|
-
{ { 0, 25, 6 } }, { { 0, 28, 6 } }, { { 0, 31, 6 } }, { { 0, 33, 6 } },
|
|
686
|
-
{ { 0, 35, 6 } }, { { 0, 37, 6 } }, { { 0, 39, 6 } }, { { 0, 41, 6 } },
|
|
687
|
-
{ { 0, 43, 6 } }, { { 0, 45, 6 } }, { { 16, 1, 4 } }, { { 0, 2, 4 } },
|
|
688
|
-
{ { 32, 3, 5 } }, { { 0, 4, 5 } }, { { 32, 6, 5 } }, { { 0, 7, 5 } },
|
|
689
|
-
{ { 0, 9, 6 } }, { { 0, 12, 6 } }, { { 0, 15, 6 } }, { { 0, 18, 6 } },
|
|
690
|
-
{ { 0, 21, 6 } }, { { 0, 24, 6 } }, { { 0, 27, 6 } }, { { 0, 30, 6 } },
|
|
691
|
-
{ { 0, 32, 6 } }, { { 0, 34, 6 } }, { { 0, 36, 6 } }, { { 0, 38, 6 } },
|
|
692
|
-
{ { 0, 40, 6 } }, { { 0, 42, 6 } }, { { 0, 44, 6 } }, { { 32, 1, 4 } },
|
|
693
|
-
{ { 48, 1, 4 } }, { { 16, 2, 4 } }, { { 32, 4, 5 } }, { { 32, 5, 5 } },
|
|
694
|
-
{ { 32, 7, 5 } }, { { 32, 8, 5 } }, { { 0, 11, 6 } }, { { 0, 14, 6 } },
|
|
695
|
-
{ { 0, 17, 6 } }, { { 0, 20, 6 } }, { { 0, 23, 6 } }, { { 0, 26, 6 } },
|
|
696
|
-
{ { 0, 29, 6 } }, { { 0, 52, 6 } }, { { 0, 51, 6 } }, { { 0, 50, 6 } },
|
|
697
|
-
{ { 0, 49, 6 } }, { { 0, 48, 6 } }, { { 0, 47, 6 } }, { { 0, 46, 6 } },
|
|
698
|
-
}; /* ML_defaultDTable */
|
|
699
|
-
|
|
700
|
-
/* Default FSE distribution table for Offset Codes */
|
|
701
|
-
static const FSE_decode_t4 OF_defaultDTable[(1<<OF_DEFAULTNORMLOG)+1] = {
|
|
702
|
-
{ { OF_DEFAULTNORMLOG, 1, 1 } }, /* header : tableLog, fastMode, fastMode */
|
|
703
|
-
/* base, symbol, bits */
|
|
704
|
-
{ { 0, 0, 5 } }, { { 0, 6, 4 } },
|
|
705
|
-
{ { 0, 9, 5 } }, { { 0, 15, 5 } },
|
|
706
|
-
{ { 0, 21, 5 } }, { { 0, 3, 5 } },
|
|
707
|
-
{ { 0, 7, 4 } }, { { 0, 12, 5 } },
|
|
708
|
-
{ { 0, 18, 5 } }, { { 0, 23, 5 } },
|
|
709
|
-
{ { 0, 5, 5 } }, { { 0, 8, 4 } },
|
|
710
|
-
{ { 0, 14, 5 } }, { { 0, 20, 5 } },
|
|
711
|
-
{ { 0, 2, 5 } }, { { 16, 7, 4 } },
|
|
712
|
-
{ { 0, 11, 5 } }, { { 0, 17, 5 } },
|
|
713
|
-
{ { 0, 22, 5 } }, { { 0, 4, 5 } },
|
|
714
|
-
{ { 16, 8, 4 } }, { { 0, 13, 5 } },
|
|
715
|
-
{ { 0, 19, 5 } }, { { 0, 1, 5 } },
|
|
716
|
-
{ { 16, 6, 4 } }, { { 0, 10, 5 } },
|
|
717
|
-
{ { 0, 16, 5 } }, { { 0, 28, 5 } },
|
|
718
|
-
{ { 0, 27, 5 } }, { { 0, 26, 5 } },
|
|
719
|
-
{ { 0, 25, 5 } }, { { 0, 24, 5 } },
|
|
720
|
-
}; /* OF_defaultDTable */
|
|
721
|
-
|
|
722
|
-
/*! ZSTD_buildSeqTable() :
|
|
723
|
-
* @return : nb bytes read from src,
|
|
724
|
-
* or an error code if it fails, testable with ZSTD_isError()
|
|
725
|
-
*/
|
|
726
|
-
static size_t ZSTD_buildSeqTable(FSE_DTable* DTableSpace, const FSE_DTable** DTablePtr,
|
|
727
|
-
symbolEncodingType_e type, U32 max, U32 maxLog,
|
|
728
|
-
const void* src, size_t srcSize,
|
|
729
|
-
const FSE_decode_t4* defaultTable, U32 flagRepeatTable)
|
|
730
|
-
{
|
|
731
|
-
const void* const tmpPtr = defaultTable; /* bypass strict aliasing */
|
|
732
|
-
switch(type)
|
|
733
|
-
{
|
|
734
|
-
case set_rle :
|
|
735
|
-
if (!srcSize) return ERROR(srcSize_wrong);
|
|
736
|
-
if ( (*(const BYTE*)src) > max) return ERROR(corruption_detected);
|
|
737
|
-
FSE_buildDTable_rle(DTableSpace, *(const BYTE*)src);
|
|
738
|
-
*DTablePtr = DTableSpace;
|
|
739
|
-
return 1;
|
|
740
|
-
case set_basic :
|
|
741
|
-
*DTablePtr = (const FSE_DTable*)tmpPtr;
|
|
742
|
-
return 0;
|
|
743
|
-
case set_repeat:
|
|
744
|
-
if (!flagRepeatTable) return ERROR(corruption_detected);
|
|
745
|
-
return 0;
|
|
746
|
-
default : /* impossible */
|
|
747
|
-
case set_compressed :
|
|
748
|
-
{ U32 tableLog;
|
|
749
|
-
S16 norm[MaxSeq+1];
|
|
750
|
-
size_t const headerSize = FSE_readNCount(norm, &max, &tableLog, src, srcSize);
|
|
751
|
-
if (FSE_isError(headerSize)) return ERROR(corruption_detected);
|
|
752
|
-
if (tableLog > maxLog) return ERROR(corruption_detected);
|
|
753
|
-
FSE_buildDTable(DTableSpace, norm, max, tableLog);
|
|
754
|
-
*DTablePtr = DTableSpace;
|
|
755
|
-
return headerSize;
|
|
756
|
-
} }
|
|
757
|
-
}
|
|
758
|
-
|
|
759
|
-
size_t ZSTD_decodeSeqHeaders(ZSTD_DCtx* dctx, int* nbSeqPtr,
|
|
760
|
-
const void* src, size_t srcSize)
|
|
761
|
-
{
|
|
762
|
-
const BYTE* const istart = (const BYTE* const)src;
|
|
763
|
-
const BYTE* const iend = istart + srcSize;
|
|
764
|
-
const BYTE* ip = istart;
|
|
765
|
-
DEBUGLOG(5, "ZSTD_decodeSeqHeaders");
|
|
766
|
-
|
|
767
|
-
/* check */
|
|
768
|
-
if (srcSize < MIN_SEQUENCES_SIZE) return ERROR(srcSize_wrong);
|
|
769
|
-
|
|
770
|
-
/* SeqHead */
|
|
771
|
-
{ int nbSeq = *ip++;
|
|
772
|
-
if (!nbSeq) { *nbSeqPtr=0; return 1; }
|
|
773
|
-
if (nbSeq > 0x7F) {
|
|
774
|
-
if (nbSeq == 0xFF) {
|
|
775
|
-
if (ip+2 > iend) return ERROR(srcSize_wrong);
|
|
776
|
-
nbSeq = MEM_readLE16(ip) + LONGNBSEQ, ip+=2;
|
|
777
|
-
} else {
|
|
778
|
-
if (ip >= iend) return ERROR(srcSize_wrong);
|
|
779
|
-
nbSeq = ((nbSeq-0x80)<<8) + *ip++;
|
|
780
|
-
}
|
|
781
|
-
}
|
|
782
|
-
*nbSeqPtr = nbSeq;
|
|
783
|
-
}
|
|
784
|
-
|
|
785
|
-
/* FSE table descriptors */
|
|
786
|
-
if (ip+4 > iend) return ERROR(srcSize_wrong); /* minimum possible size */
|
|
787
|
-
{ symbolEncodingType_e const LLtype = (symbolEncodingType_e)(*ip >> 6);
|
|
788
|
-
symbolEncodingType_e const OFtype = (symbolEncodingType_e)((*ip >> 4) & 3);
|
|
789
|
-
symbolEncodingType_e const MLtype = (symbolEncodingType_e)((*ip >> 2) & 3);
|
|
790
|
-
ip++;
|
|
791
|
-
|
|
792
|
-
/* Build DTables */
|
|
793
|
-
{ size_t const llhSize = ZSTD_buildSeqTable(dctx->entropy.LLTable, &dctx->LLTptr,
|
|
794
|
-
LLtype, MaxLL, LLFSELog,
|
|
795
|
-
ip, iend-ip, LL_defaultDTable, dctx->fseEntropy);
|
|
796
|
-
if (ZSTD_isError(llhSize)) return ERROR(corruption_detected);
|
|
797
|
-
ip += llhSize;
|
|
798
|
-
}
|
|
799
|
-
{ size_t const ofhSize = ZSTD_buildSeqTable(dctx->entropy.OFTable, &dctx->OFTptr,
|
|
800
|
-
OFtype, MaxOff, OffFSELog,
|
|
801
|
-
ip, iend-ip, OF_defaultDTable, dctx->fseEntropy);
|
|
802
|
-
if (ZSTD_isError(ofhSize)) return ERROR(corruption_detected);
|
|
803
|
-
ip += ofhSize;
|
|
804
|
-
}
|
|
805
|
-
{ size_t const mlhSize = ZSTD_buildSeqTable(dctx->entropy.MLTable, &dctx->MLTptr,
|
|
806
|
-
MLtype, MaxML, MLFSELog,
|
|
807
|
-
ip, iend-ip, ML_defaultDTable, dctx->fseEntropy);
|
|
808
|
-
if (ZSTD_isError(mlhSize)) return ERROR(corruption_detected);
|
|
809
|
-
ip += mlhSize;
|
|
810
|
-
}
|
|
811
|
-
}
|
|
812
|
-
|
|
813
|
-
return ip-istart;
|
|
814
|
-
}
|
|
815
|
-
|
|
816
|
-
|
|
817
|
-
typedef struct {
|
|
818
|
-
size_t litLength;
|
|
819
|
-
size_t matchLength;
|
|
820
|
-
size_t offset;
|
|
821
|
-
const BYTE* match;
|
|
822
|
-
} seq_t;
|
|
823
|
-
|
|
824
|
-
typedef struct {
|
|
825
|
-
BIT_DStream_t DStream;
|
|
826
|
-
FSE_DState_t stateLL;
|
|
827
|
-
FSE_DState_t stateOffb;
|
|
828
|
-
FSE_DState_t stateML;
|
|
829
|
-
size_t prevOffset[ZSTD_REP_NUM];
|
|
830
|
-
const BYTE* prefixStart;
|
|
831
|
-
const BYTE* dictEnd;
|
|
832
|
-
size_t pos;
|
|
833
|
-
} seqState_t;
|
|
834
|
-
|
|
835
|
-
|
|
836
|
-
FORCE_NOINLINE
|
|
837
|
-
size_t ZSTD_execSequenceLast7(BYTE* op,
|
|
838
|
-
BYTE* const oend, seq_t sequence,
|
|
839
|
-
const BYTE** litPtr, const BYTE* const litLimit,
|
|
840
|
-
const BYTE* const base, const BYTE* const vBase, const BYTE* const dictEnd)
|
|
841
|
-
{
|
|
842
|
-
BYTE* const oLitEnd = op + sequence.litLength;
|
|
843
|
-
size_t const sequenceLength = sequence.litLength + sequence.matchLength;
|
|
844
|
-
BYTE* const oMatchEnd = op + sequenceLength; /* risk : address space overflow (32-bits) */
|
|
845
|
-
BYTE* const oend_w = oend - WILDCOPY_OVERLENGTH;
|
|
846
|
-
const BYTE* const iLitEnd = *litPtr + sequence.litLength;
|
|
847
|
-
const BYTE* match = oLitEnd - sequence.offset;
|
|
848
|
-
|
|
849
|
-
/* check */
|
|
850
|
-
if (oMatchEnd>oend) return ERROR(dstSize_tooSmall); /* last match must start at a minimum distance of WILDCOPY_OVERLENGTH from oend */
|
|
851
|
-
if (iLitEnd > litLimit) return ERROR(corruption_detected); /* over-read beyond lit buffer */
|
|
852
|
-
if (oLitEnd <= oend_w) return ERROR(GENERIC); /* Precondition */
|
|
853
|
-
|
|
854
|
-
/* copy literals */
|
|
855
|
-
if (op < oend_w) {
|
|
856
|
-
ZSTD_wildcopy(op, *litPtr, oend_w - op);
|
|
857
|
-
*litPtr += oend_w - op;
|
|
858
|
-
op = oend_w;
|
|
859
|
-
}
|
|
860
|
-
while (op < oLitEnd) *op++ = *(*litPtr)++;
|
|
861
|
-
|
|
862
|
-
/* copy Match */
|
|
863
|
-
if (sequence.offset > (size_t)(oLitEnd - base)) {
|
|
864
|
-
/* offset beyond prefix */
|
|
865
|
-
if (sequence.offset > (size_t)(oLitEnd - vBase)) return ERROR(corruption_detected);
|
|
866
|
-
match = dictEnd - (base-match);
|
|
867
|
-
if (match + sequence.matchLength <= dictEnd) {
|
|
868
|
-
memmove(oLitEnd, match, sequence.matchLength);
|
|
869
|
-
return sequenceLength;
|
|
870
|
-
}
|
|
871
|
-
/* span extDict & currentPrefixSegment */
|
|
872
|
-
{ size_t const length1 = dictEnd - match;
|
|
873
|
-
memmove(oLitEnd, match, length1);
|
|
874
|
-
op = oLitEnd + length1;
|
|
875
|
-
sequence.matchLength -= length1;
|
|
876
|
-
match = base;
|
|
877
|
-
} }
|
|
878
|
-
while (op < oMatchEnd) *op++ = *match++;
|
|
879
|
-
return sequenceLength;
|
|
880
|
-
}
|
|
881
|
-
|
|
882
|
-
|
|
883
|
-
typedef enum { ZSTD_lo_isRegularOffset, ZSTD_lo_isLongOffset=1 } ZSTD_longOffset_e;
|
|
884
|
-
|
|
885
|
-
/* We need to add at most (ZSTD_WINDOWLOG_MAX_32 - 1) bits to read the maximum
|
|
886
|
-
* offset bits. But we can only read at most (STREAM_ACCUMULATOR_MIN_32 - 1)
|
|
887
|
-
* bits before reloading. This value is the maximum number of bytes we read
|
|
888
|
-
* after reloading when we are decoding long offets.
|
|
889
|
-
*/
|
|
890
|
-
#define LONG_OFFSETS_MAX_EXTRA_BITS_32 \
|
|
891
|
-
(ZSTD_WINDOWLOG_MAX_32 > STREAM_ACCUMULATOR_MIN_32 \
|
|
892
|
-
? ZSTD_WINDOWLOG_MAX_32 - STREAM_ACCUMULATOR_MIN_32 \
|
|
893
|
-
: 0)
|
|
894
|
-
|
|
895
|
-
static seq_t ZSTD_decodeSequence(seqState_t* seqState, const ZSTD_longOffset_e longOffsets)
|
|
896
|
-
{
|
|
897
|
-
seq_t seq;
|
|
898
|
-
|
|
899
|
-
U32 const llCode = FSE_peekSymbol(&seqState->stateLL);
|
|
900
|
-
U32 const mlCode = FSE_peekSymbol(&seqState->stateML);
|
|
901
|
-
U32 const ofCode = FSE_peekSymbol(&seqState->stateOffb); /* <= MaxOff, by table construction */
|
|
902
|
-
|
|
903
|
-
U32 const llBits = LL_bits[llCode];
|
|
904
|
-
U32 const mlBits = ML_bits[mlCode];
|
|
905
|
-
U32 const ofBits = ofCode;
|
|
906
|
-
U32 const totalBits = llBits+mlBits+ofBits;
|
|
907
|
-
|
|
908
|
-
static const U32 LL_base[MaxLL+1] = {
|
|
909
|
-
0, 1, 2, 3, 4, 5, 6, 7,
|
|
910
|
-
8, 9, 10, 11, 12, 13, 14, 15,
|
|
911
|
-
16, 18, 20, 22, 24, 28, 32, 40,
|
|
912
|
-
48, 64, 0x80, 0x100, 0x200, 0x400, 0x800, 0x1000,
|
|
913
|
-
0x2000, 0x4000, 0x8000, 0x10000 };
|
|
914
|
-
|
|
915
|
-
static const U32 ML_base[MaxML+1] = {
|
|
916
|
-
3, 4, 5, 6, 7, 8, 9, 10,
|
|
917
|
-
11, 12, 13, 14, 15, 16, 17, 18,
|
|
918
|
-
19, 20, 21, 22, 23, 24, 25, 26,
|
|
919
|
-
27, 28, 29, 30, 31, 32, 33, 34,
|
|
920
|
-
35, 37, 39, 41, 43, 47, 51, 59,
|
|
921
|
-
67, 83, 99, 0x83, 0x103, 0x203, 0x403, 0x803,
|
|
922
|
-
0x1003, 0x2003, 0x4003, 0x8003, 0x10003 };
|
|
923
|
-
|
|
924
|
-
static const U32 OF_base[MaxOff+1] = {
|
|
925
|
-
0, 1, 1, 5, 0xD, 0x1D, 0x3D, 0x7D,
|
|
926
|
-
0xFD, 0x1FD, 0x3FD, 0x7FD, 0xFFD, 0x1FFD, 0x3FFD, 0x7FFD,
|
|
927
|
-
0xFFFD, 0x1FFFD, 0x3FFFD, 0x7FFFD, 0xFFFFD, 0x1FFFFD, 0x3FFFFD, 0x7FFFFD,
|
|
928
|
-
0xFFFFFD, 0x1FFFFFD, 0x3FFFFFD, 0x7FFFFFD, 0xFFFFFFD, 0x1FFFFFFD, 0x3FFFFFFD, 0x7FFFFFFD };
|
|
929
|
-
|
|
930
|
-
/* sequence */
|
|
931
|
-
{ size_t offset;
|
|
932
|
-
if (!ofCode)
|
|
933
|
-
offset = 0;
|
|
934
|
-
else {
|
|
935
|
-
ZSTD_STATIC_ASSERT(ZSTD_lo_isLongOffset == 1);
|
|
936
|
-
ZSTD_STATIC_ASSERT(LONG_OFFSETS_MAX_EXTRA_BITS_32 == 5);
|
|
937
|
-
assert(ofBits <= MaxOff);
|
|
938
|
-
if (MEM_32bits() && longOffsets) {
|
|
939
|
-
U32 const extraBits = ofBits - MIN(ofBits, STREAM_ACCUMULATOR_MIN_32-1);
|
|
940
|
-
offset = OF_base[ofCode] + (BIT_readBitsFast(&seqState->DStream, ofBits - extraBits) << extraBits);
|
|
941
|
-
if (MEM_32bits() || extraBits) BIT_reloadDStream(&seqState->DStream);
|
|
942
|
-
if (extraBits) offset += BIT_readBitsFast(&seqState->DStream, extraBits);
|
|
943
|
-
} else {
|
|
944
|
-
offset = OF_base[ofCode] + BIT_readBitsFast(&seqState->DStream, ofBits); /* <= (ZSTD_WINDOWLOG_MAX-1) bits */
|
|
945
|
-
if (MEM_32bits()) BIT_reloadDStream(&seqState->DStream);
|
|
946
|
-
}
|
|
947
|
-
}
|
|
948
|
-
|
|
949
|
-
if (ofCode <= 1) {
|
|
950
|
-
offset += (llCode==0);
|
|
951
|
-
if (offset) {
|
|
952
|
-
size_t temp = (offset==3) ? seqState->prevOffset[0] - 1 : seqState->prevOffset[offset];
|
|
953
|
-
temp += !temp; /* 0 is not valid; input is corrupted; force offset to 1 */
|
|
954
|
-
if (offset != 1) seqState->prevOffset[2] = seqState->prevOffset[1];
|
|
955
|
-
seqState->prevOffset[1] = seqState->prevOffset[0];
|
|
956
|
-
seqState->prevOffset[0] = offset = temp;
|
|
957
|
-
} else {
|
|
958
|
-
offset = seqState->prevOffset[0];
|
|
959
|
-
}
|
|
960
|
-
} else {
|
|
961
|
-
seqState->prevOffset[2] = seqState->prevOffset[1];
|
|
962
|
-
seqState->prevOffset[1] = seqState->prevOffset[0];
|
|
963
|
-
seqState->prevOffset[0] = offset;
|
|
964
|
-
}
|
|
965
|
-
seq.offset = offset;
|
|
966
|
-
}
|
|
967
|
-
|
|
968
|
-
seq.matchLength = ML_base[mlCode]
|
|
969
|
-
+ ((mlCode>31) ? BIT_readBitsFast(&seqState->DStream, mlBits) : 0); /* <= 16 bits */
|
|
970
|
-
if (MEM_32bits() && (mlBits+llBits >= STREAM_ACCUMULATOR_MIN_32-LONG_OFFSETS_MAX_EXTRA_BITS_32))
|
|
971
|
-
BIT_reloadDStream(&seqState->DStream);
|
|
972
|
-
if (MEM_64bits() && (totalBits >= STREAM_ACCUMULATOR_MIN_64-(LLFSELog+MLFSELog+OffFSELog)))
|
|
973
|
-
BIT_reloadDStream(&seqState->DStream);
|
|
974
|
-
/* Verify that there is enough bits to read the rest of the data in 64-bit mode. */
|
|
975
|
-
ZSTD_STATIC_ASSERT(16+LLFSELog+MLFSELog+OffFSELog < STREAM_ACCUMULATOR_MIN_64);
|
|
976
|
-
|
|
977
|
-
seq.litLength = LL_base[llCode]
|
|
978
|
-
+ ((llCode>15) ? BIT_readBitsFast(&seqState->DStream, llBits) : 0); /* <= 16 bits */
|
|
979
|
-
if (MEM_32bits())
|
|
980
|
-
BIT_reloadDStream(&seqState->DStream);
|
|
981
|
-
|
|
982
|
-
DEBUGLOG(6, "seq: litL=%u, matchL=%u, offset=%u",
|
|
983
|
-
(U32)seq.litLength, (U32)seq.matchLength, (U32)seq.offset);
|
|
984
|
-
|
|
985
|
-
/* ANS state update */
|
|
986
|
-
FSE_updateState(&seqState->stateLL, &seqState->DStream); /* <= 9 bits */
|
|
987
|
-
FSE_updateState(&seqState->stateML, &seqState->DStream); /* <= 9 bits */
|
|
988
|
-
if (MEM_32bits()) BIT_reloadDStream(&seqState->DStream); /* <= 18 bits */
|
|
989
|
-
FSE_updateState(&seqState->stateOffb, &seqState->DStream); /* <= 8 bits */
|
|
990
|
-
|
|
991
|
-
return seq;
|
|
992
|
-
}
|
|
993
|
-
|
|
994
|
-
|
|
995
|
-
HINT_INLINE
|
|
996
|
-
size_t ZSTD_execSequence(BYTE* op,
|
|
997
|
-
BYTE* const oend, seq_t sequence,
|
|
998
|
-
const BYTE** litPtr, const BYTE* const litLimit,
|
|
999
|
-
const BYTE* const base, const BYTE* const vBase, const BYTE* const dictEnd)
|
|
1000
|
-
{
|
|
1001
|
-
BYTE* const oLitEnd = op + sequence.litLength;
|
|
1002
|
-
size_t const sequenceLength = sequence.litLength + sequence.matchLength;
|
|
1003
|
-
BYTE* const oMatchEnd = op + sequenceLength; /* risk : address space overflow (32-bits) */
|
|
1004
|
-
BYTE* const oend_w = oend - WILDCOPY_OVERLENGTH;
|
|
1005
|
-
const BYTE* const iLitEnd = *litPtr + sequence.litLength;
|
|
1006
|
-
const BYTE* match = oLitEnd - sequence.offset;
|
|
462
|
+
#if defined(ZSTD_LEGACY_SUPPORT) && (ZSTD_LEGACY_SUPPORT >= 1)
|
|
463
|
+
if (ZSTD_isLegacy(src, srcSize))
|
|
464
|
+
return ZSTD_findFrameSizeInfoLegacy(src, srcSize);
|
|
465
|
+
#endif
|
|
1007
466
|
|
|
1008
|
-
|
|
1009
|
-
|
|
1010
|
-
|
|
1011
|
-
|
|
1012
|
-
|
|
1013
|
-
/* copy Literals */
|
|
1014
|
-
ZSTD_copy8(op, *litPtr);
|
|
1015
|
-
if (sequence.litLength > 8)
|
|
1016
|
-
ZSTD_wildcopy(op+8, (*litPtr)+8, sequence.litLength - 8); /* note : since oLitEnd <= oend-WILDCOPY_OVERLENGTH, no risk of overwrite beyond oend */
|
|
1017
|
-
op = oLitEnd;
|
|
1018
|
-
*litPtr = iLitEnd; /* update for next sequence */
|
|
1019
|
-
|
|
1020
|
-
/* copy Match */
|
|
1021
|
-
if (sequence.offset > (size_t)(oLitEnd - base)) {
|
|
1022
|
-
/* offset beyond prefix -> go into extDict */
|
|
1023
|
-
if (sequence.offset > (size_t)(oLitEnd - vBase))
|
|
1024
|
-
return ERROR(corruption_detected);
|
|
1025
|
-
match = dictEnd + (match - base);
|
|
1026
|
-
if (match + sequence.matchLength <= dictEnd) {
|
|
1027
|
-
memmove(oLitEnd, match, sequence.matchLength);
|
|
1028
|
-
return sequenceLength;
|
|
1029
|
-
}
|
|
1030
|
-
/* span extDict & currentPrefixSegment */
|
|
1031
|
-
{ size_t const length1 = dictEnd - match;
|
|
1032
|
-
memmove(oLitEnd, match, length1);
|
|
1033
|
-
op = oLitEnd + length1;
|
|
1034
|
-
sequence.matchLength -= length1;
|
|
1035
|
-
match = base;
|
|
1036
|
-
if (op > oend_w || sequence.matchLength < MINMATCH) {
|
|
1037
|
-
U32 i;
|
|
1038
|
-
for (i = 0; i < sequence.matchLength; ++i) op[i] = match[i];
|
|
1039
|
-
return sequenceLength;
|
|
1040
|
-
}
|
|
1041
|
-
} }
|
|
1042
|
-
/* Requirement: op <= oend_w && sequence.matchLength >= MINMATCH */
|
|
1043
|
-
|
|
1044
|
-
/* match within prefix */
|
|
1045
|
-
if (sequence.offset < 8) {
|
|
1046
|
-
/* close range match, overlap */
|
|
1047
|
-
static const U32 dec32table[] = { 0, 1, 2, 1, 4, 4, 4, 4 }; /* added */
|
|
1048
|
-
static const int dec64table[] = { 8, 8, 8, 7, 8, 9,10,11 }; /* subtracted */
|
|
1049
|
-
int const sub2 = dec64table[sequence.offset];
|
|
1050
|
-
op[0] = match[0];
|
|
1051
|
-
op[1] = match[1];
|
|
1052
|
-
op[2] = match[2];
|
|
1053
|
-
op[3] = match[3];
|
|
1054
|
-
match += dec32table[sequence.offset];
|
|
1055
|
-
ZSTD_copy4(op+4, match);
|
|
1056
|
-
match -= sub2;
|
|
467
|
+
if ((srcSize >= ZSTD_SKIPPABLEHEADERSIZE)
|
|
468
|
+
&& (MEM_readLE32(src) & ZSTD_MAGIC_SKIPPABLE_MASK) == ZSTD_MAGIC_SKIPPABLE_START) {
|
|
469
|
+
frameSizeInfo.compressedSize = readSkippableFrameSize(src, srcSize);
|
|
470
|
+
return frameSizeInfo;
|
|
1057
471
|
} else {
|
|
1058
|
-
|
|
1059
|
-
|
|
1060
|
-
|
|
472
|
+
const BYTE* ip = (const BYTE*)src;
|
|
473
|
+
const BYTE* const ipstart = ip;
|
|
474
|
+
size_t remainingSize = srcSize;
|
|
475
|
+
size_t nbBlocks = 0;
|
|
476
|
+
ZSTD_frameHeader zfh;
|
|
1061
477
|
|
|
1062
|
-
|
|
1063
|
-
|
|
1064
|
-
|
|
1065
|
-
|
|
1066
|
-
|
|
478
|
+
/* Extract Frame Header */
|
|
479
|
+
{ size_t const ret = ZSTD_getFrameHeader(&zfh, src, srcSize);
|
|
480
|
+
if (ZSTD_isError(ret))
|
|
481
|
+
return ZSTD_errorFrameSizeInfo(ret);
|
|
482
|
+
if (ret > 0)
|
|
483
|
+
return ZSTD_errorFrameSizeInfo(ERROR(srcSize_wrong));
|
|
1067
484
|
}
|
|
1068
|
-
while (op < oMatchEnd) *op++ = *match++;
|
|
1069
|
-
} else {
|
|
1070
|
-
ZSTD_wildcopy(op, match, (ptrdiff_t)sequence.matchLength-8); /* works even if matchLength < 8 */
|
|
1071
|
-
}
|
|
1072
|
-
return sequenceLength;
|
|
1073
|
-
}
|
|
1074
|
-
|
|
1075
|
-
|
|
1076
|
-
static size_t ZSTD_decompressSequences(
|
|
1077
|
-
ZSTD_DCtx* dctx,
|
|
1078
|
-
void* dst, size_t maxDstSize,
|
|
1079
|
-
const void* seqStart, size_t seqSize,
|
|
1080
|
-
const ZSTD_longOffset_e isLongOffset)
|
|
1081
|
-
{
|
|
1082
|
-
const BYTE* ip = (const BYTE*)seqStart;
|
|
1083
|
-
const BYTE* const iend = ip + seqSize;
|
|
1084
|
-
BYTE* const ostart = (BYTE* const)dst;
|
|
1085
|
-
BYTE* const oend = ostart + maxDstSize;
|
|
1086
|
-
BYTE* op = ostart;
|
|
1087
|
-
const BYTE* litPtr = dctx->litPtr;
|
|
1088
|
-
const BYTE* const litEnd = litPtr + dctx->litSize;
|
|
1089
|
-
const BYTE* const base = (const BYTE*) (dctx->base);
|
|
1090
|
-
const BYTE* const vBase = (const BYTE*) (dctx->vBase);
|
|
1091
|
-
const BYTE* const dictEnd = (const BYTE*) (dctx->dictEnd);
|
|
1092
|
-
int nbSeq;
|
|
1093
|
-
DEBUGLOG(5, "ZSTD_decompressSequences");
|
|
1094
|
-
|
|
1095
|
-
/* Build Decoding Tables */
|
|
1096
|
-
{ size_t const seqHSize = ZSTD_decodeSeqHeaders(dctx, &nbSeq, ip, seqSize);
|
|
1097
|
-
DEBUGLOG(5, "ZSTD_decodeSeqHeaders: size=%u, nbSeq=%i",
|
|
1098
|
-
(U32)seqHSize, nbSeq);
|
|
1099
|
-
if (ZSTD_isError(seqHSize)) return seqHSize;
|
|
1100
|
-
ip += seqHSize;
|
|
1101
|
-
}
|
|
1102
|
-
|
|
1103
|
-
/* Regen sequences */
|
|
1104
|
-
if (nbSeq) {
|
|
1105
|
-
seqState_t seqState;
|
|
1106
|
-
dctx->fseEntropy = 1;
|
|
1107
|
-
{ U32 i; for (i=0; i<ZSTD_REP_NUM; i++) seqState.prevOffset[i] = dctx->entropy.rep[i]; }
|
|
1108
|
-
CHECK_E(BIT_initDStream(&seqState.DStream, ip, iend-ip), corruption_detected);
|
|
1109
|
-
FSE_initDState(&seqState.stateLL, &seqState.DStream, dctx->LLTptr);
|
|
1110
|
-
FSE_initDState(&seqState.stateOffb, &seqState.DStream, dctx->OFTptr);
|
|
1111
|
-
FSE_initDState(&seqState.stateML, &seqState.DStream, dctx->MLTptr);
|
|
1112
|
-
|
|
1113
|
-
for ( ; (BIT_reloadDStream(&(seqState.DStream)) <= BIT_DStream_completed) && nbSeq ; ) {
|
|
1114
|
-
nbSeq--;
|
|
1115
|
-
{ seq_t const sequence = ZSTD_decodeSequence(&seqState, isLongOffset);
|
|
1116
|
-
size_t const oneSeqSize = ZSTD_execSequence(op, oend, sequence, &litPtr, litEnd, base, vBase, dictEnd);
|
|
1117
|
-
DEBUGLOG(6, "regenerated sequence size : %u", (U32)oneSeqSize);
|
|
1118
|
-
if (ZSTD_isError(oneSeqSize)) return oneSeqSize;
|
|
1119
|
-
op += oneSeqSize;
|
|
1120
|
-
} }
|
|
1121
485
|
|
|
1122
|
-
|
|
1123
|
-
|
|
1124
|
-
if (nbSeq) return ERROR(corruption_detected);
|
|
1125
|
-
/* save reps for next block */
|
|
1126
|
-
{ U32 i; for (i=0; i<ZSTD_REP_NUM; i++) dctx->entropy.rep[i] = (U32)(seqState.prevOffset[i]); }
|
|
1127
|
-
}
|
|
486
|
+
ip += zfh.headerSize;
|
|
487
|
+
remainingSize -= zfh.headerSize;
|
|
1128
488
|
|
|
1129
|
-
|
|
1130
|
-
|
|
1131
|
-
|
|
1132
|
-
|
|
1133
|
-
|
|
1134
|
-
|
|
489
|
+
/* Iterate over each block */
|
|
490
|
+
while (1) {
|
|
491
|
+
blockProperties_t blockProperties;
|
|
492
|
+
size_t const cBlockSize = ZSTD_getcBlockSize(ip, remainingSize, &blockProperties);
|
|
493
|
+
if (ZSTD_isError(cBlockSize))
|
|
494
|
+
return ZSTD_errorFrameSizeInfo(cBlockSize);
|
|
1135
495
|
|
|
1136
|
-
|
|
1137
|
-
|
|
496
|
+
if (ZSTD_blockHeaderSize + cBlockSize > remainingSize)
|
|
497
|
+
return ZSTD_errorFrameSizeInfo(ERROR(srcSize_wrong));
|
|
1138
498
|
|
|
499
|
+
ip += ZSTD_blockHeaderSize + cBlockSize;
|
|
500
|
+
remainingSize -= ZSTD_blockHeaderSize + cBlockSize;
|
|
501
|
+
nbBlocks++;
|
|
1139
502
|
|
|
1140
|
-
|
|
1141
|
-
seq_t ZSTD_decodeSequenceLong(seqState_t* seqState, ZSTD_longOffset_e const longOffsets)
|
|
1142
|
-
{
|
|
1143
|
-
seq_t seq;
|
|
1144
|
-
|
|
1145
|
-
U32 const llCode = FSE_peekSymbol(&seqState->stateLL);
|
|
1146
|
-
U32 const mlCode = FSE_peekSymbol(&seqState->stateML);
|
|
1147
|
-
U32 const ofCode = FSE_peekSymbol(&seqState->stateOffb); /* <= MaxOff, by table construction */
|
|
1148
|
-
|
|
1149
|
-
U32 const llBits = LL_bits[llCode];
|
|
1150
|
-
U32 const mlBits = ML_bits[mlCode];
|
|
1151
|
-
U32 const ofBits = ofCode;
|
|
1152
|
-
U32 const totalBits = llBits+mlBits+ofBits;
|
|
1153
|
-
|
|
1154
|
-
static const U32 LL_base[MaxLL+1] = {
|
|
1155
|
-
0, 1, 2, 3, 4, 5, 6, 7,
|
|
1156
|
-
8, 9, 10, 11, 12, 13, 14, 15,
|
|
1157
|
-
16, 18, 20, 22, 24, 28, 32, 40,
|
|
1158
|
-
48, 64, 0x80, 0x100, 0x200, 0x400, 0x800, 0x1000,
|
|
1159
|
-
0x2000, 0x4000, 0x8000, 0x10000 };
|
|
1160
|
-
|
|
1161
|
-
static const U32 ML_base[MaxML+1] = {
|
|
1162
|
-
3, 4, 5, 6, 7, 8, 9, 10,
|
|
1163
|
-
11, 12, 13, 14, 15, 16, 17, 18,
|
|
1164
|
-
19, 20, 21, 22, 23, 24, 25, 26,
|
|
1165
|
-
27, 28, 29, 30, 31, 32, 33, 34,
|
|
1166
|
-
35, 37, 39, 41, 43, 47, 51, 59,
|
|
1167
|
-
67, 83, 99, 0x83, 0x103, 0x203, 0x403, 0x803,
|
|
1168
|
-
0x1003, 0x2003, 0x4003, 0x8003, 0x10003 };
|
|
1169
|
-
|
|
1170
|
-
static const U32 OF_base[MaxOff+1] = {
|
|
1171
|
-
0, 1, 1, 5, 0xD, 0x1D, 0x3D, 0x7D,
|
|
1172
|
-
0xFD, 0x1FD, 0x3FD, 0x7FD, 0xFFD, 0x1FFD, 0x3FFD, 0x7FFD,
|
|
1173
|
-
0xFFFD, 0x1FFFD, 0x3FFFD, 0x7FFFD, 0xFFFFD, 0x1FFFFD, 0x3FFFFD, 0x7FFFFD,
|
|
1174
|
-
0xFFFFFD, 0x1FFFFFD, 0x3FFFFFD, 0x7FFFFFD, 0xFFFFFFD, 0x1FFFFFFD, 0x3FFFFFFD, 0x7FFFFFFD };
|
|
1175
|
-
|
|
1176
|
-
/* sequence */
|
|
1177
|
-
{ size_t offset;
|
|
1178
|
-
if (!ofCode)
|
|
1179
|
-
offset = 0;
|
|
1180
|
-
else {
|
|
1181
|
-
ZSTD_STATIC_ASSERT(ZSTD_lo_isLongOffset == 1);
|
|
1182
|
-
ZSTD_STATIC_ASSERT(LONG_OFFSETS_MAX_EXTRA_BITS_32 == 5);
|
|
1183
|
-
assert(ofBits <= MaxOff);
|
|
1184
|
-
if (MEM_32bits() && longOffsets) {
|
|
1185
|
-
U32 const extraBits = ofBits - MIN(ofBits, STREAM_ACCUMULATOR_MIN_32-1);
|
|
1186
|
-
offset = OF_base[ofCode] + (BIT_readBitsFast(&seqState->DStream, ofBits - extraBits) << extraBits);
|
|
1187
|
-
if (MEM_32bits() || extraBits) BIT_reloadDStream(&seqState->DStream);
|
|
1188
|
-
if (extraBits) offset += BIT_readBitsFast(&seqState->DStream, extraBits);
|
|
1189
|
-
} else {
|
|
1190
|
-
offset = OF_base[ofCode] + BIT_readBitsFast(&seqState->DStream, ofBits); /* <= (ZSTD_WINDOWLOG_MAX-1) bits */
|
|
1191
|
-
if (MEM_32bits()) BIT_reloadDStream(&seqState->DStream);
|
|
1192
|
-
}
|
|
503
|
+
if (blockProperties.lastBlock) break;
|
|
1193
504
|
}
|
|
1194
505
|
|
|
1195
|
-
|
|
1196
|
-
|
|
1197
|
-
if (
|
|
1198
|
-
|
|
1199
|
-
|
|
1200
|
-
if (offset != 1) seqState->prevOffset[2] = seqState->prevOffset[1];
|
|
1201
|
-
seqState->prevOffset[1] = seqState->prevOffset[0];
|
|
1202
|
-
seqState->prevOffset[0] = offset = temp;
|
|
1203
|
-
} else {
|
|
1204
|
-
offset = seqState->prevOffset[0];
|
|
1205
|
-
}
|
|
1206
|
-
} else {
|
|
1207
|
-
seqState->prevOffset[2] = seqState->prevOffset[1];
|
|
1208
|
-
seqState->prevOffset[1] = seqState->prevOffset[0];
|
|
1209
|
-
seqState->prevOffset[0] = offset;
|
|
506
|
+
/* Final frame content checksum */
|
|
507
|
+
if (zfh.checksumFlag) {
|
|
508
|
+
if (remainingSize < 4)
|
|
509
|
+
return ZSTD_errorFrameSizeInfo(ERROR(srcSize_wrong));
|
|
510
|
+
ip += 4;
|
|
1210
511
|
}
|
|
1211
|
-
seq.offset = offset;
|
|
1212
|
-
}
|
|
1213
512
|
|
|
1214
|
-
|
|
1215
|
-
|
|
1216
|
-
|
|
1217
|
-
|
|
1218
|
-
|
|
1219
|
-
/* Verify that there is enough bits to read the rest of the data in 64-bit mode. */
|
|
1220
|
-
ZSTD_STATIC_ASSERT(16+LLFSELog+MLFSELog+OffFSELog < STREAM_ACCUMULATOR_MIN_64);
|
|
1221
|
-
|
|
1222
|
-
seq.litLength = LL_base[llCode] + ((llCode>15) ? BIT_readBitsFast(&seqState->DStream, llBits) : 0); /* <= 16 bits */
|
|
1223
|
-
if (MEM_32bits())
|
|
1224
|
-
BIT_reloadDStream(&seqState->DStream);
|
|
1225
|
-
|
|
1226
|
-
{ size_t const pos = seqState->pos + seq.litLength;
|
|
1227
|
-
const BYTE* const matchBase = (seq.offset > pos) ? seqState->dictEnd : seqState->prefixStart;
|
|
1228
|
-
seq.match = matchBase + pos - seq.offset; /* note : this operation can overflow when seq.offset is really too large, which can only happen when input is corrupted.
|
|
1229
|
-
* No consequence though : no memory access will occur, overly large offset will be detected in ZSTD_execSequenceLong() */
|
|
1230
|
-
seqState->pos = pos + seq.matchLength;
|
|
513
|
+
frameSizeInfo.compressedSize = ip - ipstart;
|
|
514
|
+
frameSizeInfo.decompressedBound = (zfh.frameContentSize != ZSTD_CONTENTSIZE_UNKNOWN)
|
|
515
|
+
? zfh.frameContentSize
|
|
516
|
+
: nbBlocks * zfh.blockSizeMax;
|
|
517
|
+
return frameSizeInfo;
|
|
1231
518
|
}
|
|
1232
|
-
|
|
1233
|
-
/* ANS state update */
|
|
1234
|
-
FSE_updateState(&seqState->stateLL, &seqState->DStream); /* <= 9 bits */
|
|
1235
|
-
FSE_updateState(&seqState->stateML, &seqState->DStream); /* <= 9 bits */
|
|
1236
|
-
if (MEM_32bits()) BIT_reloadDStream(&seqState->DStream); /* <= 18 bits */
|
|
1237
|
-
FSE_updateState(&seqState->stateOffb, &seqState->DStream); /* <= 8 bits */
|
|
1238
|
-
|
|
1239
|
-
return seq;
|
|
1240
519
|
}
|
|
1241
520
|
|
|
1242
|
-
|
|
1243
|
-
|
|
1244
|
-
|
|
1245
|
-
|
|
1246
|
-
|
|
1247
|
-
|
|
521
|
+
/** ZSTD_findFrameCompressedSize() :
|
|
522
|
+
* compatible with legacy mode
|
|
523
|
+
* `src` must point to the start of a ZSTD frame, ZSTD legacy frame, or skippable frame
|
|
524
|
+
* `srcSize` must be at least as large as the frame contained
|
|
525
|
+
* @return : the compressed size of the frame starting at `src` */
|
|
526
|
+
size_t ZSTD_findFrameCompressedSize(const void *src, size_t srcSize)
|
|
1248
527
|
{
|
|
1249
|
-
|
|
1250
|
-
|
|
1251
|
-
BYTE* const oMatchEnd = op + sequenceLength; /* risk : address space overflow (32-bits) */
|
|
1252
|
-
BYTE* const oend_w = oend - WILDCOPY_OVERLENGTH;
|
|
1253
|
-
const BYTE* const iLitEnd = *litPtr + sequence.litLength;
|
|
1254
|
-
const BYTE* match = sequence.match;
|
|
1255
|
-
|
|
1256
|
-
/* check */
|
|
1257
|
-
if (oMatchEnd > oend) return ERROR(dstSize_tooSmall); /* last match must start at a minimum distance of WILDCOPY_OVERLENGTH from oend */
|
|
1258
|
-
if (iLitEnd > litLimit) return ERROR(corruption_detected); /* over-read beyond lit buffer */
|
|
1259
|
-
if (oLitEnd > oend_w) return ZSTD_execSequenceLast7(op, oend, sequence, litPtr, litLimit, prefixStart, dictStart, dictEnd);
|
|
1260
|
-
|
|
1261
|
-
/* copy Literals */
|
|
1262
|
-
ZSTD_copy8(op, *litPtr); /* note : op <= oLitEnd <= oend_w == oend - 8 */
|
|
1263
|
-
if (sequence.litLength > 8)
|
|
1264
|
-
ZSTD_wildcopy(op+8, (*litPtr)+8, sequence.litLength - 8); /* note : since oLitEnd <= oend-WILDCOPY_OVERLENGTH, no risk of overwrite beyond oend */
|
|
1265
|
-
op = oLitEnd;
|
|
1266
|
-
*litPtr = iLitEnd; /* update for next sequence */
|
|
1267
|
-
|
|
1268
|
-
/* copy Match */
|
|
1269
|
-
if (sequence.offset > (size_t)(oLitEnd - prefixStart)) {
|
|
1270
|
-
/* offset beyond prefix */
|
|
1271
|
-
if (sequence.offset > (size_t)(oLitEnd - dictStart)) return ERROR(corruption_detected);
|
|
1272
|
-
if (match + sequence.matchLength <= dictEnd) {
|
|
1273
|
-
memmove(oLitEnd, match, sequence.matchLength);
|
|
1274
|
-
return sequenceLength;
|
|
1275
|
-
}
|
|
1276
|
-
/* span extDict & currentPrefixSegment */
|
|
1277
|
-
{ size_t const length1 = dictEnd - match;
|
|
1278
|
-
memmove(oLitEnd, match, length1);
|
|
1279
|
-
op = oLitEnd + length1;
|
|
1280
|
-
sequence.matchLength -= length1;
|
|
1281
|
-
match = prefixStart;
|
|
1282
|
-
if (op > oend_w || sequence.matchLength < MINMATCH) {
|
|
1283
|
-
U32 i;
|
|
1284
|
-
for (i = 0; i < sequence.matchLength; ++i) op[i] = match[i];
|
|
1285
|
-
return sequenceLength;
|
|
1286
|
-
}
|
|
1287
|
-
} }
|
|
1288
|
-
assert(op <= oend_w);
|
|
1289
|
-
assert(sequence.matchLength >= MINMATCH);
|
|
1290
|
-
|
|
1291
|
-
/* match within prefix */
|
|
1292
|
-
if (sequence.offset < 8) {
|
|
1293
|
-
/* close range match, overlap */
|
|
1294
|
-
static const U32 dec32table[] = { 0, 1, 2, 1, 4, 4, 4, 4 }; /* added */
|
|
1295
|
-
static const int dec64table[] = { 8, 8, 8, 7, 8, 9,10,11 }; /* subtracted */
|
|
1296
|
-
int const sub2 = dec64table[sequence.offset];
|
|
1297
|
-
op[0] = match[0];
|
|
1298
|
-
op[1] = match[1];
|
|
1299
|
-
op[2] = match[2];
|
|
1300
|
-
op[3] = match[3];
|
|
1301
|
-
match += dec32table[sequence.offset];
|
|
1302
|
-
ZSTD_copy4(op+4, match);
|
|
1303
|
-
match -= sub2;
|
|
1304
|
-
} else {
|
|
1305
|
-
ZSTD_copy8(op, match);
|
|
1306
|
-
}
|
|
1307
|
-
op += 8; match += 8;
|
|
1308
|
-
|
|
1309
|
-
if (oMatchEnd > oend-(16-MINMATCH)) {
|
|
1310
|
-
if (op < oend_w) {
|
|
1311
|
-
ZSTD_wildcopy(op, match, oend_w - op);
|
|
1312
|
-
match += oend_w - op;
|
|
1313
|
-
op = oend_w;
|
|
1314
|
-
}
|
|
1315
|
-
while (op < oMatchEnd) *op++ = *match++;
|
|
1316
|
-
} else {
|
|
1317
|
-
ZSTD_wildcopy(op, match, (ptrdiff_t)sequence.matchLength-8); /* works even if matchLength < 8 */
|
|
1318
|
-
}
|
|
1319
|
-
return sequenceLength;
|
|
528
|
+
ZSTD_frameSizeInfo const frameSizeInfo = ZSTD_findFrameSizeInfo(src, srcSize);
|
|
529
|
+
return frameSizeInfo.compressedSize;
|
|
1320
530
|
}
|
|
1321
531
|
|
|
1322
|
-
static size_t ZSTD_decompressSequencesLong(
|
|
1323
|
-
ZSTD_DCtx* dctx,
|
|
1324
|
-
void* dst, size_t maxDstSize,
|
|
1325
|
-
const void* seqStart, size_t seqSize,
|
|
1326
|
-
const ZSTD_longOffset_e isLongOffset)
|
|
1327
|
-
{
|
|
1328
|
-
const BYTE* ip = (const BYTE*)seqStart;
|
|
1329
|
-
const BYTE* const iend = ip + seqSize;
|
|
1330
|
-
BYTE* const ostart = (BYTE* const)dst;
|
|
1331
|
-
BYTE* const oend = ostart + maxDstSize;
|
|
1332
|
-
BYTE* op = ostart;
|
|
1333
|
-
const BYTE* litPtr = dctx->litPtr;
|
|
1334
|
-
const BYTE* const litEnd = litPtr + dctx->litSize;
|
|
1335
|
-
const BYTE* const prefixStart = (const BYTE*) (dctx->base);
|
|
1336
|
-
const BYTE* const dictStart = (const BYTE*) (dctx->vBase);
|
|
1337
|
-
const BYTE* const dictEnd = (const BYTE*) (dctx->dictEnd);
|
|
1338
|
-
int nbSeq;
|
|
1339
|
-
|
|
1340
|
-
/* Build Decoding Tables */
|
|
1341
|
-
{ size_t const seqHSize = ZSTD_decodeSeqHeaders(dctx, &nbSeq, ip, seqSize);
|
|
1342
|
-
if (ZSTD_isError(seqHSize)) return seqHSize;
|
|
1343
|
-
ip += seqHSize;
|
|
1344
|
-
}
|
|
1345
|
-
|
|
1346
|
-
/* Regen sequences */
|
|
1347
|
-
if (nbSeq) {
|
|
1348
|
-
#define STORED_SEQS 4
|
|
1349
|
-
#define STOSEQ_MASK (STORED_SEQS-1)
|
|
1350
|
-
#define ADVANCED_SEQS 4
|
|
1351
|
-
seq_t sequences[STORED_SEQS];
|
|
1352
|
-
int const seqAdvance = MIN(nbSeq, ADVANCED_SEQS);
|
|
1353
|
-
seqState_t seqState;
|
|
1354
|
-
int seqNb;
|
|
1355
|
-
dctx->fseEntropy = 1;
|
|
1356
|
-
{ U32 i; for (i=0; i<ZSTD_REP_NUM; i++) seqState.prevOffset[i] = dctx->entropy.rep[i]; }
|
|
1357
|
-
seqState.prefixStart = prefixStart;
|
|
1358
|
-
seqState.pos = (size_t)(op-prefixStart);
|
|
1359
|
-
seqState.dictEnd = dictEnd;
|
|
1360
|
-
CHECK_E(BIT_initDStream(&seqState.DStream, ip, iend-ip), corruption_detected);
|
|
1361
|
-
FSE_initDState(&seqState.stateLL, &seqState.DStream, dctx->LLTptr);
|
|
1362
|
-
FSE_initDState(&seqState.stateOffb, &seqState.DStream, dctx->OFTptr);
|
|
1363
|
-
FSE_initDState(&seqState.stateML, &seqState.DStream, dctx->MLTptr);
|
|
1364
|
-
|
|
1365
|
-
/* prepare in advance */
|
|
1366
|
-
for (seqNb=0; (BIT_reloadDStream(&seqState.DStream) <= BIT_DStream_completed) && seqNb<seqAdvance; seqNb++) {
|
|
1367
|
-
sequences[seqNb] = ZSTD_decodeSequenceLong(&seqState, isLongOffset);
|
|
1368
|
-
}
|
|
1369
|
-
if (seqNb<seqAdvance) return ERROR(corruption_detected);
|
|
1370
|
-
|
|
1371
|
-
/* decode and decompress */
|
|
1372
|
-
for ( ; (BIT_reloadDStream(&(seqState.DStream)) <= BIT_DStream_completed) && seqNb<nbSeq ; seqNb++) {
|
|
1373
|
-
seq_t const sequence = ZSTD_decodeSequenceLong(&seqState, isLongOffset);
|
|
1374
|
-
size_t const oneSeqSize = ZSTD_execSequenceLong(op, oend, sequences[(seqNb-ADVANCED_SEQS) & STOSEQ_MASK], &litPtr, litEnd, prefixStart, dictStart, dictEnd);
|
|
1375
|
-
if (ZSTD_isError(oneSeqSize)) return oneSeqSize;
|
|
1376
|
-
PREFETCH(sequence.match); /* note : it's safe to invoke PREFETCH() on any memory address, including invalid ones */
|
|
1377
|
-
sequences[seqNb&STOSEQ_MASK] = sequence;
|
|
1378
|
-
op += oneSeqSize;
|
|
1379
|
-
}
|
|
1380
|
-
if (seqNb<nbSeq) return ERROR(corruption_detected);
|
|
1381
|
-
|
|
1382
|
-
/* finish queue */
|
|
1383
|
-
seqNb -= seqAdvance;
|
|
1384
|
-
for ( ; seqNb<nbSeq ; seqNb++) {
|
|
1385
|
-
size_t const oneSeqSize = ZSTD_execSequenceLong(op, oend, sequences[seqNb&STOSEQ_MASK], &litPtr, litEnd, prefixStart, dictStart, dictEnd);
|
|
1386
|
-
if (ZSTD_isError(oneSeqSize)) return oneSeqSize;
|
|
1387
|
-
op += oneSeqSize;
|
|
1388
|
-
}
|
|
1389
532
|
|
|
1390
|
-
|
|
1391
|
-
|
|
1392
|
-
|
|
1393
|
-
|
|
1394
|
-
|
|
1395
|
-
|
|
1396
|
-
|
|
1397
|
-
|
|
1398
|
-
|
|
533
|
+
/** ZSTD_decompressBound() :
|
|
534
|
+
* compatible with legacy mode
|
|
535
|
+
* `src` must point to the start of a ZSTD frame or a skippeable frame
|
|
536
|
+
* `srcSize` must be at least as large as the frame contained
|
|
537
|
+
* @return : the maximum decompressed size of the compressed source
|
|
538
|
+
*/
|
|
539
|
+
unsigned long long ZSTD_decompressBound(const void* src, size_t srcSize)
|
|
540
|
+
{
|
|
541
|
+
unsigned long long bound = 0;
|
|
542
|
+
/* Iterate over each frame */
|
|
543
|
+
while (srcSize > 0) {
|
|
544
|
+
ZSTD_frameSizeInfo const frameSizeInfo = ZSTD_findFrameSizeInfo(src, srcSize);
|
|
545
|
+
size_t const compressedSize = frameSizeInfo.compressedSize;
|
|
546
|
+
unsigned long long const decompressedBound = frameSizeInfo.decompressedBound;
|
|
547
|
+
if (ZSTD_isError(compressedSize) || decompressedBound == ZSTD_CONTENTSIZE_ERROR)
|
|
548
|
+
return ZSTD_CONTENTSIZE_ERROR;
|
|
549
|
+
src = (const BYTE*)src + compressedSize;
|
|
550
|
+
srcSize -= compressedSize;
|
|
551
|
+
bound += decompressedBound;
|
|
1399
552
|
}
|
|
1400
|
-
|
|
1401
|
-
return op-ostart;
|
|
553
|
+
return bound;
|
|
1402
554
|
}
|
|
1403
555
|
|
|
1404
556
|
|
|
1405
|
-
|
|
1406
|
-
|
|
1407
|
-
|
|
1408
|
-
{ /* blockType == blockCompressed */
|
|
1409
|
-
const BYTE* ip = (const BYTE*)src;
|
|
1410
|
-
/* isLongOffset must be true if there are long offsets.
|
|
1411
|
-
* Offsets are long if they are larger than 2^STREAM_ACCUMULATOR_MIN.
|
|
1412
|
-
* We don't expect that to be the case in 64-bit mode.
|
|
1413
|
-
* If we are in block mode we don't know the window size, so we have to be
|
|
1414
|
-
* conservative.
|
|
1415
|
-
*/
|
|
1416
|
-
ZSTD_longOffset_e const isLongOffset = (ZSTD_longOffset_e)(MEM_32bits() && (!frame || dctx->fParams.windowSize > (1ULL << STREAM_ACCUMULATOR_MIN)));
|
|
1417
|
-
/* windowSize could be any value at this point, since it is only validated
|
|
1418
|
-
* in the streaming API.
|
|
1419
|
-
*/
|
|
1420
|
-
DEBUGLOG(5, "ZSTD_decompressBlock_internal (size : %u)", (U32)srcSize);
|
|
1421
|
-
|
|
1422
|
-
if (srcSize >= ZSTD_BLOCKSIZE_MAX) return ERROR(srcSize_wrong);
|
|
1423
|
-
|
|
1424
|
-
/* Decode literals section */
|
|
1425
|
-
{ size_t const litCSize = ZSTD_decodeLiteralsBlock(dctx, src, srcSize);
|
|
1426
|
-
DEBUGLOG(5, "ZSTD_decodeLiteralsBlock : %u", (U32)litCSize);
|
|
1427
|
-
if (ZSTD_isError(litCSize)) return litCSize;
|
|
1428
|
-
ip += litCSize;
|
|
1429
|
-
srcSize -= litCSize;
|
|
1430
|
-
}
|
|
1431
|
-
if (frame && dctx->fParams.windowSize > (1<<23))
|
|
1432
|
-
return ZSTD_decompressSequencesLong(dctx, dst, dstCapacity, ip, srcSize, isLongOffset);
|
|
1433
|
-
return ZSTD_decompressSequences(dctx, dst, dstCapacity, ip, srcSize, isLongOffset);
|
|
1434
|
-
}
|
|
557
|
+
/*-*************************************************************
|
|
558
|
+
* Frame decoding
|
|
559
|
+
***************************************************************/
|
|
1435
560
|
|
|
1436
561
|
|
|
1437
|
-
|
|
562
|
+
void ZSTD_checkContinuity(ZSTD_DCtx* dctx, const void* dst)
|
|
1438
563
|
{
|
|
1439
564
|
if (dst != dctx->previousDstEnd) { /* not contiguous */
|
|
1440
565
|
dctx->dictEnd = dctx->previousDstEnd;
|
|
1441
|
-
dctx->
|
|
1442
|
-
dctx->
|
|
566
|
+
dctx->virtualStart = (const char*)dst - ((const char*)(dctx->previousDstEnd) - (const char*)(dctx->prefixStart));
|
|
567
|
+
dctx->prefixStart = dst;
|
|
1443
568
|
dctx->previousDstEnd = dst;
|
|
1444
569
|
}
|
|
1445
570
|
}
|
|
1446
571
|
|
|
1447
|
-
size_t ZSTD_decompressBlock(ZSTD_DCtx* dctx,
|
|
1448
|
-
void* dst, size_t dstCapacity,
|
|
1449
|
-
const void* src, size_t srcSize)
|
|
1450
|
-
{
|
|
1451
|
-
size_t dSize;
|
|
1452
|
-
ZSTD_checkContinuity(dctx, dst);
|
|
1453
|
-
dSize = ZSTD_decompressBlock_internal(dctx, dst, dstCapacity, src, srcSize, /* frame */ 0);
|
|
1454
|
-
dctx->previousDstEnd = (char*)dst + dSize;
|
|
1455
|
-
return dSize;
|
|
1456
|
-
}
|
|
1457
|
-
|
|
1458
|
-
|
|
1459
572
|
/** ZSTD_insertBlock() :
|
|
1460
573
|
insert `src` block into `dctx` history. Useful to track uncompressed blocks. */
|
|
1461
|
-
|
|
574
|
+
size_t ZSTD_insertBlock(ZSTD_DCtx* dctx, const void* blockStart, size_t blockSize)
|
|
1462
575
|
{
|
|
1463
576
|
ZSTD_checkContinuity(dctx, blockStart);
|
|
1464
577
|
dctx->previousDstEnd = (const char*)blockStart + blockSize;
|
|
@@ -1466,69 +579,37 @@ ZSTDLIB_API size_t ZSTD_insertBlock(ZSTD_DCtx* dctx, const void* blockStart, siz
|
|
|
1466
579
|
}
|
|
1467
580
|
|
|
1468
581
|
|
|
1469
|
-
static size_t
|
|
582
|
+
static size_t ZSTD_copyRawBlock(void* dst, size_t dstCapacity,
|
|
583
|
+
const void* src, size_t srcSize)
|
|
1470
584
|
{
|
|
1471
|
-
|
|
1472
|
-
|
|
1473
|
-
|
|
585
|
+
DEBUGLOG(5, "ZSTD_copyRawBlock");
|
|
586
|
+
if (dst == NULL) {
|
|
587
|
+
if (srcSize == 0) return 0;
|
|
588
|
+
RETURN_ERROR(dstBuffer_null);
|
|
589
|
+
}
|
|
590
|
+
RETURN_ERROR_IF(srcSize > dstCapacity, dstSize_tooSmall);
|
|
591
|
+
memcpy(dst, src, srcSize);
|
|
592
|
+
return srcSize;
|
|
1474
593
|
}
|
|
1475
594
|
|
|
1476
|
-
|
|
1477
|
-
|
|
1478
|
-
|
|
1479
|
-
* `srcSize` must be at least as large as the frame contained
|
|
1480
|
-
* @return : the compressed size of the frame starting at `src` */
|
|
1481
|
-
size_t ZSTD_findFrameCompressedSize(const void *src, size_t srcSize)
|
|
595
|
+
static size_t ZSTD_setRleBlock(void* dst, size_t dstCapacity,
|
|
596
|
+
BYTE b,
|
|
597
|
+
size_t regenSize)
|
|
1482
598
|
{
|
|
1483
|
-
|
|
1484
|
-
|
|
1485
|
-
|
|
1486
|
-
#endif
|
|
1487
|
-
if ( (srcSize >= ZSTD_skippableHeaderSize)
|
|
1488
|
-
&& (MEM_readLE32(src) & 0xFFFFFFF0U) == ZSTD_MAGIC_SKIPPABLE_START ) {
|
|
1489
|
-
return ZSTD_skippableHeaderSize + MEM_readLE32((const BYTE*)src + ZSTD_frameIdSize);
|
|
1490
|
-
} else {
|
|
1491
|
-
const BYTE* ip = (const BYTE*)src;
|
|
1492
|
-
const BYTE* const ipstart = ip;
|
|
1493
|
-
size_t remainingSize = srcSize;
|
|
1494
|
-
ZSTD_frameHeader zfh;
|
|
1495
|
-
|
|
1496
|
-
/* Extract Frame Header */
|
|
1497
|
-
{ size_t const ret = ZSTD_getFrameHeader(&zfh, src, srcSize);
|
|
1498
|
-
if (ZSTD_isError(ret)) return ret;
|
|
1499
|
-
if (ret > 0) return ERROR(srcSize_wrong);
|
|
1500
|
-
}
|
|
1501
|
-
|
|
1502
|
-
ip += zfh.headerSize;
|
|
1503
|
-
remainingSize -= zfh.headerSize;
|
|
1504
|
-
|
|
1505
|
-
/* Loop on each block */
|
|
1506
|
-
while (1) {
|
|
1507
|
-
blockProperties_t blockProperties;
|
|
1508
|
-
size_t const cBlockSize = ZSTD_getcBlockSize(ip, remainingSize, &blockProperties);
|
|
1509
|
-
if (ZSTD_isError(cBlockSize)) return cBlockSize;
|
|
1510
|
-
|
|
1511
|
-
if (ZSTD_blockHeaderSize + cBlockSize > remainingSize)
|
|
1512
|
-
return ERROR(srcSize_wrong);
|
|
1513
|
-
|
|
1514
|
-
ip += ZSTD_blockHeaderSize + cBlockSize;
|
|
1515
|
-
remainingSize -= ZSTD_blockHeaderSize + cBlockSize;
|
|
1516
|
-
|
|
1517
|
-
if (blockProperties.lastBlock) break;
|
|
1518
|
-
}
|
|
1519
|
-
|
|
1520
|
-
if (zfh.checksumFlag) { /* Final frame content checksum */
|
|
1521
|
-
if (remainingSize < 4) return ERROR(srcSize_wrong);
|
|
1522
|
-
ip += 4;
|
|
1523
|
-
remainingSize -= 4;
|
|
1524
|
-
}
|
|
1525
|
-
|
|
1526
|
-
return ip - ipstart;
|
|
599
|
+
if (dst == NULL) {
|
|
600
|
+
if (regenSize == 0) return 0;
|
|
601
|
+
RETURN_ERROR(dstBuffer_null);
|
|
1527
602
|
}
|
|
603
|
+
RETURN_ERROR_IF(regenSize > dstCapacity, dstSize_tooSmall);
|
|
604
|
+
memset(dst, b, regenSize);
|
|
605
|
+
return regenSize;
|
|
1528
606
|
}
|
|
1529
607
|
|
|
608
|
+
|
|
1530
609
|
/*! ZSTD_decompressFrame() :
|
|
1531
|
-
*
|
|
610
|
+
* @dctx must be properly initialized
|
|
611
|
+
* will update *srcPtr and *srcSizePtr,
|
|
612
|
+
* to make *srcPtr progress by one frame. */
|
|
1532
613
|
static size_t ZSTD_decompressFrame(ZSTD_DCtx* dctx,
|
|
1533
614
|
void* dst, size_t dstCapacity,
|
|
1534
615
|
const void** srcPtr, size_t *srcSizePtr)
|
|
@@ -1537,31 +618,34 @@ static size_t ZSTD_decompressFrame(ZSTD_DCtx* dctx,
|
|
|
1537
618
|
BYTE* const ostart = (BYTE* const)dst;
|
|
1538
619
|
BYTE* const oend = ostart + dstCapacity;
|
|
1539
620
|
BYTE* op = ostart;
|
|
1540
|
-
size_t
|
|
621
|
+
size_t remainingSrcSize = *srcSizePtr;
|
|
622
|
+
|
|
623
|
+
DEBUGLOG(4, "ZSTD_decompressFrame (srcSize:%i)", (int)*srcSizePtr);
|
|
1541
624
|
|
|
1542
625
|
/* check */
|
|
1543
|
-
|
|
1544
|
-
|
|
626
|
+
RETURN_ERROR_IF(
|
|
627
|
+
remainingSrcSize < ZSTD_FRAMEHEADERSIZE_MIN+ZSTD_blockHeaderSize,
|
|
628
|
+
srcSize_wrong);
|
|
1545
629
|
|
|
1546
630
|
/* Frame Header */
|
|
1547
|
-
{ size_t const frameHeaderSize = ZSTD_frameHeaderSize(ip,
|
|
631
|
+
{ size_t const frameHeaderSize = ZSTD_frameHeaderSize(ip, ZSTD_FRAMEHEADERSIZE_PREFIX);
|
|
1548
632
|
if (ZSTD_isError(frameHeaderSize)) return frameHeaderSize;
|
|
1549
|
-
|
|
1550
|
-
|
|
1551
|
-
|
|
1552
|
-
ip += frameHeaderSize;
|
|
633
|
+
RETURN_ERROR_IF(remainingSrcSize < frameHeaderSize+ZSTD_blockHeaderSize,
|
|
634
|
+
srcSize_wrong);
|
|
635
|
+
FORWARD_IF_ERROR( ZSTD_decodeFrameHeader(dctx, ip, frameHeaderSize) );
|
|
636
|
+
ip += frameHeaderSize; remainingSrcSize -= frameHeaderSize;
|
|
1553
637
|
}
|
|
1554
638
|
|
|
1555
639
|
/* Loop on each block */
|
|
1556
640
|
while (1) {
|
|
1557
641
|
size_t decodedSize;
|
|
1558
642
|
blockProperties_t blockProperties;
|
|
1559
|
-
size_t const cBlockSize = ZSTD_getcBlockSize(ip,
|
|
643
|
+
size_t const cBlockSize = ZSTD_getcBlockSize(ip, remainingSrcSize, &blockProperties);
|
|
1560
644
|
if (ZSTD_isError(cBlockSize)) return cBlockSize;
|
|
1561
645
|
|
|
1562
646
|
ip += ZSTD_blockHeaderSize;
|
|
1563
|
-
|
|
1564
|
-
|
|
647
|
+
remainingSrcSize -= ZSTD_blockHeaderSize;
|
|
648
|
+
RETURN_ERROR_IF(cBlockSize > remainingSrcSize, srcSize_wrong);
|
|
1565
649
|
|
|
1566
650
|
switch(blockProperties.blockType)
|
|
1567
651
|
{
|
|
@@ -1572,11 +656,11 @@ static size_t ZSTD_decompressFrame(ZSTD_DCtx* dctx,
|
|
|
1572
656
|
decodedSize = ZSTD_copyRawBlock(op, oend-op, ip, cBlockSize);
|
|
1573
657
|
break;
|
|
1574
658
|
case bt_rle :
|
|
1575
|
-
decodedSize =
|
|
659
|
+
decodedSize = ZSTD_setRleBlock(op, oend-op, *ip, blockProperties.origSize);
|
|
1576
660
|
break;
|
|
1577
661
|
case bt_reserved :
|
|
1578
662
|
default:
|
|
1579
|
-
|
|
663
|
+
RETURN_ERROR(corruption_detected);
|
|
1580
664
|
}
|
|
1581
665
|
|
|
1582
666
|
if (ZSTD_isError(decodedSize)) return decodedSize;
|
|
@@ -1584,33 +668,30 @@ static size_t ZSTD_decompressFrame(ZSTD_DCtx* dctx,
|
|
|
1584
668
|
XXH64_update(&dctx->xxhState, op, decodedSize);
|
|
1585
669
|
op += decodedSize;
|
|
1586
670
|
ip += cBlockSize;
|
|
1587
|
-
|
|
671
|
+
remainingSrcSize -= cBlockSize;
|
|
1588
672
|
if (blockProperties.lastBlock) break;
|
|
1589
673
|
}
|
|
1590
674
|
|
|
1591
675
|
if (dctx->fParams.frameContentSize != ZSTD_CONTENTSIZE_UNKNOWN) {
|
|
1592
|
-
|
|
1593
|
-
|
|
1594
|
-
}
|
|
676
|
+
RETURN_ERROR_IF((U64)(op-ostart) != dctx->fParams.frameContentSize,
|
|
677
|
+
corruption_detected);
|
|
678
|
+
}
|
|
1595
679
|
if (dctx->fParams.checksumFlag) { /* Frame content checksum verification */
|
|
1596
680
|
U32 const checkCalc = (U32)XXH64_digest(&dctx->xxhState);
|
|
1597
681
|
U32 checkRead;
|
|
1598
|
-
|
|
682
|
+
RETURN_ERROR_IF(remainingSrcSize<4, checksum_wrong);
|
|
1599
683
|
checkRead = MEM_readLE32(ip);
|
|
1600
|
-
|
|
684
|
+
RETURN_ERROR_IF(checkRead != checkCalc, checksum_wrong);
|
|
1601
685
|
ip += 4;
|
|
1602
|
-
|
|
686
|
+
remainingSrcSize -= 4;
|
|
1603
687
|
}
|
|
1604
688
|
|
|
1605
689
|
/* Allow caller to get size read */
|
|
1606
690
|
*srcPtr = ip;
|
|
1607
|
-
*srcSizePtr =
|
|
691
|
+
*srcSizePtr = remainingSrcSize;
|
|
1608
692
|
return op-ostart;
|
|
1609
693
|
}
|
|
1610
694
|
|
|
1611
|
-
static const void* ZSTD_DDictDictContent(const ZSTD_DDict* ddict);
|
|
1612
|
-
static size_t ZSTD_DDictDictSize(const ZSTD_DDict* ddict);
|
|
1613
|
-
|
|
1614
695
|
static size_t ZSTD_decompressMultiFrame(ZSTD_DCtx* dctx,
|
|
1615
696
|
void* dst, size_t dstCapacity,
|
|
1616
697
|
const void* src, size_t srcSize,
|
|
@@ -1618,26 +699,30 @@ static size_t ZSTD_decompressMultiFrame(ZSTD_DCtx* dctx,
|
|
|
1618
699
|
const ZSTD_DDict* ddict)
|
|
1619
700
|
{
|
|
1620
701
|
void* const dststart = dst;
|
|
702
|
+
int moreThan1Frame = 0;
|
|
703
|
+
|
|
704
|
+
DEBUGLOG(5, "ZSTD_decompressMultiFrame");
|
|
1621
705
|
assert(dict==NULL || ddict==NULL); /* either dict or ddict set, not both */
|
|
1622
706
|
|
|
1623
707
|
if (ddict) {
|
|
1624
|
-
dict =
|
|
1625
|
-
dictSize =
|
|
708
|
+
dict = ZSTD_DDict_dictContent(ddict);
|
|
709
|
+
dictSize = ZSTD_DDict_dictSize(ddict);
|
|
1626
710
|
}
|
|
1627
711
|
|
|
1628
|
-
while (srcSize >=
|
|
1629
|
-
U32 magicNumber;
|
|
712
|
+
while (srcSize >= ZSTD_FRAMEHEADERSIZE_PREFIX) {
|
|
1630
713
|
|
|
1631
714
|
#if defined(ZSTD_LEGACY_SUPPORT) && (ZSTD_LEGACY_SUPPORT >= 1)
|
|
1632
715
|
if (ZSTD_isLegacy(src, srcSize)) {
|
|
1633
716
|
size_t decodedSize;
|
|
1634
717
|
size_t const frameSize = ZSTD_findFrameCompressedSizeLegacy(src, srcSize);
|
|
1635
718
|
if (ZSTD_isError(frameSize)) return frameSize;
|
|
1636
|
-
|
|
1637
|
-
|
|
719
|
+
RETURN_ERROR_IF(dctx->staticSize, memory_allocation,
|
|
720
|
+
"legacy support is not compatible with static dctx");
|
|
1638
721
|
|
|
1639
722
|
decodedSize = ZSTD_decompressLegacy(dst, dstCapacity, src, frameSize, dict, dictSize);
|
|
723
|
+
if (ZSTD_isError(decodedSize)) return decodedSize;
|
|
1640
724
|
|
|
725
|
+
assert(decodedSize <=- dstCapacity);
|
|
1641
726
|
dst = (BYTE*)dst + decodedSize;
|
|
1642
727
|
dstCapacity -= decodedSize;
|
|
1643
728
|
|
|
@@ -1648,45 +733,54 @@ static size_t ZSTD_decompressMultiFrame(ZSTD_DCtx* dctx,
|
|
|
1648
733
|
}
|
|
1649
734
|
#endif
|
|
1650
735
|
|
|
1651
|
-
magicNumber = MEM_readLE32(src);
|
|
1652
|
-
|
|
1653
|
-
|
|
1654
|
-
|
|
1655
|
-
|
|
1656
|
-
|
|
1657
|
-
|
|
1658
|
-
|
|
1659
|
-
skippableSize = MEM_readLE32((const BYTE*)src + ZSTD_frameIdSize)
|
|
1660
|
-
+ ZSTD_skippableHeaderSize;
|
|
1661
|
-
if (srcSize < skippableSize) return ERROR(srcSize_wrong);
|
|
736
|
+
{ U32 const magicNumber = MEM_readLE32(src);
|
|
737
|
+
DEBUGLOG(4, "reading magic number %08X (expecting %08X)",
|
|
738
|
+
(unsigned)magicNumber, ZSTD_MAGICNUMBER);
|
|
739
|
+
if ((magicNumber & ZSTD_MAGIC_SKIPPABLE_MASK) == ZSTD_MAGIC_SKIPPABLE_START) {
|
|
740
|
+
size_t const skippableSize = readSkippableFrameSize(src, srcSize);
|
|
741
|
+
if (ZSTD_isError(skippableSize))
|
|
742
|
+
return skippableSize;
|
|
743
|
+
RETURN_ERROR_IF(srcSize < skippableSize, srcSize_wrong);
|
|
1662
744
|
|
|
1663
745
|
src = (const BYTE *)src + skippableSize;
|
|
1664
746
|
srcSize -= skippableSize;
|
|
1665
747
|
continue;
|
|
1666
|
-
|
|
1667
|
-
return ERROR(prefix_unknown);
|
|
1668
|
-
}
|
|
748
|
+
} }
|
|
1669
749
|
|
|
1670
750
|
if (ddict) {
|
|
1671
751
|
/* we were called from ZSTD_decompress_usingDDict */
|
|
1672
|
-
|
|
752
|
+
FORWARD_IF_ERROR(ZSTD_decompressBegin_usingDDict(dctx, ddict));
|
|
1673
753
|
} else {
|
|
1674
754
|
/* this will initialize correctly with no dict if dict == NULL, so
|
|
1675
755
|
* use this in all cases but ddict */
|
|
1676
|
-
|
|
756
|
+
FORWARD_IF_ERROR(ZSTD_decompressBegin_usingDict(dctx, dict, dictSize));
|
|
1677
757
|
}
|
|
1678
758
|
ZSTD_checkContinuity(dctx, dst);
|
|
1679
759
|
|
|
1680
760
|
{ const size_t res = ZSTD_decompressFrame(dctx, dst, dstCapacity,
|
|
1681
761
|
&src, &srcSize);
|
|
762
|
+
RETURN_ERROR_IF(
|
|
763
|
+
(ZSTD_getErrorCode(res) == ZSTD_error_prefix_unknown)
|
|
764
|
+
&& (moreThan1Frame==1),
|
|
765
|
+
srcSize_wrong,
|
|
766
|
+
"at least one frame successfully completed, but following "
|
|
767
|
+
"bytes are garbage: it's more likely to be a srcSize error, "
|
|
768
|
+
"specifying more bytes than compressed size of frame(s). This "
|
|
769
|
+
"error message replaces ERROR(prefix_unknown), which would be "
|
|
770
|
+
"confusing, as the first header is actually correct. Note that "
|
|
771
|
+
"one could be unlucky, it might be a corruption error instead, "
|
|
772
|
+
"happening right at the place where we expect zstd magic "
|
|
773
|
+
"bytes. But this is _much_ less likely than a srcSize field "
|
|
774
|
+
"error.");
|
|
1682
775
|
if (ZSTD_isError(res)) return res;
|
|
1683
|
-
|
|
776
|
+
assert(res <= dstCapacity);
|
|
1684
777
|
dst = (BYTE*)dst + res;
|
|
1685
778
|
dstCapacity -= res;
|
|
1686
779
|
}
|
|
780
|
+
moreThan1Frame = 1;
|
|
1687
781
|
} /* while (srcSize >= ZSTD_frameHeaderSize_prefix) */
|
|
1688
782
|
|
|
1689
|
-
|
|
783
|
+
RETURN_ERROR_IF(srcSize, srcSize_wrong, "input not entirely consumed");
|
|
1690
784
|
|
|
1691
785
|
return (BYTE*)dst - (BYTE*)dststart;
|
|
1692
786
|
}
|
|
@@ -1700,9 +794,26 @@ size_t ZSTD_decompress_usingDict(ZSTD_DCtx* dctx,
|
|
|
1700
794
|
}
|
|
1701
795
|
|
|
1702
796
|
|
|
797
|
+
static ZSTD_DDict const* ZSTD_getDDict(ZSTD_DCtx* dctx)
|
|
798
|
+
{
|
|
799
|
+
switch (dctx->dictUses) {
|
|
800
|
+
default:
|
|
801
|
+
assert(0 /* Impossible */);
|
|
802
|
+
/* fall-through */
|
|
803
|
+
case ZSTD_dont_use:
|
|
804
|
+
ZSTD_clearDict(dctx);
|
|
805
|
+
return NULL;
|
|
806
|
+
case ZSTD_use_indefinitely:
|
|
807
|
+
return dctx->ddict;
|
|
808
|
+
case ZSTD_use_once:
|
|
809
|
+
dctx->dictUses = ZSTD_dont_use;
|
|
810
|
+
return dctx->ddict;
|
|
811
|
+
}
|
|
812
|
+
}
|
|
813
|
+
|
|
1703
814
|
size_t ZSTD_decompressDCtx(ZSTD_DCtx* dctx, void* dst, size_t dstCapacity, const void* src, size_t srcSize)
|
|
1704
815
|
{
|
|
1705
|
-
return
|
|
816
|
+
return ZSTD_decompress_usingDDict(dctx, dst, dstCapacity, src, srcSize, ZSTD_getDDict(dctx));
|
|
1706
817
|
}
|
|
1707
818
|
|
|
1708
819
|
|
|
@@ -1711,12 +822,13 @@ size_t ZSTD_decompress(void* dst, size_t dstCapacity, const void* src, size_t sr
|
|
|
1711
822
|
#if defined(ZSTD_HEAPMODE) && (ZSTD_HEAPMODE>=1)
|
|
1712
823
|
size_t regenSize;
|
|
1713
824
|
ZSTD_DCtx* const dctx = ZSTD_createDCtx();
|
|
1714
|
-
|
|
825
|
+
RETURN_ERROR_IF(dctx==NULL, memory_allocation);
|
|
1715
826
|
regenSize = ZSTD_decompressDCtx(dctx, dst, dstCapacity, src, srcSize);
|
|
1716
827
|
ZSTD_freeDCtx(dctx);
|
|
1717
828
|
return regenSize;
|
|
1718
829
|
#else /* stack mode */
|
|
1719
830
|
ZSTD_DCtx dctx;
|
|
831
|
+
ZSTD_initDCtx_internal(&dctx);
|
|
1720
832
|
return ZSTD_decompressDCtx(&dctx, dst, dstCapacity, src, srcSize);
|
|
1721
833
|
#endif
|
|
1722
834
|
}
|
|
@@ -1758,9 +870,9 @@ static int ZSTD_isSkipFrame(ZSTD_DCtx* dctx) { return dctx->stage == ZSTDds_skip
|
|
|
1758
870
|
* or an error code, which can be tested using ZSTD_isError() */
|
|
1759
871
|
size_t ZSTD_decompressContinue(ZSTD_DCtx* dctx, void* dst, size_t dstCapacity, const void* src, size_t srcSize)
|
|
1760
872
|
{
|
|
1761
|
-
DEBUGLOG(5, "ZSTD_decompressContinue");
|
|
873
|
+
DEBUGLOG(5, "ZSTD_decompressContinue (srcSize:%u)", (unsigned)srcSize);
|
|
1762
874
|
/* Sanity check */
|
|
1763
|
-
|
|
875
|
+
RETURN_ERROR_IF(srcSize != dctx->expected, srcSize_wrong, "not allowed");
|
|
1764
876
|
if (dstCapacity) ZSTD_checkContinuity(dctx, dst);
|
|
1765
877
|
|
|
1766
878
|
switch (dctx->stage)
|
|
@@ -1768,10 +880,10 @@ size_t ZSTD_decompressContinue(ZSTD_DCtx* dctx, void* dst, size_t dstCapacity, c
|
|
|
1768
880
|
case ZSTDds_getFrameHeaderSize :
|
|
1769
881
|
assert(src != NULL);
|
|
1770
882
|
if (dctx->format == ZSTD_f_zstd1) { /* allows header */
|
|
1771
|
-
assert(srcSize >=
|
|
1772
|
-
if ((MEM_readLE32(src) &
|
|
883
|
+
assert(srcSize >= ZSTD_FRAMEIDSIZE); /* to read skippable magic number */
|
|
884
|
+
if ((MEM_readLE32(src) & ZSTD_MAGIC_SKIPPABLE_MASK) == ZSTD_MAGIC_SKIPPABLE_START) { /* skippable frame */
|
|
1773
885
|
memcpy(dctx->headerBuffer, src, srcSize);
|
|
1774
|
-
dctx->expected =
|
|
886
|
+
dctx->expected = ZSTD_SKIPPABLEHEADERSIZE - srcSize; /* remaining to load to get full skippable frame header */
|
|
1775
887
|
dctx->stage = ZSTDds_decodeSkippableHeader;
|
|
1776
888
|
return 0;
|
|
1777
889
|
} }
|
|
@@ -1785,7 +897,7 @@ size_t ZSTD_decompressContinue(ZSTD_DCtx* dctx, void* dst, size_t dstCapacity, c
|
|
|
1785
897
|
case ZSTDds_decodeFrameHeader:
|
|
1786
898
|
assert(src != NULL);
|
|
1787
899
|
memcpy(dctx->headerBuffer + (dctx->headerSize - srcSize), src, srcSize);
|
|
1788
|
-
|
|
900
|
+
FORWARD_IF_ERROR(ZSTD_decodeFrameHeader(dctx, dctx->headerBuffer, dctx->headerSize));
|
|
1789
901
|
dctx->expected = ZSTD_blockHeaderSize;
|
|
1790
902
|
dctx->stage = ZSTDds_decodeBlockHeader;
|
|
1791
903
|
return 0;
|
|
@@ -1819,35 +931,35 @@ size_t ZSTD_decompressContinue(ZSTD_DCtx* dctx, void* dst, size_t dstCapacity, c
|
|
|
1819
931
|
|
|
1820
932
|
case ZSTDds_decompressLastBlock:
|
|
1821
933
|
case ZSTDds_decompressBlock:
|
|
1822
|
-
DEBUGLOG(5, "case ZSTDds_decompressBlock");
|
|
934
|
+
DEBUGLOG(5, "ZSTD_decompressContinue: case ZSTDds_decompressBlock");
|
|
1823
935
|
{ size_t rSize;
|
|
1824
936
|
switch(dctx->bType)
|
|
1825
937
|
{
|
|
1826
938
|
case bt_compressed:
|
|
1827
|
-
DEBUGLOG(5, "case bt_compressed");
|
|
939
|
+
DEBUGLOG(5, "ZSTD_decompressContinue: case bt_compressed");
|
|
1828
940
|
rSize = ZSTD_decompressBlock_internal(dctx, dst, dstCapacity, src, srcSize, /* frame */ 1);
|
|
1829
941
|
break;
|
|
1830
942
|
case bt_raw :
|
|
1831
943
|
rSize = ZSTD_copyRawBlock(dst, dstCapacity, src, srcSize);
|
|
1832
944
|
break;
|
|
1833
945
|
case bt_rle :
|
|
1834
|
-
rSize = ZSTD_setRleBlock(dst, dstCapacity, src,
|
|
946
|
+
rSize = ZSTD_setRleBlock(dst, dstCapacity, *(const BYTE*)src, dctx->rleSize);
|
|
1835
947
|
break;
|
|
1836
948
|
case bt_reserved : /* should never happen */
|
|
1837
949
|
default:
|
|
1838
|
-
|
|
950
|
+
RETURN_ERROR(corruption_detected);
|
|
1839
951
|
}
|
|
1840
952
|
if (ZSTD_isError(rSize)) return rSize;
|
|
1841
|
-
DEBUGLOG(5, "decoded size from block : %u", (
|
|
953
|
+
DEBUGLOG(5, "ZSTD_decompressContinue: decoded size from block : %u", (unsigned)rSize);
|
|
1842
954
|
dctx->decodedSize += rSize;
|
|
1843
955
|
if (dctx->fParams.checksumFlag) XXH64_update(&dctx->xxhState, dst, rSize);
|
|
1844
956
|
|
|
1845
957
|
if (dctx->stage == ZSTDds_decompressLastBlock) { /* end of frame */
|
|
1846
|
-
DEBUGLOG(4, "decoded size from frame : %u", (
|
|
1847
|
-
|
|
1848
|
-
|
|
1849
|
-
|
|
1850
|
-
|
|
958
|
+
DEBUGLOG(4, "ZSTD_decompressContinue: decoded size from frame : %u", (unsigned)dctx->decodedSize);
|
|
959
|
+
RETURN_ERROR_IF(
|
|
960
|
+
dctx->fParams.frameContentSize != ZSTD_CONTENTSIZE_UNKNOWN
|
|
961
|
+
&& dctx->decodedSize != dctx->fParams.frameContentSize,
|
|
962
|
+
corruption_detected);
|
|
1851
963
|
if (dctx->fParams.checksumFlag) { /* another round for frame checksum */
|
|
1852
964
|
dctx->expected = 4;
|
|
1853
965
|
dctx->stage = ZSTDds_checkChecksum;
|
|
@@ -1867,8 +979,8 @@ size_t ZSTD_decompressContinue(ZSTD_DCtx* dctx, void* dst, size_t dstCapacity, c
|
|
|
1867
979
|
assert(srcSize == 4); /* guaranteed by dctx->expected */
|
|
1868
980
|
{ U32 const h32 = (U32)XXH64_digest(&dctx->xxhState);
|
|
1869
981
|
U32 const check32 = MEM_readLE32(src);
|
|
1870
|
-
DEBUGLOG(4, "checksum : calculated %08X :: %08X read", h32, check32);
|
|
1871
|
-
|
|
982
|
+
DEBUGLOG(4, "ZSTD_decompressContinue: checksum : calculated %08X :: %08X read", (unsigned)h32, (unsigned)check32);
|
|
983
|
+
RETURN_ERROR_IF(check32 != h32, checksum_wrong);
|
|
1872
984
|
dctx->expected = 0;
|
|
1873
985
|
dctx->stage = ZSTDds_getFrameHeaderSize;
|
|
1874
986
|
return 0;
|
|
@@ -1876,9 +988,9 @@ size_t ZSTD_decompressContinue(ZSTD_DCtx* dctx, void* dst, size_t dstCapacity, c
|
|
|
1876
988
|
|
|
1877
989
|
case ZSTDds_decodeSkippableHeader:
|
|
1878
990
|
assert(src != NULL);
|
|
1879
|
-
assert(srcSize <=
|
|
1880
|
-
memcpy(dctx->headerBuffer + (
|
|
1881
|
-
dctx->expected = MEM_readLE32(dctx->headerBuffer +
|
|
991
|
+
assert(srcSize <= ZSTD_SKIPPABLEHEADERSIZE);
|
|
992
|
+
memcpy(dctx->headerBuffer + (ZSTD_SKIPPABLEHEADERSIZE - srcSize), src, srcSize); /* complete skippable header */
|
|
993
|
+
dctx->expected = MEM_readLE32(dctx->headerBuffer + ZSTD_FRAMEIDSIZE); /* note : dctx->expected can grow seriously large, beyond local buffer size */
|
|
1882
994
|
dctx->stage = ZSTDds_skipFrame;
|
|
1883
995
|
return 0;
|
|
1884
996
|
|
|
@@ -1888,7 +1000,8 @@ size_t ZSTD_decompressContinue(ZSTD_DCtx* dctx, void* dst, size_t dstCapacity, c
|
|
|
1888
1000
|
return 0;
|
|
1889
1001
|
|
|
1890
1002
|
default:
|
|
1891
|
-
|
|
1003
|
+
assert(0); /* impossible */
|
|
1004
|
+
RETURN_ERROR(GENERIC); /* some compiler require default to do something */
|
|
1892
1005
|
}
|
|
1893
1006
|
}
|
|
1894
1007
|
|
|
@@ -1896,64 +1009,91 @@ size_t ZSTD_decompressContinue(ZSTD_DCtx* dctx, void* dst, size_t dstCapacity, c
|
|
|
1896
1009
|
static size_t ZSTD_refDictContent(ZSTD_DCtx* dctx, const void* dict, size_t dictSize)
|
|
1897
1010
|
{
|
|
1898
1011
|
dctx->dictEnd = dctx->previousDstEnd;
|
|
1899
|
-
dctx->
|
|
1900
|
-
dctx->
|
|
1012
|
+
dctx->virtualStart = (const char*)dict - ((const char*)(dctx->previousDstEnd) - (const char*)(dctx->prefixStart));
|
|
1013
|
+
dctx->prefixStart = dict;
|
|
1901
1014
|
dctx->previousDstEnd = (const char*)dict + dictSize;
|
|
1902
1015
|
return 0;
|
|
1903
1016
|
}
|
|
1904
1017
|
|
|
1905
|
-
|
|
1906
|
-
*
|
|
1018
|
+
/*! ZSTD_loadDEntropy() :
|
|
1019
|
+
* dict : must point at beginning of a valid zstd dictionary.
|
|
1907
1020
|
* @return : size of entropy tables read */
|
|
1908
|
-
|
|
1021
|
+
size_t
|
|
1022
|
+
ZSTD_loadDEntropy(ZSTD_entropyDTables_t* entropy,
|
|
1023
|
+
const void* const dict, size_t const dictSize)
|
|
1909
1024
|
{
|
|
1910
1025
|
const BYTE* dictPtr = (const BYTE*)dict;
|
|
1911
1026
|
const BYTE* const dictEnd = dictPtr + dictSize;
|
|
1912
1027
|
|
|
1913
|
-
|
|
1028
|
+
RETURN_ERROR_IF(dictSize <= 8, dictionary_corrupted);
|
|
1029
|
+
assert(MEM_readLE32(dict) == ZSTD_MAGIC_DICTIONARY); /* dict must be valid */
|
|
1914
1030
|
dictPtr += 8; /* skip header = magic + dictID */
|
|
1915
1031
|
|
|
1916
|
-
|
|
1917
|
-
|
|
1918
|
-
|
|
1919
|
-
|
|
1920
|
-
|
|
1032
|
+
ZSTD_STATIC_ASSERT(offsetof(ZSTD_entropyDTables_t, OFTable) == offsetof(ZSTD_entropyDTables_t, LLTable) + sizeof(entropy->LLTable));
|
|
1033
|
+
ZSTD_STATIC_ASSERT(offsetof(ZSTD_entropyDTables_t, MLTable) == offsetof(ZSTD_entropyDTables_t, OFTable) + sizeof(entropy->OFTable));
|
|
1034
|
+
ZSTD_STATIC_ASSERT(sizeof(entropy->LLTable) + sizeof(entropy->OFTable) + sizeof(entropy->MLTable) >= HUF_DECOMPRESS_WORKSPACE_SIZE);
|
|
1035
|
+
{ void* const workspace = &entropy->LLTable; /* use fse tables as temporary workspace; implies fse tables are grouped together */
|
|
1036
|
+
size_t const workspaceSize = sizeof(entropy->LLTable) + sizeof(entropy->OFTable) + sizeof(entropy->MLTable);
|
|
1037
|
+
#ifdef HUF_FORCE_DECOMPRESS_X1
|
|
1038
|
+
/* in minimal huffman, we always use X1 variants */
|
|
1039
|
+
size_t const hSize = HUF_readDTableX1_wksp(entropy->hufTable,
|
|
1040
|
+
dictPtr, dictEnd - dictPtr,
|
|
1041
|
+
workspace, workspaceSize);
|
|
1042
|
+
#else
|
|
1043
|
+
size_t const hSize = HUF_readDTableX2_wksp(entropy->hufTable,
|
|
1044
|
+
dictPtr, dictEnd - dictPtr,
|
|
1045
|
+
workspace, workspaceSize);
|
|
1046
|
+
#endif
|
|
1047
|
+
RETURN_ERROR_IF(HUF_isError(hSize), dictionary_corrupted);
|
|
1921
1048
|
dictPtr += hSize;
|
|
1922
1049
|
}
|
|
1923
1050
|
|
|
1924
1051
|
{ short offcodeNCount[MaxOff+1];
|
|
1925
|
-
|
|
1052
|
+
unsigned offcodeMaxValue = MaxOff, offcodeLog;
|
|
1926
1053
|
size_t const offcodeHeaderSize = FSE_readNCount(offcodeNCount, &offcodeMaxValue, &offcodeLog, dictPtr, dictEnd-dictPtr);
|
|
1927
|
-
|
|
1928
|
-
|
|
1929
|
-
|
|
1054
|
+
RETURN_ERROR_IF(FSE_isError(offcodeHeaderSize), dictionary_corrupted);
|
|
1055
|
+
RETURN_ERROR_IF(offcodeMaxValue > MaxOff, dictionary_corrupted);
|
|
1056
|
+
RETURN_ERROR_IF(offcodeLog > OffFSELog, dictionary_corrupted);
|
|
1057
|
+
ZSTD_buildFSETable( entropy->OFTable,
|
|
1058
|
+
offcodeNCount, offcodeMaxValue,
|
|
1059
|
+
OF_base, OF_bits,
|
|
1060
|
+
offcodeLog);
|
|
1930
1061
|
dictPtr += offcodeHeaderSize;
|
|
1931
1062
|
}
|
|
1932
1063
|
|
|
1933
1064
|
{ short matchlengthNCount[MaxML+1];
|
|
1934
1065
|
unsigned matchlengthMaxValue = MaxML, matchlengthLog;
|
|
1935
1066
|
size_t const matchlengthHeaderSize = FSE_readNCount(matchlengthNCount, &matchlengthMaxValue, &matchlengthLog, dictPtr, dictEnd-dictPtr);
|
|
1936
|
-
|
|
1937
|
-
|
|
1938
|
-
|
|
1067
|
+
RETURN_ERROR_IF(FSE_isError(matchlengthHeaderSize), dictionary_corrupted);
|
|
1068
|
+
RETURN_ERROR_IF(matchlengthMaxValue > MaxML, dictionary_corrupted);
|
|
1069
|
+
RETURN_ERROR_IF(matchlengthLog > MLFSELog, dictionary_corrupted);
|
|
1070
|
+
ZSTD_buildFSETable( entropy->MLTable,
|
|
1071
|
+
matchlengthNCount, matchlengthMaxValue,
|
|
1072
|
+
ML_base, ML_bits,
|
|
1073
|
+
matchlengthLog);
|
|
1939
1074
|
dictPtr += matchlengthHeaderSize;
|
|
1940
1075
|
}
|
|
1941
1076
|
|
|
1942
1077
|
{ short litlengthNCount[MaxLL+1];
|
|
1943
1078
|
unsigned litlengthMaxValue = MaxLL, litlengthLog;
|
|
1944
1079
|
size_t const litlengthHeaderSize = FSE_readNCount(litlengthNCount, &litlengthMaxValue, &litlengthLog, dictPtr, dictEnd-dictPtr);
|
|
1945
|
-
|
|
1946
|
-
|
|
1947
|
-
|
|
1080
|
+
RETURN_ERROR_IF(FSE_isError(litlengthHeaderSize), dictionary_corrupted);
|
|
1081
|
+
RETURN_ERROR_IF(litlengthMaxValue > MaxLL, dictionary_corrupted);
|
|
1082
|
+
RETURN_ERROR_IF(litlengthLog > LLFSELog, dictionary_corrupted);
|
|
1083
|
+
ZSTD_buildFSETable( entropy->LLTable,
|
|
1084
|
+
litlengthNCount, litlengthMaxValue,
|
|
1085
|
+
LL_base, LL_bits,
|
|
1086
|
+
litlengthLog);
|
|
1948
1087
|
dictPtr += litlengthHeaderSize;
|
|
1949
1088
|
}
|
|
1950
1089
|
|
|
1951
|
-
|
|
1090
|
+
RETURN_ERROR_IF(dictPtr+12 > dictEnd, dictionary_corrupted);
|
|
1952
1091
|
{ int i;
|
|
1953
1092
|
size_t const dictContentSize = (size_t)(dictEnd - (dictPtr+12));
|
|
1954
1093
|
for (i=0; i<3; i++) {
|
|
1955
1094
|
U32 const rep = MEM_readLE32(dictPtr); dictPtr += 4;
|
|
1956
|
-
|
|
1095
|
+
RETURN_ERROR_IF(rep==0 || rep >= dictContentSize,
|
|
1096
|
+
dictionary_corrupted);
|
|
1957
1097
|
entropy->rep[i] = rep;
|
|
1958
1098
|
} }
|
|
1959
1099
|
|
|
@@ -1967,11 +1107,11 @@ static size_t ZSTD_decompress_insertDictionary(ZSTD_DCtx* dctx, const void* dict
|
|
|
1967
1107
|
if (magic != ZSTD_MAGIC_DICTIONARY) {
|
|
1968
1108
|
return ZSTD_refDictContent(dctx, dict, dictSize); /* pure content mode */
|
|
1969
1109
|
} }
|
|
1970
|
-
dctx->dictID = MEM_readLE32((const char*)dict +
|
|
1110
|
+
dctx->dictID = MEM_readLE32((const char*)dict + ZSTD_FRAMEIDSIZE);
|
|
1971
1111
|
|
|
1972
1112
|
/* load entropy tables */
|
|
1973
|
-
{ size_t const eSize =
|
|
1974
|
-
|
|
1113
|
+
{ size_t const eSize = ZSTD_loadDEntropy(&dctx->entropy, dict, dictSize);
|
|
1114
|
+
RETURN_ERROR_IF(ZSTD_isError(eSize), dictionary_corrupted);
|
|
1975
1115
|
dict = (const char*)dict + eSize;
|
|
1976
1116
|
dictSize -= eSize;
|
|
1977
1117
|
}
|
|
@@ -1981,7 +1121,6 @@ static size_t ZSTD_decompress_insertDictionary(ZSTD_DCtx* dctx, const void* dict
|
|
|
1981
1121
|
return ZSTD_refDictContent(dctx, dict, dictSize);
|
|
1982
1122
|
}
|
|
1983
1123
|
|
|
1984
|
-
/* Note : this function cannot fail */
|
|
1985
1124
|
size_t ZSTD_decompressBegin(ZSTD_DCtx* dctx)
|
|
1986
1125
|
{
|
|
1987
1126
|
assert(dctx != NULL);
|
|
@@ -1989,8 +1128,8 @@ size_t ZSTD_decompressBegin(ZSTD_DCtx* dctx)
|
|
|
1989
1128
|
dctx->stage = ZSTDds_getFrameHeaderSize;
|
|
1990
1129
|
dctx->decodedSize = 0;
|
|
1991
1130
|
dctx->previousDstEnd = NULL;
|
|
1992
|
-
dctx->
|
|
1993
|
-
dctx->
|
|
1131
|
+
dctx->prefixStart = NULL;
|
|
1132
|
+
dctx->virtualStart = NULL;
|
|
1994
1133
|
dctx->dictEnd = NULL;
|
|
1995
1134
|
dctx->entropy.hufTable[0] = (HUF_DTable)((HufLog)*0x1000001); /* cover both little and big endian */
|
|
1996
1135
|
dctx->litEntropy = dctx->fseEntropy = 0;
|
|
@@ -2006,183 +1145,36 @@ size_t ZSTD_decompressBegin(ZSTD_DCtx* dctx)
|
|
|
2006
1145
|
|
|
2007
1146
|
size_t ZSTD_decompressBegin_usingDict(ZSTD_DCtx* dctx, const void* dict, size_t dictSize)
|
|
2008
1147
|
{
|
|
2009
|
-
|
|
1148
|
+
FORWARD_IF_ERROR( ZSTD_decompressBegin(dctx) );
|
|
2010
1149
|
if (dict && dictSize)
|
|
2011
|
-
|
|
1150
|
+
RETURN_ERROR_IF(
|
|
1151
|
+
ZSTD_isError(ZSTD_decompress_insertDictionary(dctx, dict, dictSize)),
|
|
1152
|
+
dictionary_corrupted);
|
|
2012
1153
|
return 0;
|
|
2013
1154
|
}
|
|
2014
1155
|
|
|
2015
1156
|
|
|
2016
1157
|
/* ====== ZSTD_DDict ====== */
|
|
2017
1158
|
|
|
2018
|
-
|
|
2019
|
-
void* dictBuffer;
|
|
2020
|
-
const void* dictContent;
|
|
2021
|
-
size_t dictSize;
|
|
2022
|
-
ZSTD_entropyDTables_t entropy;
|
|
2023
|
-
U32 dictID;
|
|
2024
|
-
U32 entropyPresent;
|
|
2025
|
-
ZSTD_customMem cMem;
|
|
2026
|
-
}; /* typedef'd to ZSTD_DDict within "zstd.h" */
|
|
2027
|
-
|
|
2028
|
-
static const void* ZSTD_DDictDictContent(const ZSTD_DDict* ddict)
|
|
2029
|
-
{
|
|
2030
|
-
return ddict->dictContent;
|
|
2031
|
-
}
|
|
2032
|
-
|
|
2033
|
-
static size_t ZSTD_DDictDictSize(const ZSTD_DDict* ddict)
|
|
2034
|
-
{
|
|
2035
|
-
return ddict->dictSize;
|
|
2036
|
-
}
|
|
2037
|
-
|
|
2038
|
-
size_t ZSTD_decompressBegin_usingDDict(ZSTD_DCtx* dstDCtx, const ZSTD_DDict* ddict)
|
|
2039
|
-
{
|
|
2040
|
-
CHECK_F( ZSTD_decompressBegin(dstDCtx) );
|
|
2041
|
-
if (ddict) { /* support begin on NULL */
|
|
2042
|
-
dstDCtx->dictID = ddict->dictID;
|
|
2043
|
-
dstDCtx->base = ddict->dictContent;
|
|
2044
|
-
dstDCtx->vBase = ddict->dictContent;
|
|
2045
|
-
dstDCtx->dictEnd = (const BYTE*)ddict->dictContent + ddict->dictSize;
|
|
2046
|
-
dstDCtx->previousDstEnd = dstDCtx->dictEnd;
|
|
2047
|
-
if (ddict->entropyPresent) {
|
|
2048
|
-
dstDCtx->litEntropy = 1;
|
|
2049
|
-
dstDCtx->fseEntropy = 1;
|
|
2050
|
-
dstDCtx->LLTptr = ddict->entropy.LLTable;
|
|
2051
|
-
dstDCtx->MLTptr = ddict->entropy.MLTable;
|
|
2052
|
-
dstDCtx->OFTptr = ddict->entropy.OFTable;
|
|
2053
|
-
dstDCtx->HUFptr = ddict->entropy.hufTable;
|
|
2054
|
-
dstDCtx->entropy.rep[0] = ddict->entropy.rep[0];
|
|
2055
|
-
dstDCtx->entropy.rep[1] = ddict->entropy.rep[1];
|
|
2056
|
-
dstDCtx->entropy.rep[2] = ddict->entropy.rep[2];
|
|
2057
|
-
} else {
|
|
2058
|
-
dstDCtx->litEntropy = 0;
|
|
2059
|
-
dstDCtx->fseEntropy = 0;
|
|
2060
|
-
}
|
|
2061
|
-
}
|
|
2062
|
-
return 0;
|
|
2063
|
-
}
|
|
2064
|
-
|
|
2065
|
-
static size_t ZSTD_loadEntropy_inDDict(ZSTD_DDict* ddict)
|
|
1159
|
+
size_t ZSTD_decompressBegin_usingDDict(ZSTD_DCtx* dctx, const ZSTD_DDict* ddict)
|
|
2066
1160
|
{
|
|
2067
|
-
|
|
2068
|
-
|
|
2069
|
-
if (ddict
|
|
2070
|
-
|
|
2071
|
-
|
|
1161
|
+
DEBUGLOG(4, "ZSTD_decompressBegin_usingDDict");
|
|
1162
|
+
assert(dctx != NULL);
|
|
1163
|
+
if (ddict) {
|
|
1164
|
+
const char* const dictStart = (const char*)ZSTD_DDict_dictContent(ddict);
|
|
1165
|
+
size_t const dictSize = ZSTD_DDict_dictSize(ddict);
|
|
1166
|
+
const void* const dictEnd = dictStart + dictSize;
|
|
1167
|
+
dctx->ddictIsCold = (dctx->dictEnd != dictEnd);
|
|
1168
|
+
DEBUGLOG(4, "DDict is %s",
|
|
1169
|
+
dctx->ddictIsCold ? "~cold~" : "hot!");
|
|
2072
1170
|
}
|
|
2073
|
-
|
|
2074
|
-
|
|
2075
|
-
|
|
2076
|
-
CHECK_E( ZSTD_loadEntropy(&ddict->entropy, ddict->dictContent, ddict->dictSize), dictionary_corrupted );
|
|
2077
|
-
ddict->entropyPresent = 1;
|
|
2078
|
-
return 0;
|
|
2079
|
-
}
|
|
2080
|
-
|
|
2081
|
-
|
|
2082
|
-
static size_t ZSTD_initDDict_internal(ZSTD_DDict* ddict, const void* dict, size_t dictSize, ZSTD_dictLoadMethod_e dictLoadMethod)
|
|
2083
|
-
{
|
|
2084
|
-
if ((dictLoadMethod == ZSTD_dlm_byRef) || (!dict) || (!dictSize)) {
|
|
2085
|
-
ddict->dictBuffer = NULL;
|
|
2086
|
-
ddict->dictContent = dict;
|
|
2087
|
-
} else {
|
|
2088
|
-
void* const internalBuffer = ZSTD_malloc(dictSize, ddict->cMem);
|
|
2089
|
-
ddict->dictBuffer = internalBuffer;
|
|
2090
|
-
ddict->dictContent = internalBuffer;
|
|
2091
|
-
if (!internalBuffer) return ERROR(memory_allocation);
|
|
2092
|
-
memcpy(internalBuffer, dict, dictSize);
|
|
1171
|
+
FORWARD_IF_ERROR( ZSTD_decompressBegin(dctx) );
|
|
1172
|
+
if (ddict) { /* NULL ddict is equivalent to no dictionary */
|
|
1173
|
+
ZSTD_copyDDictParameters(dctx, ddict);
|
|
2093
1174
|
}
|
|
2094
|
-
ddict->dictSize = dictSize;
|
|
2095
|
-
ddict->entropy.hufTable[0] = (HUF_DTable)((HufLog)*0x1000001); /* cover both little and big endian */
|
|
2096
|
-
|
|
2097
|
-
/* parse dictionary content */
|
|
2098
|
-
CHECK_F( ZSTD_loadEntropy_inDDict(ddict) );
|
|
2099
|
-
|
|
2100
1175
|
return 0;
|
|
2101
1176
|
}
|
|
2102
1177
|
|
|
2103
|
-
ZSTD_DDict* ZSTD_createDDict_advanced(const void* dict, size_t dictSize, ZSTD_dictLoadMethod_e dictLoadMethod, ZSTD_customMem customMem)
|
|
2104
|
-
{
|
|
2105
|
-
if (!customMem.customAlloc ^ !customMem.customFree) return NULL;
|
|
2106
|
-
|
|
2107
|
-
{ ZSTD_DDict* const ddict = (ZSTD_DDict*) ZSTD_malloc(sizeof(ZSTD_DDict), customMem);
|
|
2108
|
-
if (!ddict) return NULL;
|
|
2109
|
-
ddict->cMem = customMem;
|
|
2110
|
-
|
|
2111
|
-
if (ZSTD_isError( ZSTD_initDDict_internal(ddict, dict, dictSize, dictLoadMethod) )) {
|
|
2112
|
-
ZSTD_freeDDict(ddict);
|
|
2113
|
-
return NULL;
|
|
2114
|
-
}
|
|
2115
|
-
|
|
2116
|
-
return ddict;
|
|
2117
|
-
}
|
|
2118
|
-
}
|
|
2119
|
-
|
|
2120
|
-
/*! ZSTD_createDDict() :
|
|
2121
|
-
* Create a digested dictionary, to start decompression without startup delay.
|
|
2122
|
-
* `dict` content is copied inside DDict.
|
|
2123
|
-
* Consequently, `dict` can be released after `ZSTD_DDict` creation */
|
|
2124
|
-
ZSTD_DDict* ZSTD_createDDict(const void* dict, size_t dictSize)
|
|
2125
|
-
{
|
|
2126
|
-
ZSTD_customMem const allocator = { NULL, NULL, NULL };
|
|
2127
|
-
return ZSTD_createDDict_advanced(dict, dictSize, ZSTD_dlm_byCopy, allocator);
|
|
2128
|
-
}
|
|
2129
|
-
|
|
2130
|
-
/*! ZSTD_createDDict_byReference() :
|
|
2131
|
-
* Create a digested dictionary, to start decompression without startup delay.
|
|
2132
|
-
* Dictionary content is simply referenced, it will be accessed during decompression.
|
|
2133
|
-
* Warning : dictBuffer must outlive DDict (DDict must be freed before dictBuffer) */
|
|
2134
|
-
ZSTD_DDict* ZSTD_createDDict_byReference(const void* dictBuffer, size_t dictSize)
|
|
2135
|
-
{
|
|
2136
|
-
ZSTD_customMem const allocator = { NULL, NULL, NULL };
|
|
2137
|
-
return ZSTD_createDDict_advanced(dictBuffer, dictSize, ZSTD_dlm_byRef, allocator);
|
|
2138
|
-
}
|
|
2139
|
-
|
|
2140
|
-
|
|
2141
|
-
ZSTD_DDict* ZSTD_initStaticDDict(void* workspace, size_t workspaceSize,
|
|
2142
|
-
const void* dict, size_t dictSize,
|
|
2143
|
-
ZSTD_dictLoadMethod_e dictLoadMethod)
|
|
2144
|
-
{
|
|
2145
|
-
size_t const neededSpace =
|
|
2146
|
-
sizeof(ZSTD_DDict) + (dictLoadMethod == ZSTD_dlm_byRef ? 0 : dictSize);
|
|
2147
|
-
ZSTD_DDict* const ddict = (ZSTD_DDict*)workspace;
|
|
2148
|
-
assert(workspace != NULL);
|
|
2149
|
-
assert(dict != NULL);
|
|
2150
|
-
if ((size_t)workspace & 7) return NULL; /* 8-aligned */
|
|
2151
|
-
if (workspaceSize < neededSpace) return NULL;
|
|
2152
|
-
if (dictLoadMethod == ZSTD_dlm_byCopy) {
|
|
2153
|
-
memcpy(ddict+1, dict, dictSize); /* local copy */
|
|
2154
|
-
dict = ddict+1;
|
|
2155
|
-
}
|
|
2156
|
-
if (ZSTD_isError( ZSTD_initDDict_internal(ddict, dict, dictSize, ZSTD_dlm_byRef) ))
|
|
2157
|
-
return NULL;
|
|
2158
|
-
return ddict;
|
|
2159
|
-
}
|
|
2160
|
-
|
|
2161
|
-
|
|
2162
|
-
size_t ZSTD_freeDDict(ZSTD_DDict* ddict)
|
|
2163
|
-
{
|
|
2164
|
-
if (ddict==NULL) return 0; /* support free on NULL */
|
|
2165
|
-
{ ZSTD_customMem const cMem = ddict->cMem;
|
|
2166
|
-
ZSTD_free(ddict->dictBuffer, cMem);
|
|
2167
|
-
ZSTD_free(ddict, cMem);
|
|
2168
|
-
return 0;
|
|
2169
|
-
}
|
|
2170
|
-
}
|
|
2171
|
-
|
|
2172
|
-
/*! ZSTD_estimateDDictSize() :
|
|
2173
|
-
* Estimate amount of memory that will be needed to create a dictionary for decompression.
|
|
2174
|
-
* Note : dictionary created by reference using ZSTD_dlm_byRef are smaller */
|
|
2175
|
-
size_t ZSTD_estimateDDictSize(size_t dictSize, ZSTD_dictLoadMethod_e dictLoadMethod)
|
|
2176
|
-
{
|
|
2177
|
-
return sizeof(ZSTD_DDict) + (dictLoadMethod == ZSTD_dlm_byRef ? 0 : dictSize);
|
|
2178
|
-
}
|
|
2179
|
-
|
|
2180
|
-
size_t ZSTD_sizeof_DDict(const ZSTD_DDict* ddict)
|
|
2181
|
-
{
|
|
2182
|
-
if (ddict==NULL) return 0; /* support sizeof on NULL */
|
|
2183
|
-
return sizeof(*ddict) + (ddict->dictBuffer ? ddict->dictSize : 0) ;
|
|
2184
|
-
}
|
|
2185
|
-
|
|
2186
1178
|
/*! ZSTD_getDictID_fromDict() :
|
|
2187
1179
|
* Provides the dictID stored within dictionary.
|
|
2188
1180
|
* if @return == 0, the dictionary is not conformant with Zstandard specification.
|
|
@@ -2191,21 +1183,11 @@ unsigned ZSTD_getDictID_fromDict(const void* dict, size_t dictSize)
|
|
|
2191
1183
|
{
|
|
2192
1184
|
if (dictSize < 8) return 0;
|
|
2193
1185
|
if (MEM_readLE32(dict) != ZSTD_MAGIC_DICTIONARY) return 0;
|
|
2194
|
-
return MEM_readLE32((const char*)dict +
|
|
2195
|
-
}
|
|
2196
|
-
|
|
2197
|
-
/*! ZSTD_getDictID_fromDDict() :
|
|
2198
|
-
* Provides the dictID of the dictionary loaded into `ddict`.
|
|
2199
|
-
* If @return == 0, the dictionary is not conformant to Zstandard specification, or empty.
|
|
2200
|
-
* Non-conformant dictionaries can still be loaded, but as content-only dictionaries. */
|
|
2201
|
-
unsigned ZSTD_getDictID_fromDDict(const ZSTD_DDict* ddict)
|
|
2202
|
-
{
|
|
2203
|
-
if (ddict==NULL) return 0;
|
|
2204
|
-
return ZSTD_getDictID_fromDict(ddict->dictContent, ddict->dictSize);
|
|
1186
|
+
return MEM_readLE32((const char*)dict + ZSTD_FRAMEIDSIZE);
|
|
2205
1187
|
}
|
|
2206
1188
|
|
|
2207
1189
|
/*! ZSTD_getDictID_fromFrame() :
|
|
2208
|
-
* Provides the dictID required to
|
|
1190
|
+
* Provides the dictID required to decompress frame stored within `src`.
|
|
2209
1191
|
* If @return == 0, the dictID could not be decoded.
|
|
2210
1192
|
* This could for one of the following reasons :
|
|
2211
1193
|
* - The frame does not require a dictionary (most common case).
|
|
@@ -2247,6 +1229,7 @@ size_t ZSTD_decompress_usingDDict(ZSTD_DCtx* dctx,
|
|
|
2247
1229
|
|
|
2248
1230
|
ZSTD_DStream* ZSTD_createDStream(void)
|
|
2249
1231
|
{
|
|
1232
|
+
DEBUGLOG(3, "ZSTD_createDStream");
|
|
2250
1233
|
return ZSTD_createDStream_advanced(ZSTD_defaultCMem);
|
|
2251
1234
|
}
|
|
2252
1235
|
|
|
@@ -2266,91 +1249,193 @@ size_t ZSTD_freeDStream(ZSTD_DStream* zds)
|
|
|
2266
1249
|
}
|
|
2267
1250
|
|
|
2268
1251
|
|
|
2269
|
-
/* ***
|
|
1252
|
+
/* *** Initialization *** */
|
|
2270
1253
|
|
|
2271
1254
|
size_t ZSTD_DStreamInSize(void) { return ZSTD_BLOCKSIZE_MAX + ZSTD_blockHeaderSize; }
|
|
2272
1255
|
size_t ZSTD_DStreamOutSize(void) { return ZSTD_BLOCKSIZE_MAX; }
|
|
2273
1256
|
|
|
2274
|
-
size_t
|
|
1257
|
+
size_t ZSTD_DCtx_loadDictionary_advanced(ZSTD_DCtx* dctx,
|
|
1258
|
+
const void* dict, size_t dictSize,
|
|
1259
|
+
ZSTD_dictLoadMethod_e dictLoadMethod,
|
|
1260
|
+
ZSTD_dictContentType_e dictContentType)
|
|
2275
1261
|
{
|
|
2276
|
-
|
|
2277
|
-
|
|
2278
|
-
ZSTD_freeDDict(zds->ddictLocal);
|
|
1262
|
+
RETURN_ERROR_IF(dctx->streamStage != zdss_init, stage_wrong);
|
|
1263
|
+
ZSTD_clearDict(dctx);
|
|
2279
1264
|
if (dict && dictSize >= 8) {
|
|
2280
|
-
|
|
2281
|
-
|
|
2282
|
-
|
|
2283
|
-
|
|
2284
|
-
|
|
2285
|
-
|
|
2286
|
-
|
|
1265
|
+
dctx->ddictLocal = ZSTD_createDDict_advanced(dict, dictSize, dictLoadMethod, dictContentType, dctx->customMem);
|
|
1266
|
+
RETURN_ERROR_IF(dctx->ddictLocal == NULL, memory_allocation);
|
|
1267
|
+
dctx->ddict = dctx->ddictLocal;
|
|
1268
|
+
dctx->dictUses = ZSTD_use_indefinitely;
|
|
1269
|
+
}
|
|
1270
|
+
return 0;
|
|
1271
|
+
}
|
|
1272
|
+
|
|
1273
|
+
size_t ZSTD_DCtx_loadDictionary_byReference(ZSTD_DCtx* dctx, const void* dict, size_t dictSize)
|
|
1274
|
+
{
|
|
1275
|
+
return ZSTD_DCtx_loadDictionary_advanced(dctx, dict, dictSize, ZSTD_dlm_byRef, ZSTD_dct_auto);
|
|
1276
|
+
}
|
|
1277
|
+
|
|
1278
|
+
size_t ZSTD_DCtx_loadDictionary(ZSTD_DCtx* dctx, const void* dict, size_t dictSize)
|
|
1279
|
+
{
|
|
1280
|
+
return ZSTD_DCtx_loadDictionary_advanced(dctx, dict, dictSize, ZSTD_dlm_byCopy, ZSTD_dct_auto);
|
|
1281
|
+
}
|
|
1282
|
+
|
|
1283
|
+
size_t ZSTD_DCtx_refPrefix_advanced(ZSTD_DCtx* dctx, const void* prefix, size_t prefixSize, ZSTD_dictContentType_e dictContentType)
|
|
1284
|
+
{
|
|
1285
|
+
FORWARD_IF_ERROR(ZSTD_DCtx_loadDictionary_advanced(dctx, prefix, prefixSize, ZSTD_dlm_byRef, dictContentType));
|
|
1286
|
+
dctx->dictUses = ZSTD_use_once;
|
|
1287
|
+
return 0;
|
|
1288
|
+
}
|
|
1289
|
+
|
|
1290
|
+
size_t ZSTD_DCtx_refPrefix(ZSTD_DCtx* dctx, const void* prefix, size_t prefixSize)
|
|
1291
|
+
{
|
|
1292
|
+
return ZSTD_DCtx_refPrefix_advanced(dctx, prefix, prefixSize, ZSTD_dct_rawContent);
|
|
1293
|
+
}
|
|
1294
|
+
|
|
1295
|
+
|
|
1296
|
+
/* ZSTD_initDStream_usingDict() :
|
|
1297
|
+
* return : expected size, aka ZSTD_FRAMEHEADERSIZE_PREFIX.
|
|
1298
|
+
* this function cannot fail */
|
|
1299
|
+
size_t ZSTD_initDStream_usingDict(ZSTD_DStream* zds, const void* dict, size_t dictSize)
|
|
1300
|
+
{
|
|
1301
|
+
DEBUGLOG(4, "ZSTD_initDStream_usingDict");
|
|
1302
|
+
FORWARD_IF_ERROR( ZSTD_DCtx_reset(zds, ZSTD_reset_session_only) );
|
|
1303
|
+
FORWARD_IF_ERROR( ZSTD_DCtx_loadDictionary(zds, dict, dictSize) );
|
|
1304
|
+
return ZSTD_FRAMEHEADERSIZE_PREFIX;
|
|
2287
1305
|
}
|
|
2288
1306
|
|
|
2289
1307
|
/* note : this variant can't fail */
|
|
2290
1308
|
size_t ZSTD_initDStream(ZSTD_DStream* zds)
|
|
2291
1309
|
{
|
|
2292
|
-
|
|
1310
|
+
DEBUGLOG(4, "ZSTD_initDStream");
|
|
1311
|
+
return ZSTD_initDStream_usingDDict(zds, NULL);
|
|
2293
1312
|
}
|
|
2294
1313
|
|
|
2295
1314
|
/* ZSTD_initDStream_usingDDict() :
|
|
2296
1315
|
* ddict will just be referenced, and must outlive decompression session
|
|
2297
1316
|
* this function cannot fail */
|
|
2298
|
-
size_t ZSTD_initDStream_usingDDict(ZSTD_DStream*
|
|
1317
|
+
size_t ZSTD_initDStream_usingDDict(ZSTD_DStream* dctx, const ZSTD_DDict* ddict)
|
|
2299
1318
|
{
|
|
2300
|
-
|
|
2301
|
-
|
|
2302
|
-
return
|
|
1319
|
+
FORWARD_IF_ERROR( ZSTD_DCtx_reset(dctx, ZSTD_reset_session_only) );
|
|
1320
|
+
FORWARD_IF_ERROR( ZSTD_DCtx_refDDict(dctx, ddict) );
|
|
1321
|
+
return ZSTD_FRAMEHEADERSIZE_PREFIX;
|
|
2303
1322
|
}
|
|
2304
1323
|
|
|
2305
|
-
|
|
1324
|
+
/* ZSTD_resetDStream() :
|
|
1325
|
+
* return : expected size, aka ZSTD_FRAMEHEADERSIZE_PREFIX.
|
|
1326
|
+
* this function cannot fail */
|
|
1327
|
+
size_t ZSTD_resetDStream(ZSTD_DStream* dctx)
|
|
2306
1328
|
{
|
|
2307
|
-
|
|
2308
|
-
|
|
2309
|
-
zds->legacyVersion = 0;
|
|
2310
|
-
zds->hostageByte = 0;
|
|
2311
|
-
return ZSTD_frameHeaderSize_prefix;
|
|
1329
|
+
FORWARD_IF_ERROR(ZSTD_DCtx_reset(dctx, ZSTD_reset_session_only));
|
|
1330
|
+
return ZSTD_FRAMEHEADERSIZE_PREFIX;
|
|
2312
1331
|
}
|
|
2313
1332
|
|
|
2314
|
-
|
|
2315
|
-
|
|
1333
|
+
|
|
1334
|
+
size_t ZSTD_DCtx_refDDict(ZSTD_DCtx* dctx, const ZSTD_DDict* ddict)
|
|
2316
1335
|
{
|
|
2317
|
-
|
|
2318
|
-
|
|
2319
|
-
|
|
2320
|
-
|
|
2321
|
-
|
|
2322
|
-
default : return ERROR(parameter_unsupported);
|
|
2323
|
-
case DStream_p_maxWindowSize :
|
|
2324
|
-
DEBUGLOG(4, "setting maxWindowSize = %u KB", paramValue >> 10);
|
|
2325
|
-
zds->maxWindowSize = paramValue ? paramValue : (U32)(-1);
|
|
2326
|
-
break;
|
|
1336
|
+
RETURN_ERROR_IF(dctx->streamStage != zdss_init, stage_wrong);
|
|
1337
|
+
ZSTD_clearDict(dctx);
|
|
1338
|
+
if (ddict) {
|
|
1339
|
+
dctx->ddict = ddict;
|
|
1340
|
+
dctx->dictUses = ZSTD_use_indefinitely;
|
|
2327
1341
|
}
|
|
2328
1342
|
return 0;
|
|
2329
1343
|
}
|
|
2330
1344
|
|
|
1345
|
+
/* ZSTD_DCtx_setMaxWindowSize() :
|
|
1346
|
+
* note : no direct equivalence in ZSTD_DCtx_setParameter,
|
|
1347
|
+
* since this version sets windowSize, and the other sets windowLog */
|
|
2331
1348
|
size_t ZSTD_DCtx_setMaxWindowSize(ZSTD_DCtx* dctx, size_t maxWindowSize)
|
|
2332
1349
|
{
|
|
2333
|
-
|
|
2334
|
-
|
|
2335
|
-
|
|
1350
|
+
ZSTD_bounds const bounds = ZSTD_dParam_getBounds(ZSTD_d_windowLogMax);
|
|
1351
|
+
size_t const min = (size_t)1 << bounds.lowerBound;
|
|
1352
|
+
size_t const max = (size_t)1 << bounds.upperBound;
|
|
1353
|
+
RETURN_ERROR_IF(dctx->streamStage != zdss_init, stage_wrong);
|
|
1354
|
+
RETURN_ERROR_IF(maxWindowSize < min, parameter_outOfBound);
|
|
1355
|
+
RETURN_ERROR_IF(maxWindowSize > max, parameter_outOfBound);
|
|
2336
1356
|
dctx->maxWindowSize = maxWindowSize;
|
|
2337
1357
|
return 0;
|
|
2338
1358
|
}
|
|
2339
1359
|
|
|
2340
1360
|
size_t ZSTD_DCtx_setFormat(ZSTD_DCtx* dctx, ZSTD_format_e format)
|
|
2341
1361
|
{
|
|
2342
|
-
|
|
2343
|
-
|
|
2344
|
-
|
|
2345
|
-
|
|
2346
|
-
|
|
1362
|
+
return ZSTD_DCtx_setParameter(dctx, ZSTD_d_format, format);
|
|
1363
|
+
}
|
|
1364
|
+
|
|
1365
|
+
ZSTD_bounds ZSTD_dParam_getBounds(ZSTD_dParameter dParam)
|
|
1366
|
+
{
|
|
1367
|
+
ZSTD_bounds bounds = { 0, 0, 0 };
|
|
1368
|
+
switch(dParam) {
|
|
1369
|
+
case ZSTD_d_windowLogMax:
|
|
1370
|
+
bounds.lowerBound = ZSTD_WINDOWLOG_ABSOLUTEMIN;
|
|
1371
|
+
bounds.upperBound = ZSTD_WINDOWLOG_MAX;
|
|
1372
|
+
return bounds;
|
|
1373
|
+
case ZSTD_d_format:
|
|
1374
|
+
bounds.lowerBound = (int)ZSTD_f_zstd1;
|
|
1375
|
+
bounds.upperBound = (int)ZSTD_f_zstd1_magicless;
|
|
1376
|
+
ZSTD_STATIC_ASSERT(ZSTD_f_zstd1 < ZSTD_f_zstd1_magicless);
|
|
1377
|
+
return bounds;
|
|
1378
|
+
default:;
|
|
1379
|
+
}
|
|
1380
|
+
bounds.error = ERROR(parameter_unsupported);
|
|
1381
|
+
return bounds;
|
|
1382
|
+
}
|
|
1383
|
+
|
|
1384
|
+
/* ZSTD_dParam_withinBounds:
|
|
1385
|
+
* @return 1 if value is within dParam bounds,
|
|
1386
|
+
* 0 otherwise */
|
|
1387
|
+
static int ZSTD_dParam_withinBounds(ZSTD_dParameter dParam, int value)
|
|
1388
|
+
{
|
|
1389
|
+
ZSTD_bounds const bounds = ZSTD_dParam_getBounds(dParam);
|
|
1390
|
+
if (ZSTD_isError(bounds.error)) return 0;
|
|
1391
|
+
if (value < bounds.lowerBound) return 0;
|
|
1392
|
+
if (value > bounds.upperBound) return 0;
|
|
1393
|
+
return 1;
|
|
1394
|
+
}
|
|
1395
|
+
|
|
1396
|
+
#define CHECK_DBOUNDS(p,v) { \
|
|
1397
|
+
RETURN_ERROR_IF(!ZSTD_dParam_withinBounds(p, v), parameter_outOfBound); \
|
|
1398
|
+
}
|
|
1399
|
+
|
|
1400
|
+
size_t ZSTD_DCtx_setParameter(ZSTD_DCtx* dctx, ZSTD_dParameter dParam, int value)
|
|
1401
|
+
{
|
|
1402
|
+
RETURN_ERROR_IF(dctx->streamStage != zdss_init, stage_wrong);
|
|
1403
|
+
switch(dParam) {
|
|
1404
|
+
case ZSTD_d_windowLogMax:
|
|
1405
|
+
if (value == 0) value = ZSTD_WINDOWLOG_LIMIT_DEFAULT;
|
|
1406
|
+
CHECK_DBOUNDS(ZSTD_d_windowLogMax, value);
|
|
1407
|
+
dctx->maxWindowSize = ((size_t)1) << value;
|
|
1408
|
+
return 0;
|
|
1409
|
+
case ZSTD_d_format:
|
|
1410
|
+
CHECK_DBOUNDS(ZSTD_d_format, value);
|
|
1411
|
+
dctx->format = (ZSTD_format_e)value;
|
|
1412
|
+
return 0;
|
|
1413
|
+
default:;
|
|
1414
|
+
}
|
|
1415
|
+
RETURN_ERROR(parameter_unsupported);
|
|
1416
|
+
}
|
|
1417
|
+
|
|
1418
|
+
size_t ZSTD_DCtx_reset(ZSTD_DCtx* dctx, ZSTD_ResetDirective reset)
|
|
1419
|
+
{
|
|
1420
|
+
if ( (reset == ZSTD_reset_session_only)
|
|
1421
|
+
|| (reset == ZSTD_reset_session_and_parameters) ) {
|
|
1422
|
+
dctx->streamStage = zdss_init;
|
|
1423
|
+
dctx->noForwardProgress = 0;
|
|
1424
|
+
}
|
|
1425
|
+
if ( (reset == ZSTD_reset_parameters)
|
|
1426
|
+
|| (reset == ZSTD_reset_session_and_parameters) ) {
|
|
1427
|
+
RETURN_ERROR_IF(dctx->streamStage != zdss_init, stage_wrong);
|
|
1428
|
+
ZSTD_clearDict(dctx);
|
|
1429
|
+
dctx->format = ZSTD_f_zstd1;
|
|
1430
|
+
dctx->maxWindowSize = ZSTD_MAXWINDOWSIZE_DEFAULT;
|
|
1431
|
+
}
|
|
2347
1432
|
return 0;
|
|
2348
1433
|
}
|
|
2349
1434
|
|
|
2350
1435
|
|
|
2351
|
-
size_t ZSTD_sizeof_DStream(const ZSTD_DStream*
|
|
1436
|
+
size_t ZSTD_sizeof_DStream(const ZSTD_DStream* dctx)
|
|
2352
1437
|
{
|
|
2353
|
-
return ZSTD_sizeof_DCtx(
|
|
1438
|
+
return ZSTD_sizeof_DCtx(dctx);
|
|
2354
1439
|
}
|
|
2355
1440
|
|
|
2356
1441
|
size_t ZSTD_decodingBufferSize_min(unsigned long long windowSize, unsigned long long frameContentSize)
|
|
@@ -2359,7 +1444,8 @@ size_t ZSTD_decodingBufferSize_min(unsigned long long windowSize, unsigned long
|
|
|
2359
1444
|
unsigned long long const neededRBSize = windowSize + blockSize + (WILDCOPY_OVERLENGTH * 2);
|
|
2360
1445
|
unsigned long long const neededSize = MIN(frameContentSize, neededRBSize);
|
|
2361
1446
|
size_t const minRBSize = (size_t) neededSize;
|
|
2362
|
-
|
|
1447
|
+
RETURN_ERROR_IF((unsigned long long)minRBSize != neededSize,
|
|
1448
|
+
frameParameter_windowTooLarge);
|
|
2363
1449
|
return minRBSize;
|
|
2364
1450
|
}
|
|
2365
1451
|
|
|
@@ -2373,13 +1459,13 @@ size_t ZSTD_estimateDStreamSize(size_t windowSize)
|
|
|
2373
1459
|
|
|
2374
1460
|
size_t ZSTD_estimateDStreamSize_fromFrame(const void* src, size_t srcSize)
|
|
2375
1461
|
{
|
|
2376
|
-
U32 const windowSizeMax = 1U << ZSTD_WINDOWLOG_MAX; /* note : should be user-selectable */
|
|
1462
|
+
U32 const windowSizeMax = 1U << ZSTD_WINDOWLOG_MAX; /* note : should be user-selectable, but requires an additional parameter (or a dctx) */
|
|
2377
1463
|
ZSTD_frameHeader zfh;
|
|
2378
1464
|
size_t const err = ZSTD_getFrameHeader(&zfh, src, srcSize);
|
|
2379
1465
|
if (ZSTD_isError(err)) return err;
|
|
2380
|
-
|
|
2381
|
-
|
|
2382
|
-
|
|
1466
|
+
RETURN_ERROR_IF(err>0, srcSize_wrong);
|
|
1467
|
+
RETURN_ERROR_IF(zfh.windowSize > windowSizeMax,
|
|
1468
|
+
frameParameter_windowTooLarge);
|
|
2383
1469
|
return ZSTD_estimateDStreamSize((size_t)zfh.windowSize);
|
|
2384
1470
|
}
|
|
2385
1471
|
|
|
@@ -2405,51 +1491,60 @@ size_t ZSTD_decompressStream(ZSTD_DStream* zds, ZSTD_outBuffer* output, ZSTD_inB
|
|
|
2405
1491
|
U32 someMoreWork = 1;
|
|
2406
1492
|
|
|
2407
1493
|
DEBUGLOG(5, "ZSTD_decompressStream");
|
|
2408
|
-
|
|
2409
|
-
|
|
2410
|
-
|
|
2411
|
-
|
|
2412
|
-
|
|
2413
|
-
|
|
2414
|
-
|
|
2415
|
-
|
|
2416
|
-
|
|
2417
|
-
|
|
1494
|
+
RETURN_ERROR_IF(
|
|
1495
|
+
input->pos > input->size,
|
|
1496
|
+
srcSize_wrong,
|
|
1497
|
+
"forbidden. in: pos: %u vs size: %u",
|
|
1498
|
+
(U32)input->pos, (U32)input->size);
|
|
1499
|
+
RETURN_ERROR_IF(
|
|
1500
|
+
output->pos > output->size,
|
|
1501
|
+
dstSize_tooSmall,
|
|
1502
|
+
"forbidden. out: pos: %u vs size: %u",
|
|
1503
|
+
(U32)output->pos, (U32)output->size);
|
|
2418
1504
|
DEBUGLOG(5, "input size : %u", (U32)(input->size - input->pos));
|
|
2419
1505
|
|
|
2420
|
-
#if defined(ZSTD_LEGACY_SUPPORT) && (ZSTD_LEGACY_SUPPORT>=1)
|
|
2421
|
-
if (zds->legacyVersion) {
|
|
2422
|
-
/* legacy support is incompatible with static dctx */
|
|
2423
|
-
if (zds->staticSize) return ERROR(memory_allocation);
|
|
2424
|
-
return ZSTD_decompressLegacyStream(zds->legacyContext, zds->legacyVersion, output, input);
|
|
2425
|
-
}
|
|
2426
|
-
#endif
|
|
2427
|
-
|
|
2428
1506
|
while (someMoreWork) {
|
|
2429
1507
|
switch(zds->streamStage)
|
|
2430
1508
|
{
|
|
2431
1509
|
case zdss_init :
|
|
2432
|
-
|
|
1510
|
+
DEBUGLOG(5, "stage zdss_init => transparent reset ");
|
|
1511
|
+
zds->streamStage = zdss_loadHeader;
|
|
1512
|
+
zds->lhSize = zds->inPos = zds->outStart = zds->outEnd = 0;
|
|
1513
|
+
zds->legacyVersion = 0;
|
|
1514
|
+
zds->hostageByte = 0;
|
|
2433
1515
|
/* fall-through */
|
|
2434
1516
|
|
|
2435
1517
|
case zdss_loadHeader :
|
|
2436
1518
|
DEBUGLOG(5, "stage zdss_loadHeader (srcSize : %u)", (U32)(iend - ip));
|
|
2437
|
-
|
|
1519
|
+
#if defined(ZSTD_LEGACY_SUPPORT) && (ZSTD_LEGACY_SUPPORT>=1)
|
|
1520
|
+
if (zds->legacyVersion) {
|
|
1521
|
+
RETURN_ERROR_IF(zds->staticSize, memory_allocation,
|
|
1522
|
+
"legacy support is incompatible with static dctx");
|
|
1523
|
+
{ size_t const hint = ZSTD_decompressLegacyStream(zds->legacyContext, zds->legacyVersion, output, input);
|
|
1524
|
+
if (hint==0) zds->streamStage = zdss_init;
|
|
1525
|
+
return hint;
|
|
1526
|
+
} }
|
|
1527
|
+
#endif
|
|
1528
|
+
{ size_t const hSize = ZSTD_getFrameHeader_advanced(&zds->fParams, zds->headerBuffer, zds->lhSize, zds->format);
|
|
2438
1529
|
DEBUGLOG(5, "header size : %u", (U32)hSize);
|
|
2439
1530
|
if (ZSTD_isError(hSize)) {
|
|
2440
1531
|
#if defined(ZSTD_LEGACY_SUPPORT) && (ZSTD_LEGACY_SUPPORT>=1)
|
|
2441
1532
|
U32 const legacyVersion = ZSTD_isLegacy(istart, iend-istart);
|
|
2442
1533
|
if (legacyVersion) {
|
|
2443
|
-
const
|
|
2444
|
-
|
|
2445
|
-
|
|
2446
|
-
|
|
2447
|
-
|
|
1534
|
+
ZSTD_DDict const* const ddict = ZSTD_getDDict(zds);
|
|
1535
|
+
const void* const dict = ddict ? ZSTD_DDict_dictContent(ddict) : NULL;
|
|
1536
|
+
size_t const dictSize = ddict ? ZSTD_DDict_dictSize(ddict) : 0;
|
|
1537
|
+
DEBUGLOG(5, "ZSTD_decompressStream: detected legacy version v0.%u", legacyVersion);
|
|
1538
|
+
RETURN_ERROR_IF(zds->staticSize, memory_allocation,
|
|
1539
|
+
"legacy support is incompatible with static dctx");
|
|
1540
|
+
FORWARD_IF_ERROR(ZSTD_initLegacyStream(&zds->legacyContext,
|
|
2448
1541
|
zds->previousLegacyVersion, legacyVersion,
|
|
2449
1542
|
dict, dictSize));
|
|
2450
1543
|
zds->legacyVersion = zds->previousLegacyVersion = legacyVersion;
|
|
2451
|
-
|
|
2452
|
-
|
|
1544
|
+
{ size_t const hint = ZSTD_decompressLegacyStream(zds->legacyContext, legacyVersion, output, input);
|
|
1545
|
+
if (hint==0) zds->streamStage = zdss_init; /* or stay in stage zdss_loadHeader */
|
|
1546
|
+
return hint;
|
|
1547
|
+
} }
|
|
2453
1548
|
#endif
|
|
2454
1549
|
return hSize; /* error */
|
|
2455
1550
|
}
|
|
@@ -2463,7 +1558,7 @@ size_t ZSTD_decompressStream(ZSTD_DStream* zds, ZSTD_outBuffer* output, ZSTD_inB
|
|
|
2463
1558
|
zds->lhSize += remainingInput;
|
|
2464
1559
|
}
|
|
2465
1560
|
input->pos = input->size;
|
|
2466
|
-
return (MAX(
|
|
1561
|
+
return (MAX(ZSTD_FRAMEHEADERSIZE_MIN, hSize) - zds->lhSize) + ZSTD_blockHeaderSize; /* remaining header bytes + next block header */
|
|
2467
1562
|
}
|
|
2468
1563
|
assert(ip != NULL);
|
|
2469
1564
|
memcpy(zds->headerBuffer + zds->lhSize, ip, toLoad); zds->lhSize = hSize; ip += toLoad;
|
|
@@ -2476,7 +1571,7 @@ size_t ZSTD_decompressStream(ZSTD_DStream* zds, ZSTD_outBuffer* output, ZSTD_inB
|
|
|
2476
1571
|
size_t const cSize = ZSTD_findFrameCompressedSize(istart, iend-istart);
|
|
2477
1572
|
if (cSize <= (size_t)(iend-istart)) {
|
|
2478
1573
|
/* shortcut : using single-pass mode */
|
|
2479
|
-
size_t const decompressedSize = ZSTD_decompress_usingDDict(zds, op, oend-op, istart, cSize, zds
|
|
1574
|
+
size_t const decompressedSize = ZSTD_decompress_usingDDict(zds, op, oend-op, istart, cSize, ZSTD_getDDict(zds));
|
|
2480
1575
|
if (ZSTD_isError(decompressedSize)) return decompressedSize;
|
|
2481
1576
|
DEBUGLOG(4, "shortcut to single-pass ZSTD_decompress_usingDDict()")
|
|
2482
1577
|
ip = istart + cSize;
|
|
@@ -2489,13 +1584,13 @@ size_t ZSTD_decompressStream(ZSTD_DStream* zds, ZSTD_outBuffer* output, ZSTD_inB
|
|
|
2489
1584
|
|
|
2490
1585
|
/* Consume header (see ZSTDds_decodeFrameHeader) */
|
|
2491
1586
|
DEBUGLOG(4, "Consume header");
|
|
2492
|
-
|
|
1587
|
+
FORWARD_IF_ERROR(ZSTD_decompressBegin_usingDDict(zds, ZSTD_getDDict(zds)));
|
|
2493
1588
|
|
|
2494
|
-
if ((MEM_readLE32(zds->headerBuffer) &
|
|
2495
|
-
zds->expected = MEM_readLE32(zds->headerBuffer +
|
|
1589
|
+
if ((MEM_readLE32(zds->headerBuffer) & ZSTD_MAGIC_SKIPPABLE_MASK) == ZSTD_MAGIC_SKIPPABLE_START) { /* skippable frame */
|
|
1590
|
+
zds->expected = MEM_readLE32(zds->headerBuffer + ZSTD_FRAMEIDSIZE);
|
|
2496
1591
|
zds->stage = ZSTDds_skipFrame;
|
|
2497
1592
|
} else {
|
|
2498
|
-
|
|
1593
|
+
FORWARD_IF_ERROR(ZSTD_decodeFrameHeader(zds, zds->headerBuffer, zds->lhSize));
|
|
2499
1594
|
zds->expected = ZSTD_blockHeaderSize;
|
|
2500
1595
|
zds->stage = ZSTDds_decodeBlockHeader;
|
|
2501
1596
|
}
|
|
@@ -2505,7 +1600,8 @@ size_t ZSTD_decompressStream(ZSTD_DStream* zds, ZSTD_outBuffer* output, ZSTD_inB
|
|
|
2505
1600
|
(U32)(zds->fParams.windowSize >>10),
|
|
2506
1601
|
(U32)(zds->maxWindowSize >> 10) );
|
|
2507
1602
|
zds->fParams.windowSize = MAX(zds->fParams.windowSize, 1U << ZSTD_WINDOWLOG_ABSOLUTEMIN);
|
|
2508
|
-
|
|
1603
|
+
RETURN_ERROR_IF(zds->fParams.windowSize > zds->maxWindowSize,
|
|
1604
|
+
frameParameter_windowTooLarge);
|
|
2509
1605
|
|
|
2510
1606
|
/* Adapt buffer sizes to frame header instructions */
|
|
2511
1607
|
{ size_t const neededInBuffSize = MAX(zds->fParams.blockSizeMax, 4 /* frame checksum */);
|
|
@@ -2519,14 +1615,15 @@ size_t ZSTD_decompressStream(ZSTD_DStream* zds, ZSTD_outBuffer* output, ZSTD_inB
|
|
|
2519
1615
|
if (zds->staticSize) { /* static DCtx */
|
|
2520
1616
|
DEBUGLOG(4, "staticSize : %u", (U32)zds->staticSize);
|
|
2521
1617
|
assert(zds->staticSize >= sizeof(ZSTD_DCtx)); /* controlled at init */
|
|
2522
|
-
|
|
2523
|
-
|
|
1618
|
+
RETURN_ERROR_IF(
|
|
1619
|
+
bufferSize > zds->staticSize - sizeof(ZSTD_DCtx),
|
|
1620
|
+
memory_allocation);
|
|
2524
1621
|
} else {
|
|
2525
1622
|
ZSTD_free(zds->inBuff, zds->customMem);
|
|
2526
1623
|
zds->inBuffSize = 0;
|
|
2527
1624
|
zds->outBuffSize = 0;
|
|
2528
1625
|
zds->inBuff = (char*)ZSTD_malloc(bufferSize, zds->customMem);
|
|
2529
|
-
|
|
1626
|
+
RETURN_ERROR_IF(zds->inBuff == NULL, memory_allocation);
|
|
2530
1627
|
}
|
|
2531
1628
|
zds->inBuffSize = neededInBuffSize;
|
|
2532
1629
|
zds->outBuff = zds->inBuff + zds->inBuffSize;
|
|
@@ -2559,6 +1656,7 @@ size_t ZSTD_decompressStream(ZSTD_DStream* zds, ZSTD_outBuffer* output, ZSTD_inB
|
|
|
2559
1656
|
if (ip==iend) { someMoreWork = 0; break; } /* no more input */
|
|
2560
1657
|
zds->streamStage = zdss_load;
|
|
2561
1658
|
/* fall-through */
|
|
1659
|
+
|
|
2562
1660
|
case zdss_load:
|
|
2563
1661
|
{ size_t const neededInSize = ZSTD_nextSrcSizeToDecompress(zds);
|
|
2564
1662
|
size_t const toLoad = neededInSize - zds->inPos;
|
|
@@ -2567,7 +1665,9 @@ size_t ZSTD_decompressStream(ZSTD_DStream* zds, ZSTD_outBuffer* output, ZSTD_inB
|
|
|
2567
1665
|
if (isSkipFrame) {
|
|
2568
1666
|
loadedSize = MIN(toLoad, (size_t)(iend-ip));
|
|
2569
1667
|
} else {
|
|
2570
|
-
|
|
1668
|
+
RETURN_ERROR_IF(toLoad > zds->inBuffSize - zds->inPos,
|
|
1669
|
+
corruption_detected,
|
|
1670
|
+
"should never happen");
|
|
2571
1671
|
loadedSize = ZSTD_limitCopy(zds->inBuff + zds->inPos, toLoad, ip, iend-ip);
|
|
2572
1672
|
}
|
|
2573
1673
|
ip += loadedSize;
|
|
@@ -2585,6 +1685,7 @@ size_t ZSTD_decompressStream(ZSTD_DStream* zds, ZSTD_outBuffer* output, ZSTD_inB
|
|
|
2585
1685
|
} }
|
|
2586
1686
|
zds->streamStage = zdss_flush;
|
|
2587
1687
|
/* fall-through */
|
|
1688
|
+
|
|
2588
1689
|
case zdss_flush:
|
|
2589
1690
|
{ size_t const toFlushSize = zds->outEnd - zds->outStart;
|
|
2590
1691
|
size_t const flushedSize = ZSTD_limitCopy(op, oend-op, zds->outBuff + zds->outStart, toFlushSize);
|
|
@@ -2605,12 +1706,24 @@ size_t ZSTD_decompressStream(ZSTD_DStream* zds, ZSTD_outBuffer* output, ZSTD_inB
|
|
|
2605
1706
|
someMoreWork = 0;
|
|
2606
1707
|
break;
|
|
2607
1708
|
|
|
2608
|
-
default:
|
|
1709
|
+
default:
|
|
1710
|
+
assert(0); /* impossible */
|
|
1711
|
+
RETURN_ERROR(GENERIC); /* some compiler require default to do something */
|
|
2609
1712
|
} }
|
|
2610
1713
|
|
|
2611
1714
|
/* result */
|
|
2612
|
-
input->pos
|
|
2613
|
-
output->pos
|
|
1715
|
+
input->pos = (size_t)(ip - (const char*)(input->src));
|
|
1716
|
+
output->pos = (size_t)(op - (char*)(output->dst));
|
|
1717
|
+
if ((ip==istart) && (op==ostart)) { /* no forward progress */
|
|
1718
|
+
zds->noForwardProgress ++;
|
|
1719
|
+
if (zds->noForwardProgress >= ZSTD_NO_FORWARD_PROGRESS_MAX) {
|
|
1720
|
+
RETURN_ERROR_IF(op==oend, dstSize_tooSmall);
|
|
1721
|
+
RETURN_ERROR_IF(ip==iend, srcSize_wrong);
|
|
1722
|
+
assert(0);
|
|
1723
|
+
}
|
|
1724
|
+
} else {
|
|
1725
|
+
zds->noForwardProgress = 0;
|
|
1726
|
+
}
|
|
2614
1727
|
{ size_t nextSrcSizeHint = ZSTD_nextSrcSizeToDecompress(zds);
|
|
2615
1728
|
if (!nextSrcSizeHint) { /* frame fully decoded */
|
|
2616
1729
|
if (zds->outEnd == zds->outStart) { /* output fully flushed */
|
|
@@ -2631,19 +1744,13 @@ size_t ZSTD_decompressStream(ZSTD_DStream* zds, ZSTD_outBuffer* output, ZSTD_inB
|
|
|
2631
1744
|
return 1;
|
|
2632
1745
|
} /* nextSrcSizeHint==0 */
|
|
2633
1746
|
nextSrcSizeHint += ZSTD_blockHeaderSize * (ZSTD_nextInputType(zds) == ZSTDnit_block); /* preload header of next block */
|
|
2634
|
-
|
|
2635
|
-
nextSrcSizeHint -= zds->inPos; /* already loaded*/
|
|
1747
|
+
assert(zds->inPos <= nextSrcSizeHint);
|
|
1748
|
+
nextSrcSizeHint -= zds->inPos; /* part already loaded*/
|
|
2636
1749
|
return nextSrcSizeHint;
|
|
2637
1750
|
}
|
|
2638
1751
|
}
|
|
2639
1752
|
|
|
2640
|
-
|
|
2641
|
-
size_t ZSTD_decompress_generic(ZSTD_DCtx* dctx, ZSTD_outBuffer* output, ZSTD_inBuffer* input)
|
|
2642
|
-
{
|
|
2643
|
-
return ZSTD_decompressStream(dctx, output, input);
|
|
2644
|
-
}
|
|
2645
|
-
|
|
2646
|
-
size_t ZSTD_decompress_generic_simpleArgs (
|
|
1753
|
+
size_t ZSTD_decompressStream_simpleArgs (
|
|
2647
1754
|
ZSTD_DCtx* dctx,
|
|
2648
1755
|
void* dst, size_t dstCapacity, size_t* dstPos,
|
|
2649
1756
|
const void* src, size_t srcSize, size_t* srcPos)
|
|
@@ -2651,15 +1758,8 @@ size_t ZSTD_decompress_generic_simpleArgs (
|
|
|
2651
1758
|
ZSTD_outBuffer output = { dst, dstCapacity, *dstPos };
|
|
2652
1759
|
ZSTD_inBuffer input = { src, srcSize, *srcPos };
|
|
2653
1760
|
/* ZSTD_compress_generic() will check validity of dstPos and srcPos */
|
|
2654
|
-
size_t const cErr =
|
|
1761
|
+
size_t const cErr = ZSTD_decompressStream(dctx, &output, &input);
|
|
2655
1762
|
*dstPos = output.pos;
|
|
2656
1763
|
*srcPos = input.pos;
|
|
2657
1764
|
return cErr;
|
|
2658
1765
|
}
|
|
2659
|
-
|
|
2660
|
-
void ZSTD_DCtx_reset(ZSTD_DCtx* dctx)
|
|
2661
|
-
{
|
|
2662
|
-
(void)ZSTD_initDStream(dctx);
|
|
2663
|
-
dctx->format = ZSTD_f_zstd1;
|
|
2664
|
-
dctx->maxWindowSize = ZSTD_MAXWINDOWSIZE_DEFAULT;
|
|
2665
|
-
}
|