extzstd 0.3.2 → 0.3.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/README.md +3 -3
- data/contrib/zstd/CHANGELOG +188 -1
- data/contrib/zstd/CONTRIBUTING.md +157 -74
- data/contrib/zstd/LICENSE +4 -4
- data/contrib/zstd/Makefile +81 -58
- data/contrib/zstd/Package.swift +36 -0
- data/contrib/zstd/README.md +59 -35
- data/contrib/zstd/TESTING.md +2 -3
- data/contrib/zstd/appveyor.yml +49 -136
- data/contrib/zstd/lib/BUCK +5 -7
- data/contrib/zstd/lib/Makefile +87 -181
- data/contrib/zstd/lib/README.md +23 -6
- 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 +33 -59
- data/contrib/zstd/lib/common/compiler.h +115 -45
- data/contrib/zstd/lib/common/cpu.h +1 -1
- data/contrib/zstd/lib/common/debug.c +1 -1
- data/contrib/zstd/lib/common/debug.h +1 -1
- 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 +82 -3
- data/contrib/zstd/lib/common/fse.h +9 -85
- data/contrib/zstd/lib/common/fse_decompress.c +29 -111
- data/contrib/zstd/lib/common/huf.h +84 -172
- data/contrib/zstd/lib/common/mem.h +58 -49
- data/contrib/zstd/lib/common/pool.c +37 -16
- data/contrib/zstd/lib/common/pool.h +9 -3
- data/contrib/zstd/lib/common/portability_macros.h +156 -0
- data/contrib/zstd/lib/common/threading.c +68 -14
- data/contrib/zstd/lib/common/threading.h +5 -10
- data/contrib/zstd/lib/common/xxhash.c +7 -809
- data/contrib/zstd/lib/common/xxhash.h +5568 -167
- 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 +64 -150
- 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 +69 -150
- 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 +773 -251
- data/contrib/zstd/lib/compress/zstd_compress.c +2650 -826
- data/contrib/zstd/lib/compress/zstd_compress_internal.h +509 -180
- 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 +33 -305
- data/contrib/zstd/lib/compress/zstd_compress_superblock.h +1 -1
- data/contrib/zstd/lib/compress/zstd_cwksp.h +266 -85
- data/contrib/zstd/lib/compress/zstd_double_fast.c +369 -132
- data/contrib/zstd/lib/compress/zstd_double_fast.h +3 -2
- data/contrib/zstd/lib/compress/zstd_fast.c +722 -258
- data/contrib/zstd/lib/compress/zstd_fast.h +3 -2
- data/contrib/zstd/lib/compress/zstd_lazy.c +1105 -360
- data/contrib/zstd/lib/compress/zstd_lazy.h +41 -1
- data/contrib/zstd/lib/compress/zstd_ldm.c +272 -208
- 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 +324 -197
- data/contrib/zstd/lib/compress/zstd_opt.h +1 -1
- data/contrib/zstd/lib/compress/zstdmt_compress.c +109 -53
- data/contrib/zstd/lib/compress/zstdmt_compress.h +9 -6
- data/contrib/zstd/lib/decompress/huf_decompress.c +1071 -539
- data/contrib/zstd/lib/decompress/huf_decompress_amd64.S +576 -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 +507 -82
- data/contrib/zstd/lib/decompress/zstd_decompress_block.c +962 -310
- data/contrib/zstd/lib/decompress/zstd_decompress_block.h +14 -3
- data/contrib/zstd/lib/decompress/zstd_decompress_internal.h +54 -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 +44 -32
- data/contrib/zstd/lib/dictBuilder/cover.h +6 -5
- data/contrib/zstd/lib/dictBuilder/divsufsort.c +1 -1
- data/contrib/zstd/lib/dictBuilder/fastcover.c +24 -16
- data/contrib/zstd/lib/dictBuilder/zdict.c +88 -95
- data/contrib/zstd/lib/legacy/zstd_legacy.h +8 -1
- data/contrib/zstd/lib/legacy/zstd_v01.c +16 -53
- data/contrib/zstd/lib/legacy/zstd_v01.h +1 -1
- data/contrib/zstd/lib/legacy/zstd_v02.c +24 -69
- data/contrib/zstd/lib/legacy/zstd_v02.h +1 -1
- data/contrib/zstd/lib/legacy/zstd_v03.c +25 -72
- data/contrib/zstd/lib/legacy/zstd_v03.h +1 -1
- data/contrib/zstd/lib/legacy/zstd_v04.c +23 -69
- data/contrib/zstd/lib/legacy/zstd_v04.h +1 -1
- data/contrib/zstd/lib/legacy/zstd_v05.c +35 -85
- data/contrib/zstd/lib/legacy/zstd_v05.h +1 -1
- data/contrib/zstd/lib/legacy/zstd_v06.c +42 -87
- data/contrib/zstd/lib/legacy/zstd_v06.h +1 -1
- data/contrib/zstd/lib/legacy/zstd_v07.c +35 -82
- data/contrib/zstd/lib/legacy/zstd_v07.h +1 -1
- data/contrib/zstd/lib/libzstd.mk +214 -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 +922 -293
- data/contrib/zstd/lib/{common/zstd_errors.h → zstd_errors.h} +27 -8
- data/ext/extconf.rb +7 -6
- data/ext/extzstd.c +13 -10
- data/ext/libzstd_conf.h +0 -1
- data/ext/zstd_decompress_asm.S +1 -0
- metadata +16 -5
|
@@ -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
|
|
@@ -55,23 +55,165 @@
|
|
|
55
55
|
/*-*******************************************************
|
|
56
56
|
* Dependencies
|
|
57
57
|
*********************************************************/
|
|
58
|
+
#include "../common/allocations.h" /* ZSTD_customMalloc, ZSTD_customCalloc, ZSTD_customFree */
|
|
58
59
|
#include "../common/zstd_deps.h" /* ZSTD_memcpy, ZSTD_memmove, ZSTD_memset */
|
|
59
|
-
#include "../common/cpu.h" /* bmi2 */
|
|
60
60
|
#include "../common/mem.h" /* low level memory routines */
|
|
61
61
|
#define FSE_STATIC_LINKING_ONLY
|
|
62
62
|
#include "../common/fse.h"
|
|
63
|
-
#define HUF_STATIC_LINKING_ONLY
|
|
64
63
|
#include "../common/huf.h"
|
|
64
|
+
#include "../common/xxhash.h" /* XXH64_reset, XXH64_update, XXH64_digest, XXH64 */
|
|
65
65
|
#include "../common/zstd_internal.h" /* blockProperties_t */
|
|
66
66
|
#include "zstd_decompress_internal.h" /* ZSTD_DCtx */
|
|
67
67
|
#include "zstd_ddict.h" /* ZSTD_DDictDictContent */
|
|
68
68
|
#include "zstd_decompress_block.h" /* ZSTD_decompressBlock_internal */
|
|
69
|
+
#include "../common/bits.h" /* ZSTD_highbit32 */
|
|
69
70
|
|
|
70
71
|
#if defined(ZSTD_LEGACY_SUPPORT) && (ZSTD_LEGACY_SUPPORT>=1)
|
|
71
72
|
# include "../legacy/zstd_legacy.h"
|
|
72
73
|
#endif
|
|
73
74
|
|
|
74
75
|
|
|
76
|
+
|
|
77
|
+
/*************************************
|
|
78
|
+
* Multiple DDicts Hashset internals *
|
|
79
|
+
*************************************/
|
|
80
|
+
|
|
81
|
+
#define DDICT_HASHSET_MAX_LOAD_FACTOR_COUNT_MULT 4
|
|
82
|
+
#define DDICT_HASHSET_MAX_LOAD_FACTOR_SIZE_MULT 3 /* These two constants represent SIZE_MULT/COUNT_MULT load factor without using a float.
|
|
83
|
+
* Currently, that means a 0.75 load factor.
|
|
84
|
+
* So, if count * COUNT_MULT / size * SIZE_MULT != 0, then we've exceeded
|
|
85
|
+
* the load factor of the ddict hash set.
|
|
86
|
+
*/
|
|
87
|
+
|
|
88
|
+
#define DDICT_HASHSET_TABLE_BASE_SIZE 64
|
|
89
|
+
#define DDICT_HASHSET_RESIZE_FACTOR 2
|
|
90
|
+
|
|
91
|
+
/* Hash function to determine starting position of dict insertion within the table
|
|
92
|
+
* Returns an index between [0, hashSet->ddictPtrTableSize]
|
|
93
|
+
*/
|
|
94
|
+
static size_t ZSTD_DDictHashSet_getIndex(const ZSTD_DDictHashSet* hashSet, U32 dictID) {
|
|
95
|
+
const U64 hash = XXH64(&dictID, sizeof(U32), 0);
|
|
96
|
+
/* DDict ptr table size is a multiple of 2, use size - 1 as mask to get index within [0, hashSet->ddictPtrTableSize) */
|
|
97
|
+
return hash & (hashSet->ddictPtrTableSize - 1);
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
/* Adds DDict to a hashset without resizing it.
|
|
101
|
+
* If inserting a DDict with a dictID that already exists in the set, replaces the one in the set.
|
|
102
|
+
* Returns 0 if successful, or a zstd error code if something went wrong.
|
|
103
|
+
*/
|
|
104
|
+
static size_t ZSTD_DDictHashSet_emplaceDDict(ZSTD_DDictHashSet* hashSet, const ZSTD_DDict* ddict) {
|
|
105
|
+
const U32 dictID = ZSTD_getDictID_fromDDict(ddict);
|
|
106
|
+
size_t idx = ZSTD_DDictHashSet_getIndex(hashSet, dictID);
|
|
107
|
+
const size_t idxRangeMask = hashSet->ddictPtrTableSize - 1;
|
|
108
|
+
RETURN_ERROR_IF(hashSet->ddictPtrCount == hashSet->ddictPtrTableSize, GENERIC, "Hash set is full!");
|
|
109
|
+
DEBUGLOG(4, "Hashed index: for dictID: %u is %zu", dictID, idx);
|
|
110
|
+
while (hashSet->ddictPtrTable[idx] != NULL) {
|
|
111
|
+
/* Replace existing ddict if inserting ddict with same dictID */
|
|
112
|
+
if (ZSTD_getDictID_fromDDict(hashSet->ddictPtrTable[idx]) == dictID) {
|
|
113
|
+
DEBUGLOG(4, "DictID already exists, replacing rather than adding");
|
|
114
|
+
hashSet->ddictPtrTable[idx] = ddict;
|
|
115
|
+
return 0;
|
|
116
|
+
}
|
|
117
|
+
idx &= idxRangeMask;
|
|
118
|
+
idx++;
|
|
119
|
+
}
|
|
120
|
+
DEBUGLOG(4, "Final idx after probing for dictID %u is: %zu", dictID, idx);
|
|
121
|
+
hashSet->ddictPtrTable[idx] = ddict;
|
|
122
|
+
hashSet->ddictPtrCount++;
|
|
123
|
+
return 0;
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
/* Expands hash table by factor of DDICT_HASHSET_RESIZE_FACTOR and
|
|
127
|
+
* rehashes all values, allocates new table, frees old table.
|
|
128
|
+
* Returns 0 on success, otherwise a zstd error code.
|
|
129
|
+
*/
|
|
130
|
+
static size_t ZSTD_DDictHashSet_expand(ZSTD_DDictHashSet* hashSet, ZSTD_customMem customMem) {
|
|
131
|
+
size_t newTableSize = hashSet->ddictPtrTableSize * DDICT_HASHSET_RESIZE_FACTOR;
|
|
132
|
+
const ZSTD_DDict** newTable = (const ZSTD_DDict**)ZSTD_customCalloc(sizeof(ZSTD_DDict*) * newTableSize, customMem);
|
|
133
|
+
const ZSTD_DDict** oldTable = hashSet->ddictPtrTable;
|
|
134
|
+
size_t oldTableSize = hashSet->ddictPtrTableSize;
|
|
135
|
+
size_t i;
|
|
136
|
+
|
|
137
|
+
DEBUGLOG(4, "Expanding DDict hash table! Old size: %zu new size: %zu", oldTableSize, newTableSize);
|
|
138
|
+
RETURN_ERROR_IF(!newTable, memory_allocation, "Expanded hashset allocation failed!");
|
|
139
|
+
hashSet->ddictPtrTable = newTable;
|
|
140
|
+
hashSet->ddictPtrTableSize = newTableSize;
|
|
141
|
+
hashSet->ddictPtrCount = 0;
|
|
142
|
+
for (i = 0; i < oldTableSize; ++i) {
|
|
143
|
+
if (oldTable[i] != NULL) {
|
|
144
|
+
FORWARD_IF_ERROR(ZSTD_DDictHashSet_emplaceDDict(hashSet, oldTable[i]), "");
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
ZSTD_customFree((void*)oldTable, customMem);
|
|
148
|
+
DEBUGLOG(4, "Finished re-hash");
|
|
149
|
+
return 0;
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
/* Fetches a DDict with the given dictID
|
|
153
|
+
* Returns the ZSTD_DDict* with the requested dictID. If it doesn't exist, then returns NULL.
|
|
154
|
+
*/
|
|
155
|
+
static const ZSTD_DDict* ZSTD_DDictHashSet_getDDict(ZSTD_DDictHashSet* hashSet, U32 dictID) {
|
|
156
|
+
size_t idx = ZSTD_DDictHashSet_getIndex(hashSet, dictID);
|
|
157
|
+
const size_t idxRangeMask = hashSet->ddictPtrTableSize - 1;
|
|
158
|
+
DEBUGLOG(4, "Hashed index: for dictID: %u is %zu", dictID, idx);
|
|
159
|
+
for (;;) {
|
|
160
|
+
size_t currDictID = ZSTD_getDictID_fromDDict(hashSet->ddictPtrTable[idx]);
|
|
161
|
+
if (currDictID == dictID || currDictID == 0) {
|
|
162
|
+
/* currDictID == 0 implies a NULL ddict entry */
|
|
163
|
+
break;
|
|
164
|
+
} else {
|
|
165
|
+
idx &= idxRangeMask; /* Goes to start of table when we reach the end */
|
|
166
|
+
idx++;
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
DEBUGLOG(4, "Final idx after probing for dictID %u is: %zu", dictID, idx);
|
|
170
|
+
return hashSet->ddictPtrTable[idx];
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
/* Allocates space for and returns a ddict hash set
|
|
174
|
+
* The hash set's ZSTD_DDict* table has all values automatically set to NULL to begin with.
|
|
175
|
+
* Returns NULL if allocation failed.
|
|
176
|
+
*/
|
|
177
|
+
static ZSTD_DDictHashSet* ZSTD_createDDictHashSet(ZSTD_customMem customMem) {
|
|
178
|
+
ZSTD_DDictHashSet* ret = (ZSTD_DDictHashSet*)ZSTD_customMalloc(sizeof(ZSTD_DDictHashSet), customMem);
|
|
179
|
+
DEBUGLOG(4, "Allocating new hash set");
|
|
180
|
+
if (!ret)
|
|
181
|
+
return NULL;
|
|
182
|
+
ret->ddictPtrTable = (const ZSTD_DDict**)ZSTD_customCalloc(DDICT_HASHSET_TABLE_BASE_SIZE * sizeof(ZSTD_DDict*), customMem);
|
|
183
|
+
if (!ret->ddictPtrTable) {
|
|
184
|
+
ZSTD_customFree(ret, customMem);
|
|
185
|
+
return NULL;
|
|
186
|
+
}
|
|
187
|
+
ret->ddictPtrTableSize = DDICT_HASHSET_TABLE_BASE_SIZE;
|
|
188
|
+
ret->ddictPtrCount = 0;
|
|
189
|
+
return ret;
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
/* Frees the table of ZSTD_DDict* within a hashset, then frees the hashset itself.
|
|
193
|
+
* Note: The ZSTD_DDict* within the table are NOT freed.
|
|
194
|
+
*/
|
|
195
|
+
static void ZSTD_freeDDictHashSet(ZSTD_DDictHashSet* hashSet, ZSTD_customMem customMem) {
|
|
196
|
+
DEBUGLOG(4, "Freeing ddict hash set");
|
|
197
|
+
if (hashSet && hashSet->ddictPtrTable) {
|
|
198
|
+
ZSTD_customFree((void*)hashSet->ddictPtrTable, customMem);
|
|
199
|
+
}
|
|
200
|
+
if (hashSet) {
|
|
201
|
+
ZSTD_customFree(hashSet, customMem);
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
/* Public function: Adds a DDict into the ZSTD_DDictHashSet, possibly triggering a resize of the hash set.
|
|
206
|
+
* Returns 0 on success, or a ZSTD error.
|
|
207
|
+
*/
|
|
208
|
+
static size_t ZSTD_DDictHashSet_addDDict(ZSTD_DDictHashSet* hashSet, const ZSTD_DDict* ddict, ZSTD_customMem customMem) {
|
|
209
|
+
DEBUGLOG(4, "Adding dict ID: %u to hashset with - Count: %zu Tablesize: %zu", ZSTD_getDictID_fromDDict(ddict), hashSet->ddictPtrCount, hashSet->ddictPtrTableSize);
|
|
210
|
+
if (hashSet->ddictPtrCount * DDICT_HASHSET_MAX_LOAD_FACTOR_COUNT_MULT / hashSet->ddictPtrTableSize * DDICT_HASHSET_MAX_LOAD_FACTOR_SIZE_MULT != 0) {
|
|
211
|
+
FORWARD_IF_ERROR(ZSTD_DDictHashSet_expand(hashSet, customMem), "");
|
|
212
|
+
}
|
|
213
|
+
FORWARD_IF_ERROR(ZSTD_DDictHashSet_emplaceDDict(hashSet, ddict), "");
|
|
214
|
+
return 0;
|
|
215
|
+
}
|
|
216
|
+
|
|
75
217
|
/*-*************************************************************
|
|
76
218
|
* Context management
|
|
77
219
|
***************************************************************/
|
|
@@ -101,6 +243,8 @@ static void ZSTD_DCtx_resetParameters(ZSTD_DCtx* dctx)
|
|
|
101
243
|
dctx->maxWindowSize = ZSTD_MAXWINDOWSIZE_DEFAULT;
|
|
102
244
|
dctx->outBufferMode = ZSTD_bm_buffered;
|
|
103
245
|
dctx->forceIgnoreChecksum = ZSTD_d_validateChecksum;
|
|
246
|
+
dctx->refMultipleDDicts = ZSTD_rmd_refSingleDDict;
|
|
247
|
+
dctx->disableHufAsm = 0;
|
|
104
248
|
}
|
|
105
249
|
|
|
106
250
|
static void ZSTD_initDCtx_internal(ZSTD_DCtx* dctx)
|
|
@@ -115,13 +259,17 @@ static void ZSTD_initDCtx_internal(ZSTD_DCtx* dctx)
|
|
|
115
259
|
dctx->inBuffSize = 0;
|
|
116
260
|
dctx->outBuffSize = 0;
|
|
117
261
|
dctx->streamStage = zdss_init;
|
|
262
|
+
#if defined(ZSTD_LEGACY_SUPPORT) && (ZSTD_LEGACY_SUPPORT>=1)
|
|
118
263
|
dctx->legacyContext = NULL;
|
|
119
264
|
dctx->previousLegacyVersion = 0;
|
|
265
|
+
#endif
|
|
120
266
|
dctx->noForwardProgress = 0;
|
|
121
267
|
dctx->oversizedDuration = 0;
|
|
122
|
-
|
|
268
|
+
#if DYNAMIC_BMI2
|
|
269
|
+
dctx->bmi2 = ZSTD_cpuSupportsBmi2();
|
|
270
|
+
#endif
|
|
271
|
+
dctx->ddictSet = NULL;
|
|
123
272
|
ZSTD_DCtx_resetParameters(dctx);
|
|
124
|
-
dctx->validateChecksum = 1;
|
|
125
273
|
#ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
|
|
126
274
|
dctx->dictContentEndForFuzzing = NULL;
|
|
127
275
|
#endif
|
|
@@ -140,8 +288,7 @@ ZSTD_DCtx* ZSTD_initStaticDCtx(void *workspace, size_t workspaceSize)
|
|
|
140
288
|
return dctx;
|
|
141
289
|
}
|
|
142
290
|
|
|
143
|
-
ZSTD_DCtx*
|
|
144
|
-
{
|
|
291
|
+
static ZSTD_DCtx* ZSTD_createDCtx_internal(ZSTD_customMem customMem) {
|
|
145
292
|
if ((!customMem.customAlloc) ^ (!customMem.customFree)) return NULL;
|
|
146
293
|
|
|
147
294
|
{ ZSTD_DCtx* const dctx = (ZSTD_DCtx*)ZSTD_customMalloc(sizeof(*dctx), customMem);
|
|
@@ -152,10 +299,15 @@ ZSTD_DCtx* ZSTD_createDCtx_advanced(ZSTD_customMem customMem)
|
|
|
152
299
|
}
|
|
153
300
|
}
|
|
154
301
|
|
|
302
|
+
ZSTD_DCtx* ZSTD_createDCtx_advanced(ZSTD_customMem customMem)
|
|
303
|
+
{
|
|
304
|
+
return ZSTD_createDCtx_internal(customMem);
|
|
305
|
+
}
|
|
306
|
+
|
|
155
307
|
ZSTD_DCtx* ZSTD_createDCtx(void)
|
|
156
308
|
{
|
|
157
309
|
DEBUGLOG(3, "ZSTD_createDCtx");
|
|
158
|
-
return
|
|
310
|
+
return ZSTD_createDCtx_internal(ZSTD_defaultCMem);
|
|
159
311
|
}
|
|
160
312
|
|
|
161
313
|
static void ZSTD_clearDict(ZSTD_DCtx* dctx)
|
|
@@ -178,6 +330,10 @@ size_t ZSTD_freeDCtx(ZSTD_DCtx* dctx)
|
|
|
178
330
|
if (dctx->legacyContext)
|
|
179
331
|
ZSTD_freeLegacyStreamContext(dctx->legacyContext, dctx->previousLegacyVersion);
|
|
180
332
|
#endif
|
|
333
|
+
if (dctx->ddictSet) {
|
|
334
|
+
ZSTD_freeDDictHashSet(dctx->ddictSet, cMem);
|
|
335
|
+
dctx->ddictSet = NULL;
|
|
336
|
+
}
|
|
181
337
|
ZSTD_customFree(dctx, cMem);
|
|
182
338
|
return 0;
|
|
183
339
|
}
|
|
@@ -190,6 +346,29 @@ void ZSTD_copyDCtx(ZSTD_DCtx* dstDCtx, const ZSTD_DCtx* srcDCtx)
|
|
|
190
346
|
ZSTD_memcpy(dstDCtx, srcDCtx, toCopy); /* no need to copy workspace */
|
|
191
347
|
}
|
|
192
348
|
|
|
349
|
+
/* Given a dctx with a digested frame params, re-selects the correct ZSTD_DDict based on
|
|
350
|
+
* the requested dict ID from the frame. If there exists a reference to the correct ZSTD_DDict, then
|
|
351
|
+
* accordingly sets the ddict to be used to decompress the frame.
|
|
352
|
+
*
|
|
353
|
+
* If no DDict is found, then no action is taken, and the ZSTD_DCtx::ddict remains as-is.
|
|
354
|
+
*
|
|
355
|
+
* ZSTD_d_refMultipleDDicts must be enabled for this function to be called.
|
|
356
|
+
*/
|
|
357
|
+
static void ZSTD_DCtx_selectFrameDDict(ZSTD_DCtx* dctx) {
|
|
358
|
+
assert(dctx->refMultipleDDicts && dctx->ddictSet);
|
|
359
|
+
DEBUGLOG(4, "Adjusting DDict based on requested dict ID from frame");
|
|
360
|
+
if (dctx->ddict) {
|
|
361
|
+
const ZSTD_DDict* frameDDict = ZSTD_DDictHashSet_getDDict(dctx->ddictSet, dctx->fParams.dictID);
|
|
362
|
+
if (frameDDict) {
|
|
363
|
+
DEBUGLOG(4, "DDict found!");
|
|
364
|
+
ZSTD_clearDict(dctx);
|
|
365
|
+
dctx->dictID = dctx->fParams.dictID;
|
|
366
|
+
dctx->ddict = frameDDict;
|
|
367
|
+
dctx->dictUses = ZSTD_use_indefinitely;
|
|
368
|
+
}
|
|
369
|
+
}
|
|
370
|
+
}
|
|
371
|
+
|
|
193
372
|
|
|
194
373
|
/*-*************************************************************
|
|
195
374
|
* Frame header decoding
|
|
@@ -213,6 +392,19 @@ unsigned ZSTD_isFrame(const void* buffer, size_t size)
|
|
|
213
392
|
return 0;
|
|
214
393
|
}
|
|
215
394
|
|
|
395
|
+
/*! ZSTD_isSkippableFrame() :
|
|
396
|
+
* Tells if the content of `buffer` starts with a valid Frame Identifier for a skippable frame.
|
|
397
|
+
* Note : Frame Identifier is 4 bytes. If `size < 4`, @return will always be 0.
|
|
398
|
+
*/
|
|
399
|
+
unsigned ZSTD_isSkippableFrame(const void* buffer, size_t size)
|
|
400
|
+
{
|
|
401
|
+
if (size < ZSTD_FRAMEIDSIZE) return 0;
|
|
402
|
+
{ U32 const magic = MEM_readLE32(buffer);
|
|
403
|
+
if ((magic & ZSTD_MAGIC_SKIPPABLE_MASK) == ZSTD_MAGIC_SKIPPABLE_START) return 1;
|
|
404
|
+
}
|
|
405
|
+
return 0;
|
|
406
|
+
}
|
|
407
|
+
|
|
216
408
|
/** ZSTD_frameHeaderSize_internal() :
|
|
217
409
|
* srcSize must be large enough to reach header size fields.
|
|
218
410
|
* note : only works for formats ZSTD_f_zstd1 and ZSTD_f_zstd1_magicless.
|
|
@@ -248,16 +440,40 @@ size_t ZSTD_frameHeaderSize(const void* src, size_t srcSize)
|
|
|
248
440
|
* note : only works for formats ZSTD_f_zstd1 and ZSTD_f_zstd1_magicless
|
|
249
441
|
* @return : 0, `zfhPtr` is correctly filled,
|
|
250
442
|
* >0, `srcSize` is too small, value is wanted `srcSize` amount,
|
|
251
|
-
|
|
443
|
+
** or an error code, which can be tested using ZSTD_isError() */
|
|
252
444
|
size_t ZSTD_getFrameHeader_advanced(ZSTD_frameHeader* zfhPtr, const void* src, size_t srcSize, ZSTD_format_e format)
|
|
253
445
|
{
|
|
254
446
|
const BYTE* ip = (const BYTE*)src;
|
|
255
447
|
size_t const minInputSize = ZSTD_startingInputLength(format);
|
|
256
448
|
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
449
|
+
DEBUGLOG(5, "ZSTD_getFrameHeader_advanced: minInputSize = %zu, srcSize = %zu", minInputSize, srcSize);
|
|
450
|
+
|
|
451
|
+
if (srcSize > 0) {
|
|
452
|
+
/* note : technically could be considered an assert(), since it's an invalid entry */
|
|
453
|
+
RETURN_ERROR_IF(src==NULL, GENERIC, "invalid parameter : src==NULL, but srcSize>0");
|
|
454
|
+
}
|
|
455
|
+
if (srcSize < minInputSize) {
|
|
456
|
+
if (srcSize > 0 && format != ZSTD_f_zstd1_magicless) {
|
|
457
|
+
/* when receiving less than @minInputSize bytes,
|
|
458
|
+
* control these bytes at least correspond to a supported magic number
|
|
459
|
+
* in order to error out early if they don't.
|
|
460
|
+
**/
|
|
461
|
+
size_t const toCopy = MIN(4, srcSize);
|
|
462
|
+
unsigned char hbuf[4]; MEM_writeLE32(hbuf, ZSTD_MAGICNUMBER);
|
|
463
|
+
assert(src != NULL);
|
|
464
|
+
ZSTD_memcpy(hbuf, src, toCopy);
|
|
465
|
+
if ( MEM_readLE32(hbuf) != ZSTD_MAGICNUMBER ) {
|
|
466
|
+
/* not a zstd frame : let's check if it's a skippable frame */
|
|
467
|
+
MEM_writeLE32(hbuf, ZSTD_MAGIC_SKIPPABLE_START);
|
|
468
|
+
ZSTD_memcpy(hbuf, src, toCopy);
|
|
469
|
+
if ((MEM_readLE32(hbuf) & ZSTD_MAGIC_SKIPPABLE_MASK) != ZSTD_MAGIC_SKIPPABLE_START) {
|
|
470
|
+
RETURN_ERROR(prefix_unknown,
|
|
471
|
+
"first bytes don't correspond to any supported magic number");
|
|
472
|
+
} } }
|
|
473
|
+
return minInputSize;
|
|
474
|
+
}
|
|
260
475
|
|
|
476
|
+
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
477
|
if ( (format != ZSTD_f_zstd1_magicless)
|
|
262
478
|
&& (MEM_readLE32(src) != ZSTD_MAGICNUMBER) ) {
|
|
263
479
|
if ((MEM_readLE32(src) & ZSTD_MAGIC_SKIPPABLE_MASK) == ZSTD_MAGIC_SKIPPABLE_START) {
|
|
@@ -299,7 +515,9 @@ size_t ZSTD_getFrameHeader_advanced(ZSTD_frameHeader* zfhPtr, const void* src, s
|
|
|
299
515
|
}
|
|
300
516
|
switch(dictIDSizeCode)
|
|
301
517
|
{
|
|
302
|
-
default:
|
|
518
|
+
default:
|
|
519
|
+
assert(0); /* impossible */
|
|
520
|
+
ZSTD_FALLTHROUGH;
|
|
303
521
|
case 0 : break;
|
|
304
522
|
case 1 : dictID = ip[pos]; pos++; break;
|
|
305
523
|
case 2 : dictID = MEM_readLE16(ip+pos); pos+=2; break;
|
|
@@ -307,7 +525,9 @@ size_t ZSTD_getFrameHeader_advanced(ZSTD_frameHeader* zfhPtr, const void* src, s
|
|
|
307
525
|
}
|
|
308
526
|
switch(fcsID)
|
|
309
527
|
{
|
|
310
|
-
default:
|
|
528
|
+
default:
|
|
529
|
+
assert(0); /* impossible */
|
|
530
|
+
ZSTD_FALLTHROUGH;
|
|
311
531
|
case 0 : if (singleSegment) frameContentSize = ip[pos]; break;
|
|
312
532
|
case 1 : frameContentSize = MEM_readLE16(ip+pos)+256; break;
|
|
313
533
|
case 2 : frameContentSize = MEM_readLE32(ip+pos); break;
|
|
@@ -336,7 +556,6 @@ size_t ZSTD_getFrameHeader(ZSTD_frameHeader* zfhPtr, const void* src, size_t src
|
|
|
336
556
|
return ZSTD_getFrameHeader_advanced(zfhPtr, src, srcSize, ZSTD_f_zstd1);
|
|
337
557
|
}
|
|
338
558
|
|
|
339
|
-
|
|
340
559
|
/** ZSTD_getFrameContentSize() :
|
|
341
560
|
* compatible with legacy mode
|
|
342
561
|
* @return : decompressed size of the single frame pointed to be `src` if known, otherwise
|
|
@@ -370,18 +589,52 @@ static size_t readSkippableFrameSize(void const* src, size_t srcSize)
|
|
|
370
589
|
sizeU32 = MEM_readLE32((BYTE const*)src + ZSTD_FRAMEIDSIZE);
|
|
371
590
|
RETURN_ERROR_IF((U32)(sizeU32 + ZSTD_SKIPPABLEHEADERSIZE) < sizeU32,
|
|
372
591
|
frameParameter_unsupported, "");
|
|
373
|
-
{
|
|
374
|
-
size_t const skippableSize = skippableHeaderSize + sizeU32;
|
|
592
|
+
{ size_t const skippableSize = skippableHeaderSize + sizeU32;
|
|
375
593
|
RETURN_ERROR_IF(skippableSize > srcSize, srcSize_wrong, "");
|
|
376
594
|
return skippableSize;
|
|
377
595
|
}
|
|
378
596
|
}
|
|
379
597
|
|
|
598
|
+
/*! ZSTD_readSkippableFrame() :
|
|
599
|
+
* Retrieves content of a skippable frame, and writes it to dst buffer.
|
|
600
|
+
*
|
|
601
|
+
* The parameter magicVariant will receive the magicVariant that was supplied when the frame was written,
|
|
602
|
+
* i.e. magicNumber - ZSTD_MAGIC_SKIPPABLE_START. This can be NULL if the caller is not interested
|
|
603
|
+
* in the magicVariant.
|
|
604
|
+
*
|
|
605
|
+
* Returns an error if destination buffer is not large enough, or if this is not a valid skippable frame.
|
|
606
|
+
*
|
|
607
|
+
* @return : number of bytes written or a ZSTD error.
|
|
608
|
+
*/
|
|
609
|
+
size_t ZSTD_readSkippableFrame(void* dst, size_t dstCapacity,
|
|
610
|
+
unsigned* magicVariant, /* optional, can be NULL */
|
|
611
|
+
const void* src, size_t srcSize)
|
|
612
|
+
{
|
|
613
|
+
RETURN_ERROR_IF(srcSize < ZSTD_SKIPPABLEHEADERSIZE, srcSize_wrong, "");
|
|
614
|
+
|
|
615
|
+
{ U32 const magicNumber = MEM_readLE32(src);
|
|
616
|
+
size_t skippableFrameSize = readSkippableFrameSize(src, srcSize);
|
|
617
|
+
size_t skippableContentSize = skippableFrameSize - ZSTD_SKIPPABLEHEADERSIZE;
|
|
618
|
+
|
|
619
|
+
/* check input validity */
|
|
620
|
+
RETURN_ERROR_IF(!ZSTD_isSkippableFrame(src, srcSize), frameParameter_unsupported, "");
|
|
621
|
+
RETURN_ERROR_IF(skippableFrameSize < ZSTD_SKIPPABLEHEADERSIZE || skippableFrameSize > srcSize, srcSize_wrong, "");
|
|
622
|
+
RETURN_ERROR_IF(skippableContentSize > dstCapacity, dstSize_tooSmall, "");
|
|
623
|
+
|
|
624
|
+
/* deliver payload */
|
|
625
|
+
if (skippableContentSize > 0 && dst != NULL)
|
|
626
|
+
ZSTD_memcpy(dst, (const BYTE *)src + ZSTD_SKIPPABLEHEADERSIZE, skippableContentSize);
|
|
627
|
+
if (magicVariant != NULL)
|
|
628
|
+
*magicVariant = magicNumber - ZSTD_MAGIC_SKIPPABLE_START;
|
|
629
|
+
return skippableContentSize;
|
|
630
|
+
}
|
|
631
|
+
}
|
|
632
|
+
|
|
380
633
|
/** ZSTD_findDecompressedSize() :
|
|
381
|
-
* compatible with legacy mode
|
|
382
634
|
* `srcSize` must be the exact length of some number of ZSTD compressed and/or
|
|
383
635
|
* skippable frames
|
|
384
|
-
*
|
|
636
|
+
* note: compatible with legacy mode
|
|
637
|
+
* @return : decompressed size of the frames contained */
|
|
385
638
|
unsigned long long ZSTD_findDecompressedSize(const void* src, size_t srcSize)
|
|
386
639
|
{
|
|
387
640
|
unsigned long long totalDstSize = 0;
|
|
@@ -391,9 +644,7 @@ unsigned long long ZSTD_findDecompressedSize(const void* src, size_t srcSize)
|
|
|
391
644
|
|
|
392
645
|
if ((magicNumber & ZSTD_MAGIC_SKIPPABLE_MASK) == ZSTD_MAGIC_SKIPPABLE_START) {
|
|
393
646
|
size_t const skippableSize = readSkippableFrameSize(src, srcSize);
|
|
394
|
-
if (ZSTD_isError(skippableSize))
|
|
395
|
-
return ZSTD_CONTENTSIZE_ERROR;
|
|
396
|
-
}
|
|
647
|
+
if (ZSTD_isError(skippableSize)) return ZSTD_CONTENTSIZE_ERROR;
|
|
397
648
|
assert(skippableSize <= srcSize);
|
|
398
649
|
|
|
399
650
|
src = (const BYTE *)src + skippableSize;
|
|
@@ -401,17 +652,17 @@ unsigned long long ZSTD_findDecompressedSize(const void* src, size_t srcSize)
|
|
|
401
652
|
continue;
|
|
402
653
|
}
|
|
403
654
|
|
|
404
|
-
{ unsigned long long const
|
|
405
|
-
if (
|
|
655
|
+
{ unsigned long long const fcs = ZSTD_getFrameContentSize(src, srcSize);
|
|
656
|
+
if (fcs >= ZSTD_CONTENTSIZE_ERROR) return fcs;
|
|
406
657
|
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
totalDstSize +=
|
|
658
|
+
if (totalDstSize + fcs < totalDstSize)
|
|
659
|
+
return ZSTD_CONTENTSIZE_ERROR; /* check for overflow */
|
|
660
|
+
totalDstSize += fcs;
|
|
410
661
|
}
|
|
662
|
+
/* skip to next frame */
|
|
411
663
|
{ size_t const frameSrcSize = ZSTD_findFrameCompressedSize(src, srcSize);
|
|
412
|
-
if (ZSTD_isError(frameSrcSize))
|
|
413
|
-
|
|
414
|
-
}
|
|
664
|
+
if (ZSTD_isError(frameSrcSize)) return ZSTD_CONTENTSIZE_ERROR;
|
|
665
|
+
assert(frameSrcSize <= srcSize);
|
|
415
666
|
|
|
416
667
|
src = (const BYTE *)src + frameSrcSize;
|
|
417
668
|
srcSize -= frameSrcSize;
|
|
@@ -441,12 +692,19 @@ unsigned long long ZSTD_getDecompressedSize(const void* src, size_t srcSize)
|
|
|
441
692
|
|
|
442
693
|
/** ZSTD_decodeFrameHeader() :
|
|
443
694
|
* `headerSize` must be the size provided by ZSTD_frameHeaderSize().
|
|
695
|
+
* If multiple DDict references are enabled, also will choose the correct DDict to use.
|
|
444
696
|
* @return : 0 if success, or an error code, which can be tested using ZSTD_isError() */
|
|
445
697
|
static size_t ZSTD_decodeFrameHeader(ZSTD_DCtx* dctx, const void* src, size_t headerSize)
|
|
446
698
|
{
|
|
447
699
|
size_t const result = ZSTD_getFrameHeader_advanced(&(dctx->fParams), src, headerSize, dctx->format);
|
|
448
700
|
if (ZSTD_isError(result)) return result; /* invalid header */
|
|
449
701
|
RETURN_ERROR_IF(result>0, srcSize_wrong, "headerSize too small");
|
|
702
|
+
|
|
703
|
+
/* Reference DDict requested by frame if dctx references multiple ddicts */
|
|
704
|
+
if (dctx->refMultipleDDicts == ZSTD_rmd_refMultipleDDicts && dctx->ddictSet) {
|
|
705
|
+
ZSTD_DCtx_selectFrameDDict(dctx);
|
|
706
|
+
}
|
|
707
|
+
|
|
450
708
|
#ifndef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
|
|
451
709
|
/* Skip the dictID check in fuzzing mode, because it makes the search
|
|
452
710
|
* harder.
|
|
@@ -456,6 +714,7 @@ static size_t ZSTD_decodeFrameHeader(ZSTD_DCtx* dctx, const void* src, size_t he
|
|
|
456
714
|
#endif
|
|
457
715
|
dctx->validateChecksum = (dctx->fParams.checksumFlag && !dctx->forceIgnoreChecksum) ? 1 : 0;
|
|
458
716
|
if (dctx->validateChecksum) XXH64_reset(&dctx->xxhState, 0);
|
|
717
|
+
dctx->processedCSize += headerSize;
|
|
459
718
|
return 0;
|
|
460
719
|
}
|
|
461
720
|
|
|
@@ -525,10 +784,11 @@ static ZSTD_frameSizeInfo ZSTD_findFrameSizeInfo(const void* src, size_t srcSize
|
|
|
525
784
|
ip += 4;
|
|
526
785
|
}
|
|
527
786
|
|
|
787
|
+
frameSizeInfo.nbBlocks = nbBlocks;
|
|
528
788
|
frameSizeInfo.compressedSize = (size_t)(ip - ipstart);
|
|
529
789
|
frameSizeInfo.decompressedBound = (zfh.frameContentSize != ZSTD_CONTENTSIZE_UNKNOWN)
|
|
530
790
|
? zfh.frameContentSize
|
|
531
|
-
: nbBlocks * zfh.blockSizeMax;
|
|
791
|
+
: (unsigned long long)nbBlocks * zfh.blockSizeMax;
|
|
532
792
|
return frameSizeInfo;
|
|
533
793
|
}
|
|
534
794
|
}
|
|
@@ -568,6 +828,48 @@ unsigned long long ZSTD_decompressBound(const void* src, size_t srcSize)
|
|
|
568
828
|
return bound;
|
|
569
829
|
}
|
|
570
830
|
|
|
831
|
+
size_t ZSTD_decompressionMargin(void const* src, size_t srcSize)
|
|
832
|
+
{
|
|
833
|
+
size_t margin = 0;
|
|
834
|
+
unsigned maxBlockSize = 0;
|
|
835
|
+
|
|
836
|
+
/* Iterate over each frame */
|
|
837
|
+
while (srcSize > 0) {
|
|
838
|
+
ZSTD_frameSizeInfo const frameSizeInfo = ZSTD_findFrameSizeInfo(src, srcSize);
|
|
839
|
+
size_t const compressedSize = frameSizeInfo.compressedSize;
|
|
840
|
+
unsigned long long const decompressedBound = frameSizeInfo.decompressedBound;
|
|
841
|
+
ZSTD_frameHeader zfh;
|
|
842
|
+
|
|
843
|
+
FORWARD_IF_ERROR(ZSTD_getFrameHeader(&zfh, src, srcSize), "");
|
|
844
|
+
if (ZSTD_isError(compressedSize) || decompressedBound == ZSTD_CONTENTSIZE_ERROR)
|
|
845
|
+
return ERROR(corruption_detected);
|
|
846
|
+
|
|
847
|
+
if (zfh.frameType == ZSTD_frame) {
|
|
848
|
+
/* Add the frame header to our margin */
|
|
849
|
+
margin += zfh.headerSize;
|
|
850
|
+
/* Add the checksum to our margin */
|
|
851
|
+
margin += zfh.checksumFlag ? 4 : 0;
|
|
852
|
+
/* Add 3 bytes per block */
|
|
853
|
+
margin += 3 * frameSizeInfo.nbBlocks;
|
|
854
|
+
|
|
855
|
+
/* Compute the max block size */
|
|
856
|
+
maxBlockSize = MAX(maxBlockSize, zfh.blockSizeMax);
|
|
857
|
+
} else {
|
|
858
|
+
assert(zfh.frameType == ZSTD_skippableFrame);
|
|
859
|
+
/* Add the entire skippable frame size to our margin. */
|
|
860
|
+
margin += compressedSize;
|
|
861
|
+
}
|
|
862
|
+
|
|
863
|
+
assert(srcSize >= compressedSize);
|
|
864
|
+
src = (const BYTE*)src + compressedSize;
|
|
865
|
+
srcSize -= compressedSize;
|
|
866
|
+
}
|
|
867
|
+
|
|
868
|
+
/* Add the max block size back to the margin. */
|
|
869
|
+
margin += maxBlockSize;
|
|
870
|
+
|
|
871
|
+
return margin;
|
|
872
|
+
}
|
|
571
873
|
|
|
572
874
|
/*-*************************************************************
|
|
573
875
|
* Frame decoding
|
|
@@ -578,7 +880,7 @@ unsigned long long ZSTD_decompressBound(const void* src, size_t srcSize)
|
|
|
578
880
|
size_t ZSTD_insertBlock(ZSTD_DCtx* dctx, const void* blockStart, size_t blockSize)
|
|
579
881
|
{
|
|
580
882
|
DEBUGLOG(5, "ZSTD_insertBlock: %u bytes", (unsigned)blockSize);
|
|
581
|
-
ZSTD_checkContinuity(dctx, blockStart);
|
|
883
|
+
ZSTD_checkContinuity(dctx, blockStart, blockSize);
|
|
582
884
|
dctx->previousDstEnd = (const char*)blockStart + blockSize;
|
|
583
885
|
return blockSize;
|
|
584
886
|
}
|
|
@@ -593,7 +895,7 @@ static size_t ZSTD_copyRawBlock(void* dst, size_t dstCapacity,
|
|
|
593
895
|
if (srcSize == 0) return 0;
|
|
594
896
|
RETURN_ERROR(dstBuffer_null, "");
|
|
595
897
|
}
|
|
596
|
-
|
|
898
|
+
ZSTD_memmove(dst, src, srcSize);
|
|
597
899
|
return srcSize;
|
|
598
900
|
}
|
|
599
901
|
|
|
@@ -610,6 +912,32 @@ static size_t ZSTD_setRleBlock(void* dst, size_t dstCapacity,
|
|
|
610
912
|
return regenSize;
|
|
611
913
|
}
|
|
612
914
|
|
|
915
|
+
static void ZSTD_DCtx_trace_end(ZSTD_DCtx const* dctx, U64 uncompressedSize, U64 compressedSize, unsigned streaming)
|
|
916
|
+
{
|
|
917
|
+
#if ZSTD_TRACE
|
|
918
|
+
if (dctx->traceCtx && ZSTD_trace_decompress_end != NULL) {
|
|
919
|
+
ZSTD_Trace trace;
|
|
920
|
+
ZSTD_memset(&trace, 0, sizeof(trace));
|
|
921
|
+
trace.version = ZSTD_VERSION_NUMBER;
|
|
922
|
+
trace.streaming = streaming;
|
|
923
|
+
if (dctx->ddict) {
|
|
924
|
+
trace.dictionaryID = ZSTD_getDictID_fromDDict(dctx->ddict);
|
|
925
|
+
trace.dictionarySize = ZSTD_DDict_dictSize(dctx->ddict);
|
|
926
|
+
trace.dictionaryIsCold = dctx->ddictIsCold;
|
|
927
|
+
}
|
|
928
|
+
trace.uncompressedSize = (size_t)uncompressedSize;
|
|
929
|
+
trace.compressedSize = (size_t)compressedSize;
|
|
930
|
+
trace.dctx = dctx;
|
|
931
|
+
ZSTD_trace_decompress_end(dctx->traceCtx, &trace);
|
|
932
|
+
}
|
|
933
|
+
#else
|
|
934
|
+
(void)dctx;
|
|
935
|
+
(void)uncompressedSize;
|
|
936
|
+
(void)compressedSize;
|
|
937
|
+
(void)streaming;
|
|
938
|
+
#endif
|
|
939
|
+
}
|
|
940
|
+
|
|
613
941
|
|
|
614
942
|
/*! ZSTD_decompressFrame() :
|
|
615
943
|
* @dctx must be properly initialized
|
|
@@ -619,8 +947,9 @@ static size_t ZSTD_decompressFrame(ZSTD_DCtx* dctx,
|
|
|
619
947
|
void* dst, size_t dstCapacity,
|
|
620
948
|
const void** srcPtr, size_t *srcSizePtr)
|
|
621
949
|
{
|
|
622
|
-
const BYTE*
|
|
623
|
-
BYTE*
|
|
950
|
+
const BYTE* const istart = (const BYTE*)(*srcPtr);
|
|
951
|
+
const BYTE* ip = istart;
|
|
952
|
+
BYTE* const ostart = (BYTE*)dst;
|
|
624
953
|
BYTE* const oend = dstCapacity != 0 ? ostart + dstCapacity : ostart;
|
|
625
954
|
BYTE* op = ostart;
|
|
626
955
|
size_t remainingSrcSize = *srcSizePtr;
|
|
@@ -644,6 +973,7 @@ static size_t ZSTD_decompressFrame(ZSTD_DCtx* dctx,
|
|
|
644
973
|
|
|
645
974
|
/* Loop on each block */
|
|
646
975
|
while (1) {
|
|
976
|
+
BYTE* oBlockEnd = oend;
|
|
647
977
|
size_t decodedSize;
|
|
648
978
|
blockProperties_t blockProperties;
|
|
649
979
|
size_t const cBlockSize = ZSTD_getcBlockSize(ip, remainingSrcSize, &blockProperties);
|
|
@@ -653,16 +983,34 @@ static size_t ZSTD_decompressFrame(ZSTD_DCtx* dctx,
|
|
|
653
983
|
remainingSrcSize -= ZSTD_blockHeaderSize;
|
|
654
984
|
RETURN_ERROR_IF(cBlockSize > remainingSrcSize, srcSize_wrong, "");
|
|
655
985
|
|
|
986
|
+
if (ip >= op && ip < oBlockEnd) {
|
|
987
|
+
/* We are decompressing in-place. Limit the output pointer so that we
|
|
988
|
+
* don't overwrite the block that we are currently reading. This will
|
|
989
|
+
* fail decompression if the input & output pointers aren't spaced
|
|
990
|
+
* far enough apart.
|
|
991
|
+
*
|
|
992
|
+
* This is important to set, even when the pointers are far enough
|
|
993
|
+
* apart, because ZSTD_decompressBlock_internal() can decide to store
|
|
994
|
+
* literals in the output buffer, after the block it is decompressing.
|
|
995
|
+
* Since we don't want anything to overwrite our input, we have to tell
|
|
996
|
+
* ZSTD_decompressBlock_internal to never write past ip.
|
|
997
|
+
*
|
|
998
|
+
* See ZSTD_allocateLiteralsBuffer() for reference.
|
|
999
|
+
*/
|
|
1000
|
+
oBlockEnd = op + (ip - op);
|
|
1001
|
+
}
|
|
1002
|
+
|
|
656
1003
|
switch(blockProperties.blockType)
|
|
657
1004
|
{
|
|
658
1005
|
case bt_compressed:
|
|
659
|
-
decodedSize = ZSTD_decompressBlock_internal(dctx, op, (size_t)(
|
|
1006
|
+
decodedSize = ZSTD_decompressBlock_internal(dctx, op, (size_t)(oBlockEnd-op), ip, cBlockSize, /* frame */ 1, not_streaming);
|
|
660
1007
|
break;
|
|
661
1008
|
case bt_raw :
|
|
1009
|
+
/* Use oend instead of oBlockEnd because this function is safe to overlap. It uses memmove. */
|
|
662
1010
|
decodedSize = ZSTD_copyRawBlock(op, (size_t)(oend-op), ip, cBlockSize);
|
|
663
1011
|
break;
|
|
664
1012
|
case bt_rle :
|
|
665
|
-
decodedSize = ZSTD_setRleBlock(op, (size_t)(
|
|
1013
|
+
decodedSize = ZSTD_setRleBlock(op, (size_t)(oBlockEnd-op), *ip, blockProperties.origSize);
|
|
666
1014
|
break;
|
|
667
1015
|
case bt_reserved :
|
|
668
1016
|
default:
|
|
@@ -695,8 +1043,9 @@ static size_t ZSTD_decompressFrame(ZSTD_DCtx* dctx,
|
|
|
695
1043
|
ip += 4;
|
|
696
1044
|
remainingSrcSize -= 4;
|
|
697
1045
|
}
|
|
698
|
-
|
|
1046
|
+
ZSTD_DCtx_trace_end(dctx, (U64)(op-ostart), (U64)(ip-istart), /* streaming */ 0);
|
|
699
1047
|
/* Allow caller to get size read */
|
|
1048
|
+
DEBUGLOG(4, "ZSTD_decompressFrame: decompressed frame of size %zi, consuming %zi bytes of input", op-ostart, ip - (const BYTE*)*srcPtr);
|
|
700
1049
|
*srcPtr = ip;
|
|
701
1050
|
*srcSizePtr = remainingSrcSize;
|
|
702
1051
|
return (size_t)(op-ostart);
|
|
@@ -743,17 +1092,18 @@ static size_t ZSTD_decompressMultiFrame(ZSTD_DCtx* dctx,
|
|
|
743
1092
|
}
|
|
744
1093
|
#endif
|
|
745
1094
|
|
|
746
|
-
|
|
747
|
-
|
|
748
|
-
|
|
1095
|
+
if (srcSize >= 4) {
|
|
1096
|
+
U32 const magicNumber = MEM_readLE32(src);
|
|
1097
|
+
DEBUGLOG(5, "reading magic number %08X", (unsigned)magicNumber);
|
|
749
1098
|
if ((magicNumber & ZSTD_MAGIC_SKIPPABLE_MASK) == ZSTD_MAGIC_SKIPPABLE_START) {
|
|
1099
|
+
/* skippable frame detected : skip it */
|
|
750
1100
|
size_t const skippableSize = readSkippableFrameSize(src, srcSize);
|
|
751
|
-
FORWARD_IF_ERROR(skippableSize, "
|
|
1101
|
+
FORWARD_IF_ERROR(skippableSize, "invalid skippable frame");
|
|
752
1102
|
assert(skippableSize <= srcSize);
|
|
753
1103
|
|
|
754
1104
|
src = (const BYTE *)src + skippableSize;
|
|
755
1105
|
srcSize -= skippableSize;
|
|
756
|
-
continue;
|
|
1106
|
+
continue; /* check next frame */
|
|
757
1107
|
} }
|
|
758
1108
|
|
|
759
1109
|
if (ddict) {
|
|
@@ -764,7 +1114,7 @@ static size_t ZSTD_decompressMultiFrame(ZSTD_DCtx* dctx,
|
|
|
764
1114
|
* use this in all cases but ddict */
|
|
765
1115
|
FORWARD_IF_ERROR(ZSTD_decompressBegin_usingDict(dctx, dict, dictSize), "");
|
|
766
1116
|
}
|
|
767
|
-
ZSTD_checkContinuity(dctx, dst);
|
|
1117
|
+
ZSTD_checkContinuity(dctx, dst, dstCapacity);
|
|
768
1118
|
|
|
769
1119
|
{ const size_t res = ZSTD_decompressFrame(dctx, dst, dstCapacity,
|
|
770
1120
|
&src, &srcSize);
|
|
@@ -807,7 +1157,7 @@ static ZSTD_DDict const* ZSTD_getDDict(ZSTD_DCtx* dctx)
|
|
|
807
1157
|
switch (dctx->dictUses) {
|
|
808
1158
|
default:
|
|
809
1159
|
assert(0 /* Impossible */);
|
|
810
|
-
|
|
1160
|
+
ZSTD_FALLTHROUGH;
|
|
811
1161
|
case ZSTD_dont_use:
|
|
812
1162
|
ZSTD_clearDict(dctx);
|
|
813
1163
|
return NULL;
|
|
@@ -829,7 +1179,7 @@ size_t ZSTD_decompress(void* dst, size_t dstCapacity, const void* src, size_t sr
|
|
|
829
1179
|
{
|
|
830
1180
|
#if defined(ZSTD_HEAPMODE) && (ZSTD_HEAPMODE>=1)
|
|
831
1181
|
size_t regenSize;
|
|
832
|
-
ZSTD_DCtx* const dctx =
|
|
1182
|
+
ZSTD_DCtx* const dctx = ZSTD_createDCtx_internal(ZSTD_defaultCMem);
|
|
833
1183
|
RETURN_ERROR_IF(dctx==NULL, memory_allocation, "NULL pointer!");
|
|
834
1184
|
regenSize = ZSTD_decompressDCtx(dctx, dst, dstCapacity, src, srcSize);
|
|
835
1185
|
ZSTD_freeDCtx(dctx);
|
|
@@ -849,8 +1199,8 @@ size_t ZSTD_decompress(void* dst, size_t dstCapacity, const void* src, size_t sr
|
|
|
849
1199
|
size_t ZSTD_nextSrcSizeToDecompress(ZSTD_DCtx* dctx) { return dctx->expected; }
|
|
850
1200
|
|
|
851
1201
|
/**
|
|
852
|
-
* Similar to ZSTD_nextSrcSizeToDecompress(), but when
|
|
853
|
-
*
|
|
1202
|
+
* Similar to ZSTD_nextSrcSizeToDecompress(), but when a block input can be streamed, we
|
|
1203
|
+
* allow taking a partial block as the input. Currently only raw uncompressed blocks can
|
|
854
1204
|
* be streamed.
|
|
855
1205
|
*
|
|
856
1206
|
* For blocks that can be streamed, this allows us to reduce the latency until we produce
|
|
@@ -863,7 +1213,7 @@ static size_t ZSTD_nextSrcSizeToDecompressWithInputSize(ZSTD_DCtx* dctx, size_t
|
|
|
863
1213
|
return dctx->expected;
|
|
864
1214
|
if (dctx->bType != bt_raw)
|
|
865
1215
|
return dctx->expected;
|
|
866
|
-
return
|
|
1216
|
+
return BOUNDED(1, inputSize, dctx->expected);
|
|
867
1217
|
}
|
|
868
1218
|
|
|
869
1219
|
ZSTD_nextInputType_e ZSTD_nextInputType(ZSTD_DCtx* dctx) {
|
|
@@ -871,7 +1221,9 @@ ZSTD_nextInputType_e ZSTD_nextInputType(ZSTD_DCtx* dctx) {
|
|
|
871
1221
|
{
|
|
872
1222
|
default: /* should not happen */
|
|
873
1223
|
assert(0);
|
|
1224
|
+
ZSTD_FALLTHROUGH;
|
|
874
1225
|
case ZSTDds_getFrameHeaderSize:
|
|
1226
|
+
ZSTD_FALLTHROUGH;
|
|
875
1227
|
case ZSTDds_decodeFrameHeader:
|
|
876
1228
|
return ZSTDnit_frameHeader;
|
|
877
1229
|
case ZSTDds_decodeBlockHeader:
|
|
@@ -883,6 +1235,7 @@ ZSTD_nextInputType_e ZSTD_nextInputType(ZSTD_DCtx* dctx) {
|
|
|
883
1235
|
case ZSTDds_checkChecksum:
|
|
884
1236
|
return ZSTDnit_checksum;
|
|
885
1237
|
case ZSTDds_decodeSkippableHeader:
|
|
1238
|
+
ZSTD_FALLTHROUGH;
|
|
886
1239
|
case ZSTDds_skipFrame:
|
|
887
1240
|
return ZSTDnit_skippableFrame;
|
|
888
1241
|
}
|
|
@@ -899,7 +1252,9 @@ size_t ZSTD_decompressContinue(ZSTD_DCtx* dctx, void* dst, size_t dstCapacity, c
|
|
|
899
1252
|
DEBUGLOG(5, "ZSTD_decompressContinue (srcSize:%u)", (unsigned)srcSize);
|
|
900
1253
|
/* Sanity check */
|
|
901
1254
|
RETURN_ERROR_IF(srcSize != ZSTD_nextSrcSizeToDecompressWithInputSize(dctx, srcSize), srcSize_wrong, "not allowed");
|
|
902
|
-
|
|
1255
|
+
ZSTD_checkContinuity(dctx, dst, dstCapacity);
|
|
1256
|
+
|
|
1257
|
+
dctx->processedCSize += srcSize;
|
|
903
1258
|
|
|
904
1259
|
switch (dctx->stage)
|
|
905
1260
|
{
|
|
@@ -964,7 +1319,7 @@ size_t ZSTD_decompressContinue(ZSTD_DCtx* dctx, void* dst, size_t dstCapacity, c
|
|
|
964
1319
|
{
|
|
965
1320
|
case bt_compressed:
|
|
966
1321
|
DEBUGLOG(5, "ZSTD_decompressContinue: case bt_compressed");
|
|
967
|
-
rSize = ZSTD_decompressBlock_internal(dctx, dst, dstCapacity, src, srcSize, /* frame */ 1);
|
|
1322
|
+
rSize = ZSTD_decompressBlock_internal(dctx, dst, dstCapacity, src, srcSize, /* frame */ 1, is_streaming);
|
|
968
1323
|
dctx->expected = 0; /* Streaming not supported */
|
|
969
1324
|
break;
|
|
970
1325
|
case bt_raw :
|
|
@@ -1004,6 +1359,7 @@ size_t ZSTD_decompressContinue(ZSTD_DCtx* dctx, void* dst, size_t dstCapacity, c
|
|
|
1004
1359
|
dctx->expected = 4;
|
|
1005
1360
|
dctx->stage = ZSTDds_checkChecksum;
|
|
1006
1361
|
} else {
|
|
1362
|
+
ZSTD_DCtx_trace_end(dctx, dctx->decodedSize, dctx->processedCSize, /* streaming */ 1);
|
|
1007
1363
|
dctx->expected = 0; /* ends here */
|
|
1008
1364
|
dctx->stage = ZSTDds_getFrameHeaderSize;
|
|
1009
1365
|
}
|
|
@@ -1023,6 +1379,7 @@ size_t ZSTD_decompressContinue(ZSTD_DCtx* dctx, void* dst, size_t dstCapacity, c
|
|
|
1023
1379
|
DEBUGLOG(4, "ZSTD_decompressContinue: checksum : calculated %08X :: %08X read", (unsigned)h32, (unsigned)check32);
|
|
1024
1380
|
RETURN_ERROR_IF(check32 != h32, checksum_wrong, "");
|
|
1025
1381
|
}
|
|
1382
|
+
ZSTD_DCtx_trace_end(dctx, dctx->decodedSize, dctx->processedCSize, /* streaming */ 1);
|
|
1026
1383
|
dctx->expected = 0;
|
|
1027
1384
|
dctx->stage = ZSTDds_getFrameHeaderSize;
|
|
1028
1385
|
return 0;
|
|
@@ -1043,7 +1400,7 @@ size_t ZSTD_decompressContinue(ZSTD_DCtx* dctx, void* dst, size_t dstCapacity, c
|
|
|
1043
1400
|
|
|
1044
1401
|
default:
|
|
1045
1402
|
assert(0); /* impossible */
|
|
1046
|
-
RETURN_ERROR(GENERIC, "impossible to reach"); /* some
|
|
1403
|
+
RETURN_ERROR(GENERIC, "impossible to reach"); /* some compilers require default to do something */
|
|
1047
1404
|
}
|
|
1048
1405
|
}
|
|
1049
1406
|
|
|
@@ -1084,11 +1441,11 @@ ZSTD_loadDEntropy(ZSTD_entropyDTables_t* entropy,
|
|
|
1084
1441
|
/* in minimal huffman, we always use X1 variants */
|
|
1085
1442
|
size_t const hSize = HUF_readDTableX1_wksp(entropy->hufTable,
|
|
1086
1443
|
dictPtr, dictEnd - dictPtr,
|
|
1087
|
-
workspace, workspaceSize);
|
|
1444
|
+
workspace, workspaceSize, /* flags */ 0);
|
|
1088
1445
|
#else
|
|
1089
1446
|
size_t const hSize = HUF_readDTableX2_wksp(entropy->hufTable,
|
|
1090
1447
|
dictPtr, (size_t)(dictEnd - dictPtr),
|
|
1091
|
-
workspace, workspaceSize);
|
|
1448
|
+
workspace, workspaceSize, /* flags */ 0);
|
|
1092
1449
|
#endif
|
|
1093
1450
|
RETURN_ERROR_IF(HUF_isError(hSize), dictionary_corrupted, "");
|
|
1094
1451
|
dictPtr += hSize;
|
|
@@ -1176,14 +1533,18 @@ static size_t ZSTD_decompress_insertDictionary(ZSTD_DCtx* dctx, const void* dict
|
|
|
1176
1533
|
size_t ZSTD_decompressBegin(ZSTD_DCtx* dctx)
|
|
1177
1534
|
{
|
|
1178
1535
|
assert(dctx != NULL);
|
|
1536
|
+
#if ZSTD_TRACE
|
|
1537
|
+
dctx->traceCtx = (ZSTD_trace_decompress_begin != NULL) ? ZSTD_trace_decompress_begin(dctx) : 0;
|
|
1538
|
+
#endif
|
|
1179
1539
|
dctx->expected = ZSTD_startingInputLength(dctx->format); /* dctx->format must be properly set */
|
|
1180
1540
|
dctx->stage = ZSTDds_getFrameHeaderSize;
|
|
1541
|
+
dctx->processedCSize = 0;
|
|
1181
1542
|
dctx->decodedSize = 0;
|
|
1182
1543
|
dctx->previousDstEnd = NULL;
|
|
1183
1544
|
dctx->prefixStart = NULL;
|
|
1184
1545
|
dctx->virtualStart = NULL;
|
|
1185
1546
|
dctx->dictEnd = NULL;
|
|
1186
|
-
dctx->entropy.hufTable[0] = (HUF_DTable)((
|
|
1547
|
+
dctx->entropy.hufTable[0] = (HUF_DTable)((ZSTD_HUFFDTABLE_CAPACITY_LOG)*0x1000001); /* cover both little and big endian */
|
|
1187
1548
|
dctx->litEntropy = dctx->fseEntropy = 0;
|
|
1188
1549
|
dctx->dictID = 0;
|
|
1189
1550
|
dctx->bType = bt_reserved;
|
|
@@ -1245,7 +1606,7 @@ unsigned ZSTD_getDictID_fromDict(const void* dict, size_t dictSize)
|
|
|
1245
1606
|
* This could for one of the following reasons :
|
|
1246
1607
|
* - The frame does not require a dictionary (most common case).
|
|
1247
1608
|
* - The frame was built with dictID intentionally removed.
|
|
1248
|
-
* Needed dictionary is a hidden information.
|
|
1609
|
+
* Needed dictionary is a hidden piece of information.
|
|
1249
1610
|
* Note : this use case also happens when using a non-conformant dictionary.
|
|
1250
1611
|
* - `srcSize` is too small, and as a result, frame header could not be decoded.
|
|
1251
1612
|
* Note : possible if `srcSize < ZSTD_FRAMEHEADERSIZE_MAX`.
|
|
@@ -1254,7 +1615,7 @@ unsigned ZSTD_getDictID_fromDict(const void* dict, size_t dictSize)
|
|
|
1254
1615
|
* ZSTD_getFrameHeader(), which will provide a more precise error code. */
|
|
1255
1616
|
unsigned ZSTD_getDictID_fromFrame(const void* src, size_t srcSize)
|
|
1256
1617
|
{
|
|
1257
|
-
ZSTD_frameHeader zfp = { 0, 0, 0, ZSTD_frame, 0, 0, 0 };
|
|
1618
|
+
ZSTD_frameHeader zfp = { 0, 0, 0, ZSTD_frame, 0, 0, 0, 0, 0 };
|
|
1258
1619
|
size_t const hError = ZSTD_getFrameHeader(&zfp, src, srcSize);
|
|
1259
1620
|
if (ZSTD_isError(hError)) return 0;
|
|
1260
1621
|
return zfp.dictID;
|
|
@@ -1283,7 +1644,7 @@ size_t ZSTD_decompress_usingDDict(ZSTD_DCtx* dctx,
|
|
|
1283
1644
|
ZSTD_DStream* ZSTD_createDStream(void)
|
|
1284
1645
|
{
|
|
1285
1646
|
DEBUGLOG(3, "ZSTD_createDStream");
|
|
1286
|
-
return
|
|
1647
|
+
return ZSTD_createDCtx_internal(ZSTD_defaultCMem);
|
|
1287
1648
|
}
|
|
1288
1649
|
|
|
1289
1650
|
ZSTD_DStream* ZSTD_initStaticDStream(void *workspace, size_t workspaceSize)
|
|
@@ -1293,7 +1654,7 @@ ZSTD_DStream* ZSTD_initStaticDStream(void *workspace, size_t workspaceSize)
|
|
|
1293
1654
|
|
|
1294
1655
|
ZSTD_DStream* ZSTD_createDStream_advanced(ZSTD_customMem customMem)
|
|
1295
1656
|
{
|
|
1296
|
-
return
|
|
1657
|
+
return ZSTD_createDCtx_internal(customMem);
|
|
1297
1658
|
}
|
|
1298
1659
|
|
|
1299
1660
|
size_t ZSTD_freeDStream(ZSTD_DStream* zds)
|
|
@@ -1361,7 +1722,9 @@ size_t ZSTD_initDStream_usingDict(ZSTD_DStream* zds, const void* dict, size_t di
|
|
|
1361
1722
|
size_t ZSTD_initDStream(ZSTD_DStream* zds)
|
|
1362
1723
|
{
|
|
1363
1724
|
DEBUGLOG(4, "ZSTD_initDStream");
|
|
1364
|
-
|
|
1725
|
+
FORWARD_IF_ERROR(ZSTD_DCtx_reset(zds, ZSTD_reset_session_only), "");
|
|
1726
|
+
FORWARD_IF_ERROR(ZSTD_DCtx_refDDict(zds, NULL), "");
|
|
1727
|
+
return ZSTD_startingInputLength(zds->format);
|
|
1365
1728
|
}
|
|
1366
1729
|
|
|
1367
1730
|
/* ZSTD_initDStream_usingDDict() :
|
|
@@ -1369,6 +1732,7 @@ size_t ZSTD_initDStream(ZSTD_DStream* zds)
|
|
|
1369
1732
|
* this function cannot fail */
|
|
1370
1733
|
size_t ZSTD_initDStream_usingDDict(ZSTD_DStream* dctx, const ZSTD_DDict* ddict)
|
|
1371
1734
|
{
|
|
1735
|
+
DEBUGLOG(4, "ZSTD_initDStream_usingDDict");
|
|
1372
1736
|
FORWARD_IF_ERROR( ZSTD_DCtx_reset(dctx, ZSTD_reset_session_only) , "");
|
|
1373
1737
|
FORWARD_IF_ERROR( ZSTD_DCtx_refDDict(dctx, ddict) , "");
|
|
1374
1738
|
return ZSTD_startingInputLength(dctx->format);
|
|
@@ -1379,6 +1743,7 @@ size_t ZSTD_initDStream_usingDDict(ZSTD_DStream* dctx, const ZSTD_DDict* ddict)
|
|
|
1379
1743
|
* this function cannot fail */
|
|
1380
1744
|
size_t ZSTD_resetDStream(ZSTD_DStream* dctx)
|
|
1381
1745
|
{
|
|
1746
|
+
DEBUGLOG(4, "ZSTD_resetDStream");
|
|
1382
1747
|
FORWARD_IF_ERROR(ZSTD_DCtx_reset(dctx, ZSTD_reset_session_only), "");
|
|
1383
1748
|
return ZSTD_startingInputLength(dctx->format);
|
|
1384
1749
|
}
|
|
@@ -1391,6 +1756,16 @@ size_t ZSTD_DCtx_refDDict(ZSTD_DCtx* dctx, const ZSTD_DDict* ddict)
|
|
|
1391
1756
|
if (ddict) {
|
|
1392
1757
|
dctx->ddict = ddict;
|
|
1393
1758
|
dctx->dictUses = ZSTD_use_indefinitely;
|
|
1759
|
+
if (dctx->refMultipleDDicts == ZSTD_rmd_refMultipleDDicts) {
|
|
1760
|
+
if (dctx->ddictSet == NULL) {
|
|
1761
|
+
dctx->ddictSet = ZSTD_createDDictHashSet(dctx->customMem);
|
|
1762
|
+
if (!dctx->ddictSet) {
|
|
1763
|
+
RETURN_ERROR(memory_allocation, "Failed to allocate memory for hash set!");
|
|
1764
|
+
}
|
|
1765
|
+
}
|
|
1766
|
+
assert(!dctx->staticSize); /* Impossible: ddictSet cannot have been allocated if static dctx */
|
|
1767
|
+
FORWARD_IF_ERROR(ZSTD_DDictHashSet_addDDict(dctx->ddictSet, ddict, dctx->customMem), "");
|
|
1768
|
+
}
|
|
1394
1769
|
}
|
|
1395
1770
|
return 0;
|
|
1396
1771
|
}
|
|
@@ -1436,6 +1811,15 @@ ZSTD_bounds ZSTD_dParam_getBounds(ZSTD_dParameter dParam)
|
|
|
1436
1811
|
bounds.lowerBound = (int)ZSTD_d_validateChecksum;
|
|
1437
1812
|
bounds.upperBound = (int)ZSTD_d_ignoreChecksum;
|
|
1438
1813
|
return bounds;
|
|
1814
|
+
case ZSTD_d_refMultipleDDicts:
|
|
1815
|
+
bounds.lowerBound = (int)ZSTD_rmd_refSingleDDict;
|
|
1816
|
+
bounds.upperBound = (int)ZSTD_rmd_refMultipleDDicts;
|
|
1817
|
+
return bounds;
|
|
1818
|
+
case ZSTD_d_disableHuffmanAssembly:
|
|
1819
|
+
bounds.lowerBound = 0;
|
|
1820
|
+
bounds.upperBound = 1;
|
|
1821
|
+
return bounds;
|
|
1822
|
+
|
|
1439
1823
|
default:;
|
|
1440
1824
|
}
|
|
1441
1825
|
bounds.error = ERROR(parameter_unsupported);
|
|
@@ -1473,6 +1857,12 @@ size_t ZSTD_DCtx_getParameter(ZSTD_DCtx* dctx, ZSTD_dParameter param, int* value
|
|
|
1473
1857
|
case ZSTD_d_forceIgnoreChecksum:
|
|
1474
1858
|
*value = (int)dctx->forceIgnoreChecksum;
|
|
1475
1859
|
return 0;
|
|
1860
|
+
case ZSTD_d_refMultipleDDicts:
|
|
1861
|
+
*value = (int)dctx->refMultipleDDicts;
|
|
1862
|
+
return 0;
|
|
1863
|
+
case ZSTD_d_disableHuffmanAssembly:
|
|
1864
|
+
*value = (int)dctx->disableHufAsm;
|
|
1865
|
+
return 0;
|
|
1476
1866
|
default:;
|
|
1477
1867
|
}
|
|
1478
1868
|
RETURN_ERROR(parameter_unsupported, "");
|
|
@@ -1499,6 +1889,17 @@ size_t ZSTD_DCtx_setParameter(ZSTD_DCtx* dctx, ZSTD_dParameter dParam, int value
|
|
|
1499
1889
|
CHECK_DBOUNDS(ZSTD_d_forceIgnoreChecksum, value);
|
|
1500
1890
|
dctx->forceIgnoreChecksum = (ZSTD_forceIgnoreChecksum_e)value;
|
|
1501
1891
|
return 0;
|
|
1892
|
+
case ZSTD_d_refMultipleDDicts:
|
|
1893
|
+
CHECK_DBOUNDS(ZSTD_d_refMultipleDDicts, value);
|
|
1894
|
+
if (dctx->staticSize != 0) {
|
|
1895
|
+
RETURN_ERROR(parameter_unsupported, "Static dctx does not support multiple DDicts!");
|
|
1896
|
+
}
|
|
1897
|
+
dctx->refMultipleDDicts = (ZSTD_refMultipleDDicts_e)value;
|
|
1898
|
+
return 0;
|
|
1899
|
+
case ZSTD_d_disableHuffmanAssembly:
|
|
1900
|
+
CHECK_DBOUNDS(ZSTD_d_disableHuffmanAssembly, value);
|
|
1901
|
+
dctx->disableHufAsm = value != 0;
|
|
1902
|
+
return 0;
|
|
1502
1903
|
default:;
|
|
1503
1904
|
}
|
|
1504
1905
|
RETURN_ERROR(parameter_unsupported, "");
|
|
@@ -1529,7 +1930,8 @@ size_t ZSTD_sizeof_DStream(const ZSTD_DStream* dctx)
|
|
|
1529
1930
|
size_t ZSTD_decodingBufferSize_min(unsigned long long windowSize, unsigned long long frameContentSize)
|
|
1530
1931
|
{
|
|
1531
1932
|
size_t const blockSize = (size_t) MIN(windowSize, ZSTD_BLOCKSIZE_MAX);
|
|
1532
|
-
|
|
1933
|
+
/* space is needed to store the litbuffer after the output of a given block without stomping the extDict of a previous run, as well as to cover both windows against wildcopy*/
|
|
1934
|
+
unsigned long long const neededRBSize = windowSize + blockSize + ZSTD_BLOCKSIZE_MAX + (WILDCOPY_OVERLENGTH * 2);
|
|
1533
1935
|
unsigned long long const neededSize = MIN(frameContentSize, neededRBSize);
|
|
1534
1936
|
size_t const minRBSize = (size_t) neededSize;
|
|
1535
1937
|
RETURN_ERROR_IF((unsigned long long)minRBSize != neededSize,
|
|
@@ -1663,10 +2065,12 @@ size_t ZSTD_decompressStream(ZSTD_DStream* zds, ZSTD_outBuffer* output, ZSTD_inB
|
|
|
1663
2065
|
DEBUGLOG(5, "stage zdss_init => transparent reset ");
|
|
1664
2066
|
zds->streamStage = zdss_loadHeader;
|
|
1665
2067
|
zds->lhSize = zds->inPos = zds->outStart = zds->outEnd = 0;
|
|
2068
|
+
#if defined(ZSTD_LEGACY_SUPPORT) && (ZSTD_LEGACY_SUPPORT>=1)
|
|
1666
2069
|
zds->legacyVersion = 0;
|
|
2070
|
+
#endif
|
|
1667
2071
|
zds->hostageByte = 0;
|
|
1668
2072
|
zds->expectedOutBuffer = *output;
|
|
1669
|
-
|
|
2073
|
+
ZSTD_FALLTHROUGH;
|
|
1670
2074
|
|
|
1671
2075
|
case zdss_loadHeader :
|
|
1672
2076
|
DEBUGLOG(5, "stage zdss_loadHeader (srcSize : %u)", (U32)(iend - ip));
|
|
@@ -1680,7 +2084,9 @@ size_t ZSTD_decompressStream(ZSTD_DStream* zds, ZSTD_outBuffer* output, ZSTD_inB
|
|
|
1680
2084
|
} }
|
|
1681
2085
|
#endif
|
|
1682
2086
|
{ size_t const hSize = ZSTD_getFrameHeader_advanced(&zds->fParams, zds->headerBuffer, zds->lhSize, zds->format);
|
|
1683
|
-
|
|
2087
|
+
if (zds->refMultipleDDicts && zds->ddictSet) {
|
|
2088
|
+
ZSTD_DCtx_selectFrameDDict(zds);
|
|
2089
|
+
}
|
|
1684
2090
|
if (ZSTD_isError(hSize)) {
|
|
1685
2091
|
#if defined(ZSTD_LEGACY_SUPPORT) && (ZSTD_LEGACY_SUPPORT>=1)
|
|
1686
2092
|
U32 const legacyVersion = ZSTD_isLegacy(istart, iend-istart);
|
|
@@ -1712,6 +2118,11 @@ size_t ZSTD_decompressStream(ZSTD_DStream* zds, ZSTD_outBuffer* output, ZSTD_inB
|
|
|
1712
2118
|
zds->lhSize += remainingInput;
|
|
1713
2119
|
}
|
|
1714
2120
|
input->pos = input->size;
|
|
2121
|
+
/* check first few bytes */
|
|
2122
|
+
FORWARD_IF_ERROR(
|
|
2123
|
+
ZSTD_getFrameHeader_advanced(&zds->fParams, zds->headerBuffer, zds->lhSize, zds->format),
|
|
2124
|
+
"First few bytes detected incorrect" );
|
|
2125
|
+
/* return hint input size */
|
|
1715
2126
|
return (MAX((size_t)ZSTD_FRAMEHEADERSIZE_MIN(zds->format), hSize) - zds->lhSize) + ZSTD_blockHeaderSize; /* remaining header bytes + next block header */
|
|
1716
2127
|
}
|
|
1717
2128
|
assert(ip != NULL);
|
|
@@ -1729,8 +2140,9 @@ size_t ZSTD_decompressStream(ZSTD_DStream* zds, ZSTD_outBuffer* output, ZSTD_inB
|
|
|
1729
2140
|
size_t const decompressedSize = ZSTD_decompress_usingDDict(zds, op, (size_t)(oend-op), istart, cSize, ZSTD_getDDict(zds));
|
|
1730
2141
|
if (ZSTD_isError(decompressedSize)) return decompressedSize;
|
|
1731
2142
|
DEBUGLOG(4, "shortcut to single-pass ZSTD_decompress_usingDDict()")
|
|
2143
|
+
assert(istart != NULL);
|
|
1732
2144
|
ip = istart + cSize;
|
|
1733
|
-
op
|
|
2145
|
+
op = op ? op + decompressedSize : op; /* can occur if frameContentSize = 0 (empty frame) */
|
|
1734
2146
|
zds->expected = 0;
|
|
1735
2147
|
zds->streamStage = zdss_init;
|
|
1736
2148
|
someMoreWork = 0;
|
|
@@ -1801,7 +2213,7 @@ size_t ZSTD_decompressStream(ZSTD_DStream* zds, ZSTD_outBuffer* output, ZSTD_inB
|
|
|
1801
2213
|
zds->outBuffSize = neededOutBuffSize;
|
|
1802
2214
|
} } }
|
|
1803
2215
|
zds->streamStage = zdss_read;
|
|
1804
|
-
|
|
2216
|
+
ZSTD_FALLTHROUGH;
|
|
1805
2217
|
|
|
1806
2218
|
case zdss_read:
|
|
1807
2219
|
DEBUGLOG(5, "stage zdss_read");
|
|
@@ -1814,13 +2226,14 @@ size_t ZSTD_decompressStream(ZSTD_DStream* zds, ZSTD_outBuffer* output, ZSTD_inB
|
|
|
1814
2226
|
}
|
|
1815
2227
|
if ((size_t)(iend-ip) >= neededInSize) { /* decode directly from src */
|
|
1816
2228
|
FORWARD_IF_ERROR(ZSTD_decompressContinueStream(zds, &op, oend, ip, neededInSize), "");
|
|
2229
|
+
assert(ip != NULL);
|
|
1817
2230
|
ip += neededInSize;
|
|
1818
2231
|
/* Function modifies the stage so we must break */
|
|
1819
2232
|
break;
|
|
1820
2233
|
} }
|
|
1821
2234
|
if (ip==iend) { someMoreWork = 0; break; } /* no more input */
|
|
1822
2235
|
zds->streamStage = zdss_load;
|
|
1823
|
-
|
|
2236
|
+
ZSTD_FALLTHROUGH;
|
|
1824
2237
|
|
|
1825
2238
|
case zdss_load:
|
|
1826
2239
|
{ size_t const neededInSize = ZSTD_nextSrcSizeToDecompress(zds);
|
|
@@ -1828,7 +2241,7 @@ size_t ZSTD_decompressStream(ZSTD_DStream* zds, ZSTD_outBuffer* output, ZSTD_inB
|
|
|
1828
2241
|
int const isSkipFrame = ZSTD_isSkipFrame(zds);
|
|
1829
2242
|
size_t loadedSize;
|
|
1830
2243
|
/* At this point we shouldn't be decompressing a block that we can stream. */
|
|
1831
|
-
assert(neededInSize == ZSTD_nextSrcSizeToDecompressWithInputSize(zds, iend - ip));
|
|
2244
|
+
assert(neededInSize == ZSTD_nextSrcSizeToDecompressWithInputSize(zds, (size_t)(iend - ip)));
|
|
1832
2245
|
if (isSkipFrame) {
|
|
1833
2246
|
loadedSize = MIN(toLoad, (size_t)(iend-ip));
|
|
1834
2247
|
} else {
|
|
@@ -1837,8 +2250,11 @@ size_t ZSTD_decompressStream(ZSTD_DStream* zds, ZSTD_outBuffer* output, ZSTD_inB
|
|
|
1837
2250
|
"should never happen");
|
|
1838
2251
|
loadedSize = ZSTD_limitCopy(zds->inBuff + zds->inPos, toLoad, ip, (size_t)(iend-ip));
|
|
1839
2252
|
}
|
|
1840
|
-
|
|
1841
|
-
|
|
2253
|
+
if (loadedSize != 0) {
|
|
2254
|
+
/* ip may be NULL */
|
|
2255
|
+
ip += loadedSize;
|
|
2256
|
+
zds->inPos += loadedSize;
|
|
2257
|
+
}
|
|
1842
2258
|
if (loadedSize < toLoad) { someMoreWork = 0; break; } /* not enough input, wait for more */
|
|
1843
2259
|
|
|
1844
2260
|
/* decode loaded input */
|
|
@@ -1848,14 +2264,17 @@ size_t ZSTD_decompressStream(ZSTD_DStream* zds, ZSTD_outBuffer* output, ZSTD_inB
|
|
|
1848
2264
|
break;
|
|
1849
2265
|
}
|
|
1850
2266
|
case zdss_flush:
|
|
1851
|
-
{
|
|
2267
|
+
{
|
|
2268
|
+
size_t const toFlushSize = zds->outEnd - zds->outStart;
|
|
1852
2269
|
size_t const flushedSize = ZSTD_limitCopy(op, (size_t)(oend-op), zds->outBuff + zds->outStart, toFlushSize);
|
|
1853
|
-
|
|
2270
|
+
|
|
2271
|
+
op = op ? op + flushedSize : op;
|
|
2272
|
+
|
|
1854
2273
|
zds->outStart += flushedSize;
|
|
1855
2274
|
if (flushedSize == toFlushSize) { /* flush completed */
|
|
1856
2275
|
zds->streamStage = zdss_read;
|
|
1857
2276
|
if ( (zds->outBuffSize < zds->fParams.frameContentSize)
|
|
1858
|
-
|
|
2277
|
+
&& (zds->outStart + zds->fParams.blockSizeMax > zds->outBuffSize) ) {
|
|
1859
2278
|
DEBUGLOG(5, "restart filling outBuff from beginning (left:%i, needed:%u)",
|
|
1860
2279
|
(int)(zds->outBuffSize - zds->outStart),
|
|
1861
2280
|
(U32)zds->fParams.blockSizeMax);
|
|
@@ -1869,7 +2288,7 @@ size_t ZSTD_decompressStream(ZSTD_DStream* zds, ZSTD_outBuffer* output, ZSTD_inB
|
|
|
1869
2288
|
|
|
1870
2289
|
default:
|
|
1871
2290
|
assert(0); /* impossible */
|
|
1872
|
-
RETURN_ERROR(GENERIC, "impossible to reach"); /* some
|
|
2291
|
+
RETURN_ERROR(GENERIC, "impossible to reach"); /* some compilers require default to do something */
|
|
1873
2292
|
} }
|
|
1874
2293
|
|
|
1875
2294
|
/* result */
|
|
@@ -1882,8 +2301,8 @@ size_t ZSTD_decompressStream(ZSTD_DStream* zds, ZSTD_outBuffer* output, ZSTD_inB
|
|
|
1882
2301
|
if ((ip==istart) && (op==ostart)) { /* no forward progress */
|
|
1883
2302
|
zds->noForwardProgress ++;
|
|
1884
2303
|
if (zds->noForwardProgress >= ZSTD_NO_FORWARD_PROGRESS_MAX) {
|
|
1885
|
-
RETURN_ERROR_IF(op==oend,
|
|
1886
|
-
RETURN_ERROR_IF(ip==iend,
|
|
2304
|
+
RETURN_ERROR_IF(op==oend, noForwardProgress_destFull, "");
|
|
2305
|
+
RETURN_ERROR_IF(ip==iend, noForwardProgress_inputEmpty, "");
|
|
1887
2306
|
assert(0);
|
|
1888
2307
|
}
|
|
1889
2308
|
} else {
|
|
@@ -1920,11 +2339,17 @@ size_t ZSTD_decompressStream_simpleArgs (
|
|
|
1920
2339
|
void* dst, size_t dstCapacity, size_t* dstPos,
|
|
1921
2340
|
const void* src, size_t srcSize, size_t* srcPos)
|
|
1922
2341
|
{
|
|
1923
|
-
ZSTD_outBuffer output
|
|
1924
|
-
ZSTD_inBuffer input
|
|
1925
|
-
|
|
1926
|
-
|
|
1927
|
-
|
|
1928
|
-
|
|
1929
|
-
|
|
2342
|
+
ZSTD_outBuffer output;
|
|
2343
|
+
ZSTD_inBuffer input;
|
|
2344
|
+
output.dst = dst;
|
|
2345
|
+
output.size = dstCapacity;
|
|
2346
|
+
output.pos = *dstPos;
|
|
2347
|
+
input.src = src;
|
|
2348
|
+
input.size = srcSize;
|
|
2349
|
+
input.pos = *srcPos;
|
|
2350
|
+
{ size_t const cErr = ZSTD_decompressStream(dctx, &output, &input);
|
|
2351
|
+
*dstPos = output.pos;
|
|
2352
|
+
*srcPos = input.pos;
|
|
2353
|
+
return cErr;
|
|
2354
|
+
}
|
|
1930
2355
|
}
|