extzstd 0.3.2 → 0.4
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/README.md +4 -3
- data/contrib/zstd/CHANGELOG +225 -1
- data/contrib/zstd/CONTRIBUTING.md +158 -75
- data/contrib/zstd/LICENSE +4 -4
- data/contrib/zstd/Makefile +106 -69
- data/contrib/zstd/Package.swift +36 -0
- data/contrib/zstd/README.md +64 -36
- data/contrib/zstd/SECURITY.md +15 -0
- data/contrib/zstd/TESTING.md +2 -3
- data/contrib/zstd/lib/BUCK +5 -7
- data/contrib/zstd/lib/Makefile +117 -199
- data/contrib/zstd/lib/README.md +37 -7
- data/contrib/zstd/lib/common/allocations.h +55 -0
- data/contrib/zstd/lib/common/bits.h +200 -0
- data/contrib/zstd/lib/common/bitstream.h +80 -86
- data/contrib/zstd/lib/common/compiler.h +225 -63
- data/contrib/zstd/lib/common/cpu.h +37 -1
- data/contrib/zstd/lib/common/debug.c +7 -1
- data/contrib/zstd/lib/common/debug.h +21 -12
- data/contrib/zstd/lib/common/entropy_common.c +15 -37
- data/contrib/zstd/lib/common/error_private.c +9 -2
- data/contrib/zstd/lib/common/error_private.h +93 -5
- data/contrib/zstd/lib/common/fse.h +12 -87
- data/contrib/zstd/lib/common/fse_decompress.c +37 -117
- data/contrib/zstd/lib/common/huf.h +97 -172
- data/contrib/zstd/lib/common/mem.h +58 -58
- data/contrib/zstd/lib/common/pool.c +38 -17
- data/contrib/zstd/lib/common/pool.h +10 -4
- data/contrib/zstd/lib/common/portability_macros.h +158 -0
- data/contrib/zstd/lib/common/threading.c +74 -14
- data/contrib/zstd/lib/common/threading.h +5 -10
- data/contrib/zstd/lib/common/xxhash.c +6 -814
- data/contrib/zstd/lib/common/xxhash.h +6930 -195
- data/contrib/zstd/lib/common/zstd_common.c +1 -36
- data/contrib/zstd/lib/common/zstd_deps.h +1 -1
- data/contrib/zstd/lib/common/zstd_internal.h +68 -154
- data/contrib/zstd/lib/common/zstd_trace.h +163 -0
- data/contrib/zstd/lib/compress/clevels.h +134 -0
- data/contrib/zstd/lib/compress/fse_compress.c +75 -155
- data/contrib/zstd/lib/compress/hist.c +1 -1
- data/contrib/zstd/lib/compress/hist.h +1 -1
- data/contrib/zstd/lib/compress/huf_compress.c +810 -259
- data/contrib/zstd/lib/compress/zstd_compress.c +2864 -919
- data/contrib/zstd/lib/compress/zstd_compress_internal.h +523 -192
- data/contrib/zstd/lib/compress/zstd_compress_literals.c +117 -40
- data/contrib/zstd/lib/compress/zstd_compress_literals.h +16 -6
- data/contrib/zstd/lib/compress/zstd_compress_sequences.c +28 -19
- data/contrib/zstd/lib/compress/zstd_compress_sequences.h +1 -1
- data/contrib/zstd/lib/compress/zstd_compress_superblock.c +251 -412
- data/contrib/zstd/lib/compress/zstd_compress_superblock.h +1 -1
- data/contrib/zstd/lib/compress/zstd_cwksp.h +284 -97
- data/contrib/zstd/lib/compress/zstd_double_fast.c +382 -133
- data/contrib/zstd/lib/compress/zstd_double_fast.h +14 -2
- data/contrib/zstd/lib/compress/zstd_fast.c +732 -260
- data/contrib/zstd/lib/compress/zstd_fast.h +3 -2
- data/contrib/zstd/lib/compress/zstd_lazy.c +1177 -390
- data/contrib/zstd/lib/compress/zstd_lazy.h +129 -14
- data/contrib/zstd/lib/compress/zstd_ldm.c +280 -210
- data/contrib/zstd/lib/compress/zstd_ldm.h +3 -2
- data/contrib/zstd/lib/compress/zstd_ldm_geartab.h +106 -0
- data/contrib/zstd/lib/compress/zstd_opt.c +516 -285
- data/contrib/zstd/lib/compress/zstd_opt.h +32 -8
- data/contrib/zstd/lib/compress/zstdmt_compress.c +202 -131
- data/contrib/zstd/lib/compress/zstdmt_compress.h +9 -6
- data/contrib/zstd/lib/decompress/huf_decompress.c +1149 -555
- data/contrib/zstd/lib/decompress/huf_decompress_amd64.S +595 -0
- data/contrib/zstd/lib/decompress/zstd_ddict.c +4 -4
- data/contrib/zstd/lib/decompress/zstd_ddict.h +1 -1
- data/contrib/zstd/lib/decompress/zstd_decompress.c +583 -106
- data/contrib/zstd/lib/decompress/zstd_decompress_block.c +1054 -379
- data/contrib/zstd/lib/decompress/zstd_decompress_block.h +14 -3
- data/contrib/zstd/lib/decompress/zstd_decompress_internal.h +56 -6
- data/contrib/zstd/lib/deprecated/zbuff.h +1 -1
- data/contrib/zstd/lib/deprecated/zbuff_common.c +1 -1
- data/contrib/zstd/lib/deprecated/zbuff_compress.c +24 -4
- data/contrib/zstd/lib/deprecated/zbuff_decompress.c +3 -1
- data/contrib/zstd/lib/dictBuilder/cover.c +60 -44
- data/contrib/zstd/lib/dictBuilder/cover.h +6 -11
- data/contrib/zstd/lib/dictBuilder/divsufsort.c +1 -1
- data/contrib/zstd/lib/dictBuilder/fastcover.c +26 -18
- data/contrib/zstd/lib/dictBuilder/zdict.c +100 -101
- data/contrib/zstd/lib/legacy/zstd_legacy.h +38 -1
- data/contrib/zstd/lib/legacy/zstd_v01.c +18 -53
- data/contrib/zstd/lib/legacy/zstd_v01.h +1 -1
- data/contrib/zstd/lib/legacy/zstd_v02.c +28 -85
- data/contrib/zstd/lib/legacy/zstd_v02.h +1 -1
- data/contrib/zstd/lib/legacy/zstd_v03.c +29 -88
- data/contrib/zstd/lib/legacy/zstd_v03.h +1 -1
- data/contrib/zstd/lib/legacy/zstd_v04.c +27 -80
- data/contrib/zstd/lib/legacy/zstd_v04.h +1 -1
- data/contrib/zstd/lib/legacy/zstd_v05.c +36 -85
- data/contrib/zstd/lib/legacy/zstd_v05.h +1 -1
- data/contrib/zstd/lib/legacy/zstd_v06.c +44 -96
- data/contrib/zstd/lib/legacy/zstd_v06.h +1 -1
- data/contrib/zstd/lib/legacy/zstd_v07.c +37 -92
- data/contrib/zstd/lib/legacy/zstd_v07.h +1 -1
- data/contrib/zstd/lib/libzstd.mk +237 -0
- data/contrib/zstd/lib/libzstd.pc.in +4 -3
- data/contrib/zstd/lib/module.modulemap +35 -0
- data/contrib/zstd/lib/{dictBuilder/zdict.h → zdict.h} +202 -33
- data/contrib/zstd/lib/zstd.h +1030 -332
- data/contrib/zstd/lib/{common/zstd_errors.h → zstd_errors.h} +27 -8
- data/ext/extconf.rb +26 -7
- data/ext/extzstd.c +51 -24
- data/ext/extzstd.h +33 -6
- data/ext/extzstd_stream.c +74 -31
- data/ext/libzstd_conf.h +0 -1
- data/ext/zstd_decompress_asm.S +1 -0
- metadata +17 -7
- data/contrib/zstd/appveyor.yml +0 -292
- data/ext/depend +0 -2
@@ -1,5 +1,5 @@
|
|
1
1
|
/*
|
2
|
-
* Copyright (c)
|
2
|
+
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
3
3
|
* All rights reserved.
|
4
4
|
*
|
5
5
|
* This source code is licensed under both the BSD-style license (found in the
|
@@ -56,13 +56,15 @@
|
|
56
56
|
* Dependencies
|
57
57
|
*********************************************************/
|
58
58
|
#include "../common/zstd_deps.h" /* ZSTD_memcpy, ZSTD_memmove, ZSTD_memset */
|
59
|
-
#include "../common/
|
59
|
+
#include "../common/allocations.h" /* ZSTD_customMalloc, ZSTD_customCalloc, ZSTD_customFree */
|
60
|
+
#include "../common/error_private.h"
|
61
|
+
#include "../common/zstd_internal.h" /* blockProperties_t */
|
60
62
|
#include "../common/mem.h" /* low level memory routines */
|
63
|
+
#include "../common/bits.h" /* ZSTD_highbit32 */
|
61
64
|
#define FSE_STATIC_LINKING_ONLY
|
62
65
|
#include "../common/fse.h"
|
63
|
-
#define HUF_STATIC_LINKING_ONLY
|
64
66
|
#include "../common/huf.h"
|
65
|
-
#include "../common/
|
67
|
+
#include "../common/xxhash.h" /* XXH64_reset, XXH64_update, XXH64_digest, XXH64 */
|
66
68
|
#include "zstd_decompress_internal.h" /* ZSTD_DCtx */
|
67
69
|
#include "zstd_ddict.h" /* ZSTD_DDictDictContent */
|
68
70
|
#include "zstd_decompress_block.h" /* ZSTD_decompressBlock_internal */
|
@@ -72,6 +74,147 @@
|
|
72
74
|
#endif
|
73
75
|
|
74
76
|
|
77
|
+
|
78
|
+
/*************************************
|
79
|
+
* Multiple DDicts Hashset internals *
|
80
|
+
*************************************/
|
81
|
+
|
82
|
+
#define DDICT_HASHSET_MAX_LOAD_FACTOR_COUNT_MULT 4
|
83
|
+
#define DDICT_HASHSET_MAX_LOAD_FACTOR_SIZE_MULT 3 /* These two constants represent SIZE_MULT/COUNT_MULT load factor without using a float.
|
84
|
+
* Currently, that means a 0.75 load factor.
|
85
|
+
* So, if count * COUNT_MULT / size * SIZE_MULT != 0, then we've exceeded
|
86
|
+
* the load factor of the ddict hash set.
|
87
|
+
*/
|
88
|
+
|
89
|
+
#define DDICT_HASHSET_TABLE_BASE_SIZE 64
|
90
|
+
#define DDICT_HASHSET_RESIZE_FACTOR 2
|
91
|
+
|
92
|
+
/* Hash function to determine starting position of dict insertion within the table
|
93
|
+
* Returns an index between [0, hashSet->ddictPtrTableSize]
|
94
|
+
*/
|
95
|
+
static size_t ZSTD_DDictHashSet_getIndex(const ZSTD_DDictHashSet* hashSet, U32 dictID) {
|
96
|
+
const U64 hash = XXH64(&dictID, sizeof(U32), 0);
|
97
|
+
/* DDict ptr table size is a multiple of 2, use size - 1 as mask to get index within [0, hashSet->ddictPtrTableSize) */
|
98
|
+
return hash & (hashSet->ddictPtrTableSize - 1);
|
99
|
+
}
|
100
|
+
|
101
|
+
/* Adds DDict to a hashset without resizing it.
|
102
|
+
* If inserting a DDict with a dictID that already exists in the set, replaces the one in the set.
|
103
|
+
* Returns 0 if successful, or a zstd error code if something went wrong.
|
104
|
+
*/
|
105
|
+
static size_t ZSTD_DDictHashSet_emplaceDDict(ZSTD_DDictHashSet* hashSet, const ZSTD_DDict* ddict) {
|
106
|
+
const U32 dictID = ZSTD_getDictID_fromDDict(ddict);
|
107
|
+
size_t idx = ZSTD_DDictHashSet_getIndex(hashSet, dictID);
|
108
|
+
const size_t idxRangeMask = hashSet->ddictPtrTableSize - 1;
|
109
|
+
RETURN_ERROR_IF(hashSet->ddictPtrCount == hashSet->ddictPtrTableSize, GENERIC, "Hash set is full!");
|
110
|
+
DEBUGLOG(4, "Hashed index: for dictID: %u is %zu", dictID, idx);
|
111
|
+
while (hashSet->ddictPtrTable[idx] != NULL) {
|
112
|
+
/* Replace existing ddict if inserting ddict with same dictID */
|
113
|
+
if (ZSTD_getDictID_fromDDict(hashSet->ddictPtrTable[idx]) == dictID) {
|
114
|
+
DEBUGLOG(4, "DictID already exists, replacing rather than adding");
|
115
|
+
hashSet->ddictPtrTable[idx] = ddict;
|
116
|
+
return 0;
|
117
|
+
}
|
118
|
+
idx &= idxRangeMask;
|
119
|
+
idx++;
|
120
|
+
}
|
121
|
+
DEBUGLOG(4, "Final idx after probing for dictID %u is: %zu", dictID, idx);
|
122
|
+
hashSet->ddictPtrTable[idx] = ddict;
|
123
|
+
hashSet->ddictPtrCount++;
|
124
|
+
return 0;
|
125
|
+
}
|
126
|
+
|
127
|
+
/* Expands hash table by factor of DDICT_HASHSET_RESIZE_FACTOR and
|
128
|
+
* rehashes all values, allocates new table, frees old table.
|
129
|
+
* Returns 0 on success, otherwise a zstd error code.
|
130
|
+
*/
|
131
|
+
static size_t ZSTD_DDictHashSet_expand(ZSTD_DDictHashSet* hashSet, ZSTD_customMem customMem) {
|
132
|
+
size_t newTableSize = hashSet->ddictPtrTableSize * DDICT_HASHSET_RESIZE_FACTOR;
|
133
|
+
const ZSTD_DDict** newTable = (const ZSTD_DDict**)ZSTD_customCalloc(sizeof(ZSTD_DDict*) * newTableSize, customMem);
|
134
|
+
const ZSTD_DDict** oldTable = hashSet->ddictPtrTable;
|
135
|
+
size_t oldTableSize = hashSet->ddictPtrTableSize;
|
136
|
+
size_t i;
|
137
|
+
|
138
|
+
DEBUGLOG(4, "Expanding DDict hash table! Old size: %zu new size: %zu", oldTableSize, newTableSize);
|
139
|
+
RETURN_ERROR_IF(!newTable, memory_allocation, "Expanded hashset allocation failed!");
|
140
|
+
hashSet->ddictPtrTable = newTable;
|
141
|
+
hashSet->ddictPtrTableSize = newTableSize;
|
142
|
+
hashSet->ddictPtrCount = 0;
|
143
|
+
for (i = 0; i < oldTableSize; ++i) {
|
144
|
+
if (oldTable[i] != NULL) {
|
145
|
+
FORWARD_IF_ERROR(ZSTD_DDictHashSet_emplaceDDict(hashSet, oldTable[i]), "");
|
146
|
+
}
|
147
|
+
}
|
148
|
+
ZSTD_customFree((void*)oldTable, customMem);
|
149
|
+
DEBUGLOG(4, "Finished re-hash");
|
150
|
+
return 0;
|
151
|
+
}
|
152
|
+
|
153
|
+
/* Fetches a DDict with the given dictID
|
154
|
+
* Returns the ZSTD_DDict* with the requested dictID. If it doesn't exist, then returns NULL.
|
155
|
+
*/
|
156
|
+
static const ZSTD_DDict* ZSTD_DDictHashSet_getDDict(ZSTD_DDictHashSet* hashSet, U32 dictID) {
|
157
|
+
size_t idx = ZSTD_DDictHashSet_getIndex(hashSet, dictID);
|
158
|
+
const size_t idxRangeMask = hashSet->ddictPtrTableSize - 1;
|
159
|
+
DEBUGLOG(4, "Hashed index: for dictID: %u is %zu", dictID, idx);
|
160
|
+
for (;;) {
|
161
|
+
size_t currDictID = ZSTD_getDictID_fromDDict(hashSet->ddictPtrTable[idx]);
|
162
|
+
if (currDictID == dictID || currDictID == 0) {
|
163
|
+
/* currDictID == 0 implies a NULL ddict entry */
|
164
|
+
break;
|
165
|
+
} else {
|
166
|
+
idx &= idxRangeMask; /* Goes to start of table when we reach the end */
|
167
|
+
idx++;
|
168
|
+
}
|
169
|
+
}
|
170
|
+
DEBUGLOG(4, "Final idx after probing for dictID %u is: %zu", dictID, idx);
|
171
|
+
return hashSet->ddictPtrTable[idx];
|
172
|
+
}
|
173
|
+
|
174
|
+
/* Allocates space for and returns a ddict hash set
|
175
|
+
* The hash set's ZSTD_DDict* table has all values automatically set to NULL to begin with.
|
176
|
+
* Returns NULL if allocation failed.
|
177
|
+
*/
|
178
|
+
static ZSTD_DDictHashSet* ZSTD_createDDictHashSet(ZSTD_customMem customMem) {
|
179
|
+
ZSTD_DDictHashSet* ret = (ZSTD_DDictHashSet*)ZSTD_customMalloc(sizeof(ZSTD_DDictHashSet), customMem);
|
180
|
+
DEBUGLOG(4, "Allocating new hash set");
|
181
|
+
if (!ret)
|
182
|
+
return NULL;
|
183
|
+
ret->ddictPtrTable = (const ZSTD_DDict**)ZSTD_customCalloc(DDICT_HASHSET_TABLE_BASE_SIZE * sizeof(ZSTD_DDict*), customMem);
|
184
|
+
if (!ret->ddictPtrTable) {
|
185
|
+
ZSTD_customFree(ret, customMem);
|
186
|
+
return NULL;
|
187
|
+
}
|
188
|
+
ret->ddictPtrTableSize = DDICT_HASHSET_TABLE_BASE_SIZE;
|
189
|
+
ret->ddictPtrCount = 0;
|
190
|
+
return ret;
|
191
|
+
}
|
192
|
+
|
193
|
+
/* Frees the table of ZSTD_DDict* within a hashset, then frees the hashset itself.
|
194
|
+
* Note: The ZSTD_DDict* within the table are NOT freed.
|
195
|
+
*/
|
196
|
+
static void ZSTD_freeDDictHashSet(ZSTD_DDictHashSet* hashSet, ZSTD_customMem customMem) {
|
197
|
+
DEBUGLOG(4, "Freeing ddict hash set");
|
198
|
+
if (hashSet && hashSet->ddictPtrTable) {
|
199
|
+
ZSTD_customFree((void*)hashSet->ddictPtrTable, customMem);
|
200
|
+
}
|
201
|
+
if (hashSet) {
|
202
|
+
ZSTD_customFree(hashSet, customMem);
|
203
|
+
}
|
204
|
+
}
|
205
|
+
|
206
|
+
/* Public function: Adds a DDict into the ZSTD_DDictHashSet, possibly triggering a resize of the hash set.
|
207
|
+
* Returns 0 on success, or a ZSTD error.
|
208
|
+
*/
|
209
|
+
static size_t ZSTD_DDictHashSet_addDDict(ZSTD_DDictHashSet* hashSet, const ZSTD_DDict* ddict, ZSTD_customMem customMem) {
|
210
|
+
DEBUGLOG(4, "Adding dict ID: %u to hashset with - Count: %zu Tablesize: %zu", ZSTD_getDictID_fromDDict(ddict), hashSet->ddictPtrCount, hashSet->ddictPtrTableSize);
|
211
|
+
if (hashSet->ddictPtrCount * DDICT_HASHSET_MAX_LOAD_FACTOR_COUNT_MULT / hashSet->ddictPtrTableSize * DDICT_HASHSET_MAX_LOAD_FACTOR_SIZE_MULT != 0) {
|
212
|
+
FORWARD_IF_ERROR(ZSTD_DDictHashSet_expand(hashSet, customMem), "");
|
213
|
+
}
|
214
|
+
FORWARD_IF_ERROR(ZSTD_DDictHashSet_emplaceDDict(hashSet, ddict), "");
|
215
|
+
return 0;
|
216
|
+
}
|
217
|
+
|
75
218
|
/*-*************************************************************
|
76
219
|
* Context management
|
77
220
|
***************************************************************/
|
@@ -101,6 +244,9 @@ static void ZSTD_DCtx_resetParameters(ZSTD_DCtx* dctx)
|
|
101
244
|
dctx->maxWindowSize = ZSTD_MAXWINDOWSIZE_DEFAULT;
|
102
245
|
dctx->outBufferMode = ZSTD_bm_buffered;
|
103
246
|
dctx->forceIgnoreChecksum = ZSTD_d_validateChecksum;
|
247
|
+
dctx->refMultipleDDicts = ZSTD_rmd_refSingleDDict;
|
248
|
+
dctx->disableHufAsm = 0;
|
249
|
+
dctx->maxBlockSizeParam = 0;
|
104
250
|
}
|
105
251
|
|
106
252
|
static void ZSTD_initDCtx_internal(ZSTD_DCtx* dctx)
|
@@ -115,13 +261,18 @@ static void ZSTD_initDCtx_internal(ZSTD_DCtx* dctx)
|
|
115
261
|
dctx->inBuffSize = 0;
|
116
262
|
dctx->outBuffSize = 0;
|
117
263
|
dctx->streamStage = zdss_init;
|
264
|
+
#if defined(ZSTD_LEGACY_SUPPORT) && (ZSTD_LEGACY_SUPPORT>=1)
|
118
265
|
dctx->legacyContext = NULL;
|
119
266
|
dctx->previousLegacyVersion = 0;
|
267
|
+
#endif
|
120
268
|
dctx->noForwardProgress = 0;
|
121
269
|
dctx->oversizedDuration = 0;
|
122
|
-
dctx->
|
270
|
+
dctx->isFrameDecompression = 1;
|
271
|
+
#if DYNAMIC_BMI2
|
272
|
+
dctx->bmi2 = ZSTD_cpuSupportsBmi2();
|
273
|
+
#endif
|
274
|
+
dctx->ddictSet = NULL;
|
123
275
|
ZSTD_DCtx_resetParameters(dctx);
|
124
|
-
dctx->validateChecksum = 1;
|
125
276
|
#ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
|
126
277
|
dctx->dictContentEndForFuzzing = NULL;
|
127
278
|
#endif
|
@@ -140,8 +291,7 @@ ZSTD_DCtx* ZSTD_initStaticDCtx(void *workspace, size_t workspaceSize)
|
|
140
291
|
return dctx;
|
141
292
|
}
|
142
293
|
|
143
|
-
ZSTD_DCtx*
|
144
|
-
{
|
294
|
+
static ZSTD_DCtx* ZSTD_createDCtx_internal(ZSTD_customMem customMem) {
|
145
295
|
if ((!customMem.customAlloc) ^ (!customMem.customFree)) return NULL;
|
146
296
|
|
147
297
|
{ ZSTD_DCtx* const dctx = (ZSTD_DCtx*)ZSTD_customMalloc(sizeof(*dctx), customMem);
|
@@ -152,10 +302,15 @@ ZSTD_DCtx* ZSTD_createDCtx_advanced(ZSTD_customMem customMem)
|
|
152
302
|
}
|
153
303
|
}
|
154
304
|
|
305
|
+
ZSTD_DCtx* ZSTD_createDCtx_advanced(ZSTD_customMem customMem)
|
306
|
+
{
|
307
|
+
return ZSTD_createDCtx_internal(customMem);
|
308
|
+
}
|
309
|
+
|
155
310
|
ZSTD_DCtx* ZSTD_createDCtx(void)
|
156
311
|
{
|
157
312
|
DEBUGLOG(3, "ZSTD_createDCtx");
|
158
|
-
return
|
313
|
+
return ZSTD_createDCtx_internal(ZSTD_defaultCMem);
|
159
314
|
}
|
160
315
|
|
161
316
|
static void ZSTD_clearDict(ZSTD_DCtx* dctx)
|
@@ -178,6 +333,10 @@ size_t ZSTD_freeDCtx(ZSTD_DCtx* dctx)
|
|
178
333
|
if (dctx->legacyContext)
|
179
334
|
ZSTD_freeLegacyStreamContext(dctx->legacyContext, dctx->previousLegacyVersion);
|
180
335
|
#endif
|
336
|
+
if (dctx->ddictSet) {
|
337
|
+
ZSTD_freeDDictHashSet(dctx->ddictSet, cMem);
|
338
|
+
dctx->ddictSet = NULL;
|
339
|
+
}
|
181
340
|
ZSTD_customFree(dctx, cMem);
|
182
341
|
return 0;
|
183
342
|
}
|
@@ -190,6 +349,29 @@ void ZSTD_copyDCtx(ZSTD_DCtx* dstDCtx, const ZSTD_DCtx* srcDCtx)
|
|
190
349
|
ZSTD_memcpy(dstDCtx, srcDCtx, toCopy); /* no need to copy workspace */
|
191
350
|
}
|
192
351
|
|
352
|
+
/* Given a dctx with a digested frame params, re-selects the correct ZSTD_DDict based on
|
353
|
+
* the requested dict ID from the frame. If there exists a reference to the correct ZSTD_DDict, then
|
354
|
+
* accordingly sets the ddict to be used to decompress the frame.
|
355
|
+
*
|
356
|
+
* If no DDict is found, then no action is taken, and the ZSTD_DCtx::ddict remains as-is.
|
357
|
+
*
|
358
|
+
* ZSTD_d_refMultipleDDicts must be enabled for this function to be called.
|
359
|
+
*/
|
360
|
+
static void ZSTD_DCtx_selectFrameDDict(ZSTD_DCtx* dctx) {
|
361
|
+
assert(dctx->refMultipleDDicts && dctx->ddictSet);
|
362
|
+
DEBUGLOG(4, "Adjusting DDict based on requested dict ID from frame");
|
363
|
+
if (dctx->ddict) {
|
364
|
+
const ZSTD_DDict* frameDDict = ZSTD_DDictHashSet_getDDict(dctx->ddictSet, dctx->fParams.dictID);
|
365
|
+
if (frameDDict) {
|
366
|
+
DEBUGLOG(4, "DDict found!");
|
367
|
+
ZSTD_clearDict(dctx);
|
368
|
+
dctx->dictID = dctx->fParams.dictID;
|
369
|
+
dctx->ddict = frameDDict;
|
370
|
+
dctx->dictUses = ZSTD_use_indefinitely;
|
371
|
+
}
|
372
|
+
}
|
373
|
+
}
|
374
|
+
|
193
375
|
|
194
376
|
/*-*************************************************************
|
195
377
|
* Frame header decoding
|
@@ -213,6 +395,19 @@ unsigned ZSTD_isFrame(const void* buffer, size_t size)
|
|
213
395
|
return 0;
|
214
396
|
}
|
215
397
|
|
398
|
+
/*! ZSTD_isSkippableFrame() :
|
399
|
+
* Tells if the content of `buffer` starts with a valid Frame Identifier for a skippable frame.
|
400
|
+
* Note : Frame Identifier is 4 bytes. If `size < 4`, @return will always be 0.
|
401
|
+
*/
|
402
|
+
unsigned ZSTD_isSkippableFrame(const void* buffer, size_t size)
|
403
|
+
{
|
404
|
+
if (size < ZSTD_FRAMEIDSIZE) return 0;
|
405
|
+
{ U32 const magic = MEM_readLE32(buffer);
|
406
|
+
if ((magic & ZSTD_MAGIC_SKIPPABLE_MASK) == ZSTD_MAGIC_SKIPPABLE_START) return 1;
|
407
|
+
}
|
408
|
+
return 0;
|
409
|
+
}
|
410
|
+
|
216
411
|
/** ZSTD_frameHeaderSize_internal() :
|
217
412
|
* srcSize must be large enough to reach header size fields.
|
218
413
|
* note : only works for formats ZSTD_f_zstd1 and ZSTD_f_zstd1_magicless.
|
@@ -248,16 +443,40 @@ size_t ZSTD_frameHeaderSize(const void* src, size_t srcSize)
|
|
248
443
|
* note : only works for formats ZSTD_f_zstd1 and ZSTD_f_zstd1_magicless
|
249
444
|
* @return : 0, `zfhPtr` is correctly filled,
|
250
445
|
* >0, `srcSize` is too small, value is wanted `srcSize` amount,
|
251
|
-
|
446
|
+
** or an error code, which can be tested using ZSTD_isError() */
|
252
447
|
size_t ZSTD_getFrameHeader_advanced(ZSTD_frameHeader* zfhPtr, const void* src, size_t srcSize, ZSTD_format_e format)
|
253
448
|
{
|
254
449
|
const BYTE* ip = (const BYTE*)src;
|
255
450
|
size_t const minInputSize = ZSTD_startingInputLength(format);
|
256
451
|
|
257
|
-
|
258
|
-
|
259
|
-
|
452
|
+
DEBUGLOG(5, "ZSTD_getFrameHeader_advanced: minInputSize = %zu, srcSize = %zu", minInputSize, srcSize);
|
453
|
+
|
454
|
+
if (srcSize > 0) {
|
455
|
+
/* note : technically could be considered an assert(), since it's an invalid entry */
|
456
|
+
RETURN_ERROR_IF(src==NULL, GENERIC, "invalid parameter : src==NULL, but srcSize>0");
|
457
|
+
}
|
458
|
+
if (srcSize < minInputSize) {
|
459
|
+
if (srcSize > 0 && format != ZSTD_f_zstd1_magicless) {
|
460
|
+
/* when receiving less than @minInputSize bytes,
|
461
|
+
* control these bytes at least correspond to a supported magic number
|
462
|
+
* in order to error out early if they don't.
|
463
|
+
**/
|
464
|
+
size_t const toCopy = MIN(4, srcSize);
|
465
|
+
unsigned char hbuf[4]; MEM_writeLE32(hbuf, ZSTD_MAGICNUMBER);
|
466
|
+
assert(src != NULL);
|
467
|
+
ZSTD_memcpy(hbuf, src, toCopy);
|
468
|
+
if ( MEM_readLE32(hbuf) != ZSTD_MAGICNUMBER ) {
|
469
|
+
/* not a zstd frame : let's check if it's a skippable frame */
|
470
|
+
MEM_writeLE32(hbuf, ZSTD_MAGIC_SKIPPABLE_START);
|
471
|
+
ZSTD_memcpy(hbuf, src, toCopy);
|
472
|
+
if ((MEM_readLE32(hbuf) & ZSTD_MAGIC_SKIPPABLE_MASK) != ZSTD_MAGIC_SKIPPABLE_START) {
|
473
|
+
RETURN_ERROR(prefix_unknown,
|
474
|
+
"first bytes don't correspond to any supported magic number");
|
475
|
+
} } }
|
476
|
+
return minInputSize;
|
477
|
+
}
|
260
478
|
|
479
|
+
ZSTD_memset(zfhPtr, 0, sizeof(*zfhPtr)); /* not strictly necessary, but static analyzers may not understand that zfhPtr will be read only if return value is zero, since they are 2 different signals */
|
261
480
|
if ( (format != ZSTD_f_zstd1_magicless)
|
262
481
|
&& (MEM_readLE32(src) != ZSTD_MAGICNUMBER) ) {
|
263
482
|
if ((MEM_readLE32(src) & ZSTD_MAGIC_SKIPPABLE_MASK) == ZSTD_MAGIC_SKIPPABLE_START) {
|
@@ -299,7 +518,9 @@ size_t ZSTD_getFrameHeader_advanced(ZSTD_frameHeader* zfhPtr, const void* src, s
|
|
299
518
|
}
|
300
519
|
switch(dictIDSizeCode)
|
301
520
|
{
|
302
|
-
default:
|
521
|
+
default:
|
522
|
+
assert(0); /* impossible */
|
523
|
+
ZSTD_FALLTHROUGH;
|
303
524
|
case 0 : break;
|
304
525
|
case 1 : dictID = ip[pos]; pos++; break;
|
305
526
|
case 2 : dictID = MEM_readLE16(ip+pos); pos+=2; break;
|
@@ -307,7 +528,9 @@ size_t ZSTD_getFrameHeader_advanced(ZSTD_frameHeader* zfhPtr, const void* src, s
|
|
307
528
|
}
|
308
529
|
switch(fcsID)
|
309
530
|
{
|
310
|
-
default:
|
531
|
+
default:
|
532
|
+
assert(0); /* impossible */
|
533
|
+
ZSTD_FALLTHROUGH;
|
311
534
|
case 0 : if (singleSegment) frameContentSize = ip[pos]; break;
|
312
535
|
case 1 : frameContentSize = MEM_readLE16(ip+pos)+256; break;
|
313
536
|
case 2 : frameContentSize = MEM_readLE32(ip+pos); break;
|
@@ -336,7 +559,6 @@ size_t ZSTD_getFrameHeader(ZSTD_frameHeader* zfhPtr, const void* src, size_t src
|
|
336
559
|
return ZSTD_getFrameHeader_advanced(zfhPtr, src, srcSize, ZSTD_f_zstd1);
|
337
560
|
}
|
338
561
|
|
339
|
-
|
340
562
|
/** ZSTD_getFrameContentSize() :
|
341
563
|
* compatible with legacy mode
|
342
564
|
* @return : decompressed size of the single frame pointed to be `src` if known, otherwise
|
@@ -370,18 +592,52 @@ static size_t readSkippableFrameSize(void const* src, size_t srcSize)
|
|
370
592
|
sizeU32 = MEM_readLE32((BYTE const*)src + ZSTD_FRAMEIDSIZE);
|
371
593
|
RETURN_ERROR_IF((U32)(sizeU32 + ZSTD_SKIPPABLEHEADERSIZE) < sizeU32,
|
372
594
|
frameParameter_unsupported, "");
|
373
|
-
{
|
374
|
-
size_t const skippableSize = skippableHeaderSize + sizeU32;
|
595
|
+
{ size_t const skippableSize = skippableHeaderSize + sizeU32;
|
375
596
|
RETURN_ERROR_IF(skippableSize > srcSize, srcSize_wrong, "");
|
376
597
|
return skippableSize;
|
377
598
|
}
|
378
599
|
}
|
379
600
|
|
601
|
+
/*! ZSTD_readSkippableFrame() :
|
602
|
+
* Retrieves content of a skippable frame, and writes it to dst buffer.
|
603
|
+
*
|
604
|
+
* The parameter magicVariant will receive the magicVariant that was supplied when the frame was written,
|
605
|
+
* i.e. magicNumber - ZSTD_MAGIC_SKIPPABLE_START. This can be NULL if the caller is not interested
|
606
|
+
* in the magicVariant.
|
607
|
+
*
|
608
|
+
* Returns an error if destination buffer is not large enough, or if this is not a valid skippable frame.
|
609
|
+
*
|
610
|
+
* @return : number of bytes written or a ZSTD error.
|
611
|
+
*/
|
612
|
+
size_t ZSTD_readSkippableFrame(void* dst, size_t dstCapacity,
|
613
|
+
unsigned* magicVariant, /* optional, can be NULL */
|
614
|
+
const void* src, size_t srcSize)
|
615
|
+
{
|
616
|
+
RETURN_ERROR_IF(srcSize < ZSTD_SKIPPABLEHEADERSIZE, srcSize_wrong, "");
|
617
|
+
|
618
|
+
{ U32 const magicNumber = MEM_readLE32(src);
|
619
|
+
size_t skippableFrameSize = readSkippableFrameSize(src, srcSize);
|
620
|
+
size_t skippableContentSize = skippableFrameSize - ZSTD_SKIPPABLEHEADERSIZE;
|
621
|
+
|
622
|
+
/* check input validity */
|
623
|
+
RETURN_ERROR_IF(!ZSTD_isSkippableFrame(src, srcSize), frameParameter_unsupported, "");
|
624
|
+
RETURN_ERROR_IF(skippableFrameSize < ZSTD_SKIPPABLEHEADERSIZE || skippableFrameSize > srcSize, srcSize_wrong, "");
|
625
|
+
RETURN_ERROR_IF(skippableContentSize > dstCapacity, dstSize_tooSmall, "");
|
626
|
+
|
627
|
+
/* deliver payload */
|
628
|
+
if (skippableContentSize > 0 && dst != NULL)
|
629
|
+
ZSTD_memcpy(dst, (const BYTE *)src + ZSTD_SKIPPABLEHEADERSIZE, skippableContentSize);
|
630
|
+
if (magicVariant != NULL)
|
631
|
+
*magicVariant = magicNumber - ZSTD_MAGIC_SKIPPABLE_START;
|
632
|
+
return skippableContentSize;
|
633
|
+
}
|
634
|
+
}
|
635
|
+
|
380
636
|
/** ZSTD_findDecompressedSize() :
|
381
|
-
* compatible with legacy mode
|
382
637
|
* `srcSize` must be the exact length of some number of ZSTD compressed and/or
|
383
638
|
* skippable frames
|
384
|
-
*
|
639
|
+
* note: compatible with legacy mode
|
640
|
+
* @return : decompressed size of the frames contained */
|
385
641
|
unsigned long long ZSTD_findDecompressedSize(const void* src, size_t srcSize)
|
386
642
|
{
|
387
643
|
unsigned long long totalDstSize = 0;
|
@@ -391,9 +647,7 @@ unsigned long long ZSTD_findDecompressedSize(const void* src, size_t srcSize)
|
|
391
647
|
|
392
648
|
if ((magicNumber & ZSTD_MAGIC_SKIPPABLE_MASK) == ZSTD_MAGIC_SKIPPABLE_START) {
|
393
649
|
size_t const skippableSize = readSkippableFrameSize(src, srcSize);
|
394
|
-
if (ZSTD_isError(skippableSize))
|
395
|
-
return ZSTD_CONTENTSIZE_ERROR;
|
396
|
-
}
|
650
|
+
if (ZSTD_isError(skippableSize)) return ZSTD_CONTENTSIZE_ERROR;
|
397
651
|
assert(skippableSize <= srcSize);
|
398
652
|
|
399
653
|
src = (const BYTE *)src + skippableSize;
|
@@ -401,17 +655,17 @@ unsigned long long ZSTD_findDecompressedSize(const void* src, size_t srcSize)
|
|
401
655
|
continue;
|
402
656
|
}
|
403
657
|
|
404
|
-
{ unsigned long long const
|
405
|
-
if (
|
658
|
+
{ unsigned long long const fcs = ZSTD_getFrameContentSize(src, srcSize);
|
659
|
+
if (fcs >= ZSTD_CONTENTSIZE_ERROR) return fcs;
|
406
660
|
|
407
|
-
|
408
|
-
|
409
|
-
totalDstSize +=
|
661
|
+
if (totalDstSize + fcs < totalDstSize)
|
662
|
+
return ZSTD_CONTENTSIZE_ERROR; /* check for overflow */
|
663
|
+
totalDstSize += fcs;
|
410
664
|
}
|
665
|
+
/* skip to next frame */
|
411
666
|
{ size_t const frameSrcSize = ZSTD_findFrameCompressedSize(src, srcSize);
|
412
|
-
if (ZSTD_isError(frameSrcSize))
|
413
|
-
|
414
|
-
}
|
667
|
+
if (ZSTD_isError(frameSrcSize)) return ZSTD_CONTENTSIZE_ERROR;
|
668
|
+
assert(frameSrcSize <= srcSize);
|
415
669
|
|
416
670
|
src = (const BYTE *)src + frameSrcSize;
|
417
671
|
srcSize -= frameSrcSize;
|
@@ -441,12 +695,19 @@ unsigned long long ZSTD_getDecompressedSize(const void* src, size_t srcSize)
|
|
441
695
|
|
442
696
|
/** ZSTD_decodeFrameHeader() :
|
443
697
|
* `headerSize` must be the size provided by ZSTD_frameHeaderSize().
|
698
|
+
* If multiple DDict references are enabled, also will choose the correct DDict to use.
|
444
699
|
* @return : 0 if success, or an error code, which can be tested using ZSTD_isError() */
|
445
700
|
static size_t ZSTD_decodeFrameHeader(ZSTD_DCtx* dctx, const void* src, size_t headerSize)
|
446
701
|
{
|
447
702
|
size_t const result = ZSTD_getFrameHeader_advanced(&(dctx->fParams), src, headerSize, dctx->format);
|
448
703
|
if (ZSTD_isError(result)) return result; /* invalid header */
|
449
704
|
RETURN_ERROR_IF(result>0, srcSize_wrong, "headerSize too small");
|
705
|
+
|
706
|
+
/* Reference DDict requested by frame if dctx references multiple ddicts */
|
707
|
+
if (dctx->refMultipleDDicts == ZSTD_rmd_refMultipleDDicts && dctx->ddictSet) {
|
708
|
+
ZSTD_DCtx_selectFrameDDict(dctx);
|
709
|
+
}
|
710
|
+
|
450
711
|
#ifndef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
|
451
712
|
/* Skip the dictID check in fuzzing mode, because it makes the search
|
452
713
|
* harder.
|
@@ -456,6 +717,7 @@ static size_t ZSTD_decodeFrameHeader(ZSTD_DCtx* dctx, const void* src, size_t he
|
|
456
717
|
#endif
|
457
718
|
dctx->validateChecksum = (dctx->fParams.checksumFlag && !dctx->forceIgnoreChecksum) ? 1 : 0;
|
458
719
|
if (dctx->validateChecksum) XXH64_reset(&dctx->xxhState, 0);
|
720
|
+
dctx->processedCSize += headerSize;
|
459
721
|
return 0;
|
460
722
|
}
|
461
723
|
|
@@ -467,17 +729,17 @@ static ZSTD_frameSizeInfo ZSTD_errorFrameSizeInfo(size_t ret)
|
|
467
729
|
return frameSizeInfo;
|
468
730
|
}
|
469
731
|
|
470
|
-
static ZSTD_frameSizeInfo ZSTD_findFrameSizeInfo(const void* src, size_t srcSize)
|
732
|
+
static ZSTD_frameSizeInfo ZSTD_findFrameSizeInfo(const void* src, size_t srcSize, ZSTD_format_e format)
|
471
733
|
{
|
472
734
|
ZSTD_frameSizeInfo frameSizeInfo;
|
473
735
|
ZSTD_memset(&frameSizeInfo, 0, sizeof(ZSTD_frameSizeInfo));
|
474
736
|
|
475
737
|
#if defined(ZSTD_LEGACY_SUPPORT) && (ZSTD_LEGACY_SUPPORT >= 1)
|
476
|
-
if (ZSTD_isLegacy(src, srcSize))
|
738
|
+
if (format == ZSTD_f_zstd1 && ZSTD_isLegacy(src, srcSize))
|
477
739
|
return ZSTD_findFrameSizeInfoLegacy(src, srcSize);
|
478
740
|
#endif
|
479
741
|
|
480
|
-
if ((srcSize >= ZSTD_SKIPPABLEHEADERSIZE)
|
742
|
+
if (format == ZSTD_f_zstd1 && (srcSize >= ZSTD_SKIPPABLEHEADERSIZE)
|
481
743
|
&& (MEM_readLE32(src) & ZSTD_MAGIC_SKIPPABLE_MASK) == ZSTD_MAGIC_SKIPPABLE_START) {
|
482
744
|
frameSizeInfo.compressedSize = readSkippableFrameSize(src, srcSize);
|
483
745
|
assert(ZSTD_isError(frameSizeInfo.compressedSize) ||
|
@@ -491,7 +753,7 @@ static ZSTD_frameSizeInfo ZSTD_findFrameSizeInfo(const void* src, size_t srcSize
|
|
491
753
|
ZSTD_frameHeader zfh;
|
492
754
|
|
493
755
|
/* Extract Frame Header */
|
494
|
-
{ size_t const ret =
|
756
|
+
{ size_t const ret = ZSTD_getFrameHeader_advanced(&zfh, src, srcSize, format);
|
495
757
|
if (ZSTD_isError(ret))
|
496
758
|
return ZSTD_errorFrameSizeInfo(ret);
|
497
759
|
if (ret > 0)
|
@@ -525,23 +787,26 @@ static ZSTD_frameSizeInfo ZSTD_findFrameSizeInfo(const void* src, size_t srcSize
|
|
525
787
|
ip += 4;
|
526
788
|
}
|
527
789
|
|
790
|
+
frameSizeInfo.nbBlocks = nbBlocks;
|
528
791
|
frameSizeInfo.compressedSize = (size_t)(ip - ipstart);
|
529
792
|
frameSizeInfo.decompressedBound = (zfh.frameContentSize != ZSTD_CONTENTSIZE_UNKNOWN)
|
530
793
|
? zfh.frameContentSize
|
531
|
-
: nbBlocks * zfh.blockSizeMax;
|
794
|
+
: (unsigned long long)nbBlocks * zfh.blockSizeMax;
|
532
795
|
return frameSizeInfo;
|
533
796
|
}
|
534
797
|
}
|
535
798
|
|
799
|
+
static size_t ZSTD_findFrameCompressedSize_advanced(const void *src, size_t srcSize, ZSTD_format_e format) {
|
800
|
+
ZSTD_frameSizeInfo const frameSizeInfo = ZSTD_findFrameSizeInfo(src, srcSize, format);
|
801
|
+
return frameSizeInfo.compressedSize;
|
802
|
+
}
|
803
|
+
|
536
804
|
/** ZSTD_findFrameCompressedSize() :
|
537
|
-
*
|
538
|
-
*
|
539
|
-
* `srcSize` must be at least as large as the frame contained
|
540
|
-
* @return : the compressed size of the frame starting at `src` */
|
805
|
+
* See docs in zstd.h
|
806
|
+
* Note: compatible with legacy mode */
|
541
807
|
size_t ZSTD_findFrameCompressedSize(const void *src, size_t srcSize)
|
542
808
|
{
|
543
|
-
|
544
|
-
return frameSizeInfo.compressedSize;
|
809
|
+
return ZSTD_findFrameCompressedSize_advanced(src, srcSize, ZSTD_f_zstd1);
|
545
810
|
}
|
546
811
|
|
547
812
|
/** ZSTD_decompressBound() :
|
@@ -555,7 +820,7 @@ unsigned long long ZSTD_decompressBound(const void* src, size_t srcSize)
|
|
555
820
|
unsigned long long bound = 0;
|
556
821
|
/* Iterate over each frame */
|
557
822
|
while (srcSize > 0) {
|
558
|
-
ZSTD_frameSizeInfo const frameSizeInfo = ZSTD_findFrameSizeInfo(src, srcSize);
|
823
|
+
ZSTD_frameSizeInfo const frameSizeInfo = ZSTD_findFrameSizeInfo(src, srcSize, ZSTD_f_zstd1);
|
559
824
|
size_t const compressedSize = frameSizeInfo.compressedSize;
|
560
825
|
unsigned long long const decompressedBound = frameSizeInfo.decompressedBound;
|
561
826
|
if (ZSTD_isError(compressedSize) || decompressedBound == ZSTD_CONTENTSIZE_ERROR)
|
@@ -568,6 +833,48 @@ unsigned long long ZSTD_decompressBound(const void* src, size_t srcSize)
|
|
568
833
|
return bound;
|
569
834
|
}
|
570
835
|
|
836
|
+
size_t ZSTD_decompressionMargin(void const* src, size_t srcSize)
|
837
|
+
{
|
838
|
+
size_t margin = 0;
|
839
|
+
unsigned maxBlockSize = 0;
|
840
|
+
|
841
|
+
/* Iterate over each frame */
|
842
|
+
while (srcSize > 0) {
|
843
|
+
ZSTD_frameSizeInfo const frameSizeInfo = ZSTD_findFrameSizeInfo(src, srcSize, ZSTD_f_zstd1);
|
844
|
+
size_t const compressedSize = frameSizeInfo.compressedSize;
|
845
|
+
unsigned long long const decompressedBound = frameSizeInfo.decompressedBound;
|
846
|
+
ZSTD_frameHeader zfh;
|
847
|
+
|
848
|
+
FORWARD_IF_ERROR(ZSTD_getFrameHeader(&zfh, src, srcSize), "");
|
849
|
+
if (ZSTD_isError(compressedSize) || decompressedBound == ZSTD_CONTENTSIZE_ERROR)
|
850
|
+
return ERROR(corruption_detected);
|
851
|
+
|
852
|
+
if (zfh.frameType == ZSTD_frame) {
|
853
|
+
/* Add the frame header to our margin */
|
854
|
+
margin += zfh.headerSize;
|
855
|
+
/* Add the checksum to our margin */
|
856
|
+
margin += zfh.checksumFlag ? 4 : 0;
|
857
|
+
/* Add 3 bytes per block */
|
858
|
+
margin += 3 * frameSizeInfo.nbBlocks;
|
859
|
+
|
860
|
+
/* Compute the max block size */
|
861
|
+
maxBlockSize = MAX(maxBlockSize, zfh.blockSizeMax);
|
862
|
+
} else {
|
863
|
+
assert(zfh.frameType == ZSTD_skippableFrame);
|
864
|
+
/* Add the entire skippable frame size to our margin. */
|
865
|
+
margin += compressedSize;
|
866
|
+
}
|
867
|
+
|
868
|
+
assert(srcSize >= compressedSize);
|
869
|
+
src = (const BYTE*)src + compressedSize;
|
870
|
+
srcSize -= compressedSize;
|
871
|
+
}
|
872
|
+
|
873
|
+
/* Add the max block size back to the margin. */
|
874
|
+
margin += maxBlockSize;
|
875
|
+
|
876
|
+
return margin;
|
877
|
+
}
|
571
878
|
|
572
879
|
/*-*************************************************************
|
573
880
|
* Frame decoding
|
@@ -578,7 +885,7 @@ unsigned long long ZSTD_decompressBound(const void* src, size_t srcSize)
|
|
578
885
|
size_t ZSTD_insertBlock(ZSTD_DCtx* dctx, const void* blockStart, size_t blockSize)
|
579
886
|
{
|
580
887
|
DEBUGLOG(5, "ZSTD_insertBlock: %u bytes", (unsigned)blockSize);
|
581
|
-
ZSTD_checkContinuity(dctx, blockStart);
|
888
|
+
ZSTD_checkContinuity(dctx, blockStart, blockSize);
|
582
889
|
dctx->previousDstEnd = (const char*)blockStart + blockSize;
|
583
890
|
return blockSize;
|
584
891
|
}
|
@@ -593,7 +900,7 @@ static size_t ZSTD_copyRawBlock(void* dst, size_t dstCapacity,
|
|
593
900
|
if (srcSize == 0) return 0;
|
594
901
|
RETURN_ERROR(dstBuffer_null, "");
|
595
902
|
}
|
596
|
-
|
903
|
+
ZSTD_memmove(dst, src, srcSize);
|
597
904
|
return srcSize;
|
598
905
|
}
|
599
906
|
|
@@ -610,6 +917,32 @@ static size_t ZSTD_setRleBlock(void* dst, size_t dstCapacity,
|
|
610
917
|
return regenSize;
|
611
918
|
}
|
612
919
|
|
920
|
+
static void ZSTD_DCtx_trace_end(ZSTD_DCtx const* dctx, U64 uncompressedSize, U64 compressedSize, unsigned streaming)
|
921
|
+
{
|
922
|
+
#if ZSTD_TRACE
|
923
|
+
if (dctx->traceCtx && ZSTD_trace_decompress_end != NULL) {
|
924
|
+
ZSTD_Trace trace;
|
925
|
+
ZSTD_memset(&trace, 0, sizeof(trace));
|
926
|
+
trace.version = ZSTD_VERSION_NUMBER;
|
927
|
+
trace.streaming = streaming;
|
928
|
+
if (dctx->ddict) {
|
929
|
+
trace.dictionaryID = ZSTD_getDictID_fromDDict(dctx->ddict);
|
930
|
+
trace.dictionarySize = ZSTD_DDict_dictSize(dctx->ddict);
|
931
|
+
trace.dictionaryIsCold = dctx->ddictIsCold;
|
932
|
+
}
|
933
|
+
trace.uncompressedSize = (size_t)uncompressedSize;
|
934
|
+
trace.compressedSize = (size_t)compressedSize;
|
935
|
+
trace.dctx = dctx;
|
936
|
+
ZSTD_trace_decompress_end(dctx->traceCtx, &trace);
|
937
|
+
}
|
938
|
+
#else
|
939
|
+
(void)dctx;
|
940
|
+
(void)uncompressedSize;
|
941
|
+
(void)compressedSize;
|
942
|
+
(void)streaming;
|
943
|
+
#endif
|
944
|
+
}
|
945
|
+
|
613
946
|
|
614
947
|
/*! ZSTD_decompressFrame() :
|
615
948
|
* @dctx must be properly initialized
|
@@ -619,8 +952,9 @@ static size_t ZSTD_decompressFrame(ZSTD_DCtx* dctx,
|
|
619
952
|
void* dst, size_t dstCapacity,
|
620
953
|
const void** srcPtr, size_t *srcSizePtr)
|
621
954
|
{
|
622
|
-
const BYTE*
|
623
|
-
BYTE*
|
955
|
+
const BYTE* const istart = (const BYTE*)(*srcPtr);
|
956
|
+
const BYTE* ip = istart;
|
957
|
+
BYTE* const ostart = (BYTE*)dst;
|
624
958
|
BYTE* const oend = dstCapacity != 0 ? ostart + dstCapacity : ostart;
|
625
959
|
BYTE* op = ostart;
|
626
960
|
size_t remainingSrcSize = *srcSizePtr;
|
@@ -642,8 +976,13 @@ static size_t ZSTD_decompressFrame(ZSTD_DCtx* dctx,
|
|
642
976
|
ip += frameHeaderSize; remainingSrcSize -= frameHeaderSize;
|
643
977
|
}
|
644
978
|
|
979
|
+
/* Shrink the blockSizeMax if enabled */
|
980
|
+
if (dctx->maxBlockSizeParam != 0)
|
981
|
+
dctx->fParams.blockSizeMax = MIN(dctx->fParams.blockSizeMax, (unsigned)dctx->maxBlockSizeParam);
|
982
|
+
|
645
983
|
/* Loop on each block */
|
646
984
|
while (1) {
|
985
|
+
BYTE* oBlockEnd = oend;
|
647
986
|
size_t decodedSize;
|
648
987
|
blockProperties_t blockProperties;
|
649
988
|
size_t const cBlockSize = ZSTD_getcBlockSize(ip, remainingSrcSize, &blockProperties);
|
@@ -653,27 +992,48 @@ static size_t ZSTD_decompressFrame(ZSTD_DCtx* dctx,
|
|
653
992
|
remainingSrcSize -= ZSTD_blockHeaderSize;
|
654
993
|
RETURN_ERROR_IF(cBlockSize > remainingSrcSize, srcSize_wrong, "");
|
655
994
|
|
995
|
+
if (ip >= op && ip < oBlockEnd) {
|
996
|
+
/* We are decompressing in-place. Limit the output pointer so that we
|
997
|
+
* don't overwrite the block that we are currently reading. This will
|
998
|
+
* fail decompression if the input & output pointers aren't spaced
|
999
|
+
* far enough apart.
|
1000
|
+
*
|
1001
|
+
* This is important to set, even when the pointers are far enough
|
1002
|
+
* apart, because ZSTD_decompressBlock_internal() can decide to store
|
1003
|
+
* literals in the output buffer, after the block it is decompressing.
|
1004
|
+
* Since we don't want anything to overwrite our input, we have to tell
|
1005
|
+
* ZSTD_decompressBlock_internal to never write past ip.
|
1006
|
+
*
|
1007
|
+
* See ZSTD_allocateLiteralsBuffer() for reference.
|
1008
|
+
*/
|
1009
|
+
oBlockEnd = op + (ip - op);
|
1010
|
+
}
|
1011
|
+
|
656
1012
|
switch(blockProperties.blockType)
|
657
1013
|
{
|
658
1014
|
case bt_compressed:
|
659
|
-
|
1015
|
+
assert(dctx->isFrameDecompression == 1);
|
1016
|
+
decodedSize = ZSTD_decompressBlock_internal(dctx, op, (size_t)(oBlockEnd-op), ip, cBlockSize, not_streaming);
|
660
1017
|
break;
|
661
1018
|
case bt_raw :
|
1019
|
+
/* Use oend instead of oBlockEnd because this function is safe to overlap. It uses memmove. */
|
662
1020
|
decodedSize = ZSTD_copyRawBlock(op, (size_t)(oend-op), ip, cBlockSize);
|
663
1021
|
break;
|
664
1022
|
case bt_rle :
|
665
|
-
decodedSize = ZSTD_setRleBlock(op, (size_t)(
|
1023
|
+
decodedSize = ZSTD_setRleBlock(op, (size_t)(oBlockEnd-op), *ip, blockProperties.origSize);
|
666
1024
|
break;
|
667
1025
|
case bt_reserved :
|
668
1026
|
default:
|
669
1027
|
RETURN_ERROR(corruption_detected, "invalid block type");
|
670
1028
|
}
|
671
|
-
|
672
|
-
|
673
|
-
if (dctx->validateChecksum)
|
1029
|
+
FORWARD_IF_ERROR(decodedSize, "Block decompression failure");
|
1030
|
+
DEBUGLOG(5, "Decompressed block of dSize = %u", (unsigned)decodedSize);
|
1031
|
+
if (dctx->validateChecksum) {
|
674
1032
|
XXH64_update(&dctx->xxhState, op, decodedSize);
|
675
|
-
|
1033
|
+
}
|
1034
|
+
if (decodedSize) /* support dst = NULL,0 */ {
|
676
1035
|
op += decodedSize;
|
1036
|
+
}
|
677
1037
|
assert(ip != NULL);
|
678
1038
|
ip += cBlockSize;
|
679
1039
|
remainingSrcSize -= cBlockSize;
|
@@ -695,14 +1055,17 @@ static size_t ZSTD_decompressFrame(ZSTD_DCtx* dctx,
|
|
695
1055
|
ip += 4;
|
696
1056
|
remainingSrcSize -= 4;
|
697
1057
|
}
|
698
|
-
|
1058
|
+
ZSTD_DCtx_trace_end(dctx, (U64)(op-ostart), (U64)(ip-istart), /* streaming */ 0);
|
699
1059
|
/* Allow caller to get size read */
|
1060
|
+
DEBUGLOG(4, "ZSTD_decompressFrame: decompressed frame of size %zi, consuming %zi bytes of input", op-ostart, ip - (const BYTE*)*srcPtr);
|
700
1061
|
*srcPtr = ip;
|
701
1062
|
*srcSizePtr = remainingSrcSize;
|
702
1063
|
return (size_t)(op-ostart);
|
703
1064
|
}
|
704
1065
|
|
705
|
-
static
|
1066
|
+
static
|
1067
|
+
ZSTD_ALLOW_POINTER_OVERFLOW_ATTR
|
1068
|
+
size_t ZSTD_decompressMultiFrame(ZSTD_DCtx* dctx,
|
706
1069
|
void* dst, size_t dstCapacity,
|
707
1070
|
const void* src, size_t srcSize,
|
708
1071
|
const void* dict, size_t dictSize,
|
@@ -722,7 +1085,7 @@ static size_t ZSTD_decompressMultiFrame(ZSTD_DCtx* dctx,
|
|
722
1085
|
while (srcSize >= ZSTD_startingInputLength(dctx->format)) {
|
723
1086
|
|
724
1087
|
#if defined(ZSTD_LEGACY_SUPPORT) && (ZSTD_LEGACY_SUPPORT >= 1)
|
725
|
-
if (ZSTD_isLegacy(src, srcSize)) {
|
1088
|
+
if (dctx->format == ZSTD_f_zstd1 && ZSTD_isLegacy(src, srcSize)) {
|
726
1089
|
size_t decodedSize;
|
727
1090
|
size_t const frameSize = ZSTD_findFrameCompressedSizeLegacy(src, srcSize);
|
728
1091
|
if (ZSTD_isError(frameSize)) return frameSize;
|
@@ -732,6 +1095,15 @@ static size_t ZSTD_decompressMultiFrame(ZSTD_DCtx* dctx,
|
|
732
1095
|
decodedSize = ZSTD_decompressLegacy(dst, dstCapacity, src, frameSize, dict, dictSize);
|
733
1096
|
if (ZSTD_isError(decodedSize)) return decodedSize;
|
734
1097
|
|
1098
|
+
{
|
1099
|
+
unsigned long long const expectedSize = ZSTD_getFrameContentSize(src, srcSize);
|
1100
|
+
RETURN_ERROR_IF(expectedSize == ZSTD_CONTENTSIZE_ERROR, corruption_detected, "Corrupted frame header!");
|
1101
|
+
if (expectedSize != ZSTD_CONTENTSIZE_UNKNOWN) {
|
1102
|
+
RETURN_ERROR_IF(expectedSize != decodedSize, corruption_detected,
|
1103
|
+
"Frame header size does not match decoded size!");
|
1104
|
+
}
|
1105
|
+
}
|
1106
|
+
|
735
1107
|
assert(decodedSize <= dstCapacity);
|
736
1108
|
dst = (BYTE*)dst + decodedSize;
|
737
1109
|
dstCapacity -= decodedSize;
|
@@ -743,17 +1115,18 @@ static size_t ZSTD_decompressMultiFrame(ZSTD_DCtx* dctx,
|
|
743
1115
|
}
|
744
1116
|
#endif
|
745
1117
|
|
746
|
-
|
747
|
-
|
748
|
-
|
1118
|
+
if (dctx->format == ZSTD_f_zstd1 && srcSize >= 4) {
|
1119
|
+
U32 const magicNumber = MEM_readLE32(src);
|
1120
|
+
DEBUGLOG(5, "reading magic number %08X", (unsigned)magicNumber);
|
749
1121
|
if ((magicNumber & ZSTD_MAGIC_SKIPPABLE_MASK) == ZSTD_MAGIC_SKIPPABLE_START) {
|
1122
|
+
/* skippable frame detected : skip it */
|
750
1123
|
size_t const skippableSize = readSkippableFrameSize(src, srcSize);
|
751
|
-
FORWARD_IF_ERROR(skippableSize, "
|
1124
|
+
FORWARD_IF_ERROR(skippableSize, "invalid skippable frame");
|
752
1125
|
assert(skippableSize <= srcSize);
|
753
1126
|
|
754
1127
|
src = (const BYTE *)src + skippableSize;
|
755
1128
|
srcSize -= skippableSize;
|
756
|
-
continue;
|
1129
|
+
continue; /* check next frame */
|
757
1130
|
} }
|
758
1131
|
|
759
1132
|
if (ddict) {
|
@@ -764,7 +1137,7 @@ static size_t ZSTD_decompressMultiFrame(ZSTD_DCtx* dctx,
|
|
764
1137
|
* use this in all cases but ddict */
|
765
1138
|
FORWARD_IF_ERROR(ZSTD_decompressBegin_usingDict(dctx, dict, dictSize), "");
|
766
1139
|
}
|
767
|
-
ZSTD_checkContinuity(dctx, dst);
|
1140
|
+
ZSTD_checkContinuity(dctx, dst, dstCapacity);
|
768
1141
|
|
769
1142
|
{ const size_t res = ZSTD_decompressFrame(dctx, dst, dstCapacity,
|
770
1143
|
&src, &srcSize);
|
@@ -807,7 +1180,7 @@ static ZSTD_DDict const* ZSTD_getDDict(ZSTD_DCtx* dctx)
|
|
807
1180
|
switch (dctx->dictUses) {
|
808
1181
|
default:
|
809
1182
|
assert(0 /* Impossible */);
|
810
|
-
|
1183
|
+
ZSTD_FALLTHROUGH;
|
811
1184
|
case ZSTD_dont_use:
|
812
1185
|
ZSTD_clearDict(dctx);
|
813
1186
|
return NULL;
|
@@ -829,7 +1202,7 @@ size_t ZSTD_decompress(void* dst, size_t dstCapacity, const void* src, size_t sr
|
|
829
1202
|
{
|
830
1203
|
#if defined(ZSTD_HEAPMODE) && (ZSTD_HEAPMODE>=1)
|
831
1204
|
size_t regenSize;
|
832
|
-
ZSTD_DCtx* const dctx =
|
1205
|
+
ZSTD_DCtx* const dctx = ZSTD_createDCtx_internal(ZSTD_defaultCMem);
|
833
1206
|
RETURN_ERROR_IF(dctx==NULL, memory_allocation, "NULL pointer!");
|
834
1207
|
regenSize = ZSTD_decompressDCtx(dctx, dst, dstCapacity, src, srcSize);
|
835
1208
|
ZSTD_freeDCtx(dctx);
|
@@ -849,8 +1222,8 @@ size_t ZSTD_decompress(void* dst, size_t dstCapacity, const void* src, size_t sr
|
|
849
1222
|
size_t ZSTD_nextSrcSizeToDecompress(ZSTD_DCtx* dctx) { return dctx->expected; }
|
850
1223
|
|
851
1224
|
/**
|
852
|
-
* Similar to ZSTD_nextSrcSizeToDecompress(), but when
|
853
|
-
*
|
1225
|
+
* Similar to ZSTD_nextSrcSizeToDecompress(), but when a block input can be streamed, we
|
1226
|
+
* allow taking a partial block as the input. Currently only raw uncompressed blocks can
|
854
1227
|
* be streamed.
|
855
1228
|
*
|
856
1229
|
* For blocks that can be streamed, this allows us to reduce the latency until we produce
|
@@ -863,7 +1236,7 @@ static size_t ZSTD_nextSrcSizeToDecompressWithInputSize(ZSTD_DCtx* dctx, size_t
|
|
863
1236
|
return dctx->expected;
|
864
1237
|
if (dctx->bType != bt_raw)
|
865
1238
|
return dctx->expected;
|
866
|
-
return
|
1239
|
+
return BOUNDED(1, inputSize, dctx->expected);
|
867
1240
|
}
|
868
1241
|
|
869
1242
|
ZSTD_nextInputType_e ZSTD_nextInputType(ZSTD_DCtx* dctx) {
|
@@ -871,7 +1244,9 @@ ZSTD_nextInputType_e ZSTD_nextInputType(ZSTD_DCtx* dctx) {
|
|
871
1244
|
{
|
872
1245
|
default: /* should not happen */
|
873
1246
|
assert(0);
|
1247
|
+
ZSTD_FALLTHROUGH;
|
874
1248
|
case ZSTDds_getFrameHeaderSize:
|
1249
|
+
ZSTD_FALLTHROUGH;
|
875
1250
|
case ZSTDds_decodeFrameHeader:
|
876
1251
|
return ZSTDnit_frameHeader;
|
877
1252
|
case ZSTDds_decodeBlockHeader:
|
@@ -883,6 +1258,7 @@ ZSTD_nextInputType_e ZSTD_nextInputType(ZSTD_DCtx* dctx) {
|
|
883
1258
|
case ZSTDds_checkChecksum:
|
884
1259
|
return ZSTDnit_checksum;
|
885
1260
|
case ZSTDds_decodeSkippableHeader:
|
1261
|
+
ZSTD_FALLTHROUGH;
|
886
1262
|
case ZSTDds_skipFrame:
|
887
1263
|
return ZSTDnit_skippableFrame;
|
888
1264
|
}
|
@@ -899,7 +1275,9 @@ size_t ZSTD_decompressContinue(ZSTD_DCtx* dctx, void* dst, size_t dstCapacity, c
|
|
899
1275
|
DEBUGLOG(5, "ZSTD_decompressContinue (srcSize:%u)", (unsigned)srcSize);
|
900
1276
|
/* Sanity check */
|
901
1277
|
RETURN_ERROR_IF(srcSize != ZSTD_nextSrcSizeToDecompressWithInputSize(dctx, srcSize), srcSize_wrong, "not allowed");
|
902
|
-
|
1278
|
+
ZSTD_checkContinuity(dctx, dst, dstCapacity);
|
1279
|
+
|
1280
|
+
dctx->processedCSize += srcSize;
|
903
1281
|
|
904
1282
|
switch (dctx->stage)
|
905
1283
|
{
|
@@ -964,7 +1342,8 @@ size_t ZSTD_decompressContinue(ZSTD_DCtx* dctx, void* dst, size_t dstCapacity, c
|
|
964
1342
|
{
|
965
1343
|
case bt_compressed:
|
966
1344
|
DEBUGLOG(5, "ZSTD_decompressContinue: case bt_compressed");
|
967
|
-
|
1345
|
+
assert(dctx->isFrameDecompression == 1);
|
1346
|
+
rSize = ZSTD_decompressBlock_internal(dctx, dst, dstCapacity, src, srcSize, is_streaming);
|
968
1347
|
dctx->expected = 0; /* Streaming not supported */
|
969
1348
|
break;
|
970
1349
|
case bt_raw :
|
@@ -1004,6 +1383,7 @@ size_t ZSTD_decompressContinue(ZSTD_DCtx* dctx, void* dst, size_t dstCapacity, c
|
|
1004
1383
|
dctx->expected = 4;
|
1005
1384
|
dctx->stage = ZSTDds_checkChecksum;
|
1006
1385
|
} else {
|
1386
|
+
ZSTD_DCtx_trace_end(dctx, dctx->decodedSize, dctx->processedCSize, /* streaming */ 1);
|
1007
1387
|
dctx->expected = 0; /* ends here */
|
1008
1388
|
dctx->stage = ZSTDds_getFrameHeaderSize;
|
1009
1389
|
}
|
@@ -1023,6 +1403,7 @@ size_t ZSTD_decompressContinue(ZSTD_DCtx* dctx, void* dst, size_t dstCapacity, c
|
|
1023
1403
|
DEBUGLOG(4, "ZSTD_decompressContinue: checksum : calculated %08X :: %08X read", (unsigned)h32, (unsigned)check32);
|
1024
1404
|
RETURN_ERROR_IF(check32 != h32, checksum_wrong, "");
|
1025
1405
|
}
|
1406
|
+
ZSTD_DCtx_trace_end(dctx, dctx->decodedSize, dctx->processedCSize, /* streaming */ 1);
|
1026
1407
|
dctx->expected = 0;
|
1027
1408
|
dctx->stage = ZSTDds_getFrameHeaderSize;
|
1028
1409
|
return 0;
|
@@ -1031,6 +1412,7 @@ size_t ZSTD_decompressContinue(ZSTD_DCtx* dctx, void* dst, size_t dstCapacity, c
|
|
1031
1412
|
case ZSTDds_decodeSkippableHeader:
|
1032
1413
|
assert(src != NULL);
|
1033
1414
|
assert(srcSize <= ZSTD_SKIPPABLEHEADERSIZE);
|
1415
|
+
assert(dctx->format != ZSTD_f_zstd1_magicless);
|
1034
1416
|
ZSTD_memcpy(dctx->headerBuffer + (ZSTD_SKIPPABLEHEADERSIZE - srcSize), src, srcSize); /* complete skippable header */
|
1035
1417
|
dctx->expected = MEM_readLE32(dctx->headerBuffer + ZSTD_FRAMEIDSIZE); /* note : dctx->expected can grow seriously large, beyond local buffer size */
|
1036
1418
|
dctx->stage = ZSTDds_skipFrame;
|
@@ -1043,7 +1425,7 @@ size_t ZSTD_decompressContinue(ZSTD_DCtx* dctx, void* dst, size_t dstCapacity, c
|
|
1043
1425
|
|
1044
1426
|
default:
|
1045
1427
|
assert(0); /* impossible */
|
1046
|
-
RETURN_ERROR(GENERIC, "impossible to reach"); /* some
|
1428
|
+
RETURN_ERROR(GENERIC, "impossible to reach"); /* some compilers require default to do something */
|
1047
1429
|
}
|
1048
1430
|
}
|
1049
1431
|
|
@@ -1084,11 +1466,11 @@ ZSTD_loadDEntropy(ZSTD_entropyDTables_t* entropy,
|
|
1084
1466
|
/* in minimal huffman, we always use X1 variants */
|
1085
1467
|
size_t const hSize = HUF_readDTableX1_wksp(entropy->hufTable,
|
1086
1468
|
dictPtr, dictEnd - dictPtr,
|
1087
|
-
workspace, workspaceSize);
|
1469
|
+
workspace, workspaceSize, /* flags */ 0);
|
1088
1470
|
#else
|
1089
1471
|
size_t const hSize = HUF_readDTableX2_wksp(entropy->hufTable,
|
1090
1472
|
dictPtr, (size_t)(dictEnd - dictPtr),
|
1091
|
-
workspace, workspaceSize);
|
1473
|
+
workspace, workspaceSize, /* flags */ 0);
|
1092
1474
|
#endif
|
1093
1475
|
RETURN_ERROR_IF(HUF_isError(hSize), dictionary_corrupted, "");
|
1094
1476
|
dictPtr += hSize;
|
@@ -1176,17 +1558,22 @@ static size_t ZSTD_decompress_insertDictionary(ZSTD_DCtx* dctx, const void* dict
|
|
1176
1558
|
size_t ZSTD_decompressBegin(ZSTD_DCtx* dctx)
|
1177
1559
|
{
|
1178
1560
|
assert(dctx != NULL);
|
1561
|
+
#if ZSTD_TRACE
|
1562
|
+
dctx->traceCtx = (ZSTD_trace_decompress_begin != NULL) ? ZSTD_trace_decompress_begin(dctx) : 0;
|
1563
|
+
#endif
|
1179
1564
|
dctx->expected = ZSTD_startingInputLength(dctx->format); /* dctx->format must be properly set */
|
1180
1565
|
dctx->stage = ZSTDds_getFrameHeaderSize;
|
1566
|
+
dctx->processedCSize = 0;
|
1181
1567
|
dctx->decodedSize = 0;
|
1182
1568
|
dctx->previousDstEnd = NULL;
|
1183
1569
|
dctx->prefixStart = NULL;
|
1184
1570
|
dctx->virtualStart = NULL;
|
1185
1571
|
dctx->dictEnd = NULL;
|
1186
|
-
dctx->entropy.hufTable[0] = (HUF_DTable)((
|
1572
|
+
dctx->entropy.hufTable[0] = (HUF_DTable)((ZSTD_HUFFDTABLE_CAPACITY_LOG)*0x1000001); /* cover both little and big endian */
|
1187
1573
|
dctx->litEntropy = dctx->fseEntropy = 0;
|
1188
1574
|
dctx->dictID = 0;
|
1189
1575
|
dctx->bType = bt_reserved;
|
1576
|
+
dctx->isFrameDecompression = 1;
|
1190
1577
|
ZSTD_STATIC_ASSERT(sizeof(dctx->entropy.rep) == sizeof(repStartValue));
|
1191
1578
|
ZSTD_memcpy(dctx->entropy.rep, repStartValue, sizeof(repStartValue)); /* initial repcodes */
|
1192
1579
|
dctx->LLTptr = dctx->entropy.LLTable;
|
@@ -1245,7 +1632,7 @@ unsigned ZSTD_getDictID_fromDict(const void* dict, size_t dictSize)
|
|
1245
1632
|
* This could for one of the following reasons :
|
1246
1633
|
* - The frame does not require a dictionary (most common case).
|
1247
1634
|
* - The frame was built with dictID intentionally removed.
|
1248
|
-
* Needed dictionary is a hidden information.
|
1635
|
+
* Needed dictionary is a hidden piece of information.
|
1249
1636
|
* Note : this use case also happens when using a non-conformant dictionary.
|
1250
1637
|
* - `srcSize` is too small, and as a result, frame header could not be decoded.
|
1251
1638
|
* Note : possible if `srcSize < ZSTD_FRAMEHEADERSIZE_MAX`.
|
@@ -1254,7 +1641,7 @@ unsigned ZSTD_getDictID_fromDict(const void* dict, size_t dictSize)
|
|
1254
1641
|
* ZSTD_getFrameHeader(), which will provide a more precise error code. */
|
1255
1642
|
unsigned ZSTD_getDictID_fromFrame(const void* src, size_t srcSize)
|
1256
1643
|
{
|
1257
|
-
ZSTD_frameHeader zfp = { 0, 0, 0, ZSTD_frame, 0, 0, 0 };
|
1644
|
+
ZSTD_frameHeader zfp = { 0, 0, 0, ZSTD_frame, 0, 0, 0, 0, 0 };
|
1258
1645
|
size_t const hError = ZSTD_getFrameHeader(&zfp, src, srcSize);
|
1259
1646
|
if (ZSTD_isError(hError)) return 0;
|
1260
1647
|
return zfp.dictID;
|
@@ -1283,7 +1670,7 @@ size_t ZSTD_decompress_usingDDict(ZSTD_DCtx* dctx,
|
|
1283
1670
|
ZSTD_DStream* ZSTD_createDStream(void)
|
1284
1671
|
{
|
1285
1672
|
DEBUGLOG(3, "ZSTD_createDStream");
|
1286
|
-
return
|
1673
|
+
return ZSTD_createDCtx_internal(ZSTD_defaultCMem);
|
1287
1674
|
}
|
1288
1675
|
|
1289
1676
|
ZSTD_DStream* ZSTD_initStaticDStream(void *workspace, size_t workspaceSize)
|
@@ -1293,7 +1680,7 @@ ZSTD_DStream* ZSTD_initStaticDStream(void *workspace, size_t workspaceSize)
|
|
1293
1680
|
|
1294
1681
|
ZSTD_DStream* ZSTD_createDStream_advanced(ZSTD_customMem customMem)
|
1295
1682
|
{
|
1296
|
-
return
|
1683
|
+
return ZSTD_createDCtx_internal(customMem);
|
1297
1684
|
}
|
1298
1685
|
|
1299
1686
|
size_t ZSTD_freeDStream(ZSTD_DStream* zds)
|
@@ -1361,7 +1748,9 @@ size_t ZSTD_initDStream_usingDict(ZSTD_DStream* zds, const void* dict, size_t di
|
|
1361
1748
|
size_t ZSTD_initDStream(ZSTD_DStream* zds)
|
1362
1749
|
{
|
1363
1750
|
DEBUGLOG(4, "ZSTD_initDStream");
|
1364
|
-
|
1751
|
+
FORWARD_IF_ERROR(ZSTD_DCtx_reset(zds, ZSTD_reset_session_only), "");
|
1752
|
+
FORWARD_IF_ERROR(ZSTD_DCtx_refDDict(zds, NULL), "");
|
1753
|
+
return ZSTD_startingInputLength(zds->format);
|
1365
1754
|
}
|
1366
1755
|
|
1367
1756
|
/* ZSTD_initDStream_usingDDict() :
|
@@ -1369,6 +1758,7 @@ size_t ZSTD_initDStream(ZSTD_DStream* zds)
|
|
1369
1758
|
* this function cannot fail */
|
1370
1759
|
size_t ZSTD_initDStream_usingDDict(ZSTD_DStream* dctx, const ZSTD_DDict* ddict)
|
1371
1760
|
{
|
1761
|
+
DEBUGLOG(4, "ZSTD_initDStream_usingDDict");
|
1372
1762
|
FORWARD_IF_ERROR( ZSTD_DCtx_reset(dctx, ZSTD_reset_session_only) , "");
|
1373
1763
|
FORWARD_IF_ERROR( ZSTD_DCtx_refDDict(dctx, ddict) , "");
|
1374
1764
|
return ZSTD_startingInputLength(dctx->format);
|
@@ -1379,6 +1769,7 @@ size_t ZSTD_initDStream_usingDDict(ZSTD_DStream* dctx, const ZSTD_DDict* ddict)
|
|
1379
1769
|
* this function cannot fail */
|
1380
1770
|
size_t ZSTD_resetDStream(ZSTD_DStream* dctx)
|
1381
1771
|
{
|
1772
|
+
DEBUGLOG(4, "ZSTD_resetDStream");
|
1382
1773
|
FORWARD_IF_ERROR(ZSTD_DCtx_reset(dctx, ZSTD_reset_session_only), "");
|
1383
1774
|
return ZSTD_startingInputLength(dctx->format);
|
1384
1775
|
}
|
@@ -1391,6 +1782,16 @@ size_t ZSTD_DCtx_refDDict(ZSTD_DCtx* dctx, const ZSTD_DDict* ddict)
|
|
1391
1782
|
if (ddict) {
|
1392
1783
|
dctx->ddict = ddict;
|
1393
1784
|
dctx->dictUses = ZSTD_use_indefinitely;
|
1785
|
+
if (dctx->refMultipleDDicts == ZSTD_rmd_refMultipleDDicts) {
|
1786
|
+
if (dctx->ddictSet == NULL) {
|
1787
|
+
dctx->ddictSet = ZSTD_createDDictHashSet(dctx->customMem);
|
1788
|
+
if (!dctx->ddictSet) {
|
1789
|
+
RETURN_ERROR(memory_allocation, "Failed to allocate memory for hash set!");
|
1790
|
+
}
|
1791
|
+
}
|
1792
|
+
assert(!dctx->staticSize); /* Impossible: ddictSet cannot have been allocated if static dctx */
|
1793
|
+
FORWARD_IF_ERROR(ZSTD_DDictHashSet_addDDict(dctx->ddictSet, ddict, dctx->customMem), "");
|
1794
|
+
}
|
1394
1795
|
}
|
1395
1796
|
return 0;
|
1396
1797
|
}
|
@@ -1436,6 +1837,19 @@ ZSTD_bounds ZSTD_dParam_getBounds(ZSTD_dParameter dParam)
|
|
1436
1837
|
bounds.lowerBound = (int)ZSTD_d_validateChecksum;
|
1437
1838
|
bounds.upperBound = (int)ZSTD_d_ignoreChecksum;
|
1438
1839
|
return bounds;
|
1840
|
+
case ZSTD_d_refMultipleDDicts:
|
1841
|
+
bounds.lowerBound = (int)ZSTD_rmd_refSingleDDict;
|
1842
|
+
bounds.upperBound = (int)ZSTD_rmd_refMultipleDDicts;
|
1843
|
+
return bounds;
|
1844
|
+
case ZSTD_d_disableHuffmanAssembly:
|
1845
|
+
bounds.lowerBound = 0;
|
1846
|
+
bounds.upperBound = 1;
|
1847
|
+
return bounds;
|
1848
|
+
case ZSTD_d_maxBlockSize:
|
1849
|
+
bounds.lowerBound = ZSTD_BLOCKSIZE_MAX_MIN;
|
1850
|
+
bounds.upperBound = ZSTD_BLOCKSIZE_MAX;
|
1851
|
+
return bounds;
|
1852
|
+
|
1439
1853
|
default:;
|
1440
1854
|
}
|
1441
1855
|
bounds.error = ERROR(parameter_unsupported);
|
@@ -1473,6 +1887,15 @@ size_t ZSTD_DCtx_getParameter(ZSTD_DCtx* dctx, ZSTD_dParameter param, int* value
|
|
1473
1887
|
case ZSTD_d_forceIgnoreChecksum:
|
1474
1888
|
*value = (int)dctx->forceIgnoreChecksum;
|
1475
1889
|
return 0;
|
1890
|
+
case ZSTD_d_refMultipleDDicts:
|
1891
|
+
*value = (int)dctx->refMultipleDDicts;
|
1892
|
+
return 0;
|
1893
|
+
case ZSTD_d_disableHuffmanAssembly:
|
1894
|
+
*value = (int)dctx->disableHufAsm;
|
1895
|
+
return 0;
|
1896
|
+
case ZSTD_d_maxBlockSize:
|
1897
|
+
*value = dctx->maxBlockSizeParam;
|
1898
|
+
return 0;
|
1476
1899
|
default:;
|
1477
1900
|
}
|
1478
1901
|
RETURN_ERROR(parameter_unsupported, "");
|
@@ -1499,6 +1922,21 @@ size_t ZSTD_DCtx_setParameter(ZSTD_DCtx* dctx, ZSTD_dParameter dParam, int value
|
|
1499
1922
|
CHECK_DBOUNDS(ZSTD_d_forceIgnoreChecksum, value);
|
1500
1923
|
dctx->forceIgnoreChecksum = (ZSTD_forceIgnoreChecksum_e)value;
|
1501
1924
|
return 0;
|
1925
|
+
case ZSTD_d_refMultipleDDicts:
|
1926
|
+
CHECK_DBOUNDS(ZSTD_d_refMultipleDDicts, value);
|
1927
|
+
if (dctx->staticSize != 0) {
|
1928
|
+
RETURN_ERROR(parameter_unsupported, "Static dctx does not support multiple DDicts!");
|
1929
|
+
}
|
1930
|
+
dctx->refMultipleDDicts = (ZSTD_refMultipleDDicts_e)value;
|
1931
|
+
return 0;
|
1932
|
+
case ZSTD_d_disableHuffmanAssembly:
|
1933
|
+
CHECK_DBOUNDS(ZSTD_d_disableHuffmanAssembly, value);
|
1934
|
+
dctx->disableHufAsm = value != 0;
|
1935
|
+
return 0;
|
1936
|
+
case ZSTD_d_maxBlockSize:
|
1937
|
+
if (value != 0) CHECK_DBOUNDS(ZSTD_d_maxBlockSize, value);
|
1938
|
+
dctx->maxBlockSizeParam = value;
|
1939
|
+
return 0;
|
1502
1940
|
default:;
|
1503
1941
|
}
|
1504
1942
|
RETURN_ERROR(parameter_unsupported, "");
|
@@ -1510,6 +1948,7 @@ size_t ZSTD_DCtx_reset(ZSTD_DCtx* dctx, ZSTD_ResetDirective reset)
|
|
1510
1948
|
|| (reset == ZSTD_reset_session_and_parameters) ) {
|
1511
1949
|
dctx->streamStage = zdss_init;
|
1512
1950
|
dctx->noForwardProgress = 0;
|
1951
|
+
dctx->isFrameDecompression = 1;
|
1513
1952
|
}
|
1514
1953
|
if ( (reset == ZSTD_reset_parameters)
|
1515
1954
|
|| (reset == ZSTD_reset_session_and_parameters) ) {
|
@@ -1526,10 +1965,17 @@ size_t ZSTD_sizeof_DStream(const ZSTD_DStream* dctx)
|
|
1526
1965
|
return ZSTD_sizeof_DCtx(dctx);
|
1527
1966
|
}
|
1528
1967
|
|
1529
|
-
size_t
|
1968
|
+
static size_t ZSTD_decodingBufferSize_internal(unsigned long long windowSize, unsigned long long frameContentSize, size_t blockSizeMax)
|
1530
1969
|
{
|
1531
|
-
size_t const blockSize = (size_t)
|
1532
|
-
|
1970
|
+
size_t const blockSize = MIN((size_t)MIN(windowSize, ZSTD_BLOCKSIZE_MAX), blockSizeMax);
|
1971
|
+
/* We need blockSize + WILDCOPY_OVERLENGTH worth of buffer so that if a block
|
1972
|
+
* ends at windowSize + WILDCOPY_OVERLENGTH + 1 bytes, we can start writing
|
1973
|
+
* the block at the beginning of the output buffer, and maintain a full window.
|
1974
|
+
*
|
1975
|
+
* We need another blockSize worth of buffer so that we can store split
|
1976
|
+
* literals at the end of the block without overwriting the extDict window.
|
1977
|
+
*/
|
1978
|
+
unsigned long long const neededRBSize = windowSize + (blockSize * 2) + (WILDCOPY_OVERLENGTH * 2);
|
1533
1979
|
unsigned long long const neededSize = MIN(frameContentSize, neededRBSize);
|
1534
1980
|
size_t const minRBSize = (size_t) neededSize;
|
1535
1981
|
RETURN_ERROR_IF((unsigned long long)minRBSize != neededSize,
|
@@ -1537,6 +1983,11 @@ size_t ZSTD_decodingBufferSize_min(unsigned long long windowSize, unsigned long
|
|
1537
1983
|
return minRBSize;
|
1538
1984
|
}
|
1539
1985
|
|
1986
|
+
size_t ZSTD_decodingBufferSize_min(unsigned long long windowSize, unsigned long long frameContentSize)
|
1987
|
+
{
|
1988
|
+
return ZSTD_decodingBufferSize_internal(windowSize, frameContentSize, ZSTD_BLOCKSIZE_MAX);
|
1989
|
+
}
|
1990
|
+
|
1540
1991
|
size_t ZSTD_estimateDStreamSize(size_t windowSize)
|
1541
1992
|
{
|
1542
1993
|
size_t const blockSize = MIN(windowSize, ZSTD_BLOCKSIZE_MAX);
|
@@ -1663,10 +2114,12 @@ size_t ZSTD_decompressStream(ZSTD_DStream* zds, ZSTD_outBuffer* output, ZSTD_inB
|
|
1663
2114
|
DEBUGLOG(5, "stage zdss_init => transparent reset ");
|
1664
2115
|
zds->streamStage = zdss_loadHeader;
|
1665
2116
|
zds->lhSize = zds->inPos = zds->outStart = zds->outEnd = 0;
|
2117
|
+
#if defined(ZSTD_LEGACY_SUPPORT) && (ZSTD_LEGACY_SUPPORT>=1)
|
1666
2118
|
zds->legacyVersion = 0;
|
2119
|
+
#endif
|
1667
2120
|
zds->hostageByte = 0;
|
1668
2121
|
zds->expectedOutBuffer = *output;
|
1669
|
-
|
2122
|
+
ZSTD_FALLTHROUGH;
|
1670
2123
|
|
1671
2124
|
case zdss_loadHeader :
|
1672
2125
|
DEBUGLOG(5, "stage zdss_loadHeader (srcSize : %u)", (U32)(iend - ip));
|
@@ -1680,7 +2133,9 @@ size_t ZSTD_decompressStream(ZSTD_DStream* zds, ZSTD_outBuffer* output, ZSTD_inB
|
|
1680
2133
|
} }
|
1681
2134
|
#endif
|
1682
2135
|
{ size_t const hSize = ZSTD_getFrameHeader_advanced(&zds->fParams, zds->headerBuffer, zds->lhSize, zds->format);
|
1683
|
-
|
2136
|
+
if (zds->refMultipleDDicts && zds->ddictSet) {
|
2137
|
+
ZSTD_DCtx_selectFrameDDict(zds);
|
2138
|
+
}
|
1684
2139
|
if (ZSTD_isError(hSize)) {
|
1685
2140
|
#if defined(ZSTD_LEGACY_SUPPORT) && (ZSTD_LEGACY_SUPPORT>=1)
|
1686
2141
|
U32 const legacyVersion = ZSTD_isLegacy(istart, iend-istart);
|
@@ -1712,6 +2167,11 @@ size_t ZSTD_decompressStream(ZSTD_DStream* zds, ZSTD_outBuffer* output, ZSTD_inB
|
|
1712
2167
|
zds->lhSize += remainingInput;
|
1713
2168
|
}
|
1714
2169
|
input->pos = input->size;
|
2170
|
+
/* check first few bytes */
|
2171
|
+
FORWARD_IF_ERROR(
|
2172
|
+
ZSTD_getFrameHeader_advanced(&zds->fParams, zds->headerBuffer, zds->lhSize, zds->format),
|
2173
|
+
"First few bytes detected incorrect" );
|
2174
|
+
/* return hint input size */
|
1715
2175
|
return (MAX((size_t)ZSTD_FRAMEHEADERSIZE_MIN(zds->format), hSize) - zds->lhSize) + ZSTD_blockHeaderSize; /* remaining header bytes + next block header */
|
1716
2176
|
}
|
1717
2177
|
assert(ip != NULL);
|
@@ -1723,14 +2183,15 @@ size_t ZSTD_decompressStream(ZSTD_DStream* zds, ZSTD_outBuffer* output, ZSTD_inB
|
|
1723
2183
|
if (zds->fParams.frameContentSize != ZSTD_CONTENTSIZE_UNKNOWN
|
1724
2184
|
&& zds->fParams.frameType != ZSTD_skippableFrame
|
1725
2185
|
&& (U64)(size_t)(oend-op) >= zds->fParams.frameContentSize) {
|
1726
|
-
size_t const cSize =
|
2186
|
+
size_t const cSize = ZSTD_findFrameCompressedSize_advanced(istart, (size_t)(iend-istart), zds->format);
|
1727
2187
|
if (cSize <= (size_t)(iend-istart)) {
|
1728
2188
|
/* shortcut : using single-pass mode */
|
1729
2189
|
size_t const decompressedSize = ZSTD_decompress_usingDDict(zds, op, (size_t)(oend-op), istart, cSize, ZSTD_getDDict(zds));
|
1730
2190
|
if (ZSTD_isError(decompressedSize)) return decompressedSize;
|
1731
|
-
DEBUGLOG(4, "shortcut to single-pass ZSTD_decompress_usingDDict()")
|
2191
|
+
DEBUGLOG(4, "shortcut to single-pass ZSTD_decompress_usingDDict()");
|
2192
|
+
assert(istart != NULL);
|
1732
2193
|
ip = istart + cSize;
|
1733
|
-
op
|
2194
|
+
op = op ? op + decompressedSize : op; /* can occur if frameContentSize = 0 (empty frame) */
|
1734
2195
|
zds->expected = 0;
|
1735
2196
|
zds->streamStage = zdss_init;
|
1736
2197
|
someMoreWork = 0;
|
@@ -1749,7 +2210,8 @@ size_t ZSTD_decompressStream(ZSTD_DStream* zds, ZSTD_outBuffer* output, ZSTD_inB
|
|
1749
2210
|
DEBUGLOG(4, "Consume header");
|
1750
2211
|
FORWARD_IF_ERROR(ZSTD_decompressBegin_usingDDict(zds, ZSTD_getDDict(zds)), "");
|
1751
2212
|
|
1752
|
-
if (
|
2213
|
+
if (zds->format == ZSTD_f_zstd1
|
2214
|
+
&& (MEM_readLE32(zds->headerBuffer) & ZSTD_MAGIC_SKIPPABLE_MASK) == ZSTD_MAGIC_SKIPPABLE_START) { /* skippable frame */
|
1753
2215
|
zds->expected = MEM_readLE32(zds->headerBuffer + ZSTD_FRAMEIDSIZE);
|
1754
2216
|
zds->stage = ZSTDds_skipFrame;
|
1755
2217
|
} else {
|
@@ -1765,11 +2227,13 @@ size_t ZSTD_decompressStream(ZSTD_DStream* zds, ZSTD_outBuffer* output, ZSTD_inB
|
|
1765
2227
|
zds->fParams.windowSize = MAX(zds->fParams.windowSize, 1U << ZSTD_WINDOWLOG_ABSOLUTEMIN);
|
1766
2228
|
RETURN_ERROR_IF(zds->fParams.windowSize > zds->maxWindowSize,
|
1767
2229
|
frameParameter_windowTooLarge, "");
|
2230
|
+
if (zds->maxBlockSizeParam != 0)
|
2231
|
+
zds->fParams.blockSizeMax = MIN(zds->fParams.blockSizeMax, (unsigned)zds->maxBlockSizeParam);
|
1768
2232
|
|
1769
2233
|
/* Adapt buffer sizes to frame header instructions */
|
1770
2234
|
{ size_t const neededInBuffSize = MAX(zds->fParams.blockSizeMax, 4 /* frame checksum */);
|
1771
2235
|
size_t const neededOutBuffSize = zds->outBufferMode == ZSTD_bm_buffered
|
1772
|
-
?
|
2236
|
+
? ZSTD_decodingBufferSize_internal(zds->fParams.windowSize, zds->fParams.frameContentSize, zds->fParams.blockSizeMax)
|
1773
2237
|
: 0;
|
1774
2238
|
|
1775
2239
|
ZSTD_DCtx_updateOversizedDuration(zds, neededInBuffSize, neededOutBuffSize);
|
@@ -1801,7 +2265,7 @@ size_t ZSTD_decompressStream(ZSTD_DStream* zds, ZSTD_outBuffer* output, ZSTD_inB
|
|
1801
2265
|
zds->outBuffSize = neededOutBuffSize;
|
1802
2266
|
} } }
|
1803
2267
|
zds->streamStage = zdss_read;
|
1804
|
-
|
2268
|
+
ZSTD_FALLTHROUGH;
|
1805
2269
|
|
1806
2270
|
case zdss_read:
|
1807
2271
|
DEBUGLOG(5, "stage zdss_read");
|
@@ -1814,13 +2278,14 @@ size_t ZSTD_decompressStream(ZSTD_DStream* zds, ZSTD_outBuffer* output, ZSTD_inB
|
|
1814
2278
|
}
|
1815
2279
|
if ((size_t)(iend-ip) >= neededInSize) { /* decode directly from src */
|
1816
2280
|
FORWARD_IF_ERROR(ZSTD_decompressContinueStream(zds, &op, oend, ip, neededInSize), "");
|
2281
|
+
assert(ip != NULL);
|
1817
2282
|
ip += neededInSize;
|
1818
2283
|
/* Function modifies the stage so we must break */
|
1819
2284
|
break;
|
1820
2285
|
} }
|
1821
2286
|
if (ip==iend) { someMoreWork = 0; break; } /* no more input */
|
1822
2287
|
zds->streamStage = zdss_load;
|
1823
|
-
|
2288
|
+
ZSTD_FALLTHROUGH;
|
1824
2289
|
|
1825
2290
|
case zdss_load:
|
1826
2291
|
{ size_t const neededInSize = ZSTD_nextSrcSizeToDecompress(zds);
|
@@ -1828,7 +2293,7 @@ size_t ZSTD_decompressStream(ZSTD_DStream* zds, ZSTD_outBuffer* output, ZSTD_inB
|
|
1828
2293
|
int const isSkipFrame = ZSTD_isSkipFrame(zds);
|
1829
2294
|
size_t loadedSize;
|
1830
2295
|
/* At this point we shouldn't be decompressing a block that we can stream. */
|
1831
|
-
assert(neededInSize == ZSTD_nextSrcSizeToDecompressWithInputSize(zds, iend - ip));
|
2296
|
+
assert(neededInSize == ZSTD_nextSrcSizeToDecompressWithInputSize(zds, (size_t)(iend - ip)));
|
1832
2297
|
if (isSkipFrame) {
|
1833
2298
|
loadedSize = MIN(toLoad, (size_t)(iend-ip));
|
1834
2299
|
} else {
|
@@ -1837,8 +2302,11 @@ size_t ZSTD_decompressStream(ZSTD_DStream* zds, ZSTD_outBuffer* output, ZSTD_inB
|
|
1837
2302
|
"should never happen");
|
1838
2303
|
loadedSize = ZSTD_limitCopy(zds->inBuff + zds->inPos, toLoad, ip, (size_t)(iend-ip));
|
1839
2304
|
}
|
1840
|
-
|
1841
|
-
|
2305
|
+
if (loadedSize != 0) {
|
2306
|
+
/* ip may be NULL */
|
2307
|
+
ip += loadedSize;
|
2308
|
+
zds->inPos += loadedSize;
|
2309
|
+
}
|
1842
2310
|
if (loadedSize < toLoad) { someMoreWork = 0; break; } /* not enough input, wait for more */
|
1843
2311
|
|
1844
2312
|
/* decode loaded input */
|
@@ -1848,14 +2316,17 @@ size_t ZSTD_decompressStream(ZSTD_DStream* zds, ZSTD_outBuffer* output, ZSTD_inB
|
|
1848
2316
|
break;
|
1849
2317
|
}
|
1850
2318
|
case zdss_flush:
|
1851
|
-
{
|
2319
|
+
{
|
2320
|
+
size_t const toFlushSize = zds->outEnd - zds->outStart;
|
1852
2321
|
size_t const flushedSize = ZSTD_limitCopy(op, (size_t)(oend-op), zds->outBuff + zds->outStart, toFlushSize);
|
1853
|
-
|
2322
|
+
|
2323
|
+
op = op ? op + flushedSize : op;
|
2324
|
+
|
1854
2325
|
zds->outStart += flushedSize;
|
1855
2326
|
if (flushedSize == toFlushSize) { /* flush completed */
|
1856
2327
|
zds->streamStage = zdss_read;
|
1857
2328
|
if ( (zds->outBuffSize < zds->fParams.frameContentSize)
|
1858
|
-
|
2329
|
+
&& (zds->outStart + zds->fParams.blockSizeMax > zds->outBuffSize) ) {
|
1859
2330
|
DEBUGLOG(5, "restart filling outBuff from beginning (left:%i, needed:%u)",
|
1860
2331
|
(int)(zds->outBuffSize - zds->outStart),
|
1861
2332
|
(U32)zds->fParams.blockSizeMax);
|
@@ -1869,7 +2340,7 @@ size_t ZSTD_decompressStream(ZSTD_DStream* zds, ZSTD_outBuffer* output, ZSTD_inB
|
|
1869
2340
|
|
1870
2341
|
default:
|
1871
2342
|
assert(0); /* impossible */
|
1872
|
-
RETURN_ERROR(GENERIC, "impossible to reach"); /* some
|
2343
|
+
RETURN_ERROR(GENERIC, "impossible to reach"); /* some compilers require default to do something */
|
1873
2344
|
} }
|
1874
2345
|
|
1875
2346
|
/* result */
|
@@ -1882,8 +2353,8 @@ size_t ZSTD_decompressStream(ZSTD_DStream* zds, ZSTD_outBuffer* output, ZSTD_inB
|
|
1882
2353
|
if ((ip==istart) && (op==ostart)) { /* no forward progress */
|
1883
2354
|
zds->noForwardProgress ++;
|
1884
2355
|
if (zds->noForwardProgress >= ZSTD_NO_FORWARD_PROGRESS_MAX) {
|
1885
|
-
RETURN_ERROR_IF(op==oend,
|
1886
|
-
RETURN_ERROR_IF(ip==iend,
|
2356
|
+
RETURN_ERROR_IF(op==oend, noForwardProgress_destFull, "");
|
2357
|
+
RETURN_ERROR_IF(ip==iend, noForwardProgress_inputEmpty, "");
|
1887
2358
|
assert(0);
|
1888
2359
|
}
|
1889
2360
|
} else {
|
@@ -1920,11 +2391,17 @@ size_t ZSTD_decompressStream_simpleArgs (
|
|
1920
2391
|
void* dst, size_t dstCapacity, size_t* dstPos,
|
1921
2392
|
const void* src, size_t srcSize, size_t* srcPos)
|
1922
2393
|
{
|
1923
|
-
ZSTD_outBuffer output
|
1924
|
-
ZSTD_inBuffer input
|
1925
|
-
|
1926
|
-
|
1927
|
-
|
1928
|
-
|
1929
|
-
|
2394
|
+
ZSTD_outBuffer output;
|
2395
|
+
ZSTD_inBuffer input;
|
2396
|
+
output.dst = dst;
|
2397
|
+
output.size = dstCapacity;
|
2398
|
+
output.pos = *dstPos;
|
2399
|
+
input.src = src;
|
2400
|
+
input.size = srcSize;
|
2401
|
+
input.pos = *srcPos;
|
2402
|
+
{ size_t const cErr = ZSTD_decompressStream(dctx, &output, &input);
|
2403
|
+
*dstPos = output.pos;
|
2404
|
+
*srcPos = input.pos;
|
2405
|
+
return cErr;
|
2406
|
+
}
|
1930
2407
|
}
|