zstd-ruby 1.4.4.0 → 1.5.5.0
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/.gitignore +2 -0
- data/README.md +78 -5
- data/Rakefile +8 -2
- data/ext/zstdruby/common.h +15 -0
- data/ext/zstdruby/extconf.rb +3 -2
- data/ext/zstdruby/libzstd/common/allocations.h +55 -0
- data/ext/zstdruby/libzstd/common/bits.h +200 -0
- data/ext/zstdruby/libzstd/common/bitstream.h +74 -97
- data/ext/zstdruby/libzstd/common/compiler.h +219 -20
- data/ext/zstdruby/libzstd/common/cpu.h +1 -3
- data/ext/zstdruby/libzstd/common/debug.c +11 -31
- data/ext/zstdruby/libzstd/common/debug.h +22 -49
- data/ext/zstdruby/libzstd/common/entropy_common.c +184 -80
- data/ext/zstdruby/libzstd/common/error_private.c +11 -2
- data/ext/zstdruby/libzstd/common/error_private.h +87 -4
- data/ext/zstdruby/libzstd/common/fse.h +47 -116
- data/ext/zstdruby/libzstd/common/fse_decompress.c +127 -127
- data/ext/zstdruby/libzstd/common/huf.h +112 -197
- data/ext/zstdruby/libzstd/common/mem.h +124 -142
- data/ext/zstdruby/libzstd/common/pool.c +54 -27
- data/ext/zstdruby/libzstd/common/pool.h +11 -5
- data/ext/zstdruby/libzstd/common/portability_macros.h +156 -0
- data/ext/zstdruby/libzstd/common/threading.c +78 -22
- data/ext/zstdruby/libzstd/common/threading.h +9 -13
- data/ext/zstdruby/libzstd/common/xxhash.c +15 -873
- data/ext/zstdruby/libzstd/common/xxhash.h +5572 -191
- data/ext/zstdruby/libzstd/common/zstd_common.c +2 -37
- data/ext/zstdruby/libzstd/common/zstd_deps.h +111 -0
- data/ext/zstdruby/libzstd/common/zstd_internal.h +186 -144
- data/ext/zstdruby/libzstd/common/zstd_trace.h +163 -0
- data/ext/zstdruby/libzstd/compress/clevels.h +134 -0
- data/ext/zstdruby/libzstd/compress/fse_compress.c +99 -196
- data/ext/zstdruby/libzstd/compress/hist.c +41 -63
- data/ext/zstdruby/libzstd/compress/hist.h +13 -33
- data/ext/zstdruby/libzstd/compress/huf_compress.c +968 -331
- data/ext/zstdruby/libzstd/compress/zstd_compress.c +4120 -1191
- data/ext/zstdruby/libzstd/compress/zstd_compress_internal.h +688 -159
- data/ext/zstdruby/libzstd/compress/zstd_compress_literals.c +121 -40
- data/ext/zstdruby/libzstd/compress/zstd_compress_literals.h +16 -6
- data/ext/zstdruby/libzstd/compress/zstd_compress_sequences.c +62 -35
- data/ext/zstdruby/libzstd/compress/zstd_compress_sequences.h +10 -3
- data/ext/zstdruby/libzstd/compress/zstd_compress_superblock.c +577 -0
- data/ext/zstdruby/libzstd/compress/zstd_compress_superblock.h +32 -0
- data/ext/zstdruby/libzstd/compress/zstd_cwksp.h +322 -115
- data/ext/zstdruby/libzstd/compress/zstd_double_fast.c +394 -154
- data/ext/zstdruby/libzstd/compress/zstd_double_fast.h +4 -3
- data/ext/zstdruby/libzstd/compress/zstd_fast.c +729 -253
- data/ext/zstdruby/libzstd/compress/zstd_fast.h +4 -3
- data/ext/zstdruby/libzstd/compress/zstd_lazy.c +1289 -247
- data/ext/zstdruby/libzstd/compress/zstd_lazy.h +61 -1
- data/ext/zstdruby/libzstd/compress/zstd_ldm.c +339 -212
- data/ext/zstdruby/libzstd/compress/zstd_ldm.h +15 -3
- data/ext/zstdruby/libzstd/compress/zstd_ldm_geartab.h +106 -0
- data/ext/zstdruby/libzstd/compress/zstd_opt.c +508 -282
- data/ext/zstdruby/libzstd/compress/zstd_opt.h +1 -1
- data/ext/zstdruby/libzstd/compress/zstdmt_compress.c +217 -466
- data/ext/zstdruby/libzstd/compress/zstdmt_compress.h +35 -114
- data/ext/zstdruby/libzstd/decompress/huf_decompress.c +1220 -572
- data/ext/zstdruby/libzstd/decompress/huf_decompress_amd64.S +576 -0
- data/ext/zstdruby/libzstd/decompress/zstd_ddict.c +23 -19
- data/ext/zstdruby/libzstd/decompress/zstd_ddict.h +3 -3
- data/ext/zstdruby/libzstd/decompress/zstd_decompress.c +859 -273
- data/ext/zstdruby/libzstd/decompress/zstd_decompress_block.c +1244 -375
- data/ext/zstdruby/libzstd/decompress/zstd_decompress_block.h +21 -7
- data/ext/zstdruby/libzstd/decompress/zstd_decompress_internal.h +74 -11
- data/ext/zstdruby/libzstd/dictBuilder/cover.c +75 -54
- data/ext/zstdruby/libzstd/dictBuilder/cover.h +20 -9
- data/ext/zstdruby/libzstd/dictBuilder/divsufsort.c +1 -1
- data/ext/zstdruby/libzstd/dictBuilder/fastcover.c +55 -36
- data/ext/zstdruby/libzstd/dictBuilder/zdict.c +126 -110
- data/ext/zstdruby/libzstd/{dictBuilder/zdict.h → zdict.h} +248 -56
- data/ext/zstdruby/libzstd/zstd.h +1277 -306
- data/ext/zstdruby/libzstd/{common/zstd_errors.h → zstd_errors.h} +29 -8
- data/ext/zstdruby/main.c +20 -0
- data/ext/zstdruby/skippable_frame.c +63 -0
- data/ext/zstdruby/streaming_compress.c +177 -0
- data/ext/zstdruby/streaming_compress.h +5 -0
- data/ext/zstdruby/streaming_decompress.c +123 -0
- data/ext/zstdruby/zstdruby.c +114 -32
- data/lib/zstd-ruby/version.rb +1 -1
- data/lib/zstd-ruby.rb +0 -1
- data/zstd-ruby.gemspec +1 -1
- metadata +24 -39
- data/.travis.yml +0 -14
- data/ext/zstdruby/libzstd/.gitignore +0 -3
- data/ext/zstdruby/libzstd/BUCK +0 -234
- data/ext/zstdruby/libzstd/Makefile +0 -289
- data/ext/zstdruby/libzstd/README.md +0 -159
- data/ext/zstdruby/libzstd/deprecated/zbuff.h +0 -214
- data/ext/zstdruby/libzstd/deprecated/zbuff_common.c +0 -26
- data/ext/zstdruby/libzstd/deprecated/zbuff_compress.c +0 -147
- data/ext/zstdruby/libzstd/deprecated/zbuff_decompress.c +0 -75
- data/ext/zstdruby/libzstd/dll/example/Makefile +0 -47
- data/ext/zstdruby/libzstd/dll/example/README.md +0 -69
- data/ext/zstdruby/libzstd/dll/example/build_package.bat +0 -20
- data/ext/zstdruby/libzstd/dll/example/fullbench-dll.sln +0 -25
- data/ext/zstdruby/libzstd/dll/example/fullbench-dll.vcxproj +0 -181
- data/ext/zstdruby/libzstd/legacy/zstd_legacy.h +0 -415
- data/ext/zstdruby/libzstd/legacy/zstd_v01.c +0 -2152
- data/ext/zstdruby/libzstd/legacy/zstd_v01.h +0 -94
- data/ext/zstdruby/libzstd/legacy/zstd_v02.c +0 -3514
- data/ext/zstdruby/libzstd/legacy/zstd_v02.h +0 -93
- data/ext/zstdruby/libzstd/legacy/zstd_v03.c +0 -3156
- data/ext/zstdruby/libzstd/legacy/zstd_v03.h +0 -93
- data/ext/zstdruby/libzstd/legacy/zstd_v04.c +0 -3641
- data/ext/zstdruby/libzstd/legacy/zstd_v04.h +0 -142
- data/ext/zstdruby/libzstd/legacy/zstd_v05.c +0 -4046
- data/ext/zstdruby/libzstd/legacy/zstd_v05.h +0 -162
- data/ext/zstdruby/libzstd/legacy/zstd_v06.c +0 -4150
- data/ext/zstdruby/libzstd/legacy/zstd_v06.h +0 -172
- data/ext/zstdruby/libzstd/legacy/zstd_v07.c +0 -4533
- data/ext/zstdruby/libzstd/legacy/zstd_v07.h +0 -187
- data/ext/zstdruby/libzstd/libzstd.pc.in +0 -15
- data/ext/zstdruby/zstdruby.h +0 -6
|
@@ -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
|
|
59
|
-
#include "
|
|
60
|
-
#include "mem.h" /* low level memory routines */
|
|
58
|
+
#include "../common/allocations.h" /* ZSTD_customMalloc, ZSTD_customCalloc, ZSTD_customFree */
|
|
59
|
+
#include "../common/zstd_deps.h" /* ZSTD_memcpy, ZSTD_memmove, ZSTD_memset */
|
|
60
|
+
#include "../common/mem.h" /* low level memory routines */
|
|
61
61
|
#define FSE_STATIC_LINKING_ONLY
|
|
62
|
-
#include "fse.h"
|
|
63
|
-
#
|
|
64
|
-
#include "
|
|
65
|
-
#include "zstd_internal.h" /* blockProperties_t */
|
|
62
|
+
#include "../common/fse.h"
|
|
63
|
+
#include "../common/huf.h"
|
|
64
|
+
#include "../common/xxhash.h" /* XXH64_reset, XXH64_update, XXH64_digest, XXH64 */
|
|
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
|
-
# include "zstd_legacy.h"
|
|
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
|
***************************************************************/
|
|
@@ -94,11 +236,20 @@ static size_t ZSTD_startingInputLength(ZSTD_format_e format)
|
|
|
94
236
|
return startingInputLength;
|
|
95
237
|
}
|
|
96
238
|
|
|
239
|
+
static void ZSTD_DCtx_resetParameters(ZSTD_DCtx* dctx)
|
|
240
|
+
{
|
|
241
|
+
assert(dctx->streamStage == zdss_init);
|
|
242
|
+
dctx->format = ZSTD_f_zstd1;
|
|
243
|
+
dctx->maxWindowSize = ZSTD_MAXWINDOWSIZE_DEFAULT;
|
|
244
|
+
dctx->outBufferMode = ZSTD_bm_buffered;
|
|
245
|
+
dctx->forceIgnoreChecksum = ZSTD_d_validateChecksum;
|
|
246
|
+
dctx->refMultipleDDicts = ZSTD_rmd_refSingleDDict;
|
|
247
|
+
dctx->disableHufAsm = 0;
|
|
248
|
+
}
|
|
249
|
+
|
|
97
250
|
static void ZSTD_initDCtx_internal(ZSTD_DCtx* dctx)
|
|
98
251
|
{
|
|
99
|
-
dctx->format = ZSTD_f_zstd1; /* ZSTD_decompressBegin() invokes ZSTD_startingInputLength() with argument dctx->format */
|
|
100
252
|
dctx->staticSize = 0;
|
|
101
|
-
dctx->maxWindowSize = ZSTD_MAXWINDOWSIZE_DEFAULT;
|
|
102
253
|
dctx->ddict = NULL;
|
|
103
254
|
dctx->ddictLocal = NULL;
|
|
104
255
|
dctx->dictEnd = NULL;
|
|
@@ -108,10 +259,20 @@ static void ZSTD_initDCtx_internal(ZSTD_DCtx* dctx)
|
|
|
108
259
|
dctx->inBuffSize = 0;
|
|
109
260
|
dctx->outBuffSize = 0;
|
|
110
261
|
dctx->streamStage = zdss_init;
|
|
262
|
+
#if defined(ZSTD_LEGACY_SUPPORT) && (ZSTD_LEGACY_SUPPORT>=1)
|
|
111
263
|
dctx->legacyContext = NULL;
|
|
112
264
|
dctx->previousLegacyVersion = 0;
|
|
265
|
+
#endif
|
|
113
266
|
dctx->noForwardProgress = 0;
|
|
114
|
-
dctx->
|
|
267
|
+
dctx->oversizedDuration = 0;
|
|
268
|
+
#if DYNAMIC_BMI2
|
|
269
|
+
dctx->bmi2 = ZSTD_cpuSupportsBmi2();
|
|
270
|
+
#endif
|
|
271
|
+
dctx->ddictSet = NULL;
|
|
272
|
+
ZSTD_DCtx_resetParameters(dctx);
|
|
273
|
+
#ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
|
|
274
|
+
dctx->dictContentEndForFuzzing = NULL;
|
|
275
|
+
#endif
|
|
115
276
|
}
|
|
116
277
|
|
|
117
278
|
ZSTD_DCtx* ZSTD_initStaticDCtx(void *workspace, size_t workspaceSize)
|
|
@@ -127,11 +288,10 @@ ZSTD_DCtx* ZSTD_initStaticDCtx(void *workspace, size_t workspaceSize)
|
|
|
127
288
|
return dctx;
|
|
128
289
|
}
|
|
129
290
|
|
|
130
|
-
ZSTD_DCtx*
|
|
131
|
-
|
|
132
|
-
if (!customMem.customAlloc ^ !customMem.customFree) return NULL;
|
|
291
|
+
static ZSTD_DCtx* ZSTD_createDCtx_internal(ZSTD_customMem customMem) {
|
|
292
|
+
if ((!customMem.customAlloc) ^ (!customMem.customFree)) return NULL;
|
|
133
293
|
|
|
134
|
-
{ ZSTD_DCtx* const dctx = (ZSTD_DCtx*)
|
|
294
|
+
{ ZSTD_DCtx* const dctx = (ZSTD_DCtx*)ZSTD_customMalloc(sizeof(*dctx), customMem);
|
|
135
295
|
if (!dctx) return NULL;
|
|
136
296
|
dctx->customMem = customMem;
|
|
137
297
|
ZSTD_initDCtx_internal(dctx);
|
|
@@ -139,10 +299,15 @@ ZSTD_DCtx* ZSTD_createDCtx_advanced(ZSTD_customMem customMem)
|
|
|
139
299
|
}
|
|
140
300
|
}
|
|
141
301
|
|
|
302
|
+
ZSTD_DCtx* ZSTD_createDCtx_advanced(ZSTD_customMem customMem)
|
|
303
|
+
{
|
|
304
|
+
return ZSTD_createDCtx_internal(customMem);
|
|
305
|
+
}
|
|
306
|
+
|
|
142
307
|
ZSTD_DCtx* ZSTD_createDCtx(void)
|
|
143
308
|
{
|
|
144
309
|
DEBUGLOG(3, "ZSTD_createDCtx");
|
|
145
|
-
return
|
|
310
|
+
return ZSTD_createDCtx_internal(ZSTD_defaultCMem);
|
|
146
311
|
}
|
|
147
312
|
|
|
148
313
|
static void ZSTD_clearDict(ZSTD_DCtx* dctx)
|
|
@@ -159,13 +324,17 @@ size_t ZSTD_freeDCtx(ZSTD_DCtx* dctx)
|
|
|
159
324
|
RETURN_ERROR_IF(dctx->staticSize, memory_allocation, "not compatible with static DCtx");
|
|
160
325
|
{ ZSTD_customMem const cMem = dctx->customMem;
|
|
161
326
|
ZSTD_clearDict(dctx);
|
|
162
|
-
|
|
327
|
+
ZSTD_customFree(dctx->inBuff, cMem);
|
|
163
328
|
dctx->inBuff = NULL;
|
|
164
329
|
#if defined(ZSTD_LEGACY_SUPPORT) && (ZSTD_LEGACY_SUPPORT >= 1)
|
|
165
330
|
if (dctx->legacyContext)
|
|
166
331
|
ZSTD_freeLegacyStreamContext(dctx->legacyContext, dctx->previousLegacyVersion);
|
|
167
332
|
#endif
|
|
168
|
-
|
|
333
|
+
if (dctx->ddictSet) {
|
|
334
|
+
ZSTD_freeDDictHashSet(dctx->ddictSet, cMem);
|
|
335
|
+
dctx->ddictSet = NULL;
|
|
336
|
+
}
|
|
337
|
+
ZSTD_customFree(dctx, cMem);
|
|
169
338
|
return 0;
|
|
170
339
|
}
|
|
171
340
|
}
|
|
@@ -174,7 +343,30 @@ size_t ZSTD_freeDCtx(ZSTD_DCtx* dctx)
|
|
|
174
343
|
void ZSTD_copyDCtx(ZSTD_DCtx* dstDCtx, const ZSTD_DCtx* srcDCtx)
|
|
175
344
|
{
|
|
176
345
|
size_t const toCopy = (size_t)((char*)(&dstDCtx->inBuff) - (char*)dstDCtx);
|
|
177
|
-
|
|
346
|
+
ZSTD_memcpy(dstDCtx, srcDCtx, toCopy); /* no need to copy workspace */
|
|
347
|
+
}
|
|
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
|
+
}
|
|
178
370
|
}
|
|
179
371
|
|
|
180
372
|
|
|
@@ -200,6 +392,19 @@ unsigned ZSTD_isFrame(const void* buffer, size_t size)
|
|
|
200
392
|
return 0;
|
|
201
393
|
}
|
|
202
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
|
+
|
|
203
408
|
/** ZSTD_frameHeaderSize_internal() :
|
|
204
409
|
* srcSize must be large enough to reach header size fields.
|
|
205
410
|
* note : only works for formats ZSTD_f_zstd1 and ZSTD_f_zstd1_magicless.
|
|
@@ -208,7 +413,7 @@ unsigned ZSTD_isFrame(const void* buffer, size_t size)
|
|
|
208
413
|
static size_t ZSTD_frameHeaderSize_internal(const void* src, size_t srcSize, ZSTD_format_e format)
|
|
209
414
|
{
|
|
210
415
|
size_t const minInputSize = ZSTD_startingInputLength(format);
|
|
211
|
-
RETURN_ERROR_IF(srcSize < minInputSize, srcSize_wrong);
|
|
416
|
+
RETURN_ERROR_IF(srcSize < minInputSize, srcSize_wrong, "");
|
|
212
417
|
|
|
213
418
|
{ BYTE const fhd = ((const BYTE*)src)[minInputSize-1];
|
|
214
419
|
U32 const dictID= fhd & 3;
|
|
@@ -235,28 +440,52 @@ size_t ZSTD_frameHeaderSize(const void* src, size_t srcSize)
|
|
|
235
440
|
* note : only works for formats ZSTD_f_zstd1 and ZSTD_f_zstd1_magicless
|
|
236
441
|
* @return : 0, `zfhPtr` is correctly filled,
|
|
237
442
|
* >0, `srcSize` is too small, value is wanted `srcSize` amount,
|
|
238
|
-
|
|
443
|
+
** or an error code, which can be tested using ZSTD_isError() */
|
|
239
444
|
size_t ZSTD_getFrameHeader_advanced(ZSTD_frameHeader* zfhPtr, const void* src, size_t srcSize, ZSTD_format_e format)
|
|
240
445
|
{
|
|
241
446
|
const BYTE* ip = (const BYTE*)src;
|
|
242
447
|
size_t const minInputSize = ZSTD_startingInputLength(format);
|
|
243
448
|
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
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
|
+
}
|
|
247
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 */
|
|
248
477
|
if ( (format != ZSTD_f_zstd1_magicless)
|
|
249
478
|
&& (MEM_readLE32(src) != ZSTD_MAGICNUMBER) ) {
|
|
250
479
|
if ((MEM_readLE32(src) & ZSTD_MAGIC_SKIPPABLE_MASK) == ZSTD_MAGIC_SKIPPABLE_START) {
|
|
251
480
|
/* skippable frame */
|
|
252
481
|
if (srcSize < ZSTD_SKIPPABLEHEADERSIZE)
|
|
253
482
|
return ZSTD_SKIPPABLEHEADERSIZE; /* magic number + frame length */
|
|
254
|
-
|
|
483
|
+
ZSTD_memset(zfhPtr, 0, sizeof(*zfhPtr));
|
|
255
484
|
zfhPtr->frameContentSize = MEM_readLE32((const char *)src + ZSTD_FRAMEIDSIZE);
|
|
256
485
|
zfhPtr->frameType = ZSTD_skippableFrame;
|
|
257
486
|
return 0;
|
|
258
487
|
}
|
|
259
|
-
RETURN_ERROR(prefix_unknown);
|
|
488
|
+
RETURN_ERROR(prefix_unknown, "");
|
|
260
489
|
}
|
|
261
490
|
|
|
262
491
|
/* ensure there is enough `srcSize` to fully read/decode frame header */
|
|
@@ -280,13 +509,15 @@ size_t ZSTD_getFrameHeader_advanced(ZSTD_frameHeader* zfhPtr, const void* src, s
|
|
|
280
509
|
if (!singleSegment) {
|
|
281
510
|
BYTE const wlByte = ip[pos++];
|
|
282
511
|
U32 const windowLog = (wlByte >> 3) + ZSTD_WINDOWLOG_ABSOLUTEMIN;
|
|
283
|
-
RETURN_ERROR_IF(windowLog > ZSTD_WINDOWLOG_MAX, frameParameter_windowTooLarge);
|
|
512
|
+
RETURN_ERROR_IF(windowLog > ZSTD_WINDOWLOG_MAX, frameParameter_windowTooLarge, "");
|
|
284
513
|
windowSize = (1ULL << windowLog);
|
|
285
514
|
windowSize += (windowSize >> 3) * (wlByte&7);
|
|
286
515
|
}
|
|
287
516
|
switch(dictIDSizeCode)
|
|
288
517
|
{
|
|
289
|
-
default:
|
|
518
|
+
default:
|
|
519
|
+
assert(0); /* impossible */
|
|
520
|
+
ZSTD_FALLTHROUGH;
|
|
290
521
|
case 0 : break;
|
|
291
522
|
case 1 : dictID = ip[pos]; pos++; break;
|
|
292
523
|
case 2 : dictID = MEM_readLE16(ip+pos); pos+=2; break;
|
|
@@ -294,7 +525,9 @@ size_t ZSTD_getFrameHeader_advanced(ZSTD_frameHeader* zfhPtr, const void* src, s
|
|
|
294
525
|
}
|
|
295
526
|
switch(fcsID)
|
|
296
527
|
{
|
|
297
|
-
default:
|
|
528
|
+
default:
|
|
529
|
+
assert(0); /* impossible */
|
|
530
|
+
ZSTD_FALLTHROUGH;
|
|
298
531
|
case 0 : if (singleSegment) frameContentSize = ip[pos]; break;
|
|
299
532
|
case 1 : frameContentSize = MEM_readLE16(ip+pos)+256; break;
|
|
300
533
|
case 2 : frameContentSize = MEM_readLE32(ip+pos); break;
|
|
@@ -323,7 +556,6 @@ size_t ZSTD_getFrameHeader(ZSTD_frameHeader* zfhPtr, const void* src, size_t src
|
|
|
323
556
|
return ZSTD_getFrameHeader_advanced(zfhPtr, src, srcSize, ZSTD_f_zstd1);
|
|
324
557
|
}
|
|
325
558
|
|
|
326
|
-
|
|
327
559
|
/** ZSTD_getFrameContentSize() :
|
|
328
560
|
* compatible with legacy mode
|
|
329
561
|
* @return : decompressed size of the single frame pointed to be `src` if known, otherwise
|
|
@@ -352,23 +584,57 @@ static size_t readSkippableFrameSize(void const* src, size_t srcSize)
|
|
|
352
584
|
size_t const skippableHeaderSize = ZSTD_SKIPPABLEHEADERSIZE;
|
|
353
585
|
U32 sizeU32;
|
|
354
586
|
|
|
355
|
-
RETURN_ERROR_IF(srcSize < ZSTD_SKIPPABLEHEADERSIZE, srcSize_wrong);
|
|
587
|
+
RETURN_ERROR_IF(srcSize < ZSTD_SKIPPABLEHEADERSIZE, srcSize_wrong, "");
|
|
356
588
|
|
|
357
589
|
sizeU32 = MEM_readLE32((BYTE const*)src + ZSTD_FRAMEIDSIZE);
|
|
358
590
|
RETURN_ERROR_IF((U32)(sizeU32 + ZSTD_SKIPPABLEHEADERSIZE) < sizeU32,
|
|
359
|
-
frameParameter_unsupported);
|
|
360
|
-
{
|
|
361
|
-
|
|
362
|
-
RETURN_ERROR_IF(skippableSize > srcSize, srcSize_wrong);
|
|
591
|
+
frameParameter_unsupported, "");
|
|
592
|
+
{ size_t const skippableSize = skippableHeaderSize + sizeU32;
|
|
593
|
+
RETURN_ERROR_IF(skippableSize > srcSize, srcSize_wrong, "");
|
|
363
594
|
return skippableSize;
|
|
364
595
|
}
|
|
365
596
|
}
|
|
366
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
|
+
|
|
367
633
|
/** ZSTD_findDecompressedSize() :
|
|
368
|
-
* compatible with legacy mode
|
|
369
634
|
* `srcSize` must be the exact length of some number of ZSTD compressed and/or
|
|
370
635
|
* skippable frames
|
|
371
|
-
*
|
|
636
|
+
* note: compatible with legacy mode
|
|
637
|
+
* @return : decompressed size of the frames contained */
|
|
372
638
|
unsigned long long ZSTD_findDecompressedSize(const void* src, size_t srcSize)
|
|
373
639
|
{
|
|
374
640
|
unsigned long long totalDstSize = 0;
|
|
@@ -378,9 +644,7 @@ unsigned long long ZSTD_findDecompressedSize(const void* src, size_t srcSize)
|
|
|
378
644
|
|
|
379
645
|
if ((magicNumber & ZSTD_MAGIC_SKIPPABLE_MASK) == ZSTD_MAGIC_SKIPPABLE_START) {
|
|
380
646
|
size_t const skippableSize = readSkippableFrameSize(src, srcSize);
|
|
381
|
-
if (ZSTD_isError(skippableSize))
|
|
382
|
-
return ZSTD_CONTENTSIZE_ERROR;
|
|
383
|
-
}
|
|
647
|
+
if (ZSTD_isError(skippableSize)) return ZSTD_CONTENTSIZE_ERROR;
|
|
384
648
|
assert(skippableSize <= srcSize);
|
|
385
649
|
|
|
386
650
|
src = (const BYTE *)src + skippableSize;
|
|
@@ -388,17 +652,17 @@ unsigned long long ZSTD_findDecompressedSize(const void* src, size_t srcSize)
|
|
|
388
652
|
continue;
|
|
389
653
|
}
|
|
390
654
|
|
|
391
|
-
{ unsigned long long const
|
|
392
|
-
if (
|
|
655
|
+
{ unsigned long long const fcs = ZSTD_getFrameContentSize(src, srcSize);
|
|
656
|
+
if (fcs >= ZSTD_CONTENTSIZE_ERROR) return fcs;
|
|
393
657
|
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
totalDstSize +=
|
|
658
|
+
if (totalDstSize + fcs < totalDstSize)
|
|
659
|
+
return ZSTD_CONTENTSIZE_ERROR; /* check for overflow */
|
|
660
|
+
totalDstSize += fcs;
|
|
397
661
|
}
|
|
662
|
+
/* skip to next frame */
|
|
398
663
|
{ size_t const frameSrcSize = ZSTD_findFrameCompressedSize(src, srcSize);
|
|
399
|
-
if (ZSTD_isError(frameSrcSize))
|
|
400
|
-
|
|
401
|
-
}
|
|
664
|
+
if (ZSTD_isError(frameSrcSize)) return ZSTD_CONTENTSIZE_ERROR;
|
|
665
|
+
assert(frameSrcSize <= srcSize);
|
|
402
666
|
|
|
403
667
|
src = (const BYTE *)src + frameSrcSize;
|
|
404
668
|
srcSize -= frameSrcSize;
|
|
@@ -428,20 +692,29 @@ unsigned long long ZSTD_getDecompressedSize(const void* src, size_t srcSize)
|
|
|
428
692
|
|
|
429
693
|
/** ZSTD_decodeFrameHeader() :
|
|
430
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.
|
|
431
696
|
* @return : 0 if success, or an error code, which can be tested using ZSTD_isError() */
|
|
432
697
|
static size_t ZSTD_decodeFrameHeader(ZSTD_DCtx* dctx, const void* src, size_t headerSize)
|
|
433
698
|
{
|
|
434
699
|
size_t const result = ZSTD_getFrameHeader_advanced(&(dctx->fParams), src, headerSize, dctx->format);
|
|
435
700
|
if (ZSTD_isError(result)) return result; /* invalid header */
|
|
436
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
|
+
|
|
437
708
|
#ifndef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
|
|
438
709
|
/* Skip the dictID check in fuzzing mode, because it makes the search
|
|
439
710
|
* harder.
|
|
440
711
|
*/
|
|
441
712
|
RETURN_ERROR_IF(dctx->fParams.dictID && (dctx->dictID != dctx->fParams.dictID),
|
|
442
|
-
dictionary_wrong);
|
|
713
|
+
dictionary_wrong, "");
|
|
443
714
|
#endif
|
|
444
|
-
|
|
715
|
+
dctx->validateChecksum = (dctx->fParams.checksumFlag && !dctx->forceIgnoreChecksum) ? 1 : 0;
|
|
716
|
+
if (dctx->validateChecksum) XXH64_reset(&dctx->xxhState, 0);
|
|
717
|
+
dctx->processedCSize += headerSize;
|
|
445
718
|
return 0;
|
|
446
719
|
}
|
|
447
720
|
|
|
@@ -456,7 +729,7 @@ static ZSTD_frameSizeInfo ZSTD_errorFrameSizeInfo(size_t ret)
|
|
|
456
729
|
static ZSTD_frameSizeInfo ZSTD_findFrameSizeInfo(const void* src, size_t srcSize)
|
|
457
730
|
{
|
|
458
731
|
ZSTD_frameSizeInfo frameSizeInfo;
|
|
459
|
-
|
|
732
|
+
ZSTD_memset(&frameSizeInfo, 0, sizeof(ZSTD_frameSizeInfo));
|
|
460
733
|
|
|
461
734
|
#if defined(ZSTD_LEGACY_SUPPORT) && (ZSTD_LEGACY_SUPPORT >= 1)
|
|
462
735
|
if (ZSTD_isLegacy(src, srcSize))
|
|
@@ -511,10 +784,11 @@ static ZSTD_frameSizeInfo ZSTD_findFrameSizeInfo(const void* src, size_t srcSize
|
|
|
511
784
|
ip += 4;
|
|
512
785
|
}
|
|
513
786
|
|
|
514
|
-
frameSizeInfo.
|
|
787
|
+
frameSizeInfo.nbBlocks = nbBlocks;
|
|
788
|
+
frameSizeInfo.compressedSize = (size_t)(ip - ipstart);
|
|
515
789
|
frameSizeInfo.decompressedBound = (zfh.frameContentSize != ZSTD_CONTENTSIZE_UNKNOWN)
|
|
516
790
|
? zfh.frameContentSize
|
|
517
|
-
: nbBlocks * zfh.blockSizeMax;
|
|
791
|
+
: (unsigned long long)nbBlocks * zfh.blockSizeMax;
|
|
518
792
|
return frameSizeInfo;
|
|
519
793
|
}
|
|
520
794
|
}
|
|
@@ -554,28 +828,59 @@ unsigned long long ZSTD_decompressBound(const void* src, size_t srcSize)
|
|
|
554
828
|
return bound;
|
|
555
829
|
}
|
|
556
830
|
|
|
831
|
+
size_t ZSTD_decompressionMargin(void const* src, size_t srcSize)
|
|
832
|
+
{
|
|
833
|
+
size_t margin = 0;
|
|
834
|
+
unsigned maxBlockSize = 0;
|
|
557
835
|
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
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;
|
|
561
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
|
+
}
|
|
562
862
|
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
dctx->dictEnd = dctx->previousDstEnd;
|
|
567
|
-
dctx->virtualStart = (const char*)dst - ((const char*)(dctx->previousDstEnd) - (const char*)(dctx->prefixStart));
|
|
568
|
-
dctx->prefixStart = dst;
|
|
569
|
-
dctx->previousDstEnd = dst;
|
|
863
|
+
assert(srcSize >= compressedSize);
|
|
864
|
+
src = (const BYTE*)src + compressedSize;
|
|
865
|
+
srcSize -= compressedSize;
|
|
570
866
|
}
|
|
867
|
+
|
|
868
|
+
/* Add the max block size back to the margin. */
|
|
869
|
+
margin += maxBlockSize;
|
|
870
|
+
|
|
871
|
+
return margin;
|
|
571
872
|
}
|
|
572
873
|
|
|
874
|
+
/*-*************************************************************
|
|
875
|
+
* Frame decoding
|
|
876
|
+
***************************************************************/
|
|
877
|
+
|
|
573
878
|
/** ZSTD_insertBlock() :
|
|
574
879
|
* insert `src` block into `dctx` history. Useful to track uncompressed blocks. */
|
|
575
880
|
size_t ZSTD_insertBlock(ZSTD_DCtx* dctx, const void* blockStart, size_t blockSize)
|
|
576
881
|
{
|
|
577
882
|
DEBUGLOG(5, "ZSTD_insertBlock: %u bytes", (unsigned)blockSize);
|
|
578
|
-
ZSTD_checkContinuity(dctx, blockStart);
|
|
883
|
+
ZSTD_checkContinuity(dctx, blockStart, blockSize);
|
|
579
884
|
dctx->previousDstEnd = (const char*)blockStart + blockSize;
|
|
580
885
|
return blockSize;
|
|
581
886
|
}
|
|
@@ -585,12 +890,12 @@ static size_t ZSTD_copyRawBlock(void* dst, size_t dstCapacity,
|
|
|
585
890
|
const void* src, size_t srcSize)
|
|
586
891
|
{
|
|
587
892
|
DEBUGLOG(5, "ZSTD_copyRawBlock");
|
|
893
|
+
RETURN_ERROR_IF(srcSize > dstCapacity, dstSize_tooSmall, "");
|
|
588
894
|
if (dst == NULL) {
|
|
589
895
|
if (srcSize == 0) return 0;
|
|
590
|
-
RETURN_ERROR(dstBuffer_null);
|
|
896
|
+
RETURN_ERROR(dstBuffer_null, "");
|
|
591
897
|
}
|
|
592
|
-
|
|
593
|
-
memcpy(dst, src, srcSize);
|
|
898
|
+
ZSTD_memmove(dst, src, srcSize);
|
|
594
899
|
return srcSize;
|
|
595
900
|
}
|
|
596
901
|
|
|
@@ -598,15 +903,41 @@ static size_t ZSTD_setRleBlock(void* dst, size_t dstCapacity,
|
|
|
598
903
|
BYTE b,
|
|
599
904
|
size_t regenSize)
|
|
600
905
|
{
|
|
906
|
+
RETURN_ERROR_IF(regenSize > dstCapacity, dstSize_tooSmall, "");
|
|
601
907
|
if (dst == NULL) {
|
|
602
908
|
if (regenSize == 0) return 0;
|
|
603
|
-
RETURN_ERROR(dstBuffer_null);
|
|
909
|
+
RETURN_ERROR(dstBuffer_null, "");
|
|
604
910
|
}
|
|
605
|
-
|
|
606
|
-
memset(dst, b, regenSize);
|
|
911
|
+
ZSTD_memset(dst, b, regenSize);
|
|
607
912
|
return regenSize;
|
|
608
913
|
}
|
|
609
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
|
+
|
|
610
941
|
|
|
611
942
|
/*! ZSTD_decompressFrame() :
|
|
612
943
|
* @dctx must be properly initialized
|
|
@@ -616,9 +947,10 @@ static size_t ZSTD_decompressFrame(ZSTD_DCtx* dctx,
|
|
|
616
947
|
void* dst, size_t dstCapacity,
|
|
617
948
|
const void** srcPtr, size_t *srcSizePtr)
|
|
618
949
|
{
|
|
619
|
-
const BYTE*
|
|
620
|
-
BYTE*
|
|
621
|
-
BYTE* const
|
|
950
|
+
const BYTE* const istart = (const BYTE*)(*srcPtr);
|
|
951
|
+
const BYTE* ip = istart;
|
|
952
|
+
BYTE* const ostart = (BYTE*)dst;
|
|
953
|
+
BYTE* const oend = dstCapacity != 0 ? ostart + dstCapacity : ostart;
|
|
622
954
|
BYTE* op = ostart;
|
|
623
955
|
size_t remainingSrcSize = *srcSizePtr;
|
|
624
956
|
|
|
@@ -627,20 +959,21 @@ static size_t ZSTD_decompressFrame(ZSTD_DCtx* dctx,
|
|
|
627
959
|
/* check */
|
|
628
960
|
RETURN_ERROR_IF(
|
|
629
961
|
remainingSrcSize < ZSTD_FRAMEHEADERSIZE_MIN(dctx->format)+ZSTD_blockHeaderSize,
|
|
630
|
-
srcSize_wrong);
|
|
962
|
+
srcSize_wrong, "");
|
|
631
963
|
|
|
632
964
|
/* Frame Header */
|
|
633
965
|
{ size_t const frameHeaderSize = ZSTD_frameHeaderSize_internal(
|
|
634
966
|
ip, ZSTD_FRAMEHEADERSIZE_PREFIX(dctx->format), dctx->format);
|
|
635
967
|
if (ZSTD_isError(frameHeaderSize)) return frameHeaderSize;
|
|
636
968
|
RETURN_ERROR_IF(remainingSrcSize < frameHeaderSize+ZSTD_blockHeaderSize,
|
|
637
|
-
srcSize_wrong);
|
|
638
|
-
FORWARD_IF_ERROR( ZSTD_decodeFrameHeader(dctx, ip, frameHeaderSize) );
|
|
969
|
+
srcSize_wrong, "");
|
|
970
|
+
FORWARD_IF_ERROR( ZSTD_decodeFrameHeader(dctx, ip, frameHeaderSize) , "");
|
|
639
971
|
ip += frameHeaderSize; remainingSrcSize -= frameHeaderSize;
|
|
640
972
|
}
|
|
641
973
|
|
|
642
974
|
/* Loop on each block */
|
|
643
975
|
while (1) {
|
|
976
|
+
BYTE* oBlockEnd = oend;
|
|
644
977
|
size_t decodedSize;
|
|
645
978
|
blockProperties_t blockProperties;
|
|
646
979
|
size_t const cBlockSize = ZSTD_getcBlockSize(ip, remainingSrcSize, &blockProperties);
|
|
@@ -648,28 +981,48 @@ static size_t ZSTD_decompressFrame(ZSTD_DCtx* dctx,
|
|
|
648
981
|
|
|
649
982
|
ip += ZSTD_blockHeaderSize;
|
|
650
983
|
remainingSrcSize -= ZSTD_blockHeaderSize;
|
|
651
|
-
RETURN_ERROR_IF(cBlockSize > remainingSrcSize, srcSize_wrong);
|
|
984
|
+
RETURN_ERROR_IF(cBlockSize > remainingSrcSize, srcSize_wrong, "");
|
|
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
|
+
}
|
|
652
1002
|
|
|
653
1003
|
switch(blockProperties.blockType)
|
|
654
1004
|
{
|
|
655
1005
|
case bt_compressed:
|
|
656
|
-
decodedSize = ZSTD_decompressBlock_internal(dctx, op,
|
|
1006
|
+
decodedSize = ZSTD_decompressBlock_internal(dctx, op, (size_t)(oBlockEnd-op), ip, cBlockSize, /* frame */ 1, not_streaming);
|
|
657
1007
|
break;
|
|
658
1008
|
case bt_raw :
|
|
659
|
-
|
|
1009
|
+
/* Use oend instead of oBlockEnd because this function is safe to overlap. It uses memmove. */
|
|
1010
|
+
decodedSize = ZSTD_copyRawBlock(op, (size_t)(oend-op), ip, cBlockSize);
|
|
660
1011
|
break;
|
|
661
1012
|
case bt_rle :
|
|
662
|
-
decodedSize = ZSTD_setRleBlock(op,
|
|
1013
|
+
decodedSize = ZSTD_setRleBlock(op, (size_t)(oBlockEnd-op), *ip, blockProperties.origSize);
|
|
663
1014
|
break;
|
|
664
1015
|
case bt_reserved :
|
|
665
1016
|
default:
|
|
666
|
-
RETURN_ERROR(corruption_detected);
|
|
1017
|
+
RETURN_ERROR(corruption_detected, "invalid block type");
|
|
667
1018
|
}
|
|
668
1019
|
|
|
669
1020
|
if (ZSTD_isError(decodedSize)) return decodedSize;
|
|
670
|
-
if (dctx->
|
|
1021
|
+
if (dctx->validateChecksum)
|
|
671
1022
|
XXH64_update(&dctx->xxhState, op, decodedSize);
|
|
672
|
-
|
|
1023
|
+
if (decodedSize != 0)
|
|
1024
|
+
op += decodedSize;
|
|
1025
|
+
assert(ip != NULL);
|
|
673
1026
|
ip += cBlockSize;
|
|
674
1027
|
remainingSrcSize -= cBlockSize;
|
|
675
1028
|
if (blockProperties.lastBlock) break;
|
|
@@ -677,22 +1030,25 @@ static size_t ZSTD_decompressFrame(ZSTD_DCtx* dctx,
|
|
|
677
1030
|
|
|
678
1031
|
if (dctx->fParams.frameContentSize != ZSTD_CONTENTSIZE_UNKNOWN) {
|
|
679
1032
|
RETURN_ERROR_IF((U64)(op-ostart) != dctx->fParams.frameContentSize,
|
|
680
|
-
corruption_detected);
|
|
1033
|
+
corruption_detected, "");
|
|
681
1034
|
}
|
|
682
1035
|
if (dctx->fParams.checksumFlag) { /* Frame content checksum verification */
|
|
683
|
-
|
|
684
|
-
|
|
685
|
-
|
|
686
|
-
|
|
687
|
-
|
|
1036
|
+
RETURN_ERROR_IF(remainingSrcSize<4, checksum_wrong, "");
|
|
1037
|
+
if (!dctx->forceIgnoreChecksum) {
|
|
1038
|
+
U32 const checkCalc = (U32)XXH64_digest(&dctx->xxhState);
|
|
1039
|
+
U32 checkRead;
|
|
1040
|
+
checkRead = MEM_readLE32(ip);
|
|
1041
|
+
RETURN_ERROR_IF(checkRead != checkCalc, checksum_wrong, "");
|
|
1042
|
+
}
|
|
688
1043
|
ip += 4;
|
|
689
1044
|
remainingSrcSize -= 4;
|
|
690
1045
|
}
|
|
691
|
-
|
|
1046
|
+
ZSTD_DCtx_trace_end(dctx, (U64)(op-ostart), (U64)(ip-istart), /* streaming */ 0);
|
|
692
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);
|
|
693
1049
|
*srcPtr = ip;
|
|
694
1050
|
*srcSizePtr = remainingSrcSize;
|
|
695
|
-
return op-ostart;
|
|
1051
|
+
return (size_t)(op-ostart);
|
|
696
1052
|
}
|
|
697
1053
|
|
|
698
1054
|
static size_t ZSTD_decompressMultiFrame(ZSTD_DCtx* dctx,
|
|
@@ -725,7 +1081,7 @@ static size_t ZSTD_decompressMultiFrame(ZSTD_DCtx* dctx,
|
|
|
725
1081
|
decodedSize = ZSTD_decompressLegacy(dst, dstCapacity, src, frameSize, dict, dictSize);
|
|
726
1082
|
if (ZSTD_isError(decodedSize)) return decodedSize;
|
|
727
1083
|
|
|
728
|
-
assert(decodedSize
|
|
1084
|
+
assert(decodedSize <= dstCapacity);
|
|
729
1085
|
dst = (BYTE*)dst + decodedSize;
|
|
730
1086
|
dstCapacity -= decodedSize;
|
|
731
1087
|
|
|
@@ -736,28 +1092,29 @@ static size_t ZSTD_decompressMultiFrame(ZSTD_DCtx* dctx,
|
|
|
736
1092
|
}
|
|
737
1093
|
#endif
|
|
738
1094
|
|
|
739
|
-
|
|
740
|
-
|
|
741
|
-
|
|
1095
|
+
if (srcSize >= 4) {
|
|
1096
|
+
U32 const magicNumber = MEM_readLE32(src);
|
|
1097
|
+
DEBUGLOG(5, "reading magic number %08X", (unsigned)magicNumber);
|
|
742
1098
|
if ((magicNumber & ZSTD_MAGIC_SKIPPABLE_MASK) == ZSTD_MAGIC_SKIPPABLE_START) {
|
|
1099
|
+
/* skippable frame detected : skip it */
|
|
743
1100
|
size_t const skippableSize = readSkippableFrameSize(src, srcSize);
|
|
744
|
-
FORWARD_IF_ERROR(skippableSize);
|
|
1101
|
+
FORWARD_IF_ERROR(skippableSize, "invalid skippable frame");
|
|
745
1102
|
assert(skippableSize <= srcSize);
|
|
746
1103
|
|
|
747
1104
|
src = (const BYTE *)src + skippableSize;
|
|
748
1105
|
srcSize -= skippableSize;
|
|
749
|
-
continue;
|
|
1106
|
+
continue; /* check next frame */
|
|
750
1107
|
} }
|
|
751
1108
|
|
|
752
1109
|
if (ddict) {
|
|
753
1110
|
/* we were called from ZSTD_decompress_usingDDict */
|
|
754
|
-
FORWARD_IF_ERROR(ZSTD_decompressBegin_usingDDict(dctx, ddict));
|
|
1111
|
+
FORWARD_IF_ERROR(ZSTD_decompressBegin_usingDDict(dctx, ddict), "");
|
|
755
1112
|
} else {
|
|
756
1113
|
/* this will initialize correctly with no dict if dict == NULL, so
|
|
757
1114
|
* use this in all cases but ddict */
|
|
758
|
-
FORWARD_IF_ERROR(ZSTD_decompressBegin_usingDict(dctx, dict, dictSize));
|
|
1115
|
+
FORWARD_IF_ERROR(ZSTD_decompressBegin_usingDict(dctx, dict, dictSize), "");
|
|
759
1116
|
}
|
|
760
|
-
ZSTD_checkContinuity(dctx, dst);
|
|
1117
|
+
ZSTD_checkContinuity(dctx, dst, dstCapacity);
|
|
761
1118
|
|
|
762
1119
|
{ const size_t res = ZSTD_decompressFrame(dctx, dst, dstCapacity,
|
|
763
1120
|
&src, &srcSize);
|
|
@@ -765,18 +1122,17 @@ static size_t ZSTD_decompressMultiFrame(ZSTD_DCtx* dctx,
|
|
|
765
1122
|
(ZSTD_getErrorCode(res) == ZSTD_error_prefix_unknown)
|
|
766
1123
|
&& (moreThan1Frame==1),
|
|
767
1124
|
srcSize_wrong,
|
|
768
|
-
"
|
|
769
|
-
"bytes are garbage:
|
|
770
|
-
"
|
|
771
|
-
"
|
|
772
|
-
"
|
|
773
|
-
"
|
|
774
|
-
"
|
|
775
|
-
"bytes. But this is _much_ less likely than a srcSize field "
|
|
776
|
-
"error.");
|
|
1125
|
+
"At least one frame successfully completed, "
|
|
1126
|
+
"but following bytes are garbage: "
|
|
1127
|
+
"it's more likely to be a srcSize error, "
|
|
1128
|
+
"specifying more input bytes than size of frame(s). "
|
|
1129
|
+
"Note: one could be unlucky, it might be a corruption error instead, "
|
|
1130
|
+
"happening right at the place where we expect zstd magic bytes. "
|
|
1131
|
+
"But this is _much_ less likely than a srcSize field error.");
|
|
777
1132
|
if (ZSTD_isError(res)) return res;
|
|
778
1133
|
assert(res <= dstCapacity);
|
|
779
|
-
|
|
1134
|
+
if (res != 0)
|
|
1135
|
+
dst = (BYTE*)dst + res;
|
|
780
1136
|
dstCapacity -= res;
|
|
781
1137
|
}
|
|
782
1138
|
moreThan1Frame = 1;
|
|
@@ -784,7 +1140,7 @@ static size_t ZSTD_decompressMultiFrame(ZSTD_DCtx* dctx,
|
|
|
784
1140
|
|
|
785
1141
|
RETURN_ERROR_IF(srcSize, srcSize_wrong, "input not entirely consumed");
|
|
786
1142
|
|
|
787
|
-
return (BYTE*)dst - (BYTE*)dststart;
|
|
1143
|
+
return (size_t)((BYTE*)dst - (BYTE*)dststart);
|
|
788
1144
|
}
|
|
789
1145
|
|
|
790
1146
|
size_t ZSTD_decompress_usingDict(ZSTD_DCtx* dctx,
|
|
@@ -801,7 +1157,7 @@ static ZSTD_DDict const* ZSTD_getDDict(ZSTD_DCtx* dctx)
|
|
|
801
1157
|
switch (dctx->dictUses) {
|
|
802
1158
|
default:
|
|
803
1159
|
assert(0 /* Impossible */);
|
|
804
|
-
|
|
1160
|
+
ZSTD_FALLTHROUGH;
|
|
805
1161
|
case ZSTD_dont_use:
|
|
806
1162
|
ZSTD_clearDict(dctx);
|
|
807
1163
|
return NULL;
|
|
@@ -823,8 +1179,8 @@ size_t ZSTD_decompress(void* dst, size_t dstCapacity, const void* src, size_t sr
|
|
|
823
1179
|
{
|
|
824
1180
|
#if defined(ZSTD_HEAPMODE) && (ZSTD_HEAPMODE>=1)
|
|
825
1181
|
size_t regenSize;
|
|
826
|
-
ZSTD_DCtx* const dctx =
|
|
827
|
-
RETURN_ERROR_IF(dctx==NULL, memory_allocation);
|
|
1182
|
+
ZSTD_DCtx* const dctx = ZSTD_createDCtx_internal(ZSTD_defaultCMem);
|
|
1183
|
+
RETURN_ERROR_IF(dctx==NULL, memory_allocation, "NULL pointer!");
|
|
828
1184
|
regenSize = ZSTD_decompressDCtx(dctx, dst, dstCapacity, src, srcSize);
|
|
829
1185
|
ZSTD_freeDCtx(dctx);
|
|
830
1186
|
return regenSize;
|
|
@@ -842,12 +1198,32 @@ size_t ZSTD_decompress(void* dst, size_t dstCapacity, const void* src, size_t sr
|
|
|
842
1198
|
****************************************/
|
|
843
1199
|
size_t ZSTD_nextSrcSizeToDecompress(ZSTD_DCtx* dctx) { return dctx->expected; }
|
|
844
1200
|
|
|
1201
|
+
/**
|
|
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
|
|
1204
|
+
* be streamed.
|
|
1205
|
+
*
|
|
1206
|
+
* For blocks that can be streamed, this allows us to reduce the latency until we produce
|
|
1207
|
+
* output, and avoid copying the input.
|
|
1208
|
+
*
|
|
1209
|
+
* @param inputSize - The total amount of input that the caller currently has.
|
|
1210
|
+
*/
|
|
1211
|
+
static size_t ZSTD_nextSrcSizeToDecompressWithInputSize(ZSTD_DCtx* dctx, size_t inputSize) {
|
|
1212
|
+
if (!(dctx->stage == ZSTDds_decompressBlock || dctx->stage == ZSTDds_decompressLastBlock))
|
|
1213
|
+
return dctx->expected;
|
|
1214
|
+
if (dctx->bType != bt_raw)
|
|
1215
|
+
return dctx->expected;
|
|
1216
|
+
return BOUNDED(1, inputSize, dctx->expected);
|
|
1217
|
+
}
|
|
1218
|
+
|
|
845
1219
|
ZSTD_nextInputType_e ZSTD_nextInputType(ZSTD_DCtx* dctx) {
|
|
846
1220
|
switch(dctx->stage)
|
|
847
1221
|
{
|
|
848
1222
|
default: /* should not happen */
|
|
849
1223
|
assert(0);
|
|
1224
|
+
ZSTD_FALLTHROUGH;
|
|
850
1225
|
case ZSTDds_getFrameHeaderSize:
|
|
1226
|
+
ZSTD_FALLTHROUGH;
|
|
851
1227
|
case ZSTDds_decodeFrameHeader:
|
|
852
1228
|
return ZSTDnit_frameHeader;
|
|
853
1229
|
case ZSTDds_decodeBlockHeader:
|
|
@@ -859,6 +1235,7 @@ ZSTD_nextInputType_e ZSTD_nextInputType(ZSTD_DCtx* dctx) {
|
|
|
859
1235
|
case ZSTDds_checkChecksum:
|
|
860
1236
|
return ZSTDnit_checksum;
|
|
861
1237
|
case ZSTDds_decodeSkippableHeader:
|
|
1238
|
+
ZSTD_FALLTHROUGH;
|
|
862
1239
|
case ZSTDds_skipFrame:
|
|
863
1240
|
return ZSTDnit_skippableFrame;
|
|
864
1241
|
}
|
|
@@ -874,8 +1251,10 @@ size_t ZSTD_decompressContinue(ZSTD_DCtx* dctx, void* dst, size_t dstCapacity, c
|
|
|
874
1251
|
{
|
|
875
1252
|
DEBUGLOG(5, "ZSTD_decompressContinue (srcSize:%u)", (unsigned)srcSize);
|
|
876
1253
|
/* Sanity check */
|
|
877
|
-
RETURN_ERROR_IF(srcSize != dctx
|
|
878
|
-
|
|
1254
|
+
RETURN_ERROR_IF(srcSize != ZSTD_nextSrcSizeToDecompressWithInputSize(dctx, srcSize), srcSize_wrong, "not allowed");
|
|
1255
|
+
ZSTD_checkContinuity(dctx, dst, dstCapacity);
|
|
1256
|
+
|
|
1257
|
+
dctx->processedCSize += srcSize;
|
|
879
1258
|
|
|
880
1259
|
switch (dctx->stage)
|
|
881
1260
|
{
|
|
@@ -884,22 +1263,22 @@ size_t ZSTD_decompressContinue(ZSTD_DCtx* dctx, void* dst, size_t dstCapacity, c
|
|
|
884
1263
|
if (dctx->format == ZSTD_f_zstd1) { /* allows header */
|
|
885
1264
|
assert(srcSize >= ZSTD_FRAMEIDSIZE); /* to read skippable magic number */
|
|
886
1265
|
if ((MEM_readLE32(src) & ZSTD_MAGIC_SKIPPABLE_MASK) == ZSTD_MAGIC_SKIPPABLE_START) { /* skippable frame */
|
|
887
|
-
|
|
1266
|
+
ZSTD_memcpy(dctx->headerBuffer, src, srcSize);
|
|
888
1267
|
dctx->expected = ZSTD_SKIPPABLEHEADERSIZE - srcSize; /* remaining to load to get full skippable frame header */
|
|
889
1268
|
dctx->stage = ZSTDds_decodeSkippableHeader;
|
|
890
1269
|
return 0;
|
|
891
1270
|
} }
|
|
892
1271
|
dctx->headerSize = ZSTD_frameHeaderSize_internal(src, srcSize, dctx->format);
|
|
893
1272
|
if (ZSTD_isError(dctx->headerSize)) return dctx->headerSize;
|
|
894
|
-
|
|
1273
|
+
ZSTD_memcpy(dctx->headerBuffer, src, srcSize);
|
|
895
1274
|
dctx->expected = dctx->headerSize - srcSize;
|
|
896
1275
|
dctx->stage = ZSTDds_decodeFrameHeader;
|
|
897
1276
|
return 0;
|
|
898
1277
|
|
|
899
1278
|
case ZSTDds_decodeFrameHeader:
|
|
900
1279
|
assert(src != NULL);
|
|
901
|
-
|
|
902
|
-
FORWARD_IF_ERROR(ZSTD_decodeFrameHeader(dctx, dctx->headerBuffer, dctx->headerSize));
|
|
1280
|
+
ZSTD_memcpy(dctx->headerBuffer + (dctx->headerSize - srcSize), src, srcSize);
|
|
1281
|
+
FORWARD_IF_ERROR(ZSTD_decodeFrameHeader(dctx, dctx->headerBuffer, dctx->headerSize), "");
|
|
903
1282
|
dctx->expected = ZSTD_blockHeaderSize;
|
|
904
1283
|
dctx->stage = ZSTDds_decodeBlockHeader;
|
|
905
1284
|
return 0;
|
|
@@ -940,51 +1319,67 @@ size_t ZSTD_decompressContinue(ZSTD_DCtx* dctx, void* dst, size_t dstCapacity, c
|
|
|
940
1319
|
{
|
|
941
1320
|
case bt_compressed:
|
|
942
1321
|
DEBUGLOG(5, "ZSTD_decompressContinue: case bt_compressed");
|
|
943
|
-
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);
|
|
1323
|
+
dctx->expected = 0; /* Streaming not supported */
|
|
944
1324
|
break;
|
|
945
1325
|
case bt_raw :
|
|
1326
|
+
assert(srcSize <= dctx->expected);
|
|
946
1327
|
rSize = ZSTD_copyRawBlock(dst, dstCapacity, src, srcSize);
|
|
1328
|
+
FORWARD_IF_ERROR(rSize, "ZSTD_copyRawBlock failed");
|
|
1329
|
+
assert(rSize == srcSize);
|
|
1330
|
+
dctx->expected -= rSize;
|
|
947
1331
|
break;
|
|
948
1332
|
case bt_rle :
|
|
949
1333
|
rSize = ZSTD_setRleBlock(dst, dstCapacity, *(const BYTE*)src, dctx->rleSize);
|
|
1334
|
+
dctx->expected = 0; /* Streaming not supported */
|
|
950
1335
|
break;
|
|
951
1336
|
case bt_reserved : /* should never happen */
|
|
952
1337
|
default:
|
|
953
|
-
RETURN_ERROR(corruption_detected);
|
|
1338
|
+
RETURN_ERROR(corruption_detected, "invalid block type");
|
|
954
1339
|
}
|
|
955
|
-
|
|
1340
|
+
FORWARD_IF_ERROR(rSize, "");
|
|
956
1341
|
RETURN_ERROR_IF(rSize > dctx->fParams.blockSizeMax, corruption_detected, "Decompressed Block Size Exceeds Maximum");
|
|
957
1342
|
DEBUGLOG(5, "ZSTD_decompressContinue: decoded size from block : %u", (unsigned)rSize);
|
|
958
1343
|
dctx->decodedSize += rSize;
|
|
959
|
-
if (dctx->
|
|
1344
|
+
if (dctx->validateChecksum) XXH64_update(&dctx->xxhState, dst, rSize);
|
|
1345
|
+
dctx->previousDstEnd = (char*)dst + rSize;
|
|
1346
|
+
|
|
1347
|
+
/* Stay on the same stage until we are finished streaming the block. */
|
|
1348
|
+
if (dctx->expected > 0) {
|
|
1349
|
+
return rSize;
|
|
1350
|
+
}
|
|
960
1351
|
|
|
961
1352
|
if (dctx->stage == ZSTDds_decompressLastBlock) { /* end of frame */
|
|
962
1353
|
DEBUGLOG(4, "ZSTD_decompressContinue: decoded size from frame : %u", (unsigned)dctx->decodedSize);
|
|
963
1354
|
RETURN_ERROR_IF(
|
|
964
1355
|
dctx->fParams.frameContentSize != ZSTD_CONTENTSIZE_UNKNOWN
|
|
965
1356
|
&& dctx->decodedSize != dctx->fParams.frameContentSize,
|
|
966
|
-
corruption_detected);
|
|
1357
|
+
corruption_detected, "");
|
|
967
1358
|
if (dctx->fParams.checksumFlag) { /* another round for frame checksum */
|
|
968
1359
|
dctx->expected = 4;
|
|
969
1360
|
dctx->stage = ZSTDds_checkChecksum;
|
|
970
1361
|
} else {
|
|
1362
|
+
ZSTD_DCtx_trace_end(dctx, dctx->decodedSize, dctx->processedCSize, /* streaming */ 1);
|
|
971
1363
|
dctx->expected = 0; /* ends here */
|
|
972
1364
|
dctx->stage = ZSTDds_getFrameHeaderSize;
|
|
973
1365
|
}
|
|
974
1366
|
} else {
|
|
975
1367
|
dctx->stage = ZSTDds_decodeBlockHeader;
|
|
976
1368
|
dctx->expected = ZSTD_blockHeaderSize;
|
|
977
|
-
dctx->previousDstEnd = (char*)dst + rSize;
|
|
978
1369
|
}
|
|
979
1370
|
return rSize;
|
|
980
1371
|
}
|
|
981
1372
|
|
|
982
1373
|
case ZSTDds_checkChecksum:
|
|
983
1374
|
assert(srcSize == 4); /* guaranteed by dctx->expected */
|
|
984
|
-
{
|
|
985
|
-
|
|
986
|
-
|
|
987
|
-
|
|
1375
|
+
{
|
|
1376
|
+
if (dctx->validateChecksum) {
|
|
1377
|
+
U32 const h32 = (U32)XXH64_digest(&dctx->xxhState);
|
|
1378
|
+
U32 const check32 = MEM_readLE32(src);
|
|
1379
|
+
DEBUGLOG(4, "ZSTD_decompressContinue: checksum : calculated %08X :: %08X read", (unsigned)h32, (unsigned)check32);
|
|
1380
|
+
RETURN_ERROR_IF(check32 != h32, checksum_wrong, "");
|
|
1381
|
+
}
|
|
1382
|
+
ZSTD_DCtx_trace_end(dctx, dctx->decodedSize, dctx->processedCSize, /* streaming */ 1);
|
|
988
1383
|
dctx->expected = 0;
|
|
989
1384
|
dctx->stage = ZSTDds_getFrameHeaderSize;
|
|
990
1385
|
return 0;
|
|
@@ -993,7 +1388,7 @@ size_t ZSTD_decompressContinue(ZSTD_DCtx* dctx, void* dst, size_t dstCapacity, c
|
|
|
993
1388
|
case ZSTDds_decodeSkippableHeader:
|
|
994
1389
|
assert(src != NULL);
|
|
995
1390
|
assert(srcSize <= ZSTD_SKIPPABLEHEADERSIZE);
|
|
996
|
-
|
|
1391
|
+
ZSTD_memcpy(dctx->headerBuffer + (ZSTD_SKIPPABLEHEADERSIZE - srcSize), src, srcSize); /* complete skippable header */
|
|
997
1392
|
dctx->expected = MEM_readLE32(dctx->headerBuffer + ZSTD_FRAMEIDSIZE); /* note : dctx->expected can grow seriously large, beyond local buffer size */
|
|
998
1393
|
dctx->stage = ZSTDds_skipFrame;
|
|
999
1394
|
return 0;
|
|
@@ -1005,7 +1400,7 @@ size_t ZSTD_decompressContinue(ZSTD_DCtx* dctx, void* dst, size_t dstCapacity, c
|
|
|
1005
1400
|
|
|
1006
1401
|
default:
|
|
1007
1402
|
assert(0); /* impossible */
|
|
1008
|
-
RETURN_ERROR(GENERIC); /* some
|
|
1403
|
+
RETURN_ERROR(GENERIC, "impossible to reach"); /* some compilers require default to do something */
|
|
1009
1404
|
}
|
|
1010
1405
|
}
|
|
1011
1406
|
|
|
@@ -1016,6 +1411,10 @@ static size_t ZSTD_refDictContent(ZSTD_DCtx* dctx, const void* dict, size_t dict
|
|
|
1016
1411
|
dctx->virtualStart = (const char*)dict - ((const char*)(dctx->previousDstEnd) - (const char*)(dctx->prefixStart));
|
|
1017
1412
|
dctx->prefixStart = dict;
|
|
1018
1413
|
dctx->previousDstEnd = (const char*)dict + dictSize;
|
|
1414
|
+
#ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
|
|
1415
|
+
dctx->dictContentBeginForFuzzing = dctx->prefixStart;
|
|
1416
|
+
dctx->dictContentEndForFuzzing = dctx->previousDstEnd;
|
|
1417
|
+
#endif
|
|
1019
1418
|
return 0;
|
|
1020
1419
|
}
|
|
1021
1420
|
|
|
@@ -1029,7 +1428,7 @@ ZSTD_loadDEntropy(ZSTD_entropyDTables_t* entropy,
|
|
|
1029
1428
|
const BYTE* dictPtr = (const BYTE*)dict;
|
|
1030
1429
|
const BYTE* const dictEnd = dictPtr + dictSize;
|
|
1031
1430
|
|
|
1032
|
-
RETURN_ERROR_IF(dictSize <= 8, dictionary_corrupted);
|
|
1431
|
+
RETURN_ERROR_IF(dictSize <= 8, dictionary_corrupted, "dict is too small");
|
|
1033
1432
|
assert(MEM_readLE32(dict) == ZSTD_MAGIC_DICTIONARY); /* dict must be valid */
|
|
1034
1433
|
dictPtr += 8; /* skip header = magic + dictID */
|
|
1035
1434
|
|
|
@@ -1042,66 +1441,72 @@ ZSTD_loadDEntropy(ZSTD_entropyDTables_t* entropy,
|
|
|
1042
1441
|
/* in minimal huffman, we always use X1 variants */
|
|
1043
1442
|
size_t const hSize = HUF_readDTableX1_wksp(entropy->hufTable,
|
|
1044
1443
|
dictPtr, dictEnd - dictPtr,
|
|
1045
|
-
workspace, workspaceSize);
|
|
1444
|
+
workspace, workspaceSize, /* flags */ 0);
|
|
1046
1445
|
#else
|
|
1047
1446
|
size_t const hSize = HUF_readDTableX2_wksp(entropy->hufTable,
|
|
1048
|
-
dictPtr, dictEnd - dictPtr,
|
|
1049
|
-
workspace, workspaceSize);
|
|
1447
|
+
dictPtr, (size_t)(dictEnd - dictPtr),
|
|
1448
|
+
workspace, workspaceSize, /* flags */ 0);
|
|
1050
1449
|
#endif
|
|
1051
|
-
RETURN_ERROR_IF(HUF_isError(hSize), dictionary_corrupted);
|
|
1450
|
+
RETURN_ERROR_IF(HUF_isError(hSize), dictionary_corrupted, "");
|
|
1052
1451
|
dictPtr += hSize;
|
|
1053
1452
|
}
|
|
1054
1453
|
|
|
1055
1454
|
{ short offcodeNCount[MaxOff+1];
|
|
1056
1455
|
unsigned offcodeMaxValue = MaxOff, offcodeLog;
|
|
1057
|
-
size_t const offcodeHeaderSize = FSE_readNCount(offcodeNCount, &offcodeMaxValue, &offcodeLog, dictPtr, dictEnd-dictPtr);
|
|
1058
|
-
RETURN_ERROR_IF(FSE_isError(offcodeHeaderSize), dictionary_corrupted);
|
|
1059
|
-
RETURN_ERROR_IF(offcodeMaxValue > MaxOff, dictionary_corrupted);
|
|
1060
|
-
RETURN_ERROR_IF(offcodeLog > OffFSELog, dictionary_corrupted);
|
|
1456
|
+
size_t const offcodeHeaderSize = FSE_readNCount(offcodeNCount, &offcodeMaxValue, &offcodeLog, dictPtr, (size_t)(dictEnd-dictPtr));
|
|
1457
|
+
RETURN_ERROR_IF(FSE_isError(offcodeHeaderSize), dictionary_corrupted, "");
|
|
1458
|
+
RETURN_ERROR_IF(offcodeMaxValue > MaxOff, dictionary_corrupted, "");
|
|
1459
|
+
RETURN_ERROR_IF(offcodeLog > OffFSELog, dictionary_corrupted, "");
|
|
1061
1460
|
ZSTD_buildFSETable( entropy->OFTable,
|
|
1062
1461
|
offcodeNCount, offcodeMaxValue,
|
|
1063
1462
|
OF_base, OF_bits,
|
|
1064
|
-
offcodeLog
|
|
1463
|
+
offcodeLog,
|
|
1464
|
+
entropy->workspace, sizeof(entropy->workspace),
|
|
1465
|
+
/* bmi2 */0);
|
|
1065
1466
|
dictPtr += offcodeHeaderSize;
|
|
1066
1467
|
}
|
|
1067
1468
|
|
|
1068
1469
|
{ short matchlengthNCount[MaxML+1];
|
|
1069
1470
|
unsigned matchlengthMaxValue = MaxML, matchlengthLog;
|
|
1070
|
-
size_t const matchlengthHeaderSize = FSE_readNCount(matchlengthNCount, &matchlengthMaxValue, &matchlengthLog, dictPtr, dictEnd-dictPtr);
|
|
1071
|
-
RETURN_ERROR_IF(FSE_isError(matchlengthHeaderSize), dictionary_corrupted);
|
|
1072
|
-
RETURN_ERROR_IF(matchlengthMaxValue > MaxML, dictionary_corrupted);
|
|
1073
|
-
RETURN_ERROR_IF(matchlengthLog > MLFSELog, dictionary_corrupted);
|
|
1471
|
+
size_t const matchlengthHeaderSize = FSE_readNCount(matchlengthNCount, &matchlengthMaxValue, &matchlengthLog, dictPtr, (size_t)(dictEnd-dictPtr));
|
|
1472
|
+
RETURN_ERROR_IF(FSE_isError(matchlengthHeaderSize), dictionary_corrupted, "");
|
|
1473
|
+
RETURN_ERROR_IF(matchlengthMaxValue > MaxML, dictionary_corrupted, "");
|
|
1474
|
+
RETURN_ERROR_IF(matchlengthLog > MLFSELog, dictionary_corrupted, "");
|
|
1074
1475
|
ZSTD_buildFSETable( entropy->MLTable,
|
|
1075
1476
|
matchlengthNCount, matchlengthMaxValue,
|
|
1076
1477
|
ML_base, ML_bits,
|
|
1077
|
-
matchlengthLog
|
|
1478
|
+
matchlengthLog,
|
|
1479
|
+
entropy->workspace, sizeof(entropy->workspace),
|
|
1480
|
+
/* bmi2 */ 0);
|
|
1078
1481
|
dictPtr += matchlengthHeaderSize;
|
|
1079
1482
|
}
|
|
1080
1483
|
|
|
1081
1484
|
{ short litlengthNCount[MaxLL+1];
|
|
1082
1485
|
unsigned litlengthMaxValue = MaxLL, litlengthLog;
|
|
1083
|
-
size_t const litlengthHeaderSize = FSE_readNCount(litlengthNCount, &litlengthMaxValue, &litlengthLog, dictPtr, dictEnd-dictPtr);
|
|
1084
|
-
RETURN_ERROR_IF(FSE_isError(litlengthHeaderSize), dictionary_corrupted);
|
|
1085
|
-
RETURN_ERROR_IF(litlengthMaxValue > MaxLL, dictionary_corrupted);
|
|
1086
|
-
RETURN_ERROR_IF(litlengthLog > LLFSELog, dictionary_corrupted);
|
|
1486
|
+
size_t const litlengthHeaderSize = FSE_readNCount(litlengthNCount, &litlengthMaxValue, &litlengthLog, dictPtr, (size_t)(dictEnd-dictPtr));
|
|
1487
|
+
RETURN_ERROR_IF(FSE_isError(litlengthHeaderSize), dictionary_corrupted, "");
|
|
1488
|
+
RETURN_ERROR_IF(litlengthMaxValue > MaxLL, dictionary_corrupted, "");
|
|
1489
|
+
RETURN_ERROR_IF(litlengthLog > LLFSELog, dictionary_corrupted, "");
|
|
1087
1490
|
ZSTD_buildFSETable( entropy->LLTable,
|
|
1088
1491
|
litlengthNCount, litlengthMaxValue,
|
|
1089
1492
|
LL_base, LL_bits,
|
|
1090
|
-
litlengthLog
|
|
1493
|
+
litlengthLog,
|
|
1494
|
+
entropy->workspace, sizeof(entropy->workspace),
|
|
1495
|
+
/* bmi2 */ 0);
|
|
1091
1496
|
dictPtr += litlengthHeaderSize;
|
|
1092
1497
|
}
|
|
1093
1498
|
|
|
1094
|
-
RETURN_ERROR_IF(dictPtr+12 > dictEnd, dictionary_corrupted);
|
|
1499
|
+
RETURN_ERROR_IF(dictPtr+12 > dictEnd, dictionary_corrupted, "");
|
|
1095
1500
|
{ int i;
|
|
1096
1501
|
size_t const dictContentSize = (size_t)(dictEnd - (dictPtr+12));
|
|
1097
1502
|
for (i=0; i<3; i++) {
|
|
1098
1503
|
U32 const rep = MEM_readLE32(dictPtr); dictPtr += 4;
|
|
1099
1504
|
RETURN_ERROR_IF(rep==0 || rep > dictContentSize,
|
|
1100
|
-
dictionary_corrupted);
|
|
1505
|
+
dictionary_corrupted, "");
|
|
1101
1506
|
entropy->rep[i] = rep;
|
|
1102
1507
|
} }
|
|
1103
1508
|
|
|
1104
|
-
return dictPtr - (const BYTE*)dict;
|
|
1509
|
+
return (size_t)(dictPtr - (const BYTE*)dict);
|
|
1105
1510
|
}
|
|
1106
1511
|
|
|
1107
1512
|
static size_t ZSTD_decompress_insertDictionary(ZSTD_DCtx* dctx, const void* dict, size_t dictSize)
|
|
@@ -1115,7 +1520,7 @@ static size_t ZSTD_decompress_insertDictionary(ZSTD_DCtx* dctx, const void* dict
|
|
|
1115
1520
|
|
|
1116
1521
|
/* load entropy tables */
|
|
1117
1522
|
{ size_t const eSize = ZSTD_loadDEntropy(&dctx->entropy, dict, dictSize);
|
|
1118
|
-
RETURN_ERROR_IF(ZSTD_isError(eSize), dictionary_corrupted);
|
|
1523
|
+
RETURN_ERROR_IF(ZSTD_isError(eSize), dictionary_corrupted, "");
|
|
1119
1524
|
dict = (const char*)dict + eSize;
|
|
1120
1525
|
dictSize -= eSize;
|
|
1121
1526
|
}
|
|
@@ -1128,18 +1533,23 @@ static size_t ZSTD_decompress_insertDictionary(ZSTD_DCtx* dctx, const void* dict
|
|
|
1128
1533
|
size_t ZSTD_decompressBegin(ZSTD_DCtx* dctx)
|
|
1129
1534
|
{
|
|
1130
1535
|
assert(dctx != NULL);
|
|
1536
|
+
#if ZSTD_TRACE
|
|
1537
|
+
dctx->traceCtx = (ZSTD_trace_decompress_begin != NULL) ? ZSTD_trace_decompress_begin(dctx) : 0;
|
|
1538
|
+
#endif
|
|
1131
1539
|
dctx->expected = ZSTD_startingInputLength(dctx->format); /* dctx->format must be properly set */
|
|
1132
1540
|
dctx->stage = ZSTDds_getFrameHeaderSize;
|
|
1541
|
+
dctx->processedCSize = 0;
|
|
1133
1542
|
dctx->decodedSize = 0;
|
|
1134
1543
|
dctx->previousDstEnd = NULL;
|
|
1135
1544
|
dctx->prefixStart = NULL;
|
|
1136
1545
|
dctx->virtualStart = NULL;
|
|
1137
1546
|
dctx->dictEnd = NULL;
|
|
1138
|
-
dctx->entropy.hufTable[0] = (HUF_DTable)((
|
|
1547
|
+
dctx->entropy.hufTable[0] = (HUF_DTable)((ZSTD_HUFFDTABLE_CAPACITY_LOG)*0x1000001); /* cover both little and big endian */
|
|
1139
1548
|
dctx->litEntropy = dctx->fseEntropy = 0;
|
|
1140
1549
|
dctx->dictID = 0;
|
|
1550
|
+
dctx->bType = bt_reserved;
|
|
1141
1551
|
ZSTD_STATIC_ASSERT(sizeof(dctx->entropy.rep) == sizeof(repStartValue));
|
|
1142
|
-
|
|
1552
|
+
ZSTD_memcpy(dctx->entropy.rep, repStartValue, sizeof(repStartValue)); /* initial repcodes */
|
|
1143
1553
|
dctx->LLTptr = dctx->entropy.LLTable;
|
|
1144
1554
|
dctx->MLTptr = dctx->entropy.MLTable;
|
|
1145
1555
|
dctx->OFTptr = dctx->entropy.OFTable;
|
|
@@ -1149,11 +1559,11 @@ size_t ZSTD_decompressBegin(ZSTD_DCtx* dctx)
|
|
|
1149
1559
|
|
|
1150
1560
|
size_t ZSTD_decompressBegin_usingDict(ZSTD_DCtx* dctx, const void* dict, size_t dictSize)
|
|
1151
1561
|
{
|
|
1152
|
-
FORWARD_IF_ERROR( ZSTD_decompressBegin(dctx) );
|
|
1562
|
+
FORWARD_IF_ERROR( ZSTD_decompressBegin(dctx) , "");
|
|
1153
1563
|
if (dict && dictSize)
|
|
1154
1564
|
RETURN_ERROR_IF(
|
|
1155
1565
|
ZSTD_isError(ZSTD_decompress_insertDictionary(dctx, dict, dictSize)),
|
|
1156
|
-
dictionary_corrupted);
|
|
1566
|
+
dictionary_corrupted, "");
|
|
1157
1567
|
return 0;
|
|
1158
1568
|
}
|
|
1159
1569
|
|
|
@@ -1172,7 +1582,7 @@ size_t ZSTD_decompressBegin_usingDDict(ZSTD_DCtx* dctx, const ZSTD_DDict* ddict)
|
|
|
1172
1582
|
DEBUGLOG(4, "DDict is %s",
|
|
1173
1583
|
dctx->ddictIsCold ? "~cold~" : "hot!");
|
|
1174
1584
|
}
|
|
1175
|
-
FORWARD_IF_ERROR( ZSTD_decompressBegin(dctx) );
|
|
1585
|
+
FORWARD_IF_ERROR( ZSTD_decompressBegin(dctx) , "");
|
|
1176
1586
|
if (ddict) { /* NULL ddict is equivalent to no dictionary */
|
|
1177
1587
|
ZSTD_copyDDictParameters(dctx, ddict);
|
|
1178
1588
|
}
|
|
@@ -1196,7 +1606,7 @@ unsigned ZSTD_getDictID_fromDict(const void* dict, size_t dictSize)
|
|
|
1196
1606
|
* This could for one of the following reasons :
|
|
1197
1607
|
* - The frame does not require a dictionary (most common case).
|
|
1198
1608
|
* - The frame was built with dictID intentionally removed.
|
|
1199
|
-
* Needed dictionary is a hidden information.
|
|
1609
|
+
* Needed dictionary is a hidden piece of information.
|
|
1200
1610
|
* Note : this use case also happens when using a non-conformant dictionary.
|
|
1201
1611
|
* - `srcSize` is too small, and as a result, frame header could not be decoded.
|
|
1202
1612
|
* Note : possible if `srcSize < ZSTD_FRAMEHEADERSIZE_MAX`.
|
|
@@ -1205,7 +1615,7 @@ unsigned ZSTD_getDictID_fromDict(const void* dict, size_t dictSize)
|
|
|
1205
1615
|
* ZSTD_getFrameHeader(), which will provide a more precise error code. */
|
|
1206
1616
|
unsigned ZSTD_getDictID_fromFrame(const void* src, size_t srcSize)
|
|
1207
1617
|
{
|
|
1208
|
-
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 };
|
|
1209
1619
|
size_t const hError = ZSTD_getFrameHeader(&zfp, src, srcSize);
|
|
1210
1620
|
if (ZSTD_isError(hError)) return 0;
|
|
1211
1621
|
return zfp.dictID;
|
|
@@ -1234,7 +1644,7 @@ size_t ZSTD_decompress_usingDDict(ZSTD_DCtx* dctx,
|
|
|
1234
1644
|
ZSTD_DStream* ZSTD_createDStream(void)
|
|
1235
1645
|
{
|
|
1236
1646
|
DEBUGLOG(3, "ZSTD_createDStream");
|
|
1237
|
-
return
|
|
1647
|
+
return ZSTD_createDCtx_internal(ZSTD_defaultCMem);
|
|
1238
1648
|
}
|
|
1239
1649
|
|
|
1240
1650
|
ZSTD_DStream* ZSTD_initStaticDStream(void *workspace, size_t workspaceSize)
|
|
@@ -1244,7 +1654,7 @@ ZSTD_DStream* ZSTD_initStaticDStream(void *workspace, size_t workspaceSize)
|
|
|
1244
1654
|
|
|
1245
1655
|
ZSTD_DStream* ZSTD_createDStream_advanced(ZSTD_customMem customMem)
|
|
1246
1656
|
{
|
|
1247
|
-
return
|
|
1657
|
+
return ZSTD_createDCtx_internal(customMem);
|
|
1248
1658
|
}
|
|
1249
1659
|
|
|
1250
1660
|
size_t ZSTD_freeDStream(ZSTD_DStream* zds)
|
|
@@ -1263,11 +1673,11 @@ size_t ZSTD_DCtx_loadDictionary_advanced(ZSTD_DCtx* dctx,
|
|
|
1263
1673
|
ZSTD_dictLoadMethod_e dictLoadMethod,
|
|
1264
1674
|
ZSTD_dictContentType_e dictContentType)
|
|
1265
1675
|
{
|
|
1266
|
-
RETURN_ERROR_IF(dctx->streamStage != zdss_init, stage_wrong);
|
|
1676
|
+
RETURN_ERROR_IF(dctx->streamStage != zdss_init, stage_wrong, "");
|
|
1267
1677
|
ZSTD_clearDict(dctx);
|
|
1268
1678
|
if (dict && dictSize != 0) {
|
|
1269
1679
|
dctx->ddictLocal = ZSTD_createDDict_advanced(dict, dictSize, dictLoadMethod, dictContentType, dctx->customMem);
|
|
1270
|
-
RETURN_ERROR_IF(dctx->ddictLocal == NULL, memory_allocation);
|
|
1680
|
+
RETURN_ERROR_IF(dctx->ddictLocal == NULL, memory_allocation, "NULL pointer!");
|
|
1271
1681
|
dctx->ddict = dctx->ddictLocal;
|
|
1272
1682
|
dctx->dictUses = ZSTD_use_indefinitely;
|
|
1273
1683
|
}
|
|
@@ -1286,7 +1696,7 @@ size_t ZSTD_DCtx_loadDictionary(ZSTD_DCtx* dctx, const void* dict, size_t dictSi
|
|
|
1286
1696
|
|
|
1287
1697
|
size_t ZSTD_DCtx_refPrefix_advanced(ZSTD_DCtx* dctx, const void* prefix, size_t prefixSize, ZSTD_dictContentType_e dictContentType)
|
|
1288
1698
|
{
|
|
1289
|
-
FORWARD_IF_ERROR(ZSTD_DCtx_loadDictionary_advanced(dctx, prefix, prefixSize, ZSTD_dlm_byRef, dictContentType));
|
|
1699
|
+
FORWARD_IF_ERROR(ZSTD_DCtx_loadDictionary_advanced(dctx, prefix, prefixSize, ZSTD_dlm_byRef, dictContentType), "");
|
|
1290
1700
|
dctx->dictUses = ZSTD_use_once;
|
|
1291
1701
|
return 0;
|
|
1292
1702
|
}
|
|
@@ -1303,8 +1713,8 @@ size_t ZSTD_DCtx_refPrefix(ZSTD_DCtx* dctx, const void* prefix, size_t prefixSiz
|
|
|
1303
1713
|
size_t ZSTD_initDStream_usingDict(ZSTD_DStream* zds, const void* dict, size_t dictSize)
|
|
1304
1714
|
{
|
|
1305
1715
|
DEBUGLOG(4, "ZSTD_initDStream_usingDict");
|
|
1306
|
-
FORWARD_IF_ERROR( ZSTD_DCtx_reset(zds, ZSTD_reset_session_only) );
|
|
1307
|
-
FORWARD_IF_ERROR( ZSTD_DCtx_loadDictionary(zds, dict, dictSize) );
|
|
1716
|
+
FORWARD_IF_ERROR( ZSTD_DCtx_reset(zds, ZSTD_reset_session_only) , "");
|
|
1717
|
+
FORWARD_IF_ERROR( ZSTD_DCtx_loadDictionary(zds, dict, dictSize) , "");
|
|
1308
1718
|
return ZSTD_startingInputLength(zds->format);
|
|
1309
1719
|
}
|
|
1310
1720
|
|
|
@@ -1312,7 +1722,9 @@ size_t ZSTD_initDStream_usingDict(ZSTD_DStream* zds, const void* dict, size_t di
|
|
|
1312
1722
|
size_t ZSTD_initDStream(ZSTD_DStream* zds)
|
|
1313
1723
|
{
|
|
1314
1724
|
DEBUGLOG(4, "ZSTD_initDStream");
|
|
1315
|
-
|
|
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);
|
|
1316
1728
|
}
|
|
1317
1729
|
|
|
1318
1730
|
/* ZSTD_initDStream_usingDDict() :
|
|
@@ -1320,8 +1732,9 @@ size_t ZSTD_initDStream(ZSTD_DStream* zds)
|
|
|
1320
1732
|
* this function cannot fail */
|
|
1321
1733
|
size_t ZSTD_initDStream_usingDDict(ZSTD_DStream* dctx, const ZSTD_DDict* ddict)
|
|
1322
1734
|
{
|
|
1323
|
-
|
|
1324
|
-
FORWARD_IF_ERROR(
|
|
1735
|
+
DEBUGLOG(4, "ZSTD_initDStream_usingDDict");
|
|
1736
|
+
FORWARD_IF_ERROR( ZSTD_DCtx_reset(dctx, ZSTD_reset_session_only) , "");
|
|
1737
|
+
FORWARD_IF_ERROR( ZSTD_DCtx_refDDict(dctx, ddict) , "");
|
|
1325
1738
|
return ZSTD_startingInputLength(dctx->format);
|
|
1326
1739
|
}
|
|
1327
1740
|
|
|
@@ -1330,18 +1743,29 @@ size_t ZSTD_initDStream_usingDDict(ZSTD_DStream* dctx, const ZSTD_DDict* ddict)
|
|
|
1330
1743
|
* this function cannot fail */
|
|
1331
1744
|
size_t ZSTD_resetDStream(ZSTD_DStream* dctx)
|
|
1332
1745
|
{
|
|
1333
|
-
|
|
1746
|
+
DEBUGLOG(4, "ZSTD_resetDStream");
|
|
1747
|
+
FORWARD_IF_ERROR(ZSTD_DCtx_reset(dctx, ZSTD_reset_session_only), "");
|
|
1334
1748
|
return ZSTD_startingInputLength(dctx->format);
|
|
1335
1749
|
}
|
|
1336
1750
|
|
|
1337
1751
|
|
|
1338
1752
|
size_t ZSTD_DCtx_refDDict(ZSTD_DCtx* dctx, const ZSTD_DDict* ddict)
|
|
1339
1753
|
{
|
|
1340
|
-
RETURN_ERROR_IF(dctx->streamStage != zdss_init, stage_wrong);
|
|
1754
|
+
RETURN_ERROR_IF(dctx->streamStage != zdss_init, stage_wrong, "");
|
|
1341
1755
|
ZSTD_clearDict(dctx);
|
|
1342
1756
|
if (ddict) {
|
|
1343
1757
|
dctx->ddict = ddict;
|
|
1344
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
|
+
}
|
|
1345
1769
|
}
|
|
1346
1770
|
return 0;
|
|
1347
1771
|
}
|
|
@@ -1354,16 +1778,16 @@ size_t ZSTD_DCtx_setMaxWindowSize(ZSTD_DCtx* dctx, size_t maxWindowSize)
|
|
|
1354
1778
|
ZSTD_bounds const bounds = ZSTD_dParam_getBounds(ZSTD_d_windowLogMax);
|
|
1355
1779
|
size_t const min = (size_t)1 << bounds.lowerBound;
|
|
1356
1780
|
size_t const max = (size_t)1 << bounds.upperBound;
|
|
1357
|
-
RETURN_ERROR_IF(dctx->streamStage != zdss_init, stage_wrong);
|
|
1358
|
-
RETURN_ERROR_IF(maxWindowSize < min, parameter_outOfBound);
|
|
1359
|
-
RETURN_ERROR_IF(maxWindowSize > max, parameter_outOfBound);
|
|
1781
|
+
RETURN_ERROR_IF(dctx->streamStage != zdss_init, stage_wrong, "");
|
|
1782
|
+
RETURN_ERROR_IF(maxWindowSize < min, parameter_outOfBound, "");
|
|
1783
|
+
RETURN_ERROR_IF(maxWindowSize > max, parameter_outOfBound, "");
|
|
1360
1784
|
dctx->maxWindowSize = maxWindowSize;
|
|
1361
1785
|
return 0;
|
|
1362
1786
|
}
|
|
1363
1787
|
|
|
1364
1788
|
size_t ZSTD_DCtx_setFormat(ZSTD_DCtx* dctx, ZSTD_format_e format)
|
|
1365
1789
|
{
|
|
1366
|
-
return ZSTD_DCtx_setParameter(dctx, ZSTD_d_format, format);
|
|
1790
|
+
return ZSTD_DCtx_setParameter(dctx, ZSTD_d_format, (int)format);
|
|
1367
1791
|
}
|
|
1368
1792
|
|
|
1369
1793
|
ZSTD_bounds ZSTD_dParam_getBounds(ZSTD_dParameter dParam)
|
|
@@ -1379,6 +1803,23 @@ ZSTD_bounds ZSTD_dParam_getBounds(ZSTD_dParameter dParam)
|
|
|
1379
1803
|
bounds.upperBound = (int)ZSTD_f_zstd1_magicless;
|
|
1380
1804
|
ZSTD_STATIC_ASSERT(ZSTD_f_zstd1 < ZSTD_f_zstd1_magicless);
|
|
1381
1805
|
return bounds;
|
|
1806
|
+
case ZSTD_d_stableOutBuffer:
|
|
1807
|
+
bounds.lowerBound = (int)ZSTD_bm_buffered;
|
|
1808
|
+
bounds.upperBound = (int)ZSTD_bm_stable;
|
|
1809
|
+
return bounds;
|
|
1810
|
+
case ZSTD_d_forceIgnoreChecksum:
|
|
1811
|
+
bounds.lowerBound = (int)ZSTD_d_validateChecksum;
|
|
1812
|
+
bounds.upperBound = (int)ZSTD_d_ignoreChecksum;
|
|
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
|
+
|
|
1382
1823
|
default:;
|
|
1383
1824
|
}
|
|
1384
1825
|
bounds.error = ERROR(parameter_unsupported);
|
|
@@ -1398,12 +1839,38 @@ static int ZSTD_dParam_withinBounds(ZSTD_dParameter dParam, int value)
|
|
|
1398
1839
|
}
|
|
1399
1840
|
|
|
1400
1841
|
#define CHECK_DBOUNDS(p,v) { \
|
|
1401
|
-
RETURN_ERROR_IF(!ZSTD_dParam_withinBounds(p, v), parameter_outOfBound); \
|
|
1842
|
+
RETURN_ERROR_IF(!ZSTD_dParam_withinBounds(p, v), parameter_outOfBound, ""); \
|
|
1843
|
+
}
|
|
1844
|
+
|
|
1845
|
+
size_t ZSTD_DCtx_getParameter(ZSTD_DCtx* dctx, ZSTD_dParameter param, int* value)
|
|
1846
|
+
{
|
|
1847
|
+
switch (param) {
|
|
1848
|
+
case ZSTD_d_windowLogMax:
|
|
1849
|
+
*value = (int)ZSTD_highbit32((U32)dctx->maxWindowSize);
|
|
1850
|
+
return 0;
|
|
1851
|
+
case ZSTD_d_format:
|
|
1852
|
+
*value = (int)dctx->format;
|
|
1853
|
+
return 0;
|
|
1854
|
+
case ZSTD_d_stableOutBuffer:
|
|
1855
|
+
*value = (int)dctx->outBufferMode;
|
|
1856
|
+
return 0;
|
|
1857
|
+
case ZSTD_d_forceIgnoreChecksum:
|
|
1858
|
+
*value = (int)dctx->forceIgnoreChecksum;
|
|
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;
|
|
1866
|
+
default:;
|
|
1867
|
+
}
|
|
1868
|
+
RETURN_ERROR(parameter_unsupported, "");
|
|
1402
1869
|
}
|
|
1403
1870
|
|
|
1404
1871
|
size_t ZSTD_DCtx_setParameter(ZSTD_DCtx* dctx, ZSTD_dParameter dParam, int value)
|
|
1405
1872
|
{
|
|
1406
|
-
RETURN_ERROR_IF(dctx->streamStage != zdss_init, stage_wrong);
|
|
1873
|
+
RETURN_ERROR_IF(dctx->streamStage != zdss_init, stage_wrong, "");
|
|
1407
1874
|
switch(dParam) {
|
|
1408
1875
|
case ZSTD_d_windowLogMax:
|
|
1409
1876
|
if (value == 0) value = ZSTD_WINDOWLOG_LIMIT_DEFAULT;
|
|
@@ -1414,9 +1881,28 @@ size_t ZSTD_DCtx_setParameter(ZSTD_DCtx* dctx, ZSTD_dParameter dParam, int value
|
|
|
1414
1881
|
CHECK_DBOUNDS(ZSTD_d_format, value);
|
|
1415
1882
|
dctx->format = (ZSTD_format_e)value;
|
|
1416
1883
|
return 0;
|
|
1884
|
+
case ZSTD_d_stableOutBuffer:
|
|
1885
|
+
CHECK_DBOUNDS(ZSTD_d_stableOutBuffer, value);
|
|
1886
|
+
dctx->outBufferMode = (ZSTD_bufferMode_e)value;
|
|
1887
|
+
return 0;
|
|
1888
|
+
case ZSTD_d_forceIgnoreChecksum:
|
|
1889
|
+
CHECK_DBOUNDS(ZSTD_d_forceIgnoreChecksum, value);
|
|
1890
|
+
dctx->forceIgnoreChecksum = (ZSTD_forceIgnoreChecksum_e)value;
|
|
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;
|
|
1417
1903
|
default:;
|
|
1418
1904
|
}
|
|
1419
|
-
RETURN_ERROR(parameter_unsupported);
|
|
1905
|
+
RETURN_ERROR(parameter_unsupported, "");
|
|
1420
1906
|
}
|
|
1421
1907
|
|
|
1422
1908
|
size_t ZSTD_DCtx_reset(ZSTD_DCtx* dctx, ZSTD_ResetDirective reset)
|
|
@@ -1428,10 +1914,9 @@ size_t ZSTD_DCtx_reset(ZSTD_DCtx* dctx, ZSTD_ResetDirective reset)
|
|
|
1428
1914
|
}
|
|
1429
1915
|
if ( (reset == ZSTD_reset_parameters)
|
|
1430
1916
|
|| (reset == ZSTD_reset_session_and_parameters) ) {
|
|
1431
|
-
RETURN_ERROR_IF(dctx->streamStage != zdss_init, stage_wrong);
|
|
1917
|
+
RETURN_ERROR_IF(dctx->streamStage != zdss_init, stage_wrong, "");
|
|
1432
1918
|
ZSTD_clearDict(dctx);
|
|
1433
|
-
dctx
|
|
1434
|
-
dctx->maxWindowSize = ZSTD_MAXWINDOWSIZE_DEFAULT;
|
|
1919
|
+
ZSTD_DCtx_resetParameters(dctx);
|
|
1435
1920
|
}
|
|
1436
1921
|
return 0;
|
|
1437
1922
|
}
|
|
@@ -1445,11 +1930,12 @@ size_t ZSTD_sizeof_DStream(const ZSTD_DStream* dctx)
|
|
|
1445
1930
|
size_t ZSTD_decodingBufferSize_min(unsigned long long windowSize, unsigned long long frameContentSize)
|
|
1446
1931
|
{
|
|
1447
1932
|
size_t const blockSize = (size_t) MIN(windowSize, ZSTD_BLOCKSIZE_MAX);
|
|
1448
|
-
|
|
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);
|
|
1449
1935
|
unsigned long long const neededSize = MIN(frameContentSize, neededRBSize);
|
|
1450
1936
|
size_t const minRBSize = (size_t) neededSize;
|
|
1451
1937
|
RETURN_ERROR_IF((unsigned long long)minRBSize != neededSize,
|
|
1452
|
-
frameParameter_windowTooLarge);
|
|
1938
|
+
frameParameter_windowTooLarge, "");
|
|
1453
1939
|
return minRBSize;
|
|
1454
1940
|
}
|
|
1455
1941
|
|
|
@@ -1467,30 +1953,94 @@ size_t ZSTD_estimateDStreamSize_fromFrame(const void* src, size_t srcSize)
|
|
|
1467
1953
|
ZSTD_frameHeader zfh;
|
|
1468
1954
|
size_t const err = ZSTD_getFrameHeader(&zfh, src, srcSize);
|
|
1469
1955
|
if (ZSTD_isError(err)) return err;
|
|
1470
|
-
RETURN_ERROR_IF(err>0, srcSize_wrong);
|
|
1956
|
+
RETURN_ERROR_IF(err>0, srcSize_wrong, "");
|
|
1471
1957
|
RETURN_ERROR_IF(zfh.windowSize > windowSizeMax,
|
|
1472
|
-
frameParameter_windowTooLarge);
|
|
1958
|
+
frameParameter_windowTooLarge, "");
|
|
1473
1959
|
return ZSTD_estimateDStreamSize((size_t)zfh.windowSize);
|
|
1474
1960
|
}
|
|
1475
1961
|
|
|
1476
1962
|
|
|
1477
1963
|
/* ***** Decompression ***** */
|
|
1478
1964
|
|
|
1479
|
-
|
|
1965
|
+
static int ZSTD_DCtx_isOverflow(ZSTD_DStream* zds, size_t const neededInBuffSize, size_t const neededOutBuffSize)
|
|
1480
1966
|
{
|
|
1481
|
-
|
|
1482
|
-
memcpy(dst, src, length);
|
|
1483
|
-
return length;
|
|
1967
|
+
return (zds->inBuffSize + zds->outBuffSize) >= (neededInBuffSize + neededOutBuffSize) * ZSTD_WORKSPACETOOLARGE_FACTOR;
|
|
1484
1968
|
}
|
|
1485
1969
|
|
|
1970
|
+
static void ZSTD_DCtx_updateOversizedDuration(ZSTD_DStream* zds, size_t const neededInBuffSize, size_t const neededOutBuffSize)
|
|
1971
|
+
{
|
|
1972
|
+
if (ZSTD_DCtx_isOverflow(zds, neededInBuffSize, neededOutBuffSize))
|
|
1973
|
+
zds->oversizedDuration++;
|
|
1974
|
+
else
|
|
1975
|
+
zds->oversizedDuration = 0;
|
|
1976
|
+
}
|
|
1977
|
+
|
|
1978
|
+
static int ZSTD_DCtx_isOversizedTooLong(ZSTD_DStream* zds)
|
|
1979
|
+
{
|
|
1980
|
+
return zds->oversizedDuration >= ZSTD_WORKSPACETOOLARGE_MAXDURATION;
|
|
1981
|
+
}
|
|
1982
|
+
|
|
1983
|
+
/* Checks that the output buffer hasn't changed if ZSTD_obm_stable is used. */
|
|
1984
|
+
static size_t ZSTD_checkOutBuffer(ZSTD_DStream const* zds, ZSTD_outBuffer const* output)
|
|
1985
|
+
{
|
|
1986
|
+
ZSTD_outBuffer const expect = zds->expectedOutBuffer;
|
|
1987
|
+
/* No requirement when ZSTD_obm_stable is not enabled. */
|
|
1988
|
+
if (zds->outBufferMode != ZSTD_bm_stable)
|
|
1989
|
+
return 0;
|
|
1990
|
+
/* Any buffer is allowed in zdss_init, this must be the same for every other call until
|
|
1991
|
+
* the context is reset.
|
|
1992
|
+
*/
|
|
1993
|
+
if (zds->streamStage == zdss_init)
|
|
1994
|
+
return 0;
|
|
1995
|
+
/* The buffer must match our expectation exactly. */
|
|
1996
|
+
if (expect.dst == output->dst && expect.pos == output->pos && expect.size == output->size)
|
|
1997
|
+
return 0;
|
|
1998
|
+
RETURN_ERROR(dstBuffer_wrong, "ZSTD_d_stableOutBuffer enabled but output differs!");
|
|
1999
|
+
}
|
|
2000
|
+
|
|
2001
|
+
/* Calls ZSTD_decompressContinue() with the right parameters for ZSTD_decompressStream()
|
|
2002
|
+
* and updates the stage and the output buffer state. This call is extracted so it can be
|
|
2003
|
+
* used both when reading directly from the ZSTD_inBuffer, and in buffered input mode.
|
|
2004
|
+
* NOTE: You must break after calling this function since the streamStage is modified.
|
|
2005
|
+
*/
|
|
2006
|
+
static size_t ZSTD_decompressContinueStream(
|
|
2007
|
+
ZSTD_DStream* zds, char** op, char* oend,
|
|
2008
|
+
void const* src, size_t srcSize) {
|
|
2009
|
+
int const isSkipFrame = ZSTD_isSkipFrame(zds);
|
|
2010
|
+
if (zds->outBufferMode == ZSTD_bm_buffered) {
|
|
2011
|
+
size_t const dstSize = isSkipFrame ? 0 : zds->outBuffSize - zds->outStart;
|
|
2012
|
+
size_t const decodedSize = ZSTD_decompressContinue(zds,
|
|
2013
|
+
zds->outBuff + zds->outStart, dstSize, src, srcSize);
|
|
2014
|
+
FORWARD_IF_ERROR(decodedSize, "");
|
|
2015
|
+
if (!decodedSize && !isSkipFrame) {
|
|
2016
|
+
zds->streamStage = zdss_read;
|
|
2017
|
+
} else {
|
|
2018
|
+
zds->outEnd = zds->outStart + decodedSize;
|
|
2019
|
+
zds->streamStage = zdss_flush;
|
|
2020
|
+
}
|
|
2021
|
+
} else {
|
|
2022
|
+
/* Write directly into the output buffer */
|
|
2023
|
+
size_t const dstSize = isSkipFrame ? 0 : (size_t)(oend - *op);
|
|
2024
|
+
size_t const decodedSize = ZSTD_decompressContinue(zds, *op, dstSize, src, srcSize);
|
|
2025
|
+
FORWARD_IF_ERROR(decodedSize, "");
|
|
2026
|
+
*op += decodedSize;
|
|
2027
|
+
/* Flushing is not needed. */
|
|
2028
|
+
zds->streamStage = zdss_read;
|
|
2029
|
+
assert(*op <= oend);
|
|
2030
|
+
assert(zds->outBufferMode == ZSTD_bm_stable);
|
|
2031
|
+
}
|
|
2032
|
+
return 0;
|
|
2033
|
+
}
|
|
1486
2034
|
|
|
1487
2035
|
size_t ZSTD_decompressStream(ZSTD_DStream* zds, ZSTD_outBuffer* output, ZSTD_inBuffer* input)
|
|
1488
2036
|
{
|
|
1489
|
-
const char* const
|
|
1490
|
-
const char* const
|
|
2037
|
+
const char* const src = (const char*)input->src;
|
|
2038
|
+
const char* const istart = input->pos != 0 ? src + input->pos : src;
|
|
2039
|
+
const char* const iend = input->size != 0 ? src + input->size : src;
|
|
1491
2040
|
const char* ip = istart;
|
|
1492
|
-
char* const
|
|
1493
|
-
char* const
|
|
2041
|
+
char* const dst = (char*)output->dst;
|
|
2042
|
+
char* const ostart = output->pos != 0 ? dst + output->pos : dst;
|
|
2043
|
+
char* const oend = output->size != 0 ? dst + output->size : dst;
|
|
1494
2044
|
char* op = ostart;
|
|
1495
2045
|
U32 someMoreWork = 1;
|
|
1496
2046
|
|
|
@@ -1506,6 +2056,7 @@ size_t ZSTD_decompressStream(ZSTD_DStream* zds, ZSTD_outBuffer* output, ZSTD_inB
|
|
|
1506
2056
|
"forbidden. out: pos: %u vs size: %u",
|
|
1507
2057
|
(U32)output->pos, (U32)output->size);
|
|
1508
2058
|
DEBUGLOG(5, "input size : %u", (U32)(input->size - input->pos));
|
|
2059
|
+
FORWARD_IF_ERROR(ZSTD_checkOutBuffer(zds, output), "");
|
|
1509
2060
|
|
|
1510
2061
|
while (someMoreWork) {
|
|
1511
2062
|
switch(zds->streamStage)
|
|
@@ -1514,9 +2065,12 @@ size_t ZSTD_decompressStream(ZSTD_DStream* zds, ZSTD_outBuffer* output, ZSTD_inB
|
|
|
1514
2065
|
DEBUGLOG(5, "stage zdss_init => transparent reset ");
|
|
1515
2066
|
zds->streamStage = zdss_loadHeader;
|
|
1516
2067
|
zds->lhSize = zds->inPos = zds->outStart = zds->outEnd = 0;
|
|
2068
|
+
#if defined(ZSTD_LEGACY_SUPPORT) && (ZSTD_LEGACY_SUPPORT>=1)
|
|
1517
2069
|
zds->legacyVersion = 0;
|
|
2070
|
+
#endif
|
|
1518
2071
|
zds->hostageByte = 0;
|
|
1519
|
-
|
|
2072
|
+
zds->expectedOutBuffer = *output;
|
|
2073
|
+
ZSTD_FALLTHROUGH;
|
|
1520
2074
|
|
|
1521
2075
|
case zdss_loadHeader :
|
|
1522
2076
|
DEBUGLOG(5, "stage zdss_loadHeader (srcSize : %u)", (U32)(iend - ip));
|
|
@@ -1530,7 +2084,9 @@ size_t ZSTD_decompressStream(ZSTD_DStream* zds, ZSTD_outBuffer* output, ZSTD_inB
|
|
|
1530
2084
|
} }
|
|
1531
2085
|
#endif
|
|
1532
2086
|
{ size_t const hSize = ZSTD_getFrameHeader_advanced(&zds->fParams, zds->headerBuffer, zds->lhSize, zds->format);
|
|
1533
|
-
|
|
2087
|
+
if (zds->refMultipleDDicts && zds->ddictSet) {
|
|
2088
|
+
ZSTD_DCtx_selectFrameDDict(zds);
|
|
2089
|
+
}
|
|
1534
2090
|
if (ZSTD_isError(hSize)) {
|
|
1535
2091
|
#if defined(ZSTD_LEGACY_SUPPORT) && (ZSTD_LEGACY_SUPPORT>=1)
|
|
1536
2092
|
U32 const legacyVersion = ZSTD_isLegacy(istart, iend-istart);
|
|
@@ -1543,7 +2099,7 @@ size_t ZSTD_decompressStream(ZSTD_DStream* zds, ZSTD_outBuffer* output, ZSTD_inB
|
|
|
1543
2099
|
"legacy support is incompatible with static dctx");
|
|
1544
2100
|
FORWARD_IF_ERROR(ZSTD_initLegacyStream(&zds->legacyContext,
|
|
1545
2101
|
zds->previousLegacyVersion, legacyVersion,
|
|
1546
|
-
dict, dictSize));
|
|
2102
|
+
dict, dictSize), "");
|
|
1547
2103
|
zds->legacyVersion = zds->previousLegacyVersion = legacyVersion;
|
|
1548
2104
|
{ size_t const hint = ZSTD_decompressLegacyStream(zds->legacyContext, legacyVersion, output, input);
|
|
1549
2105
|
if (hint==0) zds->streamStage = zdss_init; /* or stay in stage zdss_loadHeader */
|
|
@@ -1558,43 +2114,58 @@ size_t ZSTD_decompressStream(ZSTD_DStream* zds, ZSTD_outBuffer* output, ZSTD_inB
|
|
|
1558
2114
|
assert(iend >= ip);
|
|
1559
2115
|
if (toLoad > remainingInput) { /* not enough input to load full header */
|
|
1560
2116
|
if (remainingInput > 0) {
|
|
1561
|
-
|
|
2117
|
+
ZSTD_memcpy(zds->headerBuffer + zds->lhSize, ip, remainingInput);
|
|
1562
2118
|
zds->lhSize += remainingInput;
|
|
1563
2119
|
}
|
|
1564
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 */
|
|
1565
2126
|
return (MAX((size_t)ZSTD_FRAMEHEADERSIZE_MIN(zds->format), hSize) - zds->lhSize) + ZSTD_blockHeaderSize; /* remaining header bytes + next block header */
|
|
1566
2127
|
}
|
|
1567
2128
|
assert(ip != NULL);
|
|
1568
|
-
|
|
2129
|
+
ZSTD_memcpy(zds->headerBuffer + zds->lhSize, ip, toLoad); zds->lhSize = hSize; ip += toLoad;
|
|
1569
2130
|
break;
|
|
1570
2131
|
} }
|
|
1571
2132
|
|
|
1572
2133
|
/* check for single-pass mode opportunity */
|
|
1573
|
-
if (zds->fParams.frameContentSize
|
|
2134
|
+
if (zds->fParams.frameContentSize != ZSTD_CONTENTSIZE_UNKNOWN
|
|
2135
|
+
&& zds->fParams.frameType != ZSTD_skippableFrame
|
|
1574
2136
|
&& (U64)(size_t)(oend-op) >= zds->fParams.frameContentSize) {
|
|
1575
|
-
size_t const cSize = ZSTD_findFrameCompressedSize(istart, iend-istart);
|
|
2137
|
+
size_t const cSize = ZSTD_findFrameCompressedSize(istart, (size_t)(iend-istart));
|
|
1576
2138
|
if (cSize <= (size_t)(iend-istart)) {
|
|
1577
2139
|
/* shortcut : using single-pass mode */
|
|
1578
|
-
size_t const decompressedSize = ZSTD_decompress_usingDDict(zds, op, oend-op, istart, cSize, ZSTD_getDDict(zds));
|
|
2140
|
+
size_t const decompressedSize = ZSTD_decompress_usingDDict(zds, op, (size_t)(oend-op), istart, cSize, ZSTD_getDDict(zds));
|
|
1579
2141
|
if (ZSTD_isError(decompressedSize)) return decompressedSize;
|
|
1580
2142
|
DEBUGLOG(4, "shortcut to single-pass ZSTD_decompress_usingDDict()")
|
|
2143
|
+
assert(istart != NULL);
|
|
1581
2144
|
ip = istart + cSize;
|
|
1582
|
-
op
|
|
2145
|
+
op = op ? op + decompressedSize : op; /* can occur if frameContentSize = 0 (empty frame) */
|
|
1583
2146
|
zds->expected = 0;
|
|
1584
2147
|
zds->streamStage = zdss_init;
|
|
1585
2148
|
someMoreWork = 0;
|
|
1586
2149
|
break;
|
|
1587
2150
|
} }
|
|
1588
2151
|
|
|
2152
|
+
/* Check output buffer is large enough for ZSTD_odm_stable. */
|
|
2153
|
+
if (zds->outBufferMode == ZSTD_bm_stable
|
|
2154
|
+
&& zds->fParams.frameType != ZSTD_skippableFrame
|
|
2155
|
+
&& zds->fParams.frameContentSize != ZSTD_CONTENTSIZE_UNKNOWN
|
|
2156
|
+
&& (U64)(size_t)(oend-op) < zds->fParams.frameContentSize) {
|
|
2157
|
+
RETURN_ERROR(dstSize_tooSmall, "ZSTD_obm_stable passed but ZSTD_outBuffer is too small");
|
|
2158
|
+
}
|
|
2159
|
+
|
|
1589
2160
|
/* Consume header (see ZSTDds_decodeFrameHeader) */
|
|
1590
2161
|
DEBUGLOG(4, "Consume header");
|
|
1591
|
-
FORWARD_IF_ERROR(ZSTD_decompressBegin_usingDDict(zds, ZSTD_getDDict(zds)));
|
|
2162
|
+
FORWARD_IF_ERROR(ZSTD_decompressBegin_usingDDict(zds, ZSTD_getDDict(zds)), "");
|
|
1592
2163
|
|
|
1593
2164
|
if ((MEM_readLE32(zds->headerBuffer) & ZSTD_MAGIC_SKIPPABLE_MASK) == ZSTD_MAGIC_SKIPPABLE_START) { /* skippable frame */
|
|
1594
2165
|
zds->expected = MEM_readLE32(zds->headerBuffer + ZSTD_FRAMEIDSIZE);
|
|
1595
2166
|
zds->stage = ZSTDds_skipFrame;
|
|
1596
2167
|
} else {
|
|
1597
|
-
FORWARD_IF_ERROR(ZSTD_decodeFrameHeader(zds, zds->headerBuffer, zds->lhSize));
|
|
2168
|
+
FORWARD_IF_ERROR(ZSTD_decodeFrameHeader(zds, zds->headerBuffer, zds->lhSize), "");
|
|
1598
2169
|
zds->expected = ZSTD_blockHeaderSize;
|
|
1599
2170
|
zds->stage = ZSTDds_decodeBlockHeader;
|
|
1600
2171
|
}
|
|
@@ -1605,40 +2176,48 @@ size_t ZSTD_decompressStream(ZSTD_DStream* zds, ZSTD_outBuffer* output, ZSTD_inB
|
|
|
1605
2176
|
(U32)(zds->maxWindowSize >> 10) );
|
|
1606
2177
|
zds->fParams.windowSize = MAX(zds->fParams.windowSize, 1U << ZSTD_WINDOWLOG_ABSOLUTEMIN);
|
|
1607
2178
|
RETURN_ERROR_IF(zds->fParams.windowSize > zds->maxWindowSize,
|
|
1608
|
-
frameParameter_windowTooLarge);
|
|
2179
|
+
frameParameter_windowTooLarge, "");
|
|
1609
2180
|
|
|
1610
2181
|
/* Adapt buffer sizes to frame header instructions */
|
|
1611
2182
|
{ size_t const neededInBuffSize = MAX(zds->fParams.blockSizeMax, 4 /* frame checksum */);
|
|
1612
|
-
size_t const neededOutBuffSize =
|
|
1613
|
-
|
|
1614
|
-
|
|
1615
|
-
|
|
1616
|
-
|
|
1617
|
-
|
|
1618
|
-
|
|
1619
|
-
|
|
1620
|
-
|
|
1621
|
-
|
|
1622
|
-
|
|
1623
|
-
|
|
1624
|
-
|
|
1625
|
-
|
|
1626
|
-
|
|
1627
|
-
zds->
|
|
1628
|
-
|
|
1629
|
-
|
|
1630
|
-
|
|
1631
|
-
|
|
1632
|
-
|
|
1633
|
-
|
|
1634
|
-
|
|
1635
|
-
|
|
2183
|
+
size_t const neededOutBuffSize = zds->outBufferMode == ZSTD_bm_buffered
|
|
2184
|
+
? ZSTD_decodingBufferSize_min(zds->fParams.windowSize, zds->fParams.frameContentSize)
|
|
2185
|
+
: 0;
|
|
2186
|
+
|
|
2187
|
+
ZSTD_DCtx_updateOversizedDuration(zds, neededInBuffSize, neededOutBuffSize);
|
|
2188
|
+
|
|
2189
|
+
{ int const tooSmall = (zds->inBuffSize < neededInBuffSize) || (zds->outBuffSize < neededOutBuffSize);
|
|
2190
|
+
int const tooLarge = ZSTD_DCtx_isOversizedTooLong(zds);
|
|
2191
|
+
|
|
2192
|
+
if (tooSmall || tooLarge) {
|
|
2193
|
+
size_t const bufferSize = neededInBuffSize + neededOutBuffSize;
|
|
2194
|
+
DEBUGLOG(4, "inBuff : from %u to %u",
|
|
2195
|
+
(U32)zds->inBuffSize, (U32)neededInBuffSize);
|
|
2196
|
+
DEBUGLOG(4, "outBuff : from %u to %u",
|
|
2197
|
+
(U32)zds->outBuffSize, (U32)neededOutBuffSize);
|
|
2198
|
+
if (zds->staticSize) { /* static DCtx */
|
|
2199
|
+
DEBUGLOG(4, "staticSize : %u", (U32)zds->staticSize);
|
|
2200
|
+
assert(zds->staticSize >= sizeof(ZSTD_DCtx)); /* controlled at init */
|
|
2201
|
+
RETURN_ERROR_IF(
|
|
2202
|
+
bufferSize > zds->staticSize - sizeof(ZSTD_DCtx),
|
|
2203
|
+
memory_allocation, "");
|
|
2204
|
+
} else {
|
|
2205
|
+
ZSTD_customFree(zds->inBuff, zds->customMem);
|
|
2206
|
+
zds->inBuffSize = 0;
|
|
2207
|
+
zds->outBuffSize = 0;
|
|
2208
|
+
zds->inBuff = (char*)ZSTD_customMalloc(bufferSize, zds->customMem);
|
|
2209
|
+
RETURN_ERROR_IF(zds->inBuff == NULL, memory_allocation, "");
|
|
2210
|
+
}
|
|
2211
|
+
zds->inBuffSize = neededInBuffSize;
|
|
2212
|
+
zds->outBuff = zds->inBuff + zds->inBuffSize;
|
|
2213
|
+
zds->outBuffSize = neededOutBuffSize;
|
|
2214
|
+
} } }
|
|
1636
2215
|
zds->streamStage = zdss_read;
|
|
1637
|
-
|
|
2216
|
+
ZSTD_FALLTHROUGH;
|
|
1638
2217
|
|
|
1639
2218
|
case zdss_read:
|
|
1640
2219
|
DEBUGLOG(5, "stage zdss_read");
|
|
1641
|
-
{ size_t const neededInSize =
|
|
2220
|
+
{ size_t const neededInSize = ZSTD_nextSrcSizeToDecompressWithInputSize(zds, (size_t)(iend - ip));
|
|
1642
2221
|
DEBUGLOG(5, "neededInSize = %u", (U32)neededInSize);
|
|
1643
2222
|
if (neededInSize==0) { /* end of frame */
|
|
1644
2223
|
zds->streamStage = zdss_init;
|
|
@@ -1646,59 +2225,56 @@ size_t ZSTD_decompressStream(ZSTD_DStream* zds, ZSTD_outBuffer* output, ZSTD_inB
|
|
|
1646
2225
|
break;
|
|
1647
2226
|
}
|
|
1648
2227
|
if ((size_t)(iend-ip) >= neededInSize) { /* decode directly from src */
|
|
1649
|
-
|
|
1650
|
-
|
|
1651
|
-
zds->outBuff + zds->outStart, (isSkipFrame ? 0 : zds->outBuffSize - zds->outStart),
|
|
1652
|
-
ip, neededInSize);
|
|
1653
|
-
if (ZSTD_isError(decodedSize)) return decodedSize;
|
|
2228
|
+
FORWARD_IF_ERROR(ZSTD_decompressContinueStream(zds, &op, oend, ip, neededInSize), "");
|
|
2229
|
+
assert(ip != NULL);
|
|
1654
2230
|
ip += neededInSize;
|
|
1655
|
-
|
|
1656
|
-
zds->outEnd = zds->outStart + decodedSize;
|
|
1657
|
-
zds->streamStage = zdss_flush;
|
|
2231
|
+
/* Function modifies the stage so we must break */
|
|
1658
2232
|
break;
|
|
1659
2233
|
} }
|
|
1660
2234
|
if (ip==iend) { someMoreWork = 0; break; } /* no more input */
|
|
1661
2235
|
zds->streamStage = zdss_load;
|
|
1662
|
-
|
|
2236
|
+
ZSTD_FALLTHROUGH;
|
|
1663
2237
|
|
|
1664
2238
|
case zdss_load:
|
|
1665
2239
|
{ size_t const neededInSize = ZSTD_nextSrcSizeToDecompress(zds);
|
|
1666
2240
|
size_t const toLoad = neededInSize - zds->inPos;
|
|
1667
2241
|
int const isSkipFrame = ZSTD_isSkipFrame(zds);
|
|
1668
2242
|
size_t loadedSize;
|
|
2243
|
+
/* At this point we shouldn't be decompressing a block that we can stream. */
|
|
2244
|
+
assert(neededInSize == ZSTD_nextSrcSizeToDecompressWithInputSize(zds, (size_t)(iend - ip)));
|
|
1669
2245
|
if (isSkipFrame) {
|
|
1670
2246
|
loadedSize = MIN(toLoad, (size_t)(iend-ip));
|
|
1671
2247
|
} else {
|
|
1672
2248
|
RETURN_ERROR_IF(toLoad > zds->inBuffSize - zds->inPos,
|
|
1673
2249
|
corruption_detected,
|
|
1674
2250
|
"should never happen");
|
|
1675
|
-
loadedSize = ZSTD_limitCopy(zds->inBuff + zds->inPos, toLoad, ip, iend-ip);
|
|
2251
|
+
loadedSize = ZSTD_limitCopy(zds->inBuff + zds->inPos, toLoad, ip, (size_t)(iend-ip));
|
|
2252
|
+
}
|
|
2253
|
+
if (loadedSize != 0) {
|
|
2254
|
+
/* ip may be NULL */
|
|
2255
|
+
ip += loadedSize;
|
|
2256
|
+
zds->inPos += loadedSize;
|
|
1676
2257
|
}
|
|
1677
|
-
ip += loadedSize;
|
|
1678
|
-
zds->inPos += loadedSize;
|
|
1679
2258
|
if (loadedSize < toLoad) { someMoreWork = 0; break; } /* not enough input, wait for more */
|
|
1680
2259
|
|
|
1681
2260
|
/* decode loaded input */
|
|
1682
|
-
|
|
1683
|
-
|
|
1684
|
-
|
|
1685
|
-
|
|
1686
|
-
|
|
1687
|
-
if (!decodedSize && !isSkipFrame) { zds->streamStage = zdss_read; break; } /* this was just a header */
|
|
1688
|
-
zds->outEnd = zds->outStart + decodedSize;
|
|
1689
|
-
} }
|
|
1690
|
-
zds->streamStage = zdss_flush;
|
|
1691
|
-
/* fall-through */
|
|
1692
|
-
|
|
2261
|
+
zds->inPos = 0; /* input is consumed */
|
|
2262
|
+
FORWARD_IF_ERROR(ZSTD_decompressContinueStream(zds, &op, oend, zds->inBuff, neededInSize), "");
|
|
2263
|
+
/* Function modifies the stage so we must break */
|
|
2264
|
+
break;
|
|
2265
|
+
}
|
|
1693
2266
|
case zdss_flush:
|
|
1694
|
-
{
|
|
1695
|
-
size_t const
|
|
1696
|
-
op
|
|
2267
|
+
{
|
|
2268
|
+
size_t const toFlushSize = zds->outEnd - zds->outStart;
|
|
2269
|
+
size_t const flushedSize = ZSTD_limitCopy(op, (size_t)(oend-op), zds->outBuff + zds->outStart, toFlushSize);
|
|
2270
|
+
|
|
2271
|
+
op = op ? op + flushedSize : op;
|
|
2272
|
+
|
|
1697
2273
|
zds->outStart += flushedSize;
|
|
1698
2274
|
if (flushedSize == toFlushSize) { /* flush completed */
|
|
1699
2275
|
zds->streamStage = zdss_read;
|
|
1700
2276
|
if ( (zds->outBuffSize < zds->fParams.frameContentSize)
|
|
1701
|
-
|
|
2277
|
+
&& (zds->outStart + zds->fParams.blockSizeMax > zds->outBuffSize) ) {
|
|
1702
2278
|
DEBUGLOG(5, "restart filling outBuff from beginning (left:%i, needed:%u)",
|
|
1703
2279
|
(int)(zds->outBuffSize - zds->outStart),
|
|
1704
2280
|
(U32)zds->fParams.blockSizeMax);
|
|
@@ -1712,17 +2288,21 @@ size_t ZSTD_decompressStream(ZSTD_DStream* zds, ZSTD_outBuffer* output, ZSTD_inB
|
|
|
1712
2288
|
|
|
1713
2289
|
default:
|
|
1714
2290
|
assert(0); /* impossible */
|
|
1715
|
-
RETURN_ERROR(GENERIC); /* some
|
|
2291
|
+
RETURN_ERROR(GENERIC, "impossible to reach"); /* some compilers require default to do something */
|
|
1716
2292
|
} }
|
|
1717
2293
|
|
|
1718
2294
|
/* result */
|
|
1719
2295
|
input->pos = (size_t)(ip - (const char*)(input->src));
|
|
1720
2296
|
output->pos = (size_t)(op - (char*)(output->dst));
|
|
2297
|
+
|
|
2298
|
+
/* Update the expected output buffer for ZSTD_obm_stable. */
|
|
2299
|
+
zds->expectedOutBuffer = *output;
|
|
2300
|
+
|
|
1721
2301
|
if ((ip==istart) && (op==ostart)) { /* no forward progress */
|
|
1722
2302
|
zds->noForwardProgress ++;
|
|
1723
2303
|
if (zds->noForwardProgress >= ZSTD_NO_FORWARD_PROGRESS_MAX) {
|
|
1724
|
-
RETURN_ERROR_IF(op==oend,
|
|
1725
|
-
RETURN_ERROR_IF(ip==iend,
|
|
2304
|
+
RETURN_ERROR_IF(op==oend, noForwardProgress_destFull, "");
|
|
2305
|
+
RETURN_ERROR_IF(ip==iend, noForwardProgress_inputEmpty, "");
|
|
1726
2306
|
assert(0);
|
|
1727
2307
|
}
|
|
1728
2308
|
} else {
|
|
@@ -1759,11 +2339,17 @@ size_t ZSTD_decompressStream_simpleArgs (
|
|
|
1759
2339
|
void* dst, size_t dstCapacity, size_t* dstPos,
|
|
1760
2340
|
const void* src, size_t srcSize, size_t* srcPos)
|
|
1761
2341
|
{
|
|
1762
|
-
ZSTD_outBuffer output
|
|
1763
|
-
ZSTD_inBuffer input
|
|
1764
|
-
|
|
1765
|
-
|
|
1766
|
-
|
|
1767
|
-
|
|
1768
|
-
|
|
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
|
+
}
|
|
1769
2355
|
}
|