zstd-ruby 1.4.1.0 → 1.5.0.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/.github/dependabot.yml +8 -0
- data/.github/workflows/ruby.yml +35 -0
- data/README.md +2 -2
- data/ext/zstdruby/libzstd/BUCK +5 -7
- data/ext/zstdruby/libzstd/Makefile +304 -113
- data/ext/zstdruby/libzstd/README.md +83 -20
- data/ext/zstdruby/libzstd/common/bitstream.h +59 -51
- data/ext/zstdruby/libzstd/common/compiler.h +150 -8
- 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 +201 -75
- data/ext/zstdruby/libzstd/common/error_private.c +3 -1
- data/ext/zstdruby/libzstd/common/error_private.h +8 -4
- data/ext/zstdruby/libzstd/common/fse.h +50 -42
- data/ext/zstdruby/libzstd/common/fse_decompress.c +149 -55
- data/ext/zstdruby/libzstd/common/huf.h +43 -39
- data/ext/zstdruby/libzstd/common/mem.h +69 -25
- data/ext/zstdruby/libzstd/common/pool.c +30 -20
- data/ext/zstdruby/libzstd/common/pool.h +3 -3
- data/ext/zstdruby/libzstd/common/threading.c +51 -4
- data/ext/zstdruby/libzstd/common/threading.h +36 -4
- data/ext/zstdruby/libzstd/common/xxhash.c +40 -92
- data/ext/zstdruby/libzstd/common/xxhash.h +12 -32
- data/ext/zstdruby/libzstd/common/zstd_common.c +10 -10
- data/ext/zstdruby/libzstd/common/zstd_deps.h +111 -0
- data/ext/zstdruby/libzstd/common/zstd_internal.h +230 -111
- data/ext/zstdruby/libzstd/common/zstd_trace.h +154 -0
- data/ext/zstdruby/libzstd/compress/fse_compress.c +47 -63
- 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 +332 -193
- data/ext/zstdruby/libzstd/compress/zstd_compress.c +3614 -1696
- data/ext/zstdruby/libzstd/compress/zstd_compress_internal.h +546 -86
- data/ext/zstdruby/libzstd/compress/zstd_compress_literals.c +158 -0
- data/ext/zstdruby/libzstd/compress/zstd_compress_literals.h +29 -0
- data/ext/zstdruby/libzstd/compress/zstd_compress_sequences.c +441 -0
- data/ext/zstdruby/libzstd/compress/zstd_compress_sequences.h +54 -0
- data/ext/zstdruby/libzstd/compress/zstd_compress_superblock.c +572 -0
- data/ext/zstdruby/libzstd/compress/zstd_compress_superblock.h +32 -0
- data/ext/zstdruby/libzstd/compress/zstd_cwksp.h +662 -0
- data/ext/zstdruby/libzstd/compress/zstd_double_fast.c +43 -41
- data/ext/zstdruby/libzstd/compress/zstd_double_fast.h +2 -2
- data/ext/zstdruby/libzstd/compress/zstd_fast.c +85 -80
- data/ext/zstdruby/libzstd/compress/zstd_fast.h +2 -2
- data/ext/zstdruby/libzstd/compress/zstd_lazy.c +1184 -111
- data/ext/zstdruby/libzstd/compress/zstd_lazy.h +59 -1
- data/ext/zstdruby/libzstd/compress/zstd_ldm.c +333 -208
- data/ext/zstdruby/libzstd/compress/zstd_ldm.h +15 -3
- data/ext/zstdruby/libzstd/compress/zstd_ldm_geartab.h +103 -0
- data/ext/zstdruby/libzstd/compress/zstd_opt.c +228 -129
- data/ext/zstdruby/libzstd/compress/zstd_opt.h +1 -1
- data/ext/zstdruby/libzstd/compress/zstdmt_compress.c +151 -440
- data/ext/zstdruby/libzstd/compress/zstdmt_compress.h +32 -114
- data/ext/zstdruby/libzstd/decompress/huf_decompress.c +395 -276
- data/ext/zstdruby/libzstd/decompress/zstd_ddict.c +20 -16
- data/ext/zstdruby/libzstd/decompress/zstd_ddict.h +3 -3
- data/ext/zstdruby/libzstd/decompress/zstd_decompress.c +630 -231
- data/ext/zstdruby/libzstd/decompress/zstd_decompress_block.c +606 -380
- data/ext/zstdruby/libzstd/decompress/zstd_decompress_block.h +8 -5
- data/ext/zstdruby/libzstd/decompress/zstd_decompress_internal.h +39 -9
- data/ext/zstdruby/libzstd/deprecated/zbuff.h +9 -8
- data/ext/zstdruby/libzstd/deprecated/zbuff_common.c +2 -2
- data/ext/zstdruby/libzstd/deprecated/zbuff_compress.c +1 -1
- data/ext/zstdruby/libzstd/deprecated/zbuff_decompress.c +1 -1
- data/ext/zstdruby/libzstd/dictBuilder/cover.c +55 -46
- 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 +43 -31
- data/ext/zstdruby/libzstd/dictBuilder/zdict.c +53 -30
- data/ext/zstdruby/libzstd/dll/example/Makefile +2 -1
- data/ext/zstdruby/libzstd/dll/example/README.md +16 -22
- data/ext/zstdruby/libzstd/legacy/zstd_legacy.h +4 -4
- data/ext/zstdruby/libzstd/legacy/zstd_v01.c +24 -14
- data/ext/zstdruby/libzstd/legacy/zstd_v01.h +1 -1
- data/ext/zstdruby/libzstd/legacy/zstd_v02.c +17 -8
- data/ext/zstdruby/libzstd/legacy/zstd_v02.h +1 -1
- data/ext/zstdruby/libzstd/legacy/zstd_v03.c +17 -8
- data/ext/zstdruby/libzstd/legacy/zstd_v03.h +1 -1
- data/ext/zstdruby/libzstd/legacy/zstd_v04.c +25 -11
- data/ext/zstdruby/libzstd/legacy/zstd_v04.h +1 -1
- data/ext/zstdruby/libzstd/legacy/zstd_v05.c +43 -32
- data/ext/zstdruby/libzstd/legacy/zstd_v05.h +2 -2
- data/ext/zstdruby/libzstd/legacy/zstd_v06.c +27 -19
- data/ext/zstdruby/libzstd/legacy/zstd_v06.h +1 -1
- data/ext/zstdruby/libzstd/legacy/zstd_v07.c +32 -20
- data/ext/zstdruby/libzstd/legacy/zstd_v07.h +1 -1
- data/ext/zstdruby/libzstd/libzstd.pc.in +2 -1
- data/ext/zstdruby/libzstd/{dictBuilder/zdict.h → zdict.h} +201 -31
- data/ext/zstdruby/libzstd/zstd.h +740 -153
- data/ext/zstdruby/libzstd/{common/zstd_errors.h → zstd_errors.h} +3 -1
- data/lib/zstd-ruby/version.rb +1 -1
- data/zstd-ruby.gemspec +1 -1
- metadata +21 -10
- data/.travis.yml +0 -14
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/*
|
|
2
|
-
* Copyright (c)
|
|
2
|
+
* Copyright (c) Yann Collet, Facebook, Inc.
|
|
3
3
|
* All rights reserved.
|
|
4
4
|
*
|
|
5
5
|
* This source code is licensed under both the BSD-style license (found in the
|
|
@@ -14,18 +14,18 @@
|
|
|
14
14
|
/*-*******************************************************
|
|
15
15
|
* Dependencies
|
|
16
16
|
*********************************************************/
|
|
17
|
-
#include
|
|
18
|
-
#include "cpu.h" /* bmi2 */
|
|
19
|
-
#include "mem.h" /* low level memory routines */
|
|
17
|
+
#include "../common/zstd_deps.h" /* ZSTD_memcpy, ZSTD_memmove, ZSTD_memset */
|
|
18
|
+
#include "../common/cpu.h" /* bmi2 */
|
|
19
|
+
#include "../common/mem.h" /* low level memory routines */
|
|
20
20
|
#define FSE_STATIC_LINKING_ONLY
|
|
21
|
-
#include "fse.h"
|
|
21
|
+
#include "../common/fse.h"
|
|
22
22
|
#define HUF_STATIC_LINKING_ONLY
|
|
23
|
-
#include "huf.h"
|
|
23
|
+
#include "../common/huf.h"
|
|
24
24
|
#include "zstd_decompress_internal.h"
|
|
25
25
|
#include "zstd_ddict.h"
|
|
26
26
|
|
|
27
27
|
#if defined(ZSTD_LEGACY_SUPPORT) && (ZSTD_LEGACY_SUPPORT>=1)
|
|
28
|
-
# include "zstd_legacy.h"
|
|
28
|
+
# include "../legacy/zstd_legacy.h"
|
|
29
29
|
#endif
|
|
30
30
|
|
|
31
31
|
|
|
@@ -65,6 +65,10 @@ void ZSTD_copyDDictParameters(ZSTD_DCtx* dctx, const ZSTD_DDict* ddict)
|
|
|
65
65
|
dctx->virtualStart = ddict->dictContent;
|
|
66
66
|
dctx->dictEnd = (const BYTE*)ddict->dictContent + ddict->dictSize;
|
|
67
67
|
dctx->previousDstEnd = dctx->dictEnd;
|
|
68
|
+
#ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
|
|
69
|
+
dctx->dictContentBeginForFuzzing = dctx->prefixStart;
|
|
70
|
+
dctx->dictContentEndForFuzzing = dctx->previousDstEnd;
|
|
71
|
+
#endif
|
|
68
72
|
if (ddict->entropyPresent) {
|
|
69
73
|
dctx->litEntropy = 1;
|
|
70
74
|
dctx->fseEntropy = 1;
|
|
@@ -107,7 +111,7 @@ ZSTD_loadEntropy_intoDDict(ZSTD_DDict* ddict,
|
|
|
107
111
|
/* load entropy tables */
|
|
108
112
|
RETURN_ERROR_IF(ZSTD_isError(ZSTD_loadDEntropy(
|
|
109
113
|
&ddict->entropy, ddict->dictContent, ddict->dictSize)),
|
|
110
|
-
dictionary_corrupted);
|
|
114
|
+
dictionary_corrupted, "");
|
|
111
115
|
ddict->entropyPresent = 1;
|
|
112
116
|
return 0;
|
|
113
117
|
}
|
|
@@ -123,17 +127,17 @@ static size_t ZSTD_initDDict_internal(ZSTD_DDict* ddict,
|
|
|
123
127
|
ddict->dictContent = dict;
|
|
124
128
|
if (!dict) dictSize = 0;
|
|
125
129
|
} else {
|
|
126
|
-
void* const internalBuffer =
|
|
130
|
+
void* const internalBuffer = ZSTD_customMalloc(dictSize, ddict->cMem);
|
|
127
131
|
ddict->dictBuffer = internalBuffer;
|
|
128
132
|
ddict->dictContent = internalBuffer;
|
|
129
133
|
if (!internalBuffer) return ERROR(memory_allocation);
|
|
130
|
-
|
|
134
|
+
ZSTD_memcpy(internalBuffer, dict, dictSize);
|
|
131
135
|
}
|
|
132
136
|
ddict->dictSize = dictSize;
|
|
133
137
|
ddict->entropy.hufTable[0] = (HUF_DTable)((HufLog)*0x1000001); /* cover both little and big endian */
|
|
134
138
|
|
|
135
139
|
/* parse dictionary content */
|
|
136
|
-
FORWARD_IF_ERROR( ZSTD_loadEntropy_intoDDict(ddict, dictContentType) );
|
|
140
|
+
FORWARD_IF_ERROR( ZSTD_loadEntropy_intoDDict(ddict, dictContentType) , "");
|
|
137
141
|
|
|
138
142
|
return 0;
|
|
139
143
|
}
|
|
@@ -143,9 +147,9 @@ ZSTD_DDict* ZSTD_createDDict_advanced(const void* dict, size_t dictSize,
|
|
|
143
147
|
ZSTD_dictContentType_e dictContentType,
|
|
144
148
|
ZSTD_customMem customMem)
|
|
145
149
|
{
|
|
146
|
-
if (!customMem.customAlloc ^ !customMem.customFree) return NULL;
|
|
150
|
+
if ((!customMem.customAlloc) ^ (!customMem.customFree)) return NULL;
|
|
147
151
|
|
|
148
|
-
{ ZSTD_DDict* const ddict = (ZSTD_DDict*)
|
|
152
|
+
{ ZSTD_DDict* const ddict = (ZSTD_DDict*) ZSTD_customMalloc(sizeof(ZSTD_DDict), customMem);
|
|
149
153
|
if (ddict == NULL) return NULL;
|
|
150
154
|
ddict->cMem = customMem;
|
|
151
155
|
{ size_t const initResult = ZSTD_initDDict_internal(ddict,
|
|
@@ -194,7 +198,7 @@ const ZSTD_DDict* ZSTD_initStaticDDict(
|
|
|
194
198
|
if ((size_t)sBuffer & 7) return NULL; /* 8-aligned */
|
|
195
199
|
if (sBufferSize < neededSpace) return NULL;
|
|
196
200
|
if (dictLoadMethod == ZSTD_dlm_byCopy) {
|
|
197
|
-
|
|
201
|
+
ZSTD_memcpy(ddict+1, dict, dictSize); /* local copy */
|
|
198
202
|
dict = ddict+1;
|
|
199
203
|
}
|
|
200
204
|
if (ZSTD_isError( ZSTD_initDDict_internal(ddict,
|
|
@@ -209,8 +213,8 @@ size_t ZSTD_freeDDict(ZSTD_DDict* ddict)
|
|
|
209
213
|
{
|
|
210
214
|
if (ddict==NULL) return 0; /* support free on NULL */
|
|
211
215
|
{ ZSTD_customMem const cMem = ddict->cMem;
|
|
212
|
-
|
|
213
|
-
|
|
216
|
+
ZSTD_customFree(ddict->dictBuffer, cMem);
|
|
217
|
+
ZSTD_customFree(ddict, cMem);
|
|
214
218
|
return 0;
|
|
215
219
|
}
|
|
216
220
|
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/*
|
|
2
|
-
* Copyright (c)
|
|
2
|
+
* Copyright (c) Yann Collet, Facebook, Inc.
|
|
3
3
|
* All rights reserved.
|
|
4
4
|
*
|
|
5
5
|
* This source code is licensed under both the BSD-style license (found in the
|
|
@@ -15,8 +15,8 @@
|
|
|
15
15
|
/*-*******************************************************
|
|
16
16
|
* Dependencies
|
|
17
17
|
*********************************************************/
|
|
18
|
-
#include
|
|
19
|
-
#include "zstd.h" /* ZSTD_DDict, and several public functions */
|
|
18
|
+
#include "../common/zstd_deps.h" /* size_t */
|
|
19
|
+
#include "../zstd.h" /* ZSTD_DDict, and several public functions */
|
|
20
20
|
|
|
21
21
|
|
|
22
22
|
/*-*******************************************************
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/*
|
|
2
|
-
* Copyright (c)
|
|
2
|
+
* Copyright (c) Yann Collet, Facebook, Inc.
|
|
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,162 @@
|
|
|
55
55
|
/*-*******************************************************
|
|
56
56
|
* Dependencies
|
|
57
57
|
*********************************************************/
|
|
58
|
-
#include
|
|
59
|
-
#include "cpu.h" /* bmi2 */
|
|
60
|
-
#include "mem.h" /* low level memory routines */
|
|
58
|
+
#include "../common/zstd_deps.h" /* ZSTD_memcpy, ZSTD_memmove, ZSTD_memset */
|
|
59
|
+
#include "../common/cpu.h" /* bmi2 */
|
|
60
|
+
#include "../common/mem.h" /* low level memory routines */
|
|
61
61
|
#define FSE_STATIC_LINKING_ONLY
|
|
62
|
-
#include "fse.h"
|
|
62
|
+
#include "../common/fse.h"
|
|
63
63
|
#define HUF_STATIC_LINKING_ONLY
|
|
64
|
-
#include "huf.h"
|
|
65
|
-
#include "
|
|
64
|
+
#include "../common/huf.h"
|
|
65
|
+
#include "../common/xxhash.h" /* XXH64_reset, XXH64_update, XXH64_digest, XXH64 */
|
|
66
|
+
#include "../common/zstd_internal.h" /* blockProperties_t */
|
|
66
67
|
#include "zstd_decompress_internal.h" /* ZSTD_DCtx */
|
|
67
68
|
#include "zstd_ddict.h" /* ZSTD_DDictDictContent */
|
|
68
69
|
#include "zstd_decompress_block.h" /* ZSTD_decompressBlock_internal */
|
|
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
|
+
ret->ddictPtrTable = (const ZSTD_DDict**)ZSTD_customCalloc(DDICT_HASHSET_TABLE_BASE_SIZE * sizeof(ZSTD_DDict*), customMem);
|
|
181
|
+
ret->ddictPtrTableSize = DDICT_HASHSET_TABLE_BASE_SIZE;
|
|
182
|
+
ret->ddictPtrCount = 0;
|
|
183
|
+
if (!ret || !ret->ddictPtrTable) {
|
|
184
|
+
return NULL;
|
|
185
|
+
}
|
|
186
|
+
return ret;
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
/* Frees the table of ZSTD_DDict* within a hashset, then frees the hashset itself.
|
|
190
|
+
* Note: The ZSTD_DDict* within the table are NOT freed.
|
|
191
|
+
*/
|
|
192
|
+
static void ZSTD_freeDDictHashSet(ZSTD_DDictHashSet* hashSet, ZSTD_customMem customMem) {
|
|
193
|
+
DEBUGLOG(4, "Freeing ddict hash set");
|
|
194
|
+
if (hashSet && hashSet->ddictPtrTable) {
|
|
195
|
+
ZSTD_customFree((void*)hashSet->ddictPtrTable, customMem);
|
|
196
|
+
}
|
|
197
|
+
if (hashSet) {
|
|
198
|
+
ZSTD_customFree(hashSet, customMem);
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
/* Public function: Adds a DDict into the ZSTD_DDictHashSet, possibly triggering a resize of the hash set.
|
|
203
|
+
* Returns 0 on success, or a ZSTD error.
|
|
204
|
+
*/
|
|
205
|
+
static size_t ZSTD_DDictHashSet_addDDict(ZSTD_DDictHashSet* hashSet, const ZSTD_DDict* ddict, ZSTD_customMem customMem) {
|
|
206
|
+
DEBUGLOG(4, "Adding dict ID: %u to hashset with - Count: %zu Tablesize: %zu", ZSTD_getDictID_fromDDict(ddict), hashSet->ddictPtrCount, hashSet->ddictPtrTableSize);
|
|
207
|
+
if (hashSet->ddictPtrCount * DDICT_HASHSET_MAX_LOAD_FACTOR_COUNT_MULT / hashSet->ddictPtrTableSize * DDICT_HASHSET_MAX_LOAD_FACTOR_SIZE_MULT != 0) {
|
|
208
|
+
FORWARD_IF_ERROR(ZSTD_DDictHashSet_expand(hashSet, customMem), "");
|
|
209
|
+
}
|
|
210
|
+
FORWARD_IF_ERROR(ZSTD_DDictHashSet_emplaceDDict(hashSet, ddict), "");
|
|
211
|
+
return 0;
|
|
212
|
+
}
|
|
213
|
+
|
|
75
214
|
/*-*************************************************************
|
|
76
215
|
* Context management
|
|
77
216
|
***************************************************************/
|
|
@@ -88,20 +227,25 @@ size_t ZSTD_estimateDCtxSize(void) { return sizeof(ZSTD_DCtx); }
|
|
|
88
227
|
|
|
89
228
|
static size_t ZSTD_startingInputLength(ZSTD_format_e format)
|
|
90
229
|
{
|
|
91
|
-
size_t const startingInputLength = (format
|
|
92
|
-
ZSTD_FRAMEHEADERSIZE_PREFIX - ZSTD_FRAMEIDSIZE :
|
|
93
|
-
ZSTD_FRAMEHEADERSIZE_PREFIX;
|
|
94
|
-
ZSTD_STATIC_ASSERT(ZSTD_FRAMEHEADERSIZE_PREFIX >= ZSTD_FRAMEIDSIZE);
|
|
230
|
+
size_t const startingInputLength = ZSTD_FRAMEHEADERSIZE_PREFIX(format);
|
|
95
231
|
/* only supports formats ZSTD_f_zstd1 and ZSTD_f_zstd1_magicless */
|
|
96
232
|
assert( (format == ZSTD_f_zstd1) || (format == ZSTD_f_zstd1_magicless) );
|
|
97
233
|
return startingInputLength;
|
|
98
234
|
}
|
|
99
235
|
|
|
236
|
+
static void ZSTD_DCtx_resetParameters(ZSTD_DCtx* dctx)
|
|
237
|
+
{
|
|
238
|
+
assert(dctx->streamStage == zdss_init);
|
|
239
|
+
dctx->format = ZSTD_f_zstd1;
|
|
240
|
+
dctx->maxWindowSize = ZSTD_MAXWINDOWSIZE_DEFAULT;
|
|
241
|
+
dctx->outBufferMode = ZSTD_bm_buffered;
|
|
242
|
+
dctx->forceIgnoreChecksum = ZSTD_d_validateChecksum;
|
|
243
|
+
dctx->refMultipleDDicts = ZSTD_rmd_refSingleDDict;
|
|
244
|
+
}
|
|
245
|
+
|
|
100
246
|
static void ZSTD_initDCtx_internal(ZSTD_DCtx* dctx)
|
|
101
247
|
{
|
|
102
|
-
dctx->format = ZSTD_f_zstd1; /* ZSTD_decompressBegin() invokes ZSTD_startingInputLength() with argument dctx->format */
|
|
103
248
|
dctx->staticSize = 0;
|
|
104
|
-
dctx->maxWindowSize = ZSTD_MAXWINDOWSIZE_DEFAULT;
|
|
105
249
|
dctx->ddict = NULL;
|
|
106
250
|
dctx->ddictLocal = NULL;
|
|
107
251
|
dctx->dictEnd = NULL;
|
|
@@ -114,7 +258,13 @@ static void ZSTD_initDCtx_internal(ZSTD_DCtx* dctx)
|
|
|
114
258
|
dctx->legacyContext = NULL;
|
|
115
259
|
dctx->previousLegacyVersion = 0;
|
|
116
260
|
dctx->noForwardProgress = 0;
|
|
261
|
+
dctx->oversizedDuration = 0;
|
|
117
262
|
dctx->bmi2 = ZSTD_cpuid_bmi2(ZSTD_cpuid());
|
|
263
|
+
dctx->ddictSet = NULL;
|
|
264
|
+
ZSTD_DCtx_resetParameters(dctx);
|
|
265
|
+
#ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
|
|
266
|
+
dctx->dictContentEndForFuzzing = NULL;
|
|
267
|
+
#endif
|
|
118
268
|
}
|
|
119
269
|
|
|
120
270
|
ZSTD_DCtx* ZSTD_initStaticDCtx(void *workspace, size_t workspaceSize)
|
|
@@ -132,9 +282,9 @@ ZSTD_DCtx* ZSTD_initStaticDCtx(void *workspace, size_t workspaceSize)
|
|
|
132
282
|
|
|
133
283
|
ZSTD_DCtx* ZSTD_createDCtx_advanced(ZSTD_customMem customMem)
|
|
134
284
|
{
|
|
135
|
-
if (!customMem.customAlloc ^ !customMem.customFree) return NULL;
|
|
285
|
+
if ((!customMem.customAlloc) ^ (!customMem.customFree)) return NULL;
|
|
136
286
|
|
|
137
|
-
{ ZSTD_DCtx* const dctx = (ZSTD_DCtx*)
|
|
287
|
+
{ ZSTD_DCtx* const dctx = (ZSTD_DCtx*)ZSTD_customMalloc(sizeof(*dctx), customMem);
|
|
138
288
|
if (!dctx) return NULL;
|
|
139
289
|
dctx->customMem = customMem;
|
|
140
290
|
ZSTD_initDCtx_internal(dctx);
|
|
@@ -162,13 +312,17 @@ size_t ZSTD_freeDCtx(ZSTD_DCtx* dctx)
|
|
|
162
312
|
RETURN_ERROR_IF(dctx->staticSize, memory_allocation, "not compatible with static DCtx");
|
|
163
313
|
{ ZSTD_customMem const cMem = dctx->customMem;
|
|
164
314
|
ZSTD_clearDict(dctx);
|
|
165
|
-
|
|
315
|
+
ZSTD_customFree(dctx->inBuff, cMem);
|
|
166
316
|
dctx->inBuff = NULL;
|
|
167
317
|
#if defined(ZSTD_LEGACY_SUPPORT) && (ZSTD_LEGACY_SUPPORT >= 1)
|
|
168
318
|
if (dctx->legacyContext)
|
|
169
319
|
ZSTD_freeLegacyStreamContext(dctx->legacyContext, dctx->previousLegacyVersion);
|
|
170
320
|
#endif
|
|
171
|
-
|
|
321
|
+
if (dctx->ddictSet) {
|
|
322
|
+
ZSTD_freeDDictHashSet(dctx->ddictSet, cMem);
|
|
323
|
+
dctx->ddictSet = NULL;
|
|
324
|
+
}
|
|
325
|
+
ZSTD_customFree(dctx, cMem);
|
|
172
326
|
return 0;
|
|
173
327
|
}
|
|
174
328
|
}
|
|
@@ -177,7 +331,30 @@ size_t ZSTD_freeDCtx(ZSTD_DCtx* dctx)
|
|
|
177
331
|
void ZSTD_copyDCtx(ZSTD_DCtx* dstDCtx, const ZSTD_DCtx* srcDCtx)
|
|
178
332
|
{
|
|
179
333
|
size_t const toCopy = (size_t)((char*)(&dstDCtx->inBuff) - (char*)dstDCtx);
|
|
180
|
-
|
|
334
|
+
ZSTD_memcpy(dstDCtx, srcDCtx, toCopy); /* no need to copy workspace */
|
|
335
|
+
}
|
|
336
|
+
|
|
337
|
+
/* Given a dctx with a digested frame params, re-selects the correct ZSTD_DDict based on
|
|
338
|
+
* the requested dict ID from the frame. If there exists a reference to the correct ZSTD_DDict, then
|
|
339
|
+
* accordingly sets the ddict to be used to decompress the frame.
|
|
340
|
+
*
|
|
341
|
+
* If no DDict is found, then no action is taken, and the ZSTD_DCtx::ddict remains as-is.
|
|
342
|
+
*
|
|
343
|
+
* ZSTD_d_refMultipleDDicts must be enabled for this function to be called.
|
|
344
|
+
*/
|
|
345
|
+
static void ZSTD_DCtx_selectFrameDDict(ZSTD_DCtx* dctx) {
|
|
346
|
+
assert(dctx->refMultipleDDicts && dctx->ddictSet);
|
|
347
|
+
DEBUGLOG(4, "Adjusting DDict based on requested dict ID from frame");
|
|
348
|
+
if (dctx->ddict) {
|
|
349
|
+
const ZSTD_DDict* frameDDict = ZSTD_DDictHashSet_getDDict(dctx->ddictSet, dctx->fParams.dictID);
|
|
350
|
+
if (frameDDict) {
|
|
351
|
+
DEBUGLOG(4, "DDict found!");
|
|
352
|
+
ZSTD_clearDict(dctx);
|
|
353
|
+
dctx->dictID = dctx->fParams.dictID;
|
|
354
|
+
dctx->ddict = frameDDict;
|
|
355
|
+
dctx->dictUses = ZSTD_use_indefinitely;
|
|
356
|
+
}
|
|
357
|
+
}
|
|
181
358
|
}
|
|
182
359
|
|
|
183
360
|
|
|
@@ -211,7 +388,7 @@ unsigned ZSTD_isFrame(const void* buffer, size_t size)
|
|
|
211
388
|
static size_t ZSTD_frameHeaderSize_internal(const void* src, size_t srcSize, ZSTD_format_e format)
|
|
212
389
|
{
|
|
213
390
|
size_t const minInputSize = ZSTD_startingInputLength(format);
|
|
214
|
-
RETURN_ERROR_IF(srcSize < minInputSize, srcSize_wrong);
|
|
391
|
+
RETURN_ERROR_IF(srcSize < minInputSize, srcSize_wrong, "");
|
|
215
392
|
|
|
216
393
|
{ BYTE const fhd = ((const BYTE*)src)[minInputSize-1];
|
|
217
394
|
U32 const dictID= fhd & 3;
|
|
@@ -244,7 +421,7 @@ size_t ZSTD_getFrameHeader_advanced(ZSTD_frameHeader* zfhPtr, const void* src, s
|
|
|
244
421
|
const BYTE* ip = (const BYTE*)src;
|
|
245
422
|
size_t const minInputSize = ZSTD_startingInputLength(format);
|
|
246
423
|
|
|
247
|
-
|
|
424
|
+
ZSTD_memset(zfhPtr, 0, sizeof(*zfhPtr)); /* not strictly necessary, but static analyzer do not understand that zfhPtr is only going to be read only if return value is zero, since they are 2 different signals */
|
|
248
425
|
if (srcSize < minInputSize) return minInputSize;
|
|
249
426
|
RETURN_ERROR_IF(src==NULL, GENERIC, "invalid parameter");
|
|
250
427
|
|
|
@@ -254,12 +431,12 @@ size_t ZSTD_getFrameHeader_advanced(ZSTD_frameHeader* zfhPtr, const void* src, s
|
|
|
254
431
|
/* skippable frame */
|
|
255
432
|
if (srcSize < ZSTD_SKIPPABLEHEADERSIZE)
|
|
256
433
|
return ZSTD_SKIPPABLEHEADERSIZE; /* magic number + frame length */
|
|
257
|
-
|
|
434
|
+
ZSTD_memset(zfhPtr, 0, sizeof(*zfhPtr));
|
|
258
435
|
zfhPtr->frameContentSize = MEM_readLE32((const char *)src + ZSTD_FRAMEIDSIZE);
|
|
259
436
|
zfhPtr->frameType = ZSTD_skippableFrame;
|
|
260
437
|
return 0;
|
|
261
438
|
}
|
|
262
|
-
RETURN_ERROR(prefix_unknown);
|
|
439
|
+
RETURN_ERROR(prefix_unknown, "");
|
|
263
440
|
}
|
|
264
441
|
|
|
265
442
|
/* ensure there is enough `srcSize` to fully read/decode frame header */
|
|
@@ -283,7 +460,7 @@ size_t ZSTD_getFrameHeader_advanced(ZSTD_frameHeader* zfhPtr, const void* src, s
|
|
|
283
460
|
if (!singleSegment) {
|
|
284
461
|
BYTE const wlByte = ip[pos++];
|
|
285
462
|
U32 const windowLog = (wlByte >> 3) + ZSTD_WINDOWLOG_ABSOLUTEMIN;
|
|
286
|
-
RETURN_ERROR_IF(windowLog > ZSTD_WINDOWLOG_MAX, frameParameter_windowTooLarge);
|
|
463
|
+
RETURN_ERROR_IF(windowLog > ZSTD_WINDOWLOG_MAX, frameParameter_windowTooLarge, "");
|
|
287
464
|
windowSize = (1ULL << windowLog);
|
|
288
465
|
windowSize += (windowSize >> 3) * (wlByte&7);
|
|
289
466
|
}
|
|
@@ -355,14 +532,14 @@ static size_t readSkippableFrameSize(void const* src, size_t srcSize)
|
|
|
355
532
|
size_t const skippableHeaderSize = ZSTD_SKIPPABLEHEADERSIZE;
|
|
356
533
|
U32 sizeU32;
|
|
357
534
|
|
|
358
|
-
RETURN_ERROR_IF(srcSize < ZSTD_SKIPPABLEHEADERSIZE, srcSize_wrong);
|
|
535
|
+
RETURN_ERROR_IF(srcSize < ZSTD_SKIPPABLEHEADERSIZE, srcSize_wrong, "");
|
|
359
536
|
|
|
360
537
|
sizeU32 = MEM_readLE32((BYTE const*)src + ZSTD_FRAMEIDSIZE);
|
|
361
538
|
RETURN_ERROR_IF((U32)(sizeU32 + ZSTD_SKIPPABLEHEADERSIZE) < sizeU32,
|
|
362
|
-
frameParameter_unsupported);
|
|
539
|
+
frameParameter_unsupported, "");
|
|
363
540
|
{
|
|
364
541
|
size_t const skippableSize = skippableHeaderSize + sizeU32;
|
|
365
|
-
RETURN_ERROR_IF(skippableSize > srcSize, srcSize_wrong);
|
|
542
|
+
RETURN_ERROR_IF(skippableSize > srcSize, srcSize_wrong, "");
|
|
366
543
|
return skippableSize;
|
|
367
544
|
}
|
|
368
545
|
}
|
|
@@ -376,7 +553,7 @@ unsigned long long ZSTD_findDecompressedSize(const void* src, size_t srcSize)
|
|
|
376
553
|
{
|
|
377
554
|
unsigned long long totalDstSize = 0;
|
|
378
555
|
|
|
379
|
-
while (srcSize >=
|
|
556
|
+
while (srcSize >= ZSTD_startingInputLength(ZSTD_f_zstd1)) {
|
|
380
557
|
U32 const magicNumber = MEM_readLE32(src);
|
|
381
558
|
|
|
382
559
|
if ((magicNumber & ZSTD_MAGIC_SKIPPABLE_MASK) == ZSTD_MAGIC_SKIPPABLE_START) {
|
|
@@ -431,20 +608,29 @@ unsigned long long ZSTD_getDecompressedSize(const void* src, size_t srcSize)
|
|
|
431
608
|
|
|
432
609
|
/** ZSTD_decodeFrameHeader() :
|
|
433
610
|
* `headerSize` must be the size provided by ZSTD_frameHeaderSize().
|
|
611
|
+
* If multiple DDict references are enabled, also will choose the correct DDict to use.
|
|
434
612
|
* @return : 0 if success, or an error code, which can be tested using ZSTD_isError() */
|
|
435
613
|
static size_t ZSTD_decodeFrameHeader(ZSTD_DCtx* dctx, const void* src, size_t headerSize)
|
|
436
614
|
{
|
|
437
615
|
size_t const result = ZSTD_getFrameHeader_advanced(&(dctx->fParams), src, headerSize, dctx->format);
|
|
438
616
|
if (ZSTD_isError(result)) return result; /* invalid header */
|
|
439
617
|
RETURN_ERROR_IF(result>0, srcSize_wrong, "headerSize too small");
|
|
618
|
+
|
|
619
|
+
/* Reference DDict requested by frame if dctx references multiple ddicts */
|
|
620
|
+
if (dctx->refMultipleDDicts == ZSTD_rmd_refMultipleDDicts && dctx->ddictSet) {
|
|
621
|
+
ZSTD_DCtx_selectFrameDDict(dctx);
|
|
622
|
+
}
|
|
623
|
+
|
|
440
624
|
#ifndef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
|
|
441
625
|
/* Skip the dictID check in fuzzing mode, because it makes the search
|
|
442
626
|
* harder.
|
|
443
627
|
*/
|
|
444
628
|
RETURN_ERROR_IF(dctx->fParams.dictID && (dctx->dictID != dctx->fParams.dictID),
|
|
445
|
-
dictionary_wrong);
|
|
629
|
+
dictionary_wrong, "");
|
|
446
630
|
#endif
|
|
447
|
-
|
|
631
|
+
dctx->validateChecksum = (dctx->fParams.checksumFlag && !dctx->forceIgnoreChecksum) ? 1 : 0;
|
|
632
|
+
if (dctx->validateChecksum) XXH64_reset(&dctx->xxhState, 0);
|
|
633
|
+
dctx->processedCSize += headerSize;
|
|
448
634
|
return 0;
|
|
449
635
|
}
|
|
450
636
|
|
|
@@ -459,7 +645,7 @@ static ZSTD_frameSizeInfo ZSTD_errorFrameSizeInfo(size_t ret)
|
|
|
459
645
|
static ZSTD_frameSizeInfo ZSTD_findFrameSizeInfo(const void* src, size_t srcSize)
|
|
460
646
|
{
|
|
461
647
|
ZSTD_frameSizeInfo frameSizeInfo;
|
|
462
|
-
|
|
648
|
+
ZSTD_memset(&frameSizeInfo, 0, sizeof(ZSTD_frameSizeInfo));
|
|
463
649
|
|
|
464
650
|
#if defined(ZSTD_LEGACY_SUPPORT) && (ZSTD_LEGACY_SUPPORT >= 1)
|
|
465
651
|
if (ZSTD_isLegacy(src, srcSize))
|
|
@@ -514,7 +700,7 @@ static ZSTD_frameSizeInfo ZSTD_findFrameSizeInfo(const void* src, size_t srcSize
|
|
|
514
700
|
ip += 4;
|
|
515
701
|
}
|
|
516
702
|
|
|
517
|
-
frameSizeInfo.compressedSize = ip - ipstart;
|
|
703
|
+
frameSizeInfo.compressedSize = (size_t)(ip - ipstart);
|
|
518
704
|
frameSizeInfo.decompressedBound = (zfh.frameContentSize != ZSTD_CONTENTSIZE_UNKNOWN)
|
|
519
705
|
? zfh.frameContentSize
|
|
520
706
|
: nbBlocks * zfh.blockSizeMax;
|
|
@@ -562,22 +748,12 @@ unsigned long long ZSTD_decompressBound(const void* src, size_t srcSize)
|
|
|
562
748
|
* Frame decoding
|
|
563
749
|
***************************************************************/
|
|
564
750
|
|
|
565
|
-
|
|
566
|
-
void ZSTD_checkContinuity(ZSTD_DCtx* dctx, const void* dst)
|
|
567
|
-
{
|
|
568
|
-
if (dst != dctx->previousDstEnd) { /* not contiguous */
|
|
569
|
-
dctx->dictEnd = dctx->previousDstEnd;
|
|
570
|
-
dctx->virtualStart = (const char*)dst - ((const char*)(dctx->previousDstEnd) - (const char*)(dctx->prefixStart));
|
|
571
|
-
dctx->prefixStart = dst;
|
|
572
|
-
dctx->previousDstEnd = dst;
|
|
573
|
-
}
|
|
574
|
-
}
|
|
575
|
-
|
|
576
751
|
/** ZSTD_insertBlock() :
|
|
577
|
-
|
|
752
|
+
* insert `src` block into `dctx` history. Useful to track uncompressed blocks. */
|
|
578
753
|
size_t ZSTD_insertBlock(ZSTD_DCtx* dctx, const void* blockStart, size_t blockSize)
|
|
579
754
|
{
|
|
580
|
-
|
|
755
|
+
DEBUGLOG(5, "ZSTD_insertBlock: %u bytes", (unsigned)blockSize);
|
|
756
|
+
ZSTD_checkContinuity(dctx, blockStart, blockSize);
|
|
581
757
|
dctx->previousDstEnd = (const char*)blockStart + blockSize;
|
|
582
758
|
return blockSize;
|
|
583
759
|
}
|
|
@@ -587,12 +763,12 @@ static size_t ZSTD_copyRawBlock(void* dst, size_t dstCapacity,
|
|
|
587
763
|
const void* src, size_t srcSize)
|
|
588
764
|
{
|
|
589
765
|
DEBUGLOG(5, "ZSTD_copyRawBlock");
|
|
766
|
+
RETURN_ERROR_IF(srcSize > dstCapacity, dstSize_tooSmall, "");
|
|
590
767
|
if (dst == NULL) {
|
|
591
768
|
if (srcSize == 0) return 0;
|
|
592
|
-
RETURN_ERROR(dstBuffer_null);
|
|
769
|
+
RETURN_ERROR(dstBuffer_null, "");
|
|
593
770
|
}
|
|
594
|
-
|
|
595
|
-
memcpy(dst, src, srcSize);
|
|
771
|
+
ZSTD_memcpy(dst, src, srcSize);
|
|
596
772
|
return srcSize;
|
|
597
773
|
}
|
|
598
774
|
|
|
@@ -600,15 +776,41 @@ static size_t ZSTD_setRleBlock(void* dst, size_t dstCapacity,
|
|
|
600
776
|
BYTE b,
|
|
601
777
|
size_t regenSize)
|
|
602
778
|
{
|
|
779
|
+
RETURN_ERROR_IF(regenSize > dstCapacity, dstSize_tooSmall, "");
|
|
603
780
|
if (dst == NULL) {
|
|
604
781
|
if (regenSize == 0) return 0;
|
|
605
|
-
RETURN_ERROR(dstBuffer_null);
|
|
782
|
+
RETURN_ERROR(dstBuffer_null, "");
|
|
606
783
|
}
|
|
607
|
-
|
|
608
|
-
memset(dst, b, regenSize);
|
|
784
|
+
ZSTD_memset(dst, b, regenSize);
|
|
609
785
|
return regenSize;
|
|
610
786
|
}
|
|
611
787
|
|
|
788
|
+
static void ZSTD_DCtx_trace_end(ZSTD_DCtx const* dctx, U64 uncompressedSize, U64 compressedSize, unsigned streaming)
|
|
789
|
+
{
|
|
790
|
+
#if ZSTD_TRACE
|
|
791
|
+
if (dctx->traceCtx && ZSTD_trace_decompress_end != NULL) {
|
|
792
|
+
ZSTD_Trace trace;
|
|
793
|
+
ZSTD_memset(&trace, 0, sizeof(trace));
|
|
794
|
+
trace.version = ZSTD_VERSION_NUMBER;
|
|
795
|
+
trace.streaming = streaming;
|
|
796
|
+
if (dctx->ddict) {
|
|
797
|
+
trace.dictionaryID = ZSTD_getDictID_fromDDict(dctx->ddict);
|
|
798
|
+
trace.dictionarySize = ZSTD_DDict_dictSize(dctx->ddict);
|
|
799
|
+
trace.dictionaryIsCold = dctx->ddictIsCold;
|
|
800
|
+
}
|
|
801
|
+
trace.uncompressedSize = (size_t)uncompressedSize;
|
|
802
|
+
trace.compressedSize = (size_t)compressedSize;
|
|
803
|
+
trace.dctx = dctx;
|
|
804
|
+
ZSTD_trace_decompress_end(dctx->traceCtx, &trace);
|
|
805
|
+
}
|
|
806
|
+
#else
|
|
807
|
+
(void)dctx;
|
|
808
|
+
(void)uncompressedSize;
|
|
809
|
+
(void)compressedSize;
|
|
810
|
+
(void)streaming;
|
|
811
|
+
#endif
|
|
812
|
+
}
|
|
813
|
+
|
|
612
814
|
|
|
613
815
|
/*! ZSTD_decompressFrame() :
|
|
614
816
|
* @dctx must be properly initialized
|
|
@@ -618,9 +820,10 @@ static size_t ZSTD_decompressFrame(ZSTD_DCtx* dctx,
|
|
|
618
820
|
void* dst, size_t dstCapacity,
|
|
619
821
|
const void** srcPtr, size_t *srcSizePtr)
|
|
620
822
|
{
|
|
621
|
-
const BYTE*
|
|
622
|
-
BYTE*
|
|
623
|
-
BYTE* const
|
|
823
|
+
const BYTE* const istart = (const BYTE*)(*srcPtr);
|
|
824
|
+
const BYTE* ip = istart;
|
|
825
|
+
BYTE* const ostart = (BYTE*)dst;
|
|
826
|
+
BYTE* const oend = dstCapacity != 0 ? ostart + dstCapacity : ostart;
|
|
624
827
|
BYTE* op = ostart;
|
|
625
828
|
size_t remainingSrcSize = *srcSizePtr;
|
|
626
829
|
|
|
@@ -628,15 +831,16 @@ static size_t ZSTD_decompressFrame(ZSTD_DCtx* dctx,
|
|
|
628
831
|
|
|
629
832
|
/* check */
|
|
630
833
|
RETURN_ERROR_IF(
|
|
631
|
-
remainingSrcSize < ZSTD_FRAMEHEADERSIZE_MIN+ZSTD_blockHeaderSize,
|
|
632
|
-
srcSize_wrong);
|
|
834
|
+
remainingSrcSize < ZSTD_FRAMEHEADERSIZE_MIN(dctx->format)+ZSTD_blockHeaderSize,
|
|
835
|
+
srcSize_wrong, "");
|
|
633
836
|
|
|
634
837
|
/* Frame Header */
|
|
635
|
-
{ size_t const frameHeaderSize =
|
|
838
|
+
{ size_t const frameHeaderSize = ZSTD_frameHeaderSize_internal(
|
|
839
|
+
ip, ZSTD_FRAMEHEADERSIZE_PREFIX(dctx->format), dctx->format);
|
|
636
840
|
if (ZSTD_isError(frameHeaderSize)) return frameHeaderSize;
|
|
637
841
|
RETURN_ERROR_IF(remainingSrcSize < frameHeaderSize+ZSTD_blockHeaderSize,
|
|
638
|
-
srcSize_wrong);
|
|
639
|
-
FORWARD_IF_ERROR( ZSTD_decodeFrameHeader(dctx, ip, frameHeaderSize) );
|
|
842
|
+
srcSize_wrong, "");
|
|
843
|
+
FORWARD_IF_ERROR( ZSTD_decodeFrameHeader(dctx, ip, frameHeaderSize) , "");
|
|
640
844
|
ip += frameHeaderSize; remainingSrcSize -= frameHeaderSize;
|
|
641
845
|
}
|
|
642
846
|
|
|
@@ -649,28 +853,30 @@ static size_t ZSTD_decompressFrame(ZSTD_DCtx* dctx,
|
|
|
649
853
|
|
|
650
854
|
ip += ZSTD_blockHeaderSize;
|
|
651
855
|
remainingSrcSize -= ZSTD_blockHeaderSize;
|
|
652
|
-
RETURN_ERROR_IF(cBlockSize > remainingSrcSize, srcSize_wrong);
|
|
856
|
+
RETURN_ERROR_IF(cBlockSize > remainingSrcSize, srcSize_wrong, "");
|
|
653
857
|
|
|
654
858
|
switch(blockProperties.blockType)
|
|
655
859
|
{
|
|
656
860
|
case bt_compressed:
|
|
657
|
-
decodedSize = ZSTD_decompressBlock_internal(dctx, op, oend-op, ip, cBlockSize, /* frame */ 1);
|
|
861
|
+
decodedSize = ZSTD_decompressBlock_internal(dctx, op, (size_t)(oend-op), ip, cBlockSize, /* frame */ 1);
|
|
658
862
|
break;
|
|
659
863
|
case bt_raw :
|
|
660
|
-
decodedSize = ZSTD_copyRawBlock(op, oend-op, ip, cBlockSize);
|
|
864
|
+
decodedSize = ZSTD_copyRawBlock(op, (size_t)(oend-op), ip, cBlockSize);
|
|
661
865
|
break;
|
|
662
866
|
case bt_rle :
|
|
663
|
-
decodedSize = ZSTD_setRleBlock(op, oend-op, *ip, blockProperties.origSize);
|
|
867
|
+
decodedSize = ZSTD_setRleBlock(op, (size_t)(oend-op), *ip, blockProperties.origSize);
|
|
664
868
|
break;
|
|
665
869
|
case bt_reserved :
|
|
666
870
|
default:
|
|
667
|
-
RETURN_ERROR(corruption_detected);
|
|
871
|
+
RETURN_ERROR(corruption_detected, "invalid block type");
|
|
668
872
|
}
|
|
669
873
|
|
|
670
874
|
if (ZSTD_isError(decodedSize)) return decodedSize;
|
|
671
|
-
if (dctx->
|
|
875
|
+
if (dctx->validateChecksum)
|
|
672
876
|
XXH64_update(&dctx->xxhState, op, decodedSize);
|
|
673
|
-
|
|
877
|
+
if (decodedSize != 0)
|
|
878
|
+
op += decodedSize;
|
|
879
|
+
assert(ip != NULL);
|
|
674
880
|
ip += cBlockSize;
|
|
675
881
|
remainingSrcSize -= cBlockSize;
|
|
676
882
|
if (blockProperties.lastBlock) break;
|
|
@@ -678,22 +884,24 @@ static size_t ZSTD_decompressFrame(ZSTD_DCtx* dctx,
|
|
|
678
884
|
|
|
679
885
|
if (dctx->fParams.frameContentSize != ZSTD_CONTENTSIZE_UNKNOWN) {
|
|
680
886
|
RETURN_ERROR_IF((U64)(op-ostart) != dctx->fParams.frameContentSize,
|
|
681
|
-
corruption_detected);
|
|
887
|
+
corruption_detected, "");
|
|
682
888
|
}
|
|
683
889
|
if (dctx->fParams.checksumFlag) { /* Frame content checksum verification */
|
|
684
|
-
|
|
685
|
-
|
|
686
|
-
|
|
687
|
-
|
|
688
|
-
|
|
890
|
+
RETURN_ERROR_IF(remainingSrcSize<4, checksum_wrong, "");
|
|
891
|
+
if (!dctx->forceIgnoreChecksum) {
|
|
892
|
+
U32 const checkCalc = (U32)XXH64_digest(&dctx->xxhState);
|
|
893
|
+
U32 checkRead;
|
|
894
|
+
checkRead = MEM_readLE32(ip);
|
|
895
|
+
RETURN_ERROR_IF(checkRead != checkCalc, checksum_wrong, "");
|
|
896
|
+
}
|
|
689
897
|
ip += 4;
|
|
690
898
|
remainingSrcSize -= 4;
|
|
691
899
|
}
|
|
692
|
-
|
|
900
|
+
ZSTD_DCtx_trace_end(dctx, (U64)(op-ostart), (U64)(ip-istart), /* streaming */ 0);
|
|
693
901
|
/* Allow caller to get size read */
|
|
694
902
|
*srcPtr = ip;
|
|
695
903
|
*srcSizePtr = remainingSrcSize;
|
|
696
|
-
return op-ostart;
|
|
904
|
+
return (size_t)(op-ostart);
|
|
697
905
|
}
|
|
698
906
|
|
|
699
907
|
static size_t ZSTD_decompressMultiFrame(ZSTD_DCtx* dctx,
|
|
@@ -713,7 +921,7 @@ static size_t ZSTD_decompressMultiFrame(ZSTD_DCtx* dctx,
|
|
|
713
921
|
dictSize = ZSTD_DDict_dictSize(ddict);
|
|
714
922
|
}
|
|
715
923
|
|
|
716
|
-
while (srcSize >=
|
|
924
|
+
while (srcSize >= ZSTD_startingInputLength(dctx->format)) {
|
|
717
925
|
|
|
718
926
|
#if defined(ZSTD_LEGACY_SUPPORT) && (ZSTD_LEGACY_SUPPORT >= 1)
|
|
719
927
|
if (ZSTD_isLegacy(src, srcSize)) {
|
|
@@ -726,7 +934,7 @@ static size_t ZSTD_decompressMultiFrame(ZSTD_DCtx* dctx,
|
|
|
726
934
|
decodedSize = ZSTD_decompressLegacy(dst, dstCapacity, src, frameSize, dict, dictSize);
|
|
727
935
|
if (ZSTD_isError(decodedSize)) return decodedSize;
|
|
728
936
|
|
|
729
|
-
assert(decodedSize
|
|
937
|
+
assert(decodedSize <= dstCapacity);
|
|
730
938
|
dst = (BYTE*)dst + decodedSize;
|
|
731
939
|
dstCapacity -= decodedSize;
|
|
732
940
|
|
|
@@ -742,7 +950,7 @@ static size_t ZSTD_decompressMultiFrame(ZSTD_DCtx* dctx,
|
|
|
742
950
|
(unsigned)magicNumber, ZSTD_MAGICNUMBER);
|
|
743
951
|
if ((magicNumber & ZSTD_MAGIC_SKIPPABLE_MASK) == ZSTD_MAGIC_SKIPPABLE_START) {
|
|
744
952
|
size_t const skippableSize = readSkippableFrameSize(src, srcSize);
|
|
745
|
-
FORWARD_IF_ERROR(skippableSize);
|
|
953
|
+
FORWARD_IF_ERROR(skippableSize, "readSkippableFrameSize failed");
|
|
746
954
|
assert(skippableSize <= srcSize);
|
|
747
955
|
|
|
748
956
|
src = (const BYTE *)src + skippableSize;
|
|
@@ -752,13 +960,13 @@ static size_t ZSTD_decompressMultiFrame(ZSTD_DCtx* dctx,
|
|
|
752
960
|
|
|
753
961
|
if (ddict) {
|
|
754
962
|
/* we were called from ZSTD_decompress_usingDDict */
|
|
755
|
-
FORWARD_IF_ERROR(ZSTD_decompressBegin_usingDDict(dctx, ddict));
|
|
963
|
+
FORWARD_IF_ERROR(ZSTD_decompressBegin_usingDDict(dctx, ddict), "");
|
|
756
964
|
} else {
|
|
757
965
|
/* this will initialize correctly with no dict if dict == NULL, so
|
|
758
966
|
* use this in all cases but ddict */
|
|
759
|
-
FORWARD_IF_ERROR(ZSTD_decompressBegin_usingDict(dctx, dict, dictSize));
|
|
967
|
+
FORWARD_IF_ERROR(ZSTD_decompressBegin_usingDict(dctx, dict, dictSize), "");
|
|
760
968
|
}
|
|
761
|
-
ZSTD_checkContinuity(dctx, dst);
|
|
969
|
+
ZSTD_checkContinuity(dctx, dst, dstCapacity);
|
|
762
970
|
|
|
763
971
|
{ const size_t res = ZSTD_decompressFrame(dctx, dst, dstCapacity,
|
|
764
972
|
&src, &srcSize);
|
|
@@ -766,18 +974,17 @@ static size_t ZSTD_decompressMultiFrame(ZSTD_DCtx* dctx,
|
|
|
766
974
|
(ZSTD_getErrorCode(res) == ZSTD_error_prefix_unknown)
|
|
767
975
|
&& (moreThan1Frame==1),
|
|
768
976
|
srcSize_wrong,
|
|
769
|
-
"
|
|
770
|
-
"bytes are garbage:
|
|
771
|
-
"
|
|
772
|
-
"
|
|
773
|
-
"
|
|
774
|
-
"
|
|
775
|
-
"
|
|
776
|
-
"bytes. But this is _much_ less likely than a srcSize field "
|
|
777
|
-
"error.");
|
|
977
|
+
"At least one frame successfully completed, "
|
|
978
|
+
"but following bytes are garbage: "
|
|
979
|
+
"it's more likely to be a srcSize error, "
|
|
980
|
+
"specifying more input bytes than size of frame(s). "
|
|
981
|
+
"Note: one could be unlucky, it might be a corruption error instead, "
|
|
982
|
+
"happening right at the place where we expect zstd magic bytes. "
|
|
983
|
+
"But this is _much_ less likely than a srcSize field error.");
|
|
778
984
|
if (ZSTD_isError(res)) return res;
|
|
779
985
|
assert(res <= dstCapacity);
|
|
780
|
-
|
|
986
|
+
if (res != 0)
|
|
987
|
+
dst = (BYTE*)dst + res;
|
|
781
988
|
dstCapacity -= res;
|
|
782
989
|
}
|
|
783
990
|
moreThan1Frame = 1;
|
|
@@ -785,7 +992,7 @@ static size_t ZSTD_decompressMultiFrame(ZSTD_DCtx* dctx,
|
|
|
785
992
|
|
|
786
993
|
RETURN_ERROR_IF(srcSize, srcSize_wrong, "input not entirely consumed");
|
|
787
994
|
|
|
788
|
-
return (BYTE*)dst - (BYTE*)dststart;
|
|
995
|
+
return (size_t)((BYTE*)dst - (BYTE*)dststart);
|
|
789
996
|
}
|
|
790
997
|
|
|
791
998
|
size_t ZSTD_decompress_usingDict(ZSTD_DCtx* dctx,
|
|
@@ -825,7 +1032,7 @@ size_t ZSTD_decompress(void* dst, size_t dstCapacity, const void* src, size_t sr
|
|
|
825
1032
|
#if defined(ZSTD_HEAPMODE) && (ZSTD_HEAPMODE>=1)
|
|
826
1033
|
size_t regenSize;
|
|
827
1034
|
ZSTD_DCtx* const dctx = ZSTD_createDCtx();
|
|
828
|
-
RETURN_ERROR_IF(dctx==NULL, memory_allocation);
|
|
1035
|
+
RETURN_ERROR_IF(dctx==NULL, memory_allocation, "NULL pointer!");
|
|
829
1036
|
regenSize = ZSTD_decompressDCtx(dctx, dst, dstCapacity, src, srcSize);
|
|
830
1037
|
ZSTD_freeDCtx(dctx);
|
|
831
1038
|
return regenSize;
|
|
@@ -843,6 +1050,24 @@ size_t ZSTD_decompress(void* dst, size_t dstCapacity, const void* src, size_t sr
|
|
|
843
1050
|
****************************************/
|
|
844
1051
|
size_t ZSTD_nextSrcSizeToDecompress(ZSTD_DCtx* dctx) { return dctx->expected; }
|
|
845
1052
|
|
|
1053
|
+
/**
|
|
1054
|
+
* Similar to ZSTD_nextSrcSizeToDecompress(), but when when a block input can be streamed,
|
|
1055
|
+
* we allow taking a partial block as the input. Currently only raw uncompressed blocks can
|
|
1056
|
+
* be streamed.
|
|
1057
|
+
*
|
|
1058
|
+
* For blocks that can be streamed, this allows us to reduce the latency until we produce
|
|
1059
|
+
* output, and avoid copying the input.
|
|
1060
|
+
*
|
|
1061
|
+
* @param inputSize - The total amount of input that the caller currently has.
|
|
1062
|
+
*/
|
|
1063
|
+
static size_t ZSTD_nextSrcSizeToDecompressWithInputSize(ZSTD_DCtx* dctx, size_t inputSize) {
|
|
1064
|
+
if (!(dctx->stage == ZSTDds_decompressBlock || dctx->stage == ZSTDds_decompressLastBlock))
|
|
1065
|
+
return dctx->expected;
|
|
1066
|
+
if (dctx->bType != bt_raw)
|
|
1067
|
+
return dctx->expected;
|
|
1068
|
+
return MIN(MAX(inputSize, 1), dctx->expected);
|
|
1069
|
+
}
|
|
1070
|
+
|
|
846
1071
|
ZSTD_nextInputType_e ZSTD_nextInputType(ZSTD_DCtx* dctx) {
|
|
847
1072
|
switch(dctx->stage)
|
|
848
1073
|
{
|
|
@@ -875,8 +1100,10 @@ size_t ZSTD_decompressContinue(ZSTD_DCtx* dctx, void* dst, size_t dstCapacity, c
|
|
|
875
1100
|
{
|
|
876
1101
|
DEBUGLOG(5, "ZSTD_decompressContinue (srcSize:%u)", (unsigned)srcSize);
|
|
877
1102
|
/* Sanity check */
|
|
878
|
-
RETURN_ERROR_IF(srcSize != dctx
|
|
879
|
-
|
|
1103
|
+
RETURN_ERROR_IF(srcSize != ZSTD_nextSrcSizeToDecompressWithInputSize(dctx, srcSize), srcSize_wrong, "not allowed");
|
|
1104
|
+
ZSTD_checkContinuity(dctx, dst, dstCapacity);
|
|
1105
|
+
|
|
1106
|
+
dctx->processedCSize += srcSize;
|
|
880
1107
|
|
|
881
1108
|
switch (dctx->stage)
|
|
882
1109
|
{
|
|
@@ -885,22 +1112,22 @@ size_t ZSTD_decompressContinue(ZSTD_DCtx* dctx, void* dst, size_t dstCapacity, c
|
|
|
885
1112
|
if (dctx->format == ZSTD_f_zstd1) { /* allows header */
|
|
886
1113
|
assert(srcSize >= ZSTD_FRAMEIDSIZE); /* to read skippable magic number */
|
|
887
1114
|
if ((MEM_readLE32(src) & ZSTD_MAGIC_SKIPPABLE_MASK) == ZSTD_MAGIC_SKIPPABLE_START) { /* skippable frame */
|
|
888
|
-
|
|
1115
|
+
ZSTD_memcpy(dctx->headerBuffer, src, srcSize);
|
|
889
1116
|
dctx->expected = ZSTD_SKIPPABLEHEADERSIZE - srcSize; /* remaining to load to get full skippable frame header */
|
|
890
1117
|
dctx->stage = ZSTDds_decodeSkippableHeader;
|
|
891
1118
|
return 0;
|
|
892
1119
|
} }
|
|
893
1120
|
dctx->headerSize = ZSTD_frameHeaderSize_internal(src, srcSize, dctx->format);
|
|
894
1121
|
if (ZSTD_isError(dctx->headerSize)) return dctx->headerSize;
|
|
895
|
-
|
|
1122
|
+
ZSTD_memcpy(dctx->headerBuffer, src, srcSize);
|
|
896
1123
|
dctx->expected = dctx->headerSize - srcSize;
|
|
897
1124
|
dctx->stage = ZSTDds_decodeFrameHeader;
|
|
898
1125
|
return 0;
|
|
899
1126
|
|
|
900
1127
|
case ZSTDds_decodeFrameHeader:
|
|
901
1128
|
assert(src != NULL);
|
|
902
|
-
|
|
903
|
-
FORWARD_IF_ERROR(ZSTD_decodeFrameHeader(dctx, dctx->headerBuffer, dctx->headerSize));
|
|
1129
|
+
ZSTD_memcpy(dctx->headerBuffer + (dctx->headerSize - srcSize), src, srcSize);
|
|
1130
|
+
FORWARD_IF_ERROR(ZSTD_decodeFrameHeader(dctx, dctx->headerBuffer, dctx->headerSize), "");
|
|
904
1131
|
dctx->expected = ZSTD_blockHeaderSize;
|
|
905
1132
|
dctx->stage = ZSTDds_decodeBlockHeader;
|
|
906
1133
|
return 0;
|
|
@@ -909,6 +1136,7 @@ size_t ZSTD_decompressContinue(ZSTD_DCtx* dctx, void* dst, size_t dstCapacity, c
|
|
|
909
1136
|
{ blockProperties_t bp;
|
|
910
1137
|
size_t const cBlockSize = ZSTD_getcBlockSize(src, ZSTD_blockHeaderSize, &bp);
|
|
911
1138
|
if (ZSTD_isError(cBlockSize)) return cBlockSize;
|
|
1139
|
+
RETURN_ERROR_IF(cBlockSize > dctx->fParams.blockSizeMax, corruption_detected, "Block Size Exceeds Maximum");
|
|
912
1140
|
dctx->expected = cBlockSize;
|
|
913
1141
|
dctx->bType = bp.blockType;
|
|
914
1142
|
dctx->rleSize = bp.origSize;
|
|
@@ -941,49 +1169,66 @@ size_t ZSTD_decompressContinue(ZSTD_DCtx* dctx, void* dst, size_t dstCapacity, c
|
|
|
941
1169
|
case bt_compressed:
|
|
942
1170
|
DEBUGLOG(5, "ZSTD_decompressContinue: case bt_compressed");
|
|
943
1171
|
rSize = ZSTD_decompressBlock_internal(dctx, dst, dstCapacity, src, srcSize, /* frame */ 1);
|
|
1172
|
+
dctx->expected = 0; /* Streaming not supported */
|
|
944
1173
|
break;
|
|
945
1174
|
case bt_raw :
|
|
1175
|
+
assert(srcSize <= dctx->expected);
|
|
946
1176
|
rSize = ZSTD_copyRawBlock(dst, dstCapacity, src, srcSize);
|
|
1177
|
+
FORWARD_IF_ERROR(rSize, "ZSTD_copyRawBlock failed");
|
|
1178
|
+
assert(rSize == srcSize);
|
|
1179
|
+
dctx->expected -= rSize;
|
|
947
1180
|
break;
|
|
948
1181
|
case bt_rle :
|
|
949
1182
|
rSize = ZSTD_setRleBlock(dst, dstCapacity, *(const BYTE*)src, dctx->rleSize);
|
|
1183
|
+
dctx->expected = 0; /* Streaming not supported */
|
|
950
1184
|
break;
|
|
951
1185
|
case bt_reserved : /* should never happen */
|
|
952
1186
|
default:
|
|
953
|
-
RETURN_ERROR(corruption_detected);
|
|
1187
|
+
RETURN_ERROR(corruption_detected, "invalid block type");
|
|
954
1188
|
}
|
|
955
|
-
|
|
1189
|
+
FORWARD_IF_ERROR(rSize, "");
|
|
1190
|
+
RETURN_ERROR_IF(rSize > dctx->fParams.blockSizeMax, corruption_detected, "Decompressed Block Size Exceeds Maximum");
|
|
956
1191
|
DEBUGLOG(5, "ZSTD_decompressContinue: decoded size from block : %u", (unsigned)rSize);
|
|
957
1192
|
dctx->decodedSize += rSize;
|
|
958
|
-
if (dctx->
|
|
1193
|
+
if (dctx->validateChecksum) XXH64_update(&dctx->xxhState, dst, rSize);
|
|
1194
|
+
dctx->previousDstEnd = (char*)dst + rSize;
|
|
1195
|
+
|
|
1196
|
+
/* Stay on the same stage until we are finished streaming the block. */
|
|
1197
|
+
if (dctx->expected > 0) {
|
|
1198
|
+
return rSize;
|
|
1199
|
+
}
|
|
959
1200
|
|
|
960
1201
|
if (dctx->stage == ZSTDds_decompressLastBlock) { /* end of frame */
|
|
961
1202
|
DEBUGLOG(4, "ZSTD_decompressContinue: decoded size from frame : %u", (unsigned)dctx->decodedSize);
|
|
962
1203
|
RETURN_ERROR_IF(
|
|
963
1204
|
dctx->fParams.frameContentSize != ZSTD_CONTENTSIZE_UNKNOWN
|
|
964
1205
|
&& dctx->decodedSize != dctx->fParams.frameContentSize,
|
|
965
|
-
corruption_detected);
|
|
1206
|
+
corruption_detected, "");
|
|
966
1207
|
if (dctx->fParams.checksumFlag) { /* another round for frame checksum */
|
|
967
1208
|
dctx->expected = 4;
|
|
968
1209
|
dctx->stage = ZSTDds_checkChecksum;
|
|
969
1210
|
} else {
|
|
1211
|
+
ZSTD_DCtx_trace_end(dctx, dctx->decodedSize, dctx->processedCSize, /* streaming */ 1);
|
|
970
1212
|
dctx->expected = 0; /* ends here */
|
|
971
1213
|
dctx->stage = ZSTDds_getFrameHeaderSize;
|
|
972
1214
|
}
|
|
973
1215
|
} else {
|
|
974
1216
|
dctx->stage = ZSTDds_decodeBlockHeader;
|
|
975
1217
|
dctx->expected = ZSTD_blockHeaderSize;
|
|
976
|
-
dctx->previousDstEnd = (char*)dst + rSize;
|
|
977
1218
|
}
|
|
978
1219
|
return rSize;
|
|
979
1220
|
}
|
|
980
1221
|
|
|
981
1222
|
case ZSTDds_checkChecksum:
|
|
982
1223
|
assert(srcSize == 4); /* guaranteed by dctx->expected */
|
|
983
|
-
{
|
|
984
|
-
|
|
985
|
-
|
|
986
|
-
|
|
1224
|
+
{
|
|
1225
|
+
if (dctx->validateChecksum) {
|
|
1226
|
+
U32 const h32 = (U32)XXH64_digest(&dctx->xxhState);
|
|
1227
|
+
U32 const check32 = MEM_readLE32(src);
|
|
1228
|
+
DEBUGLOG(4, "ZSTD_decompressContinue: checksum : calculated %08X :: %08X read", (unsigned)h32, (unsigned)check32);
|
|
1229
|
+
RETURN_ERROR_IF(check32 != h32, checksum_wrong, "");
|
|
1230
|
+
}
|
|
1231
|
+
ZSTD_DCtx_trace_end(dctx, dctx->decodedSize, dctx->processedCSize, /* streaming */ 1);
|
|
987
1232
|
dctx->expected = 0;
|
|
988
1233
|
dctx->stage = ZSTDds_getFrameHeaderSize;
|
|
989
1234
|
return 0;
|
|
@@ -992,7 +1237,7 @@ size_t ZSTD_decompressContinue(ZSTD_DCtx* dctx, void* dst, size_t dstCapacity, c
|
|
|
992
1237
|
case ZSTDds_decodeSkippableHeader:
|
|
993
1238
|
assert(src != NULL);
|
|
994
1239
|
assert(srcSize <= ZSTD_SKIPPABLEHEADERSIZE);
|
|
995
|
-
|
|
1240
|
+
ZSTD_memcpy(dctx->headerBuffer + (ZSTD_SKIPPABLEHEADERSIZE - srcSize), src, srcSize); /* complete skippable header */
|
|
996
1241
|
dctx->expected = MEM_readLE32(dctx->headerBuffer + ZSTD_FRAMEIDSIZE); /* note : dctx->expected can grow seriously large, beyond local buffer size */
|
|
997
1242
|
dctx->stage = ZSTDds_skipFrame;
|
|
998
1243
|
return 0;
|
|
@@ -1004,7 +1249,7 @@ size_t ZSTD_decompressContinue(ZSTD_DCtx* dctx, void* dst, size_t dstCapacity, c
|
|
|
1004
1249
|
|
|
1005
1250
|
default:
|
|
1006
1251
|
assert(0); /* impossible */
|
|
1007
|
-
RETURN_ERROR(GENERIC); /* some compiler require default to do something */
|
|
1252
|
+
RETURN_ERROR(GENERIC, "impossible to reach"); /* some compiler require default to do something */
|
|
1008
1253
|
}
|
|
1009
1254
|
}
|
|
1010
1255
|
|
|
@@ -1015,6 +1260,10 @@ static size_t ZSTD_refDictContent(ZSTD_DCtx* dctx, const void* dict, size_t dict
|
|
|
1015
1260
|
dctx->virtualStart = (const char*)dict - ((const char*)(dctx->previousDstEnd) - (const char*)(dctx->prefixStart));
|
|
1016
1261
|
dctx->prefixStart = dict;
|
|
1017
1262
|
dctx->previousDstEnd = (const char*)dict + dictSize;
|
|
1263
|
+
#ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
|
|
1264
|
+
dctx->dictContentBeginForFuzzing = dctx->prefixStart;
|
|
1265
|
+
dctx->dictContentEndForFuzzing = dctx->previousDstEnd;
|
|
1266
|
+
#endif
|
|
1018
1267
|
return 0;
|
|
1019
1268
|
}
|
|
1020
1269
|
|
|
@@ -1028,7 +1277,7 @@ ZSTD_loadDEntropy(ZSTD_entropyDTables_t* entropy,
|
|
|
1028
1277
|
const BYTE* dictPtr = (const BYTE*)dict;
|
|
1029
1278
|
const BYTE* const dictEnd = dictPtr + dictSize;
|
|
1030
1279
|
|
|
1031
|
-
RETURN_ERROR_IF(dictSize <= 8, dictionary_corrupted);
|
|
1280
|
+
RETURN_ERROR_IF(dictSize <= 8, dictionary_corrupted, "dict is too small");
|
|
1032
1281
|
assert(MEM_readLE32(dict) == ZSTD_MAGIC_DICTIONARY); /* dict must be valid */
|
|
1033
1282
|
dictPtr += 8; /* skip header = magic + dictID */
|
|
1034
1283
|
|
|
@@ -1044,63 +1293,69 @@ ZSTD_loadDEntropy(ZSTD_entropyDTables_t* entropy,
|
|
|
1044
1293
|
workspace, workspaceSize);
|
|
1045
1294
|
#else
|
|
1046
1295
|
size_t const hSize = HUF_readDTableX2_wksp(entropy->hufTable,
|
|
1047
|
-
dictPtr, dictEnd - dictPtr,
|
|
1296
|
+
dictPtr, (size_t)(dictEnd - dictPtr),
|
|
1048
1297
|
workspace, workspaceSize);
|
|
1049
1298
|
#endif
|
|
1050
|
-
RETURN_ERROR_IF(HUF_isError(hSize), dictionary_corrupted);
|
|
1299
|
+
RETURN_ERROR_IF(HUF_isError(hSize), dictionary_corrupted, "");
|
|
1051
1300
|
dictPtr += hSize;
|
|
1052
1301
|
}
|
|
1053
1302
|
|
|
1054
1303
|
{ short offcodeNCount[MaxOff+1];
|
|
1055
1304
|
unsigned offcodeMaxValue = MaxOff, offcodeLog;
|
|
1056
|
-
size_t const offcodeHeaderSize = FSE_readNCount(offcodeNCount, &offcodeMaxValue, &offcodeLog, dictPtr, dictEnd-dictPtr);
|
|
1057
|
-
RETURN_ERROR_IF(FSE_isError(offcodeHeaderSize), dictionary_corrupted);
|
|
1058
|
-
RETURN_ERROR_IF(offcodeMaxValue > MaxOff, dictionary_corrupted);
|
|
1059
|
-
RETURN_ERROR_IF(offcodeLog > OffFSELog, dictionary_corrupted);
|
|
1305
|
+
size_t const offcodeHeaderSize = FSE_readNCount(offcodeNCount, &offcodeMaxValue, &offcodeLog, dictPtr, (size_t)(dictEnd-dictPtr));
|
|
1306
|
+
RETURN_ERROR_IF(FSE_isError(offcodeHeaderSize), dictionary_corrupted, "");
|
|
1307
|
+
RETURN_ERROR_IF(offcodeMaxValue > MaxOff, dictionary_corrupted, "");
|
|
1308
|
+
RETURN_ERROR_IF(offcodeLog > OffFSELog, dictionary_corrupted, "");
|
|
1060
1309
|
ZSTD_buildFSETable( entropy->OFTable,
|
|
1061
1310
|
offcodeNCount, offcodeMaxValue,
|
|
1062
1311
|
OF_base, OF_bits,
|
|
1063
|
-
offcodeLog
|
|
1312
|
+
offcodeLog,
|
|
1313
|
+
entropy->workspace, sizeof(entropy->workspace),
|
|
1314
|
+
/* bmi2 */0);
|
|
1064
1315
|
dictPtr += offcodeHeaderSize;
|
|
1065
1316
|
}
|
|
1066
1317
|
|
|
1067
1318
|
{ short matchlengthNCount[MaxML+1];
|
|
1068
1319
|
unsigned matchlengthMaxValue = MaxML, matchlengthLog;
|
|
1069
|
-
size_t const matchlengthHeaderSize = FSE_readNCount(matchlengthNCount, &matchlengthMaxValue, &matchlengthLog, dictPtr, dictEnd-dictPtr);
|
|
1070
|
-
RETURN_ERROR_IF(FSE_isError(matchlengthHeaderSize), dictionary_corrupted);
|
|
1071
|
-
RETURN_ERROR_IF(matchlengthMaxValue > MaxML, dictionary_corrupted);
|
|
1072
|
-
RETURN_ERROR_IF(matchlengthLog > MLFSELog, dictionary_corrupted);
|
|
1320
|
+
size_t const matchlengthHeaderSize = FSE_readNCount(matchlengthNCount, &matchlengthMaxValue, &matchlengthLog, dictPtr, (size_t)(dictEnd-dictPtr));
|
|
1321
|
+
RETURN_ERROR_IF(FSE_isError(matchlengthHeaderSize), dictionary_corrupted, "");
|
|
1322
|
+
RETURN_ERROR_IF(matchlengthMaxValue > MaxML, dictionary_corrupted, "");
|
|
1323
|
+
RETURN_ERROR_IF(matchlengthLog > MLFSELog, dictionary_corrupted, "");
|
|
1073
1324
|
ZSTD_buildFSETable( entropy->MLTable,
|
|
1074
1325
|
matchlengthNCount, matchlengthMaxValue,
|
|
1075
1326
|
ML_base, ML_bits,
|
|
1076
|
-
matchlengthLog
|
|
1327
|
+
matchlengthLog,
|
|
1328
|
+
entropy->workspace, sizeof(entropy->workspace),
|
|
1329
|
+
/* bmi2 */ 0);
|
|
1077
1330
|
dictPtr += matchlengthHeaderSize;
|
|
1078
1331
|
}
|
|
1079
1332
|
|
|
1080
1333
|
{ short litlengthNCount[MaxLL+1];
|
|
1081
1334
|
unsigned litlengthMaxValue = MaxLL, litlengthLog;
|
|
1082
|
-
size_t const litlengthHeaderSize = FSE_readNCount(litlengthNCount, &litlengthMaxValue, &litlengthLog, dictPtr, dictEnd-dictPtr);
|
|
1083
|
-
RETURN_ERROR_IF(FSE_isError(litlengthHeaderSize), dictionary_corrupted);
|
|
1084
|
-
RETURN_ERROR_IF(litlengthMaxValue > MaxLL, dictionary_corrupted);
|
|
1085
|
-
RETURN_ERROR_IF(litlengthLog > LLFSELog, dictionary_corrupted);
|
|
1335
|
+
size_t const litlengthHeaderSize = FSE_readNCount(litlengthNCount, &litlengthMaxValue, &litlengthLog, dictPtr, (size_t)(dictEnd-dictPtr));
|
|
1336
|
+
RETURN_ERROR_IF(FSE_isError(litlengthHeaderSize), dictionary_corrupted, "");
|
|
1337
|
+
RETURN_ERROR_IF(litlengthMaxValue > MaxLL, dictionary_corrupted, "");
|
|
1338
|
+
RETURN_ERROR_IF(litlengthLog > LLFSELog, dictionary_corrupted, "");
|
|
1086
1339
|
ZSTD_buildFSETable( entropy->LLTable,
|
|
1087
1340
|
litlengthNCount, litlengthMaxValue,
|
|
1088
1341
|
LL_base, LL_bits,
|
|
1089
|
-
litlengthLog
|
|
1342
|
+
litlengthLog,
|
|
1343
|
+
entropy->workspace, sizeof(entropy->workspace),
|
|
1344
|
+
/* bmi2 */ 0);
|
|
1090
1345
|
dictPtr += litlengthHeaderSize;
|
|
1091
1346
|
}
|
|
1092
1347
|
|
|
1093
|
-
RETURN_ERROR_IF(dictPtr+12 > dictEnd, dictionary_corrupted);
|
|
1348
|
+
RETURN_ERROR_IF(dictPtr+12 > dictEnd, dictionary_corrupted, "");
|
|
1094
1349
|
{ int i;
|
|
1095
1350
|
size_t const dictContentSize = (size_t)(dictEnd - (dictPtr+12));
|
|
1096
1351
|
for (i=0; i<3; i++) {
|
|
1097
1352
|
U32 const rep = MEM_readLE32(dictPtr); dictPtr += 4;
|
|
1098
|
-
RETURN_ERROR_IF(rep==0 || rep
|
|
1099
|
-
dictionary_corrupted);
|
|
1353
|
+
RETURN_ERROR_IF(rep==0 || rep > dictContentSize,
|
|
1354
|
+
dictionary_corrupted, "");
|
|
1100
1355
|
entropy->rep[i] = rep;
|
|
1101
1356
|
} }
|
|
1102
1357
|
|
|
1103
|
-
return dictPtr - (const BYTE*)dict;
|
|
1358
|
+
return (size_t)(dictPtr - (const BYTE*)dict);
|
|
1104
1359
|
}
|
|
1105
1360
|
|
|
1106
1361
|
static size_t ZSTD_decompress_insertDictionary(ZSTD_DCtx* dctx, const void* dict, size_t dictSize)
|
|
@@ -1114,7 +1369,7 @@ static size_t ZSTD_decompress_insertDictionary(ZSTD_DCtx* dctx, const void* dict
|
|
|
1114
1369
|
|
|
1115
1370
|
/* load entropy tables */
|
|
1116
1371
|
{ size_t const eSize = ZSTD_loadDEntropy(&dctx->entropy, dict, dictSize);
|
|
1117
|
-
RETURN_ERROR_IF(ZSTD_isError(eSize), dictionary_corrupted);
|
|
1372
|
+
RETURN_ERROR_IF(ZSTD_isError(eSize), dictionary_corrupted, "");
|
|
1118
1373
|
dict = (const char*)dict + eSize;
|
|
1119
1374
|
dictSize -= eSize;
|
|
1120
1375
|
}
|
|
@@ -1127,8 +1382,12 @@ static size_t ZSTD_decompress_insertDictionary(ZSTD_DCtx* dctx, const void* dict
|
|
|
1127
1382
|
size_t ZSTD_decompressBegin(ZSTD_DCtx* dctx)
|
|
1128
1383
|
{
|
|
1129
1384
|
assert(dctx != NULL);
|
|
1385
|
+
#if ZSTD_TRACE
|
|
1386
|
+
dctx->traceCtx = (ZSTD_trace_decompress_begin != NULL) ? ZSTD_trace_decompress_begin(dctx) : 0;
|
|
1387
|
+
#endif
|
|
1130
1388
|
dctx->expected = ZSTD_startingInputLength(dctx->format); /* dctx->format must be properly set */
|
|
1131
1389
|
dctx->stage = ZSTDds_getFrameHeaderSize;
|
|
1390
|
+
dctx->processedCSize = 0;
|
|
1132
1391
|
dctx->decodedSize = 0;
|
|
1133
1392
|
dctx->previousDstEnd = NULL;
|
|
1134
1393
|
dctx->prefixStart = NULL;
|
|
@@ -1137,8 +1396,9 @@ size_t ZSTD_decompressBegin(ZSTD_DCtx* dctx)
|
|
|
1137
1396
|
dctx->entropy.hufTable[0] = (HUF_DTable)((HufLog)*0x1000001); /* cover both little and big endian */
|
|
1138
1397
|
dctx->litEntropy = dctx->fseEntropy = 0;
|
|
1139
1398
|
dctx->dictID = 0;
|
|
1399
|
+
dctx->bType = bt_reserved;
|
|
1140
1400
|
ZSTD_STATIC_ASSERT(sizeof(dctx->entropy.rep) == sizeof(repStartValue));
|
|
1141
|
-
|
|
1401
|
+
ZSTD_memcpy(dctx->entropy.rep, repStartValue, sizeof(repStartValue)); /* initial repcodes */
|
|
1142
1402
|
dctx->LLTptr = dctx->entropy.LLTable;
|
|
1143
1403
|
dctx->MLTptr = dctx->entropy.MLTable;
|
|
1144
1404
|
dctx->OFTptr = dctx->entropy.OFTable;
|
|
@@ -1148,11 +1408,11 @@ size_t ZSTD_decompressBegin(ZSTD_DCtx* dctx)
|
|
|
1148
1408
|
|
|
1149
1409
|
size_t ZSTD_decompressBegin_usingDict(ZSTD_DCtx* dctx, const void* dict, size_t dictSize)
|
|
1150
1410
|
{
|
|
1151
|
-
FORWARD_IF_ERROR( ZSTD_decompressBegin(dctx) );
|
|
1411
|
+
FORWARD_IF_ERROR( ZSTD_decompressBegin(dctx) , "");
|
|
1152
1412
|
if (dict && dictSize)
|
|
1153
1413
|
RETURN_ERROR_IF(
|
|
1154
1414
|
ZSTD_isError(ZSTD_decompress_insertDictionary(dctx, dict, dictSize)),
|
|
1155
|
-
dictionary_corrupted);
|
|
1415
|
+
dictionary_corrupted, "");
|
|
1156
1416
|
return 0;
|
|
1157
1417
|
}
|
|
1158
1418
|
|
|
@@ -1171,7 +1431,7 @@ size_t ZSTD_decompressBegin_usingDDict(ZSTD_DCtx* dctx, const ZSTD_DDict* ddict)
|
|
|
1171
1431
|
DEBUGLOG(4, "DDict is %s",
|
|
1172
1432
|
dctx->ddictIsCold ? "~cold~" : "hot!");
|
|
1173
1433
|
}
|
|
1174
|
-
FORWARD_IF_ERROR( ZSTD_decompressBegin(dctx) );
|
|
1434
|
+
FORWARD_IF_ERROR( ZSTD_decompressBegin(dctx) , "");
|
|
1175
1435
|
if (ddict) { /* NULL ddict is equivalent to no dictionary */
|
|
1176
1436
|
ZSTD_copyDDictParameters(dctx, ddict);
|
|
1177
1437
|
}
|
|
@@ -1262,11 +1522,11 @@ size_t ZSTD_DCtx_loadDictionary_advanced(ZSTD_DCtx* dctx,
|
|
|
1262
1522
|
ZSTD_dictLoadMethod_e dictLoadMethod,
|
|
1263
1523
|
ZSTD_dictContentType_e dictContentType)
|
|
1264
1524
|
{
|
|
1265
|
-
RETURN_ERROR_IF(dctx->streamStage != zdss_init, stage_wrong);
|
|
1525
|
+
RETURN_ERROR_IF(dctx->streamStage != zdss_init, stage_wrong, "");
|
|
1266
1526
|
ZSTD_clearDict(dctx);
|
|
1267
|
-
if (dict && dictSize
|
|
1527
|
+
if (dict && dictSize != 0) {
|
|
1268
1528
|
dctx->ddictLocal = ZSTD_createDDict_advanced(dict, dictSize, dictLoadMethod, dictContentType, dctx->customMem);
|
|
1269
|
-
RETURN_ERROR_IF(dctx->ddictLocal == NULL, memory_allocation);
|
|
1529
|
+
RETURN_ERROR_IF(dctx->ddictLocal == NULL, memory_allocation, "NULL pointer!");
|
|
1270
1530
|
dctx->ddict = dctx->ddictLocal;
|
|
1271
1531
|
dctx->dictUses = ZSTD_use_indefinitely;
|
|
1272
1532
|
}
|
|
@@ -1285,7 +1545,7 @@ size_t ZSTD_DCtx_loadDictionary(ZSTD_DCtx* dctx, const void* dict, size_t dictSi
|
|
|
1285
1545
|
|
|
1286
1546
|
size_t ZSTD_DCtx_refPrefix_advanced(ZSTD_DCtx* dctx, const void* prefix, size_t prefixSize, ZSTD_dictContentType_e dictContentType)
|
|
1287
1547
|
{
|
|
1288
|
-
FORWARD_IF_ERROR(ZSTD_DCtx_loadDictionary_advanced(dctx, prefix, prefixSize, ZSTD_dlm_byRef, dictContentType));
|
|
1548
|
+
FORWARD_IF_ERROR(ZSTD_DCtx_loadDictionary_advanced(dctx, prefix, prefixSize, ZSTD_dlm_byRef, dictContentType), "");
|
|
1289
1549
|
dctx->dictUses = ZSTD_use_once;
|
|
1290
1550
|
return 0;
|
|
1291
1551
|
}
|
|
@@ -1297,14 +1557,14 @@ size_t ZSTD_DCtx_refPrefix(ZSTD_DCtx* dctx, const void* prefix, size_t prefixSiz
|
|
|
1297
1557
|
|
|
1298
1558
|
|
|
1299
1559
|
/* ZSTD_initDStream_usingDict() :
|
|
1300
|
-
* return : expected size, aka
|
|
1560
|
+
* return : expected size, aka ZSTD_startingInputLength().
|
|
1301
1561
|
* this function cannot fail */
|
|
1302
1562
|
size_t ZSTD_initDStream_usingDict(ZSTD_DStream* zds, const void* dict, size_t dictSize)
|
|
1303
1563
|
{
|
|
1304
1564
|
DEBUGLOG(4, "ZSTD_initDStream_usingDict");
|
|
1305
|
-
FORWARD_IF_ERROR( ZSTD_DCtx_reset(zds, ZSTD_reset_session_only) );
|
|
1306
|
-
FORWARD_IF_ERROR( ZSTD_DCtx_loadDictionary(zds, dict, dictSize) );
|
|
1307
|
-
return
|
|
1565
|
+
FORWARD_IF_ERROR( ZSTD_DCtx_reset(zds, ZSTD_reset_session_only) , "");
|
|
1566
|
+
FORWARD_IF_ERROR( ZSTD_DCtx_loadDictionary(zds, dict, dictSize) , "");
|
|
1567
|
+
return ZSTD_startingInputLength(zds->format);
|
|
1308
1568
|
}
|
|
1309
1569
|
|
|
1310
1570
|
/* note : this variant can't fail */
|
|
@@ -1319,28 +1579,38 @@ size_t ZSTD_initDStream(ZSTD_DStream* zds)
|
|
|
1319
1579
|
* this function cannot fail */
|
|
1320
1580
|
size_t ZSTD_initDStream_usingDDict(ZSTD_DStream* dctx, const ZSTD_DDict* ddict)
|
|
1321
1581
|
{
|
|
1322
|
-
FORWARD_IF_ERROR( ZSTD_DCtx_reset(dctx, ZSTD_reset_session_only) );
|
|
1323
|
-
FORWARD_IF_ERROR( ZSTD_DCtx_refDDict(dctx, ddict) );
|
|
1324
|
-
return
|
|
1582
|
+
FORWARD_IF_ERROR( ZSTD_DCtx_reset(dctx, ZSTD_reset_session_only) , "");
|
|
1583
|
+
FORWARD_IF_ERROR( ZSTD_DCtx_refDDict(dctx, ddict) , "");
|
|
1584
|
+
return ZSTD_startingInputLength(dctx->format);
|
|
1325
1585
|
}
|
|
1326
1586
|
|
|
1327
1587
|
/* ZSTD_resetDStream() :
|
|
1328
|
-
* return : expected size, aka
|
|
1588
|
+
* return : expected size, aka ZSTD_startingInputLength().
|
|
1329
1589
|
* this function cannot fail */
|
|
1330
1590
|
size_t ZSTD_resetDStream(ZSTD_DStream* dctx)
|
|
1331
1591
|
{
|
|
1332
|
-
FORWARD_IF_ERROR(ZSTD_DCtx_reset(dctx, ZSTD_reset_session_only));
|
|
1333
|
-
return
|
|
1592
|
+
FORWARD_IF_ERROR(ZSTD_DCtx_reset(dctx, ZSTD_reset_session_only), "");
|
|
1593
|
+
return ZSTD_startingInputLength(dctx->format);
|
|
1334
1594
|
}
|
|
1335
1595
|
|
|
1336
1596
|
|
|
1337
1597
|
size_t ZSTD_DCtx_refDDict(ZSTD_DCtx* dctx, const ZSTD_DDict* ddict)
|
|
1338
1598
|
{
|
|
1339
|
-
RETURN_ERROR_IF(dctx->streamStage != zdss_init, stage_wrong);
|
|
1599
|
+
RETURN_ERROR_IF(dctx->streamStage != zdss_init, stage_wrong, "");
|
|
1340
1600
|
ZSTD_clearDict(dctx);
|
|
1341
1601
|
if (ddict) {
|
|
1342
1602
|
dctx->ddict = ddict;
|
|
1343
1603
|
dctx->dictUses = ZSTD_use_indefinitely;
|
|
1604
|
+
if (dctx->refMultipleDDicts == ZSTD_rmd_refMultipleDDicts) {
|
|
1605
|
+
if (dctx->ddictSet == NULL) {
|
|
1606
|
+
dctx->ddictSet = ZSTD_createDDictHashSet(dctx->customMem);
|
|
1607
|
+
if (!dctx->ddictSet) {
|
|
1608
|
+
RETURN_ERROR(memory_allocation, "Failed to allocate memory for hash set!");
|
|
1609
|
+
}
|
|
1610
|
+
}
|
|
1611
|
+
assert(!dctx->staticSize); /* Impossible: ddictSet cannot have been allocated if static dctx */
|
|
1612
|
+
FORWARD_IF_ERROR(ZSTD_DDictHashSet_addDDict(dctx->ddictSet, ddict, dctx->customMem), "");
|
|
1613
|
+
}
|
|
1344
1614
|
}
|
|
1345
1615
|
return 0;
|
|
1346
1616
|
}
|
|
@@ -1353,16 +1623,16 @@ size_t ZSTD_DCtx_setMaxWindowSize(ZSTD_DCtx* dctx, size_t maxWindowSize)
|
|
|
1353
1623
|
ZSTD_bounds const bounds = ZSTD_dParam_getBounds(ZSTD_d_windowLogMax);
|
|
1354
1624
|
size_t const min = (size_t)1 << bounds.lowerBound;
|
|
1355
1625
|
size_t const max = (size_t)1 << bounds.upperBound;
|
|
1356
|
-
RETURN_ERROR_IF(dctx->streamStage != zdss_init, stage_wrong);
|
|
1357
|
-
RETURN_ERROR_IF(maxWindowSize < min, parameter_outOfBound);
|
|
1358
|
-
RETURN_ERROR_IF(maxWindowSize > max, parameter_outOfBound);
|
|
1626
|
+
RETURN_ERROR_IF(dctx->streamStage != zdss_init, stage_wrong, "");
|
|
1627
|
+
RETURN_ERROR_IF(maxWindowSize < min, parameter_outOfBound, "");
|
|
1628
|
+
RETURN_ERROR_IF(maxWindowSize > max, parameter_outOfBound, "");
|
|
1359
1629
|
dctx->maxWindowSize = maxWindowSize;
|
|
1360
1630
|
return 0;
|
|
1361
1631
|
}
|
|
1362
1632
|
|
|
1363
1633
|
size_t ZSTD_DCtx_setFormat(ZSTD_DCtx* dctx, ZSTD_format_e format)
|
|
1364
1634
|
{
|
|
1365
|
-
return ZSTD_DCtx_setParameter(dctx, ZSTD_d_format, format);
|
|
1635
|
+
return ZSTD_DCtx_setParameter(dctx, ZSTD_d_format, (int)format);
|
|
1366
1636
|
}
|
|
1367
1637
|
|
|
1368
1638
|
ZSTD_bounds ZSTD_dParam_getBounds(ZSTD_dParameter dParam)
|
|
@@ -1378,6 +1648,18 @@ ZSTD_bounds ZSTD_dParam_getBounds(ZSTD_dParameter dParam)
|
|
|
1378
1648
|
bounds.upperBound = (int)ZSTD_f_zstd1_magicless;
|
|
1379
1649
|
ZSTD_STATIC_ASSERT(ZSTD_f_zstd1 < ZSTD_f_zstd1_magicless);
|
|
1380
1650
|
return bounds;
|
|
1651
|
+
case ZSTD_d_stableOutBuffer:
|
|
1652
|
+
bounds.lowerBound = (int)ZSTD_bm_buffered;
|
|
1653
|
+
bounds.upperBound = (int)ZSTD_bm_stable;
|
|
1654
|
+
return bounds;
|
|
1655
|
+
case ZSTD_d_forceIgnoreChecksum:
|
|
1656
|
+
bounds.lowerBound = (int)ZSTD_d_validateChecksum;
|
|
1657
|
+
bounds.upperBound = (int)ZSTD_d_ignoreChecksum;
|
|
1658
|
+
return bounds;
|
|
1659
|
+
case ZSTD_d_refMultipleDDicts:
|
|
1660
|
+
bounds.lowerBound = (int)ZSTD_rmd_refSingleDDict;
|
|
1661
|
+
bounds.upperBound = (int)ZSTD_rmd_refMultipleDDicts;
|
|
1662
|
+
return bounds;
|
|
1381
1663
|
default:;
|
|
1382
1664
|
}
|
|
1383
1665
|
bounds.error = ERROR(parameter_unsupported);
|
|
@@ -1397,12 +1679,35 @@ static int ZSTD_dParam_withinBounds(ZSTD_dParameter dParam, int value)
|
|
|
1397
1679
|
}
|
|
1398
1680
|
|
|
1399
1681
|
#define CHECK_DBOUNDS(p,v) { \
|
|
1400
|
-
RETURN_ERROR_IF(!ZSTD_dParam_withinBounds(p, v), parameter_outOfBound); \
|
|
1682
|
+
RETURN_ERROR_IF(!ZSTD_dParam_withinBounds(p, v), parameter_outOfBound, ""); \
|
|
1683
|
+
}
|
|
1684
|
+
|
|
1685
|
+
size_t ZSTD_DCtx_getParameter(ZSTD_DCtx* dctx, ZSTD_dParameter param, int* value)
|
|
1686
|
+
{
|
|
1687
|
+
switch (param) {
|
|
1688
|
+
case ZSTD_d_windowLogMax:
|
|
1689
|
+
*value = (int)ZSTD_highbit32((U32)dctx->maxWindowSize);
|
|
1690
|
+
return 0;
|
|
1691
|
+
case ZSTD_d_format:
|
|
1692
|
+
*value = (int)dctx->format;
|
|
1693
|
+
return 0;
|
|
1694
|
+
case ZSTD_d_stableOutBuffer:
|
|
1695
|
+
*value = (int)dctx->outBufferMode;
|
|
1696
|
+
return 0;
|
|
1697
|
+
case ZSTD_d_forceIgnoreChecksum:
|
|
1698
|
+
*value = (int)dctx->forceIgnoreChecksum;
|
|
1699
|
+
return 0;
|
|
1700
|
+
case ZSTD_d_refMultipleDDicts:
|
|
1701
|
+
*value = (int)dctx->refMultipleDDicts;
|
|
1702
|
+
return 0;
|
|
1703
|
+
default:;
|
|
1704
|
+
}
|
|
1705
|
+
RETURN_ERROR(parameter_unsupported, "");
|
|
1401
1706
|
}
|
|
1402
1707
|
|
|
1403
1708
|
size_t ZSTD_DCtx_setParameter(ZSTD_DCtx* dctx, ZSTD_dParameter dParam, int value)
|
|
1404
1709
|
{
|
|
1405
|
-
RETURN_ERROR_IF(dctx->streamStage != zdss_init, stage_wrong);
|
|
1710
|
+
RETURN_ERROR_IF(dctx->streamStage != zdss_init, stage_wrong, "");
|
|
1406
1711
|
switch(dParam) {
|
|
1407
1712
|
case ZSTD_d_windowLogMax:
|
|
1408
1713
|
if (value == 0) value = ZSTD_WINDOWLOG_LIMIT_DEFAULT;
|
|
@@ -1413,9 +1718,24 @@ size_t ZSTD_DCtx_setParameter(ZSTD_DCtx* dctx, ZSTD_dParameter dParam, int value
|
|
|
1413
1718
|
CHECK_DBOUNDS(ZSTD_d_format, value);
|
|
1414
1719
|
dctx->format = (ZSTD_format_e)value;
|
|
1415
1720
|
return 0;
|
|
1721
|
+
case ZSTD_d_stableOutBuffer:
|
|
1722
|
+
CHECK_DBOUNDS(ZSTD_d_stableOutBuffer, value);
|
|
1723
|
+
dctx->outBufferMode = (ZSTD_bufferMode_e)value;
|
|
1724
|
+
return 0;
|
|
1725
|
+
case ZSTD_d_forceIgnoreChecksum:
|
|
1726
|
+
CHECK_DBOUNDS(ZSTD_d_forceIgnoreChecksum, value);
|
|
1727
|
+
dctx->forceIgnoreChecksum = (ZSTD_forceIgnoreChecksum_e)value;
|
|
1728
|
+
return 0;
|
|
1729
|
+
case ZSTD_d_refMultipleDDicts:
|
|
1730
|
+
CHECK_DBOUNDS(ZSTD_d_refMultipleDDicts, value);
|
|
1731
|
+
if (dctx->staticSize != 0) {
|
|
1732
|
+
RETURN_ERROR(parameter_unsupported, "Static dctx does not support multiple DDicts!");
|
|
1733
|
+
}
|
|
1734
|
+
dctx->refMultipleDDicts = (ZSTD_refMultipleDDicts_e)value;
|
|
1735
|
+
return 0;
|
|
1416
1736
|
default:;
|
|
1417
1737
|
}
|
|
1418
|
-
RETURN_ERROR(parameter_unsupported);
|
|
1738
|
+
RETURN_ERROR(parameter_unsupported, "");
|
|
1419
1739
|
}
|
|
1420
1740
|
|
|
1421
1741
|
size_t ZSTD_DCtx_reset(ZSTD_DCtx* dctx, ZSTD_ResetDirective reset)
|
|
@@ -1427,10 +1747,9 @@ size_t ZSTD_DCtx_reset(ZSTD_DCtx* dctx, ZSTD_ResetDirective reset)
|
|
|
1427
1747
|
}
|
|
1428
1748
|
if ( (reset == ZSTD_reset_parameters)
|
|
1429
1749
|
|| (reset == ZSTD_reset_session_and_parameters) ) {
|
|
1430
|
-
RETURN_ERROR_IF(dctx->streamStage != zdss_init, stage_wrong);
|
|
1750
|
+
RETURN_ERROR_IF(dctx->streamStage != zdss_init, stage_wrong, "");
|
|
1431
1751
|
ZSTD_clearDict(dctx);
|
|
1432
|
-
dctx
|
|
1433
|
-
dctx->maxWindowSize = ZSTD_MAXWINDOWSIZE_DEFAULT;
|
|
1752
|
+
ZSTD_DCtx_resetParameters(dctx);
|
|
1434
1753
|
}
|
|
1435
1754
|
return 0;
|
|
1436
1755
|
}
|
|
@@ -1448,7 +1767,7 @@ size_t ZSTD_decodingBufferSize_min(unsigned long long windowSize, unsigned long
|
|
|
1448
1767
|
unsigned long long const neededSize = MIN(frameContentSize, neededRBSize);
|
|
1449
1768
|
size_t const minRBSize = (size_t) neededSize;
|
|
1450
1769
|
RETURN_ERROR_IF((unsigned long long)minRBSize != neededSize,
|
|
1451
|
-
frameParameter_windowTooLarge);
|
|
1770
|
+
frameParameter_windowTooLarge, "");
|
|
1452
1771
|
return minRBSize;
|
|
1453
1772
|
}
|
|
1454
1773
|
|
|
@@ -1466,30 +1785,94 @@ size_t ZSTD_estimateDStreamSize_fromFrame(const void* src, size_t srcSize)
|
|
|
1466
1785
|
ZSTD_frameHeader zfh;
|
|
1467
1786
|
size_t const err = ZSTD_getFrameHeader(&zfh, src, srcSize);
|
|
1468
1787
|
if (ZSTD_isError(err)) return err;
|
|
1469
|
-
RETURN_ERROR_IF(err>0, srcSize_wrong);
|
|
1788
|
+
RETURN_ERROR_IF(err>0, srcSize_wrong, "");
|
|
1470
1789
|
RETURN_ERROR_IF(zfh.windowSize > windowSizeMax,
|
|
1471
|
-
frameParameter_windowTooLarge);
|
|
1790
|
+
frameParameter_windowTooLarge, "");
|
|
1472
1791
|
return ZSTD_estimateDStreamSize((size_t)zfh.windowSize);
|
|
1473
1792
|
}
|
|
1474
1793
|
|
|
1475
1794
|
|
|
1476
1795
|
/* ***** Decompression ***** */
|
|
1477
1796
|
|
|
1478
|
-
|
|
1797
|
+
static int ZSTD_DCtx_isOverflow(ZSTD_DStream* zds, size_t const neededInBuffSize, size_t const neededOutBuffSize)
|
|
1798
|
+
{
|
|
1799
|
+
return (zds->inBuffSize + zds->outBuffSize) >= (neededInBuffSize + neededOutBuffSize) * ZSTD_WORKSPACETOOLARGE_FACTOR;
|
|
1800
|
+
}
|
|
1801
|
+
|
|
1802
|
+
static void ZSTD_DCtx_updateOversizedDuration(ZSTD_DStream* zds, size_t const neededInBuffSize, size_t const neededOutBuffSize)
|
|
1803
|
+
{
|
|
1804
|
+
if (ZSTD_DCtx_isOverflow(zds, neededInBuffSize, neededOutBuffSize))
|
|
1805
|
+
zds->oversizedDuration++;
|
|
1806
|
+
else
|
|
1807
|
+
zds->oversizedDuration = 0;
|
|
1808
|
+
}
|
|
1809
|
+
|
|
1810
|
+
static int ZSTD_DCtx_isOversizedTooLong(ZSTD_DStream* zds)
|
|
1479
1811
|
{
|
|
1480
|
-
|
|
1481
|
-
|
|
1482
|
-
|
|
1812
|
+
return zds->oversizedDuration >= ZSTD_WORKSPACETOOLARGE_MAXDURATION;
|
|
1813
|
+
}
|
|
1814
|
+
|
|
1815
|
+
/* Checks that the output buffer hasn't changed if ZSTD_obm_stable is used. */
|
|
1816
|
+
static size_t ZSTD_checkOutBuffer(ZSTD_DStream const* zds, ZSTD_outBuffer const* output)
|
|
1817
|
+
{
|
|
1818
|
+
ZSTD_outBuffer const expect = zds->expectedOutBuffer;
|
|
1819
|
+
/* No requirement when ZSTD_obm_stable is not enabled. */
|
|
1820
|
+
if (zds->outBufferMode != ZSTD_bm_stable)
|
|
1821
|
+
return 0;
|
|
1822
|
+
/* Any buffer is allowed in zdss_init, this must be the same for every other call until
|
|
1823
|
+
* the context is reset.
|
|
1824
|
+
*/
|
|
1825
|
+
if (zds->streamStage == zdss_init)
|
|
1826
|
+
return 0;
|
|
1827
|
+
/* The buffer must match our expectation exactly. */
|
|
1828
|
+
if (expect.dst == output->dst && expect.pos == output->pos && expect.size == output->size)
|
|
1829
|
+
return 0;
|
|
1830
|
+
RETURN_ERROR(dstBuffer_wrong, "ZSTD_d_stableOutBuffer enabled but output differs!");
|
|
1483
1831
|
}
|
|
1484
1832
|
|
|
1833
|
+
/* Calls ZSTD_decompressContinue() with the right parameters for ZSTD_decompressStream()
|
|
1834
|
+
* and updates the stage and the output buffer state. This call is extracted so it can be
|
|
1835
|
+
* used both when reading directly from the ZSTD_inBuffer, and in buffered input mode.
|
|
1836
|
+
* NOTE: You must break after calling this function since the streamStage is modified.
|
|
1837
|
+
*/
|
|
1838
|
+
static size_t ZSTD_decompressContinueStream(
|
|
1839
|
+
ZSTD_DStream* zds, char** op, char* oend,
|
|
1840
|
+
void const* src, size_t srcSize) {
|
|
1841
|
+
int const isSkipFrame = ZSTD_isSkipFrame(zds);
|
|
1842
|
+
if (zds->outBufferMode == ZSTD_bm_buffered) {
|
|
1843
|
+
size_t const dstSize = isSkipFrame ? 0 : zds->outBuffSize - zds->outStart;
|
|
1844
|
+
size_t const decodedSize = ZSTD_decompressContinue(zds,
|
|
1845
|
+
zds->outBuff + zds->outStart, dstSize, src, srcSize);
|
|
1846
|
+
FORWARD_IF_ERROR(decodedSize, "");
|
|
1847
|
+
if (!decodedSize && !isSkipFrame) {
|
|
1848
|
+
zds->streamStage = zdss_read;
|
|
1849
|
+
} else {
|
|
1850
|
+
zds->outEnd = zds->outStart + decodedSize;
|
|
1851
|
+
zds->streamStage = zdss_flush;
|
|
1852
|
+
}
|
|
1853
|
+
} else {
|
|
1854
|
+
/* Write directly into the output buffer */
|
|
1855
|
+
size_t const dstSize = isSkipFrame ? 0 : (size_t)(oend - *op);
|
|
1856
|
+
size_t const decodedSize = ZSTD_decompressContinue(zds, *op, dstSize, src, srcSize);
|
|
1857
|
+
FORWARD_IF_ERROR(decodedSize, "");
|
|
1858
|
+
*op += decodedSize;
|
|
1859
|
+
/* Flushing is not needed. */
|
|
1860
|
+
zds->streamStage = zdss_read;
|
|
1861
|
+
assert(*op <= oend);
|
|
1862
|
+
assert(zds->outBufferMode == ZSTD_bm_stable);
|
|
1863
|
+
}
|
|
1864
|
+
return 0;
|
|
1865
|
+
}
|
|
1485
1866
|
|
|
1486
1867
|
size_t ZSTD_decompressStream(ZSTD_DStream* zds, ZSTD_outBuffer* output, ZSTD_inBuffer* input)
|
|
1487
1868
|
{
|
|
1488
|
-
const char* const
|
|
1489
|
-
const char* const
|
|
1869
|
+
const char* const src = (const char*)input->src;
|
|
1870
|
+
const char* const istart = input->pos != 0 ? src + input->pos : src;
|
|
1871
|
+
const char* const iend = input->size != 0 ? src + input->size : src;
|
|
1490
1872
|
const char* ip = istart;
|
|
1491
|
-
char* const
|
|
1492
|
-
char* const
|
|
1873
|
+
char* const dst = (char*)output->dst;
|
|
1874
|
+
char* const ostart = output->pos != 0 ? dst + output->pos : dst;
|
|
1875
|
+
char* const oend = output->size != 0 ? dst + output->size : dst;
|
|
1493
1876
|
char* op = ostart;
|
|
1494
1877
|
U32 someMoreWork = 1;
|
|
1495
1878
|
|
|
@@ -1505,6 +1888,7 @@ size_t ZSTD_decompressStream(ZSTD_DStream* zds, ZSTD_outBuffer* output, ZSTD_inB
|
|
|
1505
1888
|
"forbidden. out: pos: %u vs size: %u",
|
|
1506
1889
|
(U32)output->pos, (U32)output->size);
|
|
1507
1890
|
DEBUGLOG(5, "input size : %u", (U32)(input->size - input->pos));
|
|
1891
|
+
FORWARD_IF_ERROR(ZSTD_checkOutBuffer(zds, output), "");
|
|
1508
1892
|
|
|
1509
1893
|
while (someMoreWork) {
|
|
1510
1894
|
switch(zds->streamStage)
|
|
@@ -1515,6 +1899,7 @@ size_t ZSTD_decompressStream(ZSTD_DStream* zds, ZSTD_outBuffer* output, ZSTD_inB
|
|
|
1515
1899
|
zds->lhSize = zds->inPos = zds->outStart = zds->outEnd = 0;
|
|
1516
1900
|
zds->legacyVersion = 0;
|
|
1517
1901
|
zds->hostageByte = 0;
|
|
1902
|
+
zds->expectedOutBuffer = *output;
|
|
1518
1903
|
/* fall-through */
|
|
1519
1904
|
|
|
1520
1905
|
case zdss_loadHeader :
|
|
@@ -1529,6 +1914,9 @@ size_t ZSTD_decompressStream(ZSTD_DStream* zds, ZSTD_outBuffer* output, ZSTD_inB
|
|
|
1529
1914
|
} }
|
|
1530
1915
|
#endif
|
|
1531
1916
|
{ size_t const hSize = ZSTD_getFrameHeader_advanced(&zds->fParams, zds->headerBuffer, zds->lhSize, zds->format);
|
|
1917
|
+
if (zds->refMultipleDDicts && zds->ddictSet) {
|
|
1918
|
+
ZSTD_DCtx_selectFrameDDict(zds);
|
|
1919
|
+
}
|
|
1532
1920
|
DEBUGLOG(5, "header size : %u", (U32)hSize);
|
|
1533
1921
|
if (ZSTD_isError(hSize)) {
|
|
1534
1922
|
#if defined(ZSTD_LEGACY_SUPPORT) && (ZSTD_LEGACY_SUPPORT>=1)
|
|
@@ -1542,7 +1930,7 @@ size_t ZSTD_decompressStream(ZSTD_DStream* zds, ZSTD_outBuffer* output, ZSTD_inB
|
|
|
1542
1930
|
"legacy support is incompatible with static dctx");
|
|
1543
1931
|
FORWARD_IF_ERROR(ZSTD_initLegacyStream(&zds->legacyContext,
|
|
1544
1932
|
zds->previousLegacyVersion, legacyVersion,
|
|
1545
|
-
dict, dictSize));
|
|
1933
|
+
dict, dictSize), "");
|
|
1546
1934
|
zds->legacyVersion = zds->previousLegacyVersion = legacyVersion;
|
|
1547
1935
|
{ size_t const hint = ZSTD_decompressLegacyStream(zds->legacyContext, legacyVersion, output, input);
|
|
1548
1936
|
if (hint==0) zds->streamStage = zdss_init; /* or stay in stage zdss_loadHeader */
|
|
@@ -1557,24 +1945,25 @@ size_t ZSTD_decompressStream(ZSTD_DStream* zds, ZSTD_outBuffer* output, ZSTD_inB
|
|
|
1557
1945
|
assert(iend >= ip);
|
|
1558
1946
|
if (toLoad > remainingInput) { /* not enough input to load full header */
|
|
1559
1947
|
if (remainingInput > 0) {
|
|
1560
|
-
|
|
1948
|
+
ZSTD_memcpy(zds->headerBuffer + zds->lhSize, ip, remainingInput);
|
|
1561
1949
|
zds->lhSize += remainingInput;
|
|
1562
1950
|
}
|
|
1563
1951
|
input->pos = input->size;
|
|
1564
|
-
return (MAX(ZSTD_FRAMEHEADERSIZE_MIN, hSize) - zds->lhSize) + ZSTD_blockHeaderSize; /* remaining header bytes + next block header */
|
|
1952
|
+
return (MAX((size_t)ZSTD_FRAMEHEADERSIZE_MIN(zds->format), hSize) - zds->lhSize) + ZSTD_blockHeaderSize; /* remaining header bytes + next block header */
|
|
1565
1953
|
}
|
|
1566
1954
|
assert(ip != NULL);
|
|
1567
|
-
|
|
1955
|
+
ZSTD_memcpy(zds->headerBuffer + zds->lhSize, ip, toLoad); zds->lhSize = hSize; ip += toLoad;
|
|
1568
1956
|
break;
|
|
1569
1957
|
} }
|
|
1570
1958
|
|
|
1571
1959
|
/* check for single-pass mode opportunity */
|
|
1572
|
-
if (zds->fParams.frameContentSize
|
|
1960
|
+
if (zds->fParams.frameContentSize != ZSTD_CONTENTSIZE_UNKNOWN
|
|
1961
|
+
&& zds->fParams.frameType != ZSTD_skippableFrame
|
|
1573
1962
|
&& (U64)(size_t)(oend-op) >= zds->fParams.frameContentSize) {
|
|
1574
|
-
size_t const cSize = ZSTD_findFrameCompressedSize(istart, iend-istart);
|
|
1963
|
+
size_t const cSize = ZSTD_findFrameCompressedSize(istart, (size_t)(iend-istart));
|
|
1575
1964
|
if (cSize <= (size_t)(iend-istart)) {
|
|
1576
1965
|
/* shortcut : using single-pass mode */
|
|
1577
|
-
size_t const decompressedSize = ZSTD_decompress_usingDDict(zds, op, oend-op, istart, cSize, ZSTD_getDDict(zds));
|
|
1966
|
+
size_t const decompressedSize = ZSTD_decompress_usingDDict(zds, op, (size_t)(oend-op), istart, cSize, ZSTD_getDDict(zds));
|
|
1578
1967
|
if (ZSTD_isError(decompressedSize)) return decompressedSize;
|
|
1579
1968
|
DEBUGLOG(4, "shortcut to single-pass ZSTD_decompress_usingDDict()")
|
|
1580
1969
|
ip = istart + cSize;
|
|
@@ -1585,15 +1974,23 @@ size_t ZSTD_decompressStream(ZSTD_DStream* zds, ZSTD_outBuffer* output, ZSTD_inB
|
|
|
1585
1974
|
break;
|
|
1586
1975
|
} }
|
|
1587
1976
|
|
|
1977
|
+
/* Check output buffer is large enough for ZSTD_odm_stable. */
|
|
1978
|
+
if (zds->outBufferMode == ZSTD_bm_stable
|
|
1979
|
+
&& zds->fParams.frameType != ZSTD_skippableFrame
|
|
1980
|
+
&& zds->fParams.frameContentSize != ZSTD_CONTENTSIZE_UNKNOWN
|
|
1981
|
+
&& (U64)(size_t)(oend-op) < zds->fParams.frameContentSize) {
|
|
1982
|
+
RETURN_ERROR(dstSize_tooSmall, "ZSTD_obm_stable passed but ZSTD_outBuffer is too small");
|
|
1983
|
+
}
|
|
1984
|
+
|
|
1588
1985
|
/* Consume header (see ZSTDds_decodeFrameHeader) */
|
|
1589
1986
|
DEBUGLOG(4, "Consume header");
|
|
1590
|
-
FORWARD_IF_ERROR(ZSTD_decompressBegin_usingDDict(zds, ZSTD_getDDict(zds)));
|
|
1987
|
+
FORWARD_IF_ERROR(ZSTD_decompressBegin_usingDDict(zds, ZSTD_getDDict(zds)), "");
|
|
1591
1988
|
|
|
1592
1989
|
if ((MEM_readLE32(zds->headerBuffer) & ZSTD_MAGIC_SKIPPABLE_MASK) == ZSTD_MAGIC_SKIPPABLE_START) { /* skippable frame */
|
|
1593
1990
|
zds->expected = MEM_readLE32(zds->headerBuffer + ZSTD_FRAMEIDSIZE);
|
|
1594
1991
|
zds->stage = ZSTDds_skipFrame;
|
|
1595
1992
|
} else {
|
|
1596
|
-
FORWARD_IF_ERROR(ZSTD_decodeFrameHeader(zds, zds->headerBuffer, zds->lhSize));
|
|
1993
|
+
FORWARD_IF_ERROR(ZSTD_decodeFrameHeader(zds, zds->headerBuffer, zds->lhSize), "");
|
|
1597
1994
|
zds->expected = ZSTD_blockHeaderSize;
|
|
1598
1995
|
zds->stage = ZSTDds_decodeBlockHeader;
|
|
1599
1996
|
}
|
|
@@ -1604,40 +2001,48 @@ size_t ZSTD_decompressStream(ZSTD_DStream* zds, ZSTD_outBuffer* output, ZSTD_inB
|
|
|
1604
2001
|
(U32)(zds->maxWindowSize >> 10) );
|
|
1605
2002
|
zds->fParams.windowSize = MAX(zds->fParams.windowSize, 1U << ZSTD_WINDOWLOG_ABSOLUTEMIN);
|
|
1606
2003
|
RETURN_ERROR_IF(zds->fParams.windowSize > zds->maxWindowSize,
|
|
1607
|
-
frameParameter_windowTooLarge);
|
|
2004
|
+
frameParameter_windowTooLarge, "");
|
|
1608
2005
|
|
|
1609
2006
|
/* Adapt buffer sizes to frame header instructions */
|
|
1610
2007
|
{ size_t const neededInBuffSize = MAX(zds->fParams.blockSizeMax, 4 /* frame checksum */);
|
|
1611
|
-
size_t const neededOutBuffSize =
|
|
1612
|
-
|
|
1613
|
-
|
|
1614
|
-
|
|
1615
|
-
|
|
1616
|
-
|
|
1617
|
-
|
|
1618
|
-
|
|
1619
|
-
|
|
1620
|
-
|
|
1621
|
-
|
|
1622
|
-
|
|
1623
|
-
|
|
1624
|
-
|
|
1625
|
-
|
|
1626
|
-
zds->
|
|
1627
|
-
|
|
1628
|
-
|
|
1629
|
-
|
|
1630
|
-
|
|
1631
|
-
|
|
1632
|
-
|
|
1633
|
-
|
|
1634
|
-
|
|
2008
|
+
size_t const neededOutBuffSize = zds->outBufferMode == ZSTD_bm_buffered
|
|
2009
|
+
? ZSTD_decodingBufferSize_min(zds->fParams.windowSize, zds->fParams.frameContentSize)
|
|
2010
|
+
: 0;
|
|
2011
|
+
|
|
2012
|
+
ZSTD_DCtx_updateOversizedDuration(zds, neededInBuffSize, neededOutBuffSize);
|
|
2013
|
+
|
|
2014
|
+
{ int const tooSmall = (zds->inBuffSize < neededInBuffSize) || (zds->outBuffSize < neededOutBuffSize);
|
|
2015
|
+
int const tooLarge = ZSTD_DCtx_isOversizedTooLong(zds);
|
|
2016
|
+
|
|
2017
|
+
if (tooSmall || tooLarge) {
|
|
2018
|
+
size_t const bufferSize = neededInBuffSize + neededOutBuffSize;
|
|
2019
|
+
DEBUGLOG(4, "inBuff : from %u to %u",
|
|
2020
|
+
(U32)zds->inBuffSize, (U32)neededInBuffSize);
|
|
2021
|
+
DEBUGLOG(4, "outBuff : from %u to %u",
|
|
2022
|
+
(U32)zds->outBuffSize, (U32)neededOutBuffSize);
|
|
2023
|
+
if (zds->staticSize) { /* static DCtx */
|
|
2024
|
+
DEBUGLOG(4, "staticSize : %u", (U32)zds->staticSize);
|
|
2025
|
+
assert(zds->staticSize >= sizeof(ZSTD_DCtx)); /* controlled at init */
|
|
2026
|
+
RETURN_ERROR_IF(
|
|
2027
|
+
bufferSize > zds->staticSize - sizeof(ZSTD_DCtx),
|
|
2028
|
+
memory_allocation, "");
|
|
2029
|
+
} else {
|
|
2030
|
+
ZSTD_customFree(zds->inBuff, zds->customMem);
|
|
2031
|
+
zds->inBuffSize = 0;
|
|
2032
|
+
zds->outBuffSize = 0;
|
|
2033
|
+
zds->inBuff = (char*)ZSTD_customMalloc(bufferSize, zds->customMem);
|
|
2034
|
+
RETURN_ERROR_IF(zds->inBuff == NULL, memory_allocation, "");
|
|
2035
|
+
}
|
|
2036
|
+
zds->inBuffSize = neededInBuffSize;
|
|
2037
|
+
zds->outBuff = zds->inBuff + zds->inBuffSize;
|
|
2038
|
+
zds->outBuffSize = neededOutBuffSize;
|
|
2039
|
+
} } }
|
|
1635
2040
|
zds->streamStage = zdss_read;
|
|
1636
2041
|
/* fall-through */
|
|
1637
2042
|
|
|
1638
2043
|
case zdss_read:
|
|
1639
2044
|
DEBUGLOG(5, "stage zdss_read");
|
|
1640
|
-
{ size_t const neededInSize =
|
|
2045
|
+
{ size_t const neededInSize = ZSTD_nextSrcSizeToDecompressWithInputSize(zds, (size_t)(iend - ip));
|
|
1641
2046
|
DEBUGLOG(5, "neededInSize = %u", (U32)neededInSize);
|
|
1642
2047
|
if (neededInSize==0) { /* end of frame */
|
|
1643
2048
|
zds->streamStage = zdss_init;
|
|
@@ -1645,15 +2050,9 @@ size_t ZSTD_decompressStream(ZSTD_DStream* zds, ZSTD_outBuffer* output, ZSTD_inB
|
|
|
1645
2050
|
break;
|
|
1646
2051
|
}
|
|
1647
2052
|
if ((size_t)(iend-ip) >= neededInSize) { /* decode directly from src */
|
|
1648
|
-
|
|
1649
|
-
size_t const decodedSize = ZSTD_decompressContinue(zds,
|
|
1650
|
-
zds->outBuff + zds->outStart, (isSkipFrame ? 0 : zds->outBuffSize - zds->outStart),
|
|
1651
|
-
ip, neededInSize);
|
|
1652
|
-
if (ZSTD_isError(decodedSize)) return decodedSize;
|
|
2053
|
+
FORWARD_IF_ERROR(ZSTD_decompressContinueStream(zds, &op, oend, ip, neededInSize), "");
|
|
1653
2054
|
ip += neededInSize;
|
|
1654
|
-
|
|
1655
|
-
zds->outEnd = zds->outStart + decodedSize;
|
|
1656
|
-
zds->streamStage = zdss_flush;
|
|
2055
|
+
/* Function modifies the stage so we must break */
|
|
1657
2056
|
break;
|
|
1658
2057
|
} }
|
|
1659
2058
|
if (ip==iend) { someMoreWork = 0; break; } /* no more input */
|
|
@@ -1665,33 +2064,29 @@ size_t ZSTD_decompressStream(ZSTD_DStream* zds, ZSTD_outBuffer* output, ZSTD_inB
|
|
|
1665
2064
|
size_t const toLoad = neededInSize - zds->inPos;
|
|
1666
2065
|
int const isSkipFrame = ZSTD_isSkipFrame(zds);
|
|
1667
2066
|
size_t loadedSize;
|
|
2067
|
+
/* At this point we shouldn't be decompressing a block that we can stream. */
|
|
2068
|
+
assert(neededInSize == ZSTD_nextSrcSizeToDecompressWithInputSize(zds, iend - ip));
|
|
1668
2069
|
if (isSkipFrame) {
|
|
1669
2070
|
loadedSize = MIN(toLoad, (size_t)(iend-ip));
|
|
1670
2071
|
} else {
|
|
1671
2072
|
RETURN_ERROR_IF(toLoad > zds->inBuffSize - zds->inPos,
|
|
1672
2073
|
corruption_detected,
|
|
1673
2074
|
"should never happen");
|
|
1674
|
-
loadedSize = ZSTD_limitCopy(zds->inBuff + zds->inPos, toLoad, ip, iend-ip);
|
|
2075
|
+
loadedSize = ZSTD_limitCopy(zds->inBuff + zds->inPos, toLoad, ip, (size_t)(iend-ip));
|
|
1675
2076
|
}
|
|
1676
2077
|
ip += loadedSize;
|
|
1677
2078
|
zds->inPos += loadedSize;
|
|
1678
2079
|
if (loadedSize < toLoad) { someMoreWork = 0; break; } /* not enough input, wait for more */
|
|
1679
2080
|
|
|
1680
2081
|
/* decode loaded input */
|
|
1681
|
-
|
|
1682
|
-
|
|
1683
|
-
|
|
1684
|
-
|
|
1685
|
-
|
|
1686
|
-
if (!decodedSize && !isSkipFrame) { zds->streamStage = zdss_read; break; } /* this was just a header */
|
|
1687
|
-
zds->outEnd = zds->outStart + decodedSize;
|
|
1688
|
-
} }
|
|
1689
|
-
zds->streamStage = zdss_flush;
|
|
1690
|
-
/* fall-through */
|
|
1691
|
-
|
|
2082
|
+
zds->inPos = 0; /* input is consumed */
|
|
2083
|
+
FORWARD_IF_ERROR(ZSTD_decompressContinueStream(zds, &op, oend, zds->inBuff, neededInSize), "");
|
|
2084
|
+
/* Function modifies the stage so we must break */
|
|
2085
|
+
break;
|
|
2086
|
+
}
|
|
1692
2087
|
case zdss_flush:
|
|
1693
2088
|
{ size_t const toFlushSize = zds->outEnd - zds->outStart;
|
|
1694
|
-
size_t const flushedSize = ZSTD_limitCopy(op, oend-op, zds->outBuff + zds->outStart, toFlushSize);
|
|
2089
|
+
size_t const flushedSize = ZSTD_limitCopy(op, (size_t)(oend-op), zds->outBuff + zds->outStart, toFlushSize);
|
|
1695
2090
|
op += flushedSize;
|
|
1696
2091
|
zds->outStart += flushedSize;
|
|
1697
2092
|
if (flushedSize == toFlushSize) { /* flush completed */
|
|
@@ -1711,17 +2106,21 @@ size_t ZSTD_decompressStream(ZSTD_DStream* zds, ZSTD_outBuffer* output, ZSTD_inB
|
|
|
1711
2106
|
|
|
1712
2107
|
default:
|
|
1713
2108
|
assert(0); /* impossible */
|
|
1714
|
-
RETURN_ERROR(GENERIC); /* some compiler require default to do something */
|
|
2109
|
+
RETURN_ERROR(GENERIC, "impossible to reach"); /* some compiler require default to do something */
|
|
1715
2110
|
} }
|
|
1716
2111
|
|
|
1717
2112
|
/* result */
|
|
1718
2113
|
input->pos = (size_t)(ip - (const char*)(input->src));
|
|
1719
2114
|
output->pos = (size_t)(op - (char*)(output->dst));
|
|
2115
|
+
|
|
2116
|
+
/* Update the expected output buffer for ZSTD_obm_stable. */
|
|
2117
|
+
zds->expectedOutBuffer = *output;
|
|
2118
|
+
|
|
1720
2119
|
if ((ip==istart) && (op==ostart)) { /* no forward progress */
|
|
1721
2120
|
zds->noForwardProgress ++;
|
|
1722
2121
|
if (zds->noForwardProgress >= ZSTD_NO_FORWARD_PROGRESS_MAX) {
|
|
1723
|
-
RETURN_ERROR_IF(op==oend, dstSize_tooSmall);
|
|
1724
|
-
RETURN_ERROR_IF(ip==iend, srcSize_wrong);
|
|
2122
|
+
RETURN_ERROR_IF(op==oend, dstSize_tooSmall, "");
|
|
2123
|
+
RETURN_ERROR_IF(ip==iend, srcSize_wrong, "");
|
|
1725
2124
|
assert(0);
|
|
1726
2125
|
}
|
|
1727
2126
|
} else {
|