zstdlib 0.3.0-x86-mingw32 → 0.8.0-x86-mingw32
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/CHANGES.md +30 -1
- data/README.md +2 -2
- data/Rakefile +1 -1
- data/ext/zstdlib/extconf.rb +3 -3
- data/ext/zstdlib/ruby/zlib-2.7/zstdlib.c +4895 -0
- data/ext/zstdlib/ruby/zlib-3.0/zstdlib.c +4994 -0
- data/ext/zstdlib/{zstd-1.4.2 → zstd-1.5.0}/lib/common/bitstream.h +59 -51
- data/ext/zstdlib/zstd-1.5.0/lib/common/compiler.h +289 -0
- data/ext/zstdlib/{zstd-1.4.2 → zstd-1.5.0}/lib/common/cpu.h +1 -3
- data/ext/zstdlib/zstd-1.5.0/lib/common/debug.c +24 -0
- data/ext/zstdlib/{zstd-1.4.2 → zstd-1.5.0}/lib/common/debug.h +22 -49
- data/ext/zstdlib/zstd-1.5.0/lib/common/entropy_common.c +362 -0
- data/ext/zstdlib/{zstd-1.4.2 → zstd-1.5.0}/lib/common/error_private.c +3 -1
- data/ext/zstdlib/{zstd-1.4.2 → zstd-1.5.0}/lib/common/error_private.h +8 -4
- data/ext/zstdlib/{zstd-1.4.2 → zstd-1.5.0}/lib/common/fse.h +50 -42
- data/ext/zstdlib/{zstd-1.4.2 → zstd-1.5.0}/lib/common/fse_decompress.c +149 -55
- data/ext/zstdlib/{zstd-1.4.2 → zstd-1.5.0}/lib/common/huf.h +43 -39
- data/ext/zstdlib/{zstd-1.4.2 → zstd-1.5.0}/lib/common/mem.h +69 -25
- data/ext/zstdlib/{zstd-1.4.2 → zstd-1.5.0}/lib/common/pool.c +30 -20
- data/ext/zstdlib/{zstd-1.4.2 → zstd-1.5.0}/lib/common/pool.h +3 -3
- data/ext/zstdlib/{zstd-1.4.2 → zstd-1.5.0}/lib/common/threading.c +51 -4
- data/ext/zstdlib/{zstd-1.4.2 → zstd-1.5.0}/lib/common/threading.h +36 -4
- data/ext/zstdlib/{zstd-1.4.2 → zstd-1.5.0}/lib/common/xxhash.c +40 -92
- data/ext/zstdlib/{zstd-1.4.2 → zstd-1.5.0}/lib/common/xxhash.h +12 -32
- data/ext/zstdlib/{zstd-1.4.2 → zstd-1.5.0}/lib/common/zstd_common.c +10 -10
- data/ext/zstdlib/zstd-1.5.0/lib/common/zstd_deps.h +111 -0
- data/ext/zstdlib/zstd-1.5.0/lib/common/zstd_internal.h +490 -0
- data/ext/zstdlib/zstd-1.5.0/lib/common/zstd_trace.h +154 -0
- data/ext/zstdlib/{zstd-1.4.2 → zstd-1.5.0}/lib/compress/fse_compress.c +47 -63
- data/ext/zstdlib/{zstd-1.4.2 → zstd-1.5.0}/lib/compress/hist.c +41 -63
- data/ext/zstdlib/{zstd-1.4.2 → zstd-1.5.0}/lib/compress/hist.h +13 -33
- data/ext/zstdlib/{zstd-1.4.2 → zstd-1.5.0}/lib/compress/huf_compress.c +332 -193
- data/ext/zstdlib/zstd-1.5.0/lib/compress/zstd_compress.c +6393 -0
- data/ext/zstdlib/{zstd-1.4.2 → zstd-1.5.0}/lib/compress/zstd_compress_internal.h +522 -86
- data/ext/zstdlib/{zstd-1.4.2 → zstd-1.5.0}/lib/compress/zstd_compress_literals.c +25 -16
- data/ext/zstdlib/{zstd-1.4.2 → zstd-1.5.0}/lib/compress/zstd_compress_literals.h +2 -2
- data/ext/zstdlib/{zstd-1.4.2 → zstd-1.5.0}/lib/compress/zstd_compress_sequences.c +50 -24
- data/ext/zstdlib/{zstd-1.4.2 → zstd-1.5.0}/lib/compress/zstd_compress_sequences.h +11 -4
- data/ext/zstdlib/zstd-1.5.0/lib/compress/zstd_compress_superblock.c +572 -0
- data/ext/zstdlib/zstd-1.5.0/lib/compress/zstd_compress_superblock.h +32 -0
- data/ext/zstdlib/zstd-1.5.0/lib/compress/zstd_cwksp.h +662 -0
- data/ext/zstdlib/{zstd-1.4.2 → zstd-1.5.0}/lib/compress/zstd_double_fast.c +43 -41
- data/ext/zstdlib/{zstd-1.4.2 → zstd-1.5.0}/lib/compress/zstd_double_fast.h +2 -2
- data/ext/zstdlib/{zstd-1.4.2 → zstd-1.5.0}/lib/compress/zstd_fast.c +85 -80
- data/ext/zstdlib/{zstd-1.4.2 → zstd-1.5.0}/lib/compress/zstd_fast.h +2 -2
- data/ext/zstdlib/zstd-1.5.0/lib/compress/zstd_lazy.c +2184 -0
- data/ext/zstdlib/zstd-1.5.0/lib/compress/zstd_lazy.h +125 -0
- data/ext/zstdlib/{zstd-1.4.2 → zstd-1.5.0}/lib/compress/zstd_ldm.c +333 -208
- data/ext/zstdlib/{zstd-1.4.2 → zstd-1.5.0}/lib/compress/zstd_ldm.h +15 -3
- data/ext/zstdlib/zstd-1.5.0/lib/compress/zstd_ldm_geartab.h +103 -0
- data/ext/zstdlib/{zstd-1.4.2 → zstd-1.5.0}/lib/compress/zstd_opt.c +228 -129
- data/ext/zstdlib/{zstd-1.4.2 → zstd-1.5.0}/lib/compress/zstd_opt.h +1 -1
- data/ext/zstdlib/{zstd-1.4.2 → zstd-1.5.0}/lib/compress/zstdmt_compress.c +151 -440
- data/ext/zstdlib/zstd-1.5.0/lib/compress/zstdmt_compress.h +110 -0
- data/ext/zstdlib/{zstd-1.4.2 → zstd-1.5.0}/lib/decompress/huf_decompress.c +395 -276
- data/ext/zstdlib/{zstd-1.4.2 → zstd-1.5.0}/lib/decompress/zstd_ddict.c +20 -16
- data/ext/zstdlib/{zstd-1.4.2 → zstd-1.5.0}/lib/decompress/zstd_ddict.h +3 -3
- data/ext/zstdlib/{zstd-1.4.2 → zstd-1.5.0}/lib/decompress/zstd_decompress.c +628 -231
- data/ext/zstdlib/{zstd-1.4.2 → zstd-1.5.0}/lib/decompress/zstd_decompress_block.c +606 -380
- data/ext/zstdlib/{zstd-1.4.2 → zstd-1.5.0}/lib/decompress/zstd_decompress_block.h +8 -5
- data/ext/zstdlib/{zstd-1.4.2 → zstd-1.5.0}/lib/decompress/zstd_decompress_internal.h +39 -9
- data/ext/zstdlib/zstd-1.5.0/lib/zdict.h +452 -0
- data/ext/zstdlib/{zstd-1.4.2 → zstd-1.5.0}/lib/zstd.h +740 -153
- data/ext/zstdlib/{zstd-1.4.2/lib/common → zstd-1.5.0/lib}/zstd_errors.h +3 -1
- data/ext/zstdlib/{zstd-1.4.2 → zstd-1.5.0}/zlibWrapper/gzclose.c +1 -1
- data/ext/zstdlib/{zstd-1.4.2 → zstd-1.5.0}/zlibWrapper/gzcompatibility.h +1 -1
- data/ext/zstdlib/{zstd-1.4.2 → zstd-1.5.0}/zlibWrapper/gzguts.h +0 -0
- data/ext/zstdlib/{zstd-1.4.2 → zstd-1.5.0}/zlibWrapper/gzlib.c +9 -9
- data/ext/zstdlib/{zstd-1.4.2 → zstd-1.5.0}/zlibWrapper/gzread.c +16 -8
- data/ext/zstdlib/{zstd-1.4.2 → zstd-1.5.0}/zlibWrapper/gzwrite.c +8 -8
- data/ext/zstdlib/{zstd-1.4.2 → zstd-1.5.0}/zlibWrapper/zstd_zlibwrapper.c +131 -45
- data/ext/zstdlib/{zstd-1.4.2 → zstd-1.5.0}/zlibWrapper/zstd_zlibwrapper.h +1 -1
- data/lib/2.2/zstdlib.so +0 -0
- data/lib/2.3/zstdlib.so +0 -0
- data/lib/2.4/zstdlib.so +0 -0
- data/lib/2.5/zstdlib.so +0 -0
- data/lib/2.6/zstdlib.so +0 -0
- data/lib/2.7/zstdlib.so +0 -0
- metadata +76 -67
- data/ext/zstdlib/zstd-1.4.2/lib/common/compiler.h +0 -147
- data/ext/zstdlib/zstd-1.4.2/lib/common/debug.c +0 -44
- data/ext/zstdlib/zstd-1.4.2/lib/common/entropy_common.c +0 -236
- data/ext/zstdlib/zstd-1.4.2/lib/common/zstd_internal.h +0 -371
- data/ext/zstdlib/zstd-1.4.2/lib/compress/zstd_compress.c +0 -3904
- data/ext/zstdlib/zstd-1.4.2/lib/compress/zstd_lazy.c +0 -1111
- data/ext/zstdlib/zstd-1.4.2/lib/compress/zstd_lazy.h +0 -67
- data/ext/zstdlib/zstd-1.4.2/lib/compress/zstdmt_compress.h +0 -192
@@ -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;
|
@@ -942,50 +1169,66 @@ size_t ZSTD_decompressContinue(ZSTD_DCtx* dctx, void* dst, size_t dstCapacity, c
|
|
942
1169
|
case bt_compressed:
|
943
1170
|
DEBUGLOG(5, "ZSTD_decompressContinue: case bt_compressed");
|
944
1171
|
rSize = ZSTD_decompressBlock_internal(dctx, dst, dstCapacity, src, srcSize, /* frame */ 1);
|
1172
|
+
dctx->expected = 0; /* Streaming not supported */
|
945
1173
|
break;
|
946
1174
|
case bt_raw :
|
1175
|
+
assert(srcSize <= dctx->expected);
|
947
1176
|
rSize = ZSTD_copyRawBlock(dst, dstCapacity, src, srcSize);
|
1177
|
+
FORWARD_IF_ERROR(rSize, "ZSTD_copyRawBlock failed");
|
1178
|
+
assert(rSize == srcSize);
|
1179
|
+
dctx->expected -= rSize;
|
948
1180
|
break;
|
949
1181
|
case bt_rle :
|
950
1182
|
rSize = ZSTD_setRleBlock(dst, dstCapacity, *(const BYTE*)src, dctx->rleSize);
|
1183
|
+
dctx->expected = 0; /* Streaming not supported */
|
951
1184
|
break;
|
952
1185
|
case bt_reserved : /* should never happen */
|
953
1186
|
default:
|
954
|
-
RETURN_ERROR(corruption_detected);
|
1187
|
+
RETURN_ERROR(corruption_detected, "invalid block type");
|
955
1188
|
}
|
956
|
-
|
1189
|
+
FORWARD_IF_ERROR(rSize, "");
|
957
1190
|
RETURN_ERROR_IF(rSize > dctx->fParams.blockSizeMax, corruption_detected, "Decompressed Block Size Exceeds Maximum");
|
958
1191
|
DEBUGLOG(5, "ZSTD_decompressContinue: decoded size from block : %u", (unsigned)rSize);
|
959
1192
|
dctx->decodedSize += rSize;
|
960
|
-
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
|
+
}
|
961
1200
|
|
962
1201
|
if (dctx->stage == ZSTDds_decompressLastBlock) { /* end of frame */
|
963
1202
|
DEBUGLOG(4, "ZSTD_decompressContinue: decoded size from frame : %u", (unsigned)dctx->decodedSize);
|
964
1203
|
RETURN_ERROR_IF(
|
965
1204
|
dctx->fParams.frameContentSize != ZSTD_CONTENTSIZE_UNKNOWN
|
966
1205
|
&& dctx->decodedSize != dctx->fParams.frameContentSize,
|
967
|
-
corruption_detected);
|
1206
|
+
corruption_detected, "");
|
968
1207
|
if (dctx->fParams.checksumFlag) { /* another round for frame checksum */
|
969
1208
|
dctx->expected = 4;
|
970
1209
|
dctx->stage = ZSTDds_checkChecksum;
|
971
1210
|
} else {
|
1211
|
+
ZSTD_DCtx_trace_end(dctx, dctx->decodedSize, dctx->processedCSize, /* streaming */ 1);
|
972
1212
|
dctx->expected = 0; /* ends here */
|
973
1213
|
dctx->stage = ZSTDds_getFrameHeaderSize;
|
974
1214
|
}
|
975
1215
|
} else {
|
976
1216
|
dctx->stage = ZSTDds_decodeBlockHeader;
|
977
1217
|
dctx->expected = ZSTD_blockHeaderSize;
|
978
|
-
dctx->previousDstEnd = (char*)dst + rSize;
|
979
1218
|
}
|
980
1219
|
return rSize;
|
981
1220
|
}
|
982
1221
|
|
983
1222
|
case ZSTDds_checkChecksum:
|
984
1223
|
assert(srcSize == 4); /* guaranteed by dctx->expected */
|
985
|
-
{
|
986
|
-
|
987
|
-
|
988
|
-
|
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);
|
989
1232
|
dctx->expected = 0;
|
990
1233
|
dctx->stage = ZSTDds_getFrameHeaderSize;
|
991
1234
|
return 0;
|
@@ -994,7 +1237,7 @@ size_t ZSTD_decompressContinue(ZSTD_DCtx* dctx, void* dst, size_t dstCapacity, c
|
|
994
1237
|
case ZSTDds_decodeSkippableHeader:
|
995
1238
|
assert(src != NULL);
|
996
1239
|
assert(srcSize <= ZSTD_SKIPPABLEHEADERSIZE);
|
997
|
-
|
1240
|
+
ZSTD_memcpy(dctx->headerBuffer + (ZSTD_SKIPPABLEHEADERSIZE - srcSize), src, srcSize); /* complete skippable header */
|
998
1241
|
dctx->expected = MEM_readLE32(dctx->headerBuffer + ZSTD_FRAMEIDSIZE); /* note : dctx->expected can grow seriously large, beyond local buffer size */
|
999
1242
|
dctx->stage = ZSTDds_skipFrame;
|
1000
1243
|
return 0;
|
@@ -1006,7 +1249,7 @@ size_t ZSTD_decompressContinue(ZSTD_DCtx* dctx, void* dst, size_t dstCapacity, c
|
|
1006
1249
|
|
1007
1250
|
default:
|
1008
1251
|
assert(0); /* impossible */
|
1009
|
-
RETURN_ERROR(GENERIC); /* some compiler require default to do something */
|
1252
|
+
RETURN_ERROR(GENERIC, "impossible to reach"); /* some compiler require default to do something */
|
1010
1253
|
}
|
1011
1254
|
}
|
1012
1255
|
|
@@ -1017,6 +1260,10 @@ static size_t ZSTD_refDictContent(ZSTD_DCtx* dctx, const void* dict, size_t dict
|
|
1017
1260
|
dctx->virtualStart = (const char*)dict - ((const char*)(dctx->previousDstEnd) - (const char*)(dctx->prefixStart));
|
1018
1261
|
dctx->prefixStart = dict;
|
1019
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
|
1020
1267
|
return 0;
|
1021
1268
|
}
|
1022
1269
|
|
@@ -1030,7 +1277,7 @@ ZSTD_loadDEntropy(ZSTD_entropyDTables_t* entropy,
|
|
1030
1277
|
const BYTE* dictPtr = (const BYTE*)dict;
|
1031
1278
|
const BYTE* const dictEnd = dictPtr + dictSize;
|
1032
1279
|
|
1033
|
-
RETURN_ERROR_IF(dictSize <= 8, dictionary_corrupted);
|
1280
|
+
RETURN_ERROR_IF(dictSize <= 8, dictionary_corrupted, "dict is too small");
|
1034
1281
|
assert(MEM_readLE32(dict) == ZSTD_MAGIC_DICTIONARY); /* dict must be valid */
|
1035
1282
|
dictPtr += 8; /* skip header = magic + dictID */
|
1036
1283
|
|
@@ -1046,63 +1293,69 @@ ZSTD_loadDEntropy(ZSTD_entropyDTables_t* entropy,
|
|
1046
1293
|
workspace, workspaceSize);
|
1047
1294
|
#else
|
1048
1295
|
size_t const hSize = HUF_readDTableX2_wksp(entropy->hufTable,
|
1049
|
-
dictPtr, dictEnd - dictPtr,
|
1296
|
+
dictPtr, (size_t)(dictEnd - dictPtr),
|
1050
1297
|
workspace, workspaceSize);
|
1051
1298
|
#endif
|
1052
|
-
RETURN_ERROR_IF(HUF_isError(hSize), dictionary_corrupted);
|
1299
|
+
RETURN_ERROR_IF(HUF_isError(hSize), dictionary_corrupted, "");
|
1053
1300
|
dictPtr += hSize;
|
1054
1301
|
}
|
1055
1302
|
|
1056
1303
|
{ short offcodeNCount[MaxOff+1];
|
1057
1304
|
unsigned offcodeMaxValue = MaxOff, offcodeLog;
|
1058
|
-
size_t const offcodeHeaderSize = FSE_readNCount(offcodeNCount, &offcodeMaxValue, &offcodeLog, dictPtr, dictEnd-dictPtr);
|
1059
|
-
RETURN_ERROR_IF(FSE_isError(offcodeHeaderSize), dictionary_corrupted);
|
1060
|
-
RETURN_ERROR_IF(offcodeMaxValue > MaxOff, dictionary_corrupted);
|
1061
|
-
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, "");
|
1062
1309
|
ZSTD_buildFSETable( entropy->OFTable,
|
1063
1310
|
offcodeNCount, offcodeMaxValue,
|
1064
1311
|
OF_base, OF_bits,
|
1065
|
-
offcodeLog
|
1312
|
+
offcodeLog,
|
1313
|
+
entropy->workspace, sizeof(entropy->workspace),
|
1314
|
+
/* bmi2 */0);
|
1066
1315
|
dictPtr += offcodeHeaderSize;
|
1067
1316
|
}
|
1068
1317
|
|
1069
1318
|
{ short matchlengthNCount[MaxML+1];
|
1070
1319
|
unsigned matchlengthMaxValue = MaxML, matchlengthLog;
|
1071
|
-
size_t const matchlengthHeaderSize = FSE_readNCount(matchlengthNCount, &matchlengthMaxValue, &matchlengthLog, dictPtr, dictEnd-dictPtr);
|
1072
|
-
RETURN_ERROR_IF(FSE_isError(matchlengthHeaderSize), dictionary_corrupted);
|
1073
|
-
RETURN_ERROR_IF(matchlengthMaxValue > MaxML, dictionary_corrupted);
|
1074
|
-
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, "");
|
1075
1324
|
ZSTD_buildFSETable( entropy->MLTable,
|
1076
1325
|
matchlengthNCount, matchlengthMaxValue,
|
1077
1326
|
ML_base, ML_bits,
|
1078
|
-
matchlengthLog
|
1327
|
+
matchlengthLog,
|
1328
|
+
entropy->workspace, sizeof(entropy->workspace),
|
1329
|
+
/* bmi2 */ 0);
|
1079
1330
|
dictPtr += matchlengthHeaderSize;
|
1080
1331
|
}
|
1081
1332
|
|
1082
1333
|
{ short litlengthNCount[MaxLL+1];
|
1083
1334
|
unsigned litlengthMaxValue = MaxLL, litlengthLog;
|
1084
|
-
size_t const litlengthHeaderSize = FSE_readNCount(litlengthNCount, &litlengthMaxValue, &litlengthLog, dictPtr, dictEnd-dictPtr);
|
1085
|
-
RETURN_ERROR_IF(FSE_isError(litlengthHeaderSize), dictionary_corrupted);
|
1086
|
-
RETURN_ERROR_IF(litlengthMaxValue > MaxLL, dictionary_corrupted);
|
1087
|
-
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, "");
|
1088
1339
|
ZSTD_buildFSETable( entropy->LLTable,
|
1089
1340
|
litlengthNCount, litlengthMaxValue,
|
1090
1341
|
LL_base, LL_bits,
|
1091
|
-
litlengthLog
|
1342
|
+
litlengthLog,
|
1343
|
+
entropy->workspace, sizeof(entropy->workspace),
|
1344
|
+
/* bmi2 */ 0);
|
1092
1345
|
dictPtr += litlengthHeaderSize;
|
1093
1346
|
}
|
1094
1347
|
|
1095
|
-
RETURN_ERROR_IF(dictPtr+12 > dictEnd, dictionary_corrupted);
|
1348
|
+
RETURN_ERROR_IF(dictPtr+12 > dictEnd, dictionary_corrupted, "");
|
1096
1349
|
{ int i;
|
1097
1350
|
size_t const dictContentSize = (size_t)(dictEnd - (dictPtr+12));
|
1098
1351
|
for (i=0; i<3; i++) {
|
1099
1352
|
U32 const rep = MEM_readLE32(dictPtr); dictPtr += 4;
|
1100
|
-
RETURN_ERROR_IF(rep==0 || rep
|
1101
|
-
dictionary_corrupted);
|
1353
|
+
RETURN_ERROR_IF(rep==0 || rep > dictContentSize,
|
1354
|
+
dictionary_corrupted, "");
|
1102
1355
|
entropy->rep[i] = rep;
|
1103
1356
|
} }
|
1104
1357
|
|
1105
|
-
return dictPtr - (const BYTE*)dict;
|
1358
|
+
return (size_t)(dictPtr - (const BYTE*)dict);
|
1106
1359
|
}
|
1107
1360
|
|
1108
1361
|
static size_t ZSTD_decompress_insertDictionary(ZSTD_DCtx* dctx, const void* dict, size_t dictSize)
|
@@ -1116,7 +1369,7 @@ static size_t ZSTD_decompress_insertDictionary(ZSTD_DCtx* dctx, const void* dict
|
|
1116
1369
|
|
1117
1370
|
/* load entropy tables */
|
1118
1371
|
{ size_t const eSize = ZSTD_loadDEntropy(&dctx->entropy, dict, dictSize);
|
1119
|
-
RETURN_ERROR_IF(ZSTD_isError(eSize), dictionary_corrupted);
|
1372
|
+
RETURN_ERROR_IF(ZSTD_isError(eSize), dictionary_corrupted, "");
|
1120
1373
|
dict = (const char*)dict + eSize;
|
1121
1374
|
dictSize -= eSize;
|
1122
1375
|
}
|
@@ -1129,8 +1382,12 @@ static size_t ZSTD_decompress_insertDictionary(ZSTD_DCtx* dctx, const void* dict
|
|
1129
1382
|
size_t ZSTD_decompressBegin(ZSTD_DCtx* dctx)
|
1130
1383
|
{
|
1131
1384
|
assert(dctx != NULL);
|
1385
|
+
#if ZSTD_TRACE
|
1386
|
+
dctx->traceCtx = (ZSTD_trace_decompress_begin != NULL) ? ZSTD_trace_decompress_begin(dctx) : 0;
|
1387
|
+
#endif
|
1132
1388
|
dctx->expected = ZSTD_startingInputLength(dctx->format); /* dctx->format must be properly set */
|
1133
1389
|
dctx->stage = ZSTDds_getFrameHeaderSize;
|
1390
|
+
dctx->processedCSize = 0;
|
1134
1391
|
dctx->decodedSize = 0;
|
1135
1392
|
dctx->previousDstEnd = NULL;
|
1136
1393
|
dctx->prefixStart = NULL;
|
@@ -1139,8 +1396,9 @@ size_t ZSTD_decompressBegin(ZSTD_DCtx* dctx)
|
|
1139
1396
|
dctx->entropy.hufTable[0] = (HUF_DTable)((HufLog)*0x1000001); /* cover both little and big endian */
|
1140
1397
|
dctx->litEntropy = dctx->fseEntropy = 0;
|
1141
1398
|
dctx->dictID = 0;
|
1399
|
+
dctx->bType = bt_reserved;
|
1142
1400
|
ZSTD_STATIC_ASSERT(sizeof(dctx->entropy.rep) == sizeof(repStartValue));
|
1143
|
-
|
1401
|
+
ZSTD_memcpy(dctx->entropy.rep, repStartValue, sizeof(repStartValue)); /* initial repcodes */
|
1144
1402
|
dctx->LLTptr = dctx->entropy.LLTable;
|
1145
1403
|
dctx->MLTptr = dctx->entropy.MLTable;
|
1146
1404
|
dctx->OFTptr = dctx->entropy.OFTable;
|
@@ -1150,11 +1408,11 @@ size_t ZSTD_decompressBegin(ZSTD_DCtx* dctx)
|
|
1150
1408
|
|
1151
1409
|
size_t ZSTD_decompressBegin_usingDict(ZSTD_DCtx* dctx, const void* dict, size_t dictSize)
|
1152
1410
|
{
|
1153
|
-
FORWARD_IF_ERROR( ZSTD_decompressBegin(dctx) );
|
1411
|
+
FORWARD_IF_ERROR( ZSTD_decompressBegin(dctx) , "");
|
1154
1412
|
if (dict && dictSize)
|
1155
1413
|
RETURN_ERROR_IF(
|
1156
1414
|
ZSTD_isError(ZSTD_decompress_insertDictionary(dctx, dict, dictSize)),
|
1157
|
-
dictionary_corrupted);
|
1415
|
+
dictionary_corrupted, "");
|
1158
1416
|
return 0;
|
1159
1417
|
}
|
1160
1418
|
|
@@ -1173,7 +1431,7 @@ size_t ZSTD_decompressBegin_usingDDict(ZSTD_DCtx* dctx, const ZSTD_DDict* ddict)
|
|
1173
1431
|
DEBUGLOG(4, "DDict is %s",
|
1174
1432
|
dctx->ddictIsCold ? "~cold~" : "hot!");
|
1175
1433
|
}
|
1176
|
-
FORWARD_IF_ERROR( ZSTD_decompressBegin(dctx) );
|
1434
|
+
FORWARD_IF_ERROR( ZSTD_decompressBegin(dctx) , "");
|
1177
1435
|
if (ddict) { /* NULL ddict is equivalent to no dictionary */
|
1178
1436
|
ZSTD_copyDDictParameters(dctx, ddict);
|
1179
1437
|
}
|
@@ -1264,11 +1522,11 @@ size_t ZSTD_DCtx_loadDictionary_advanced(ZSTD_DCtx* dctx,
|
|
1264
1522
|
ZSTD_dictLoadMethod_e dictLoadMethod,
|
1265
1523
|
ZSTD_dictContentType_e dictContentType)
|
1266
1524
|
{
|
1267
|
-
RETURN_ERROR_IF(dctx->streamStage != zdss_init, stage_wrong);
|
1525
|
+
RETURN_ERROR_IF(dctx->streamStage != zdss_init, stage_wrong, "");
|
1268
1526
|
ZSTD_clearDict(dctx);
|
1269
|
-
if (dict && dictSize
|
1527
|
+
if (dict && dictSize != 0) {
|
1270
1528
|
dctx->ddictLocal = ZSTD_createDDict_advanced(dict, dictSize, dictLoadMethod, dictContentType, dctx->customMem);
|
1271
|
-
RETURN_ERROR_IF(dctx->ddictLocal == NULL, memory_allocation);
|
1529
|
+
RETURN_ERROR_IF(dctx->ddictLocal == NULL, memory_allocation, "NULL pointer!");
|
1272
1530
|
dctx->ddict = dctx->ddictLocal;
|
1273
1531
|
dctx->dictUses = ZSTD_use_indefinitely;
|
1274
1532
|
}
|
@@ -1287,7 +1545,7 @@ size_t ZSTD_DCtx_loadDictionary(ZSTD_DCtx* dctx, const void* dict, size_t dictSi
|
|
1287
1545
|
|
1288
1546
|
size_t ZSTD_DCtx_refPrefix_advanced(ZSTD_DCtx* dctx, const void* prefix, size_t prefixSize, ZSTD_dictContentType_e dictContentType)
|
1289
1547
|
{
|
1290
|
-
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), "");
|
1291
1549
|
dctx->dictUses = ZSTD_use_once;
|
1292
1550
|
return 0;
|
1293
1551
|
}
|
@@ -1299,14 +1557,14 @@ size_t ZSTD_DCtx_refPrefix(ZSTD_DCtx* dctx, const void* prefix, size_t prefixSiz
|
|
1299
1557
|
|
1300
1558
|
|
1301
1559
|
/* ZSTD_initDStream_usingDict() :
|
1302
|
-
* return : expected size, aka
|
1560
|
+
* return : expected size, aka ZSTD_startingInputLength().
|
1303
1561
|
* this function cannot fail */
|
1304
1562
|
size_t ZSTD_initDStream_usingDict(ZSTD_DStream* zds, const void* dict, size_t dictSize)
|
1305
1563
|
{
|
1306
1564
|
DEBUGLOG(4, "ZSTD_initDStream_usingDict");
|
1307
|
-
FORWARD_IF_ERROR( ZSTD_DCtx_reset(zds, ZSTD_reset_session_only) );
|
1308
|
-
FORWARD_IF_ERROR( ZSTD_DCtx_loadDictionary(zds, dict, dictSize) );
|
1309
|
-
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);
|
1310
1568
|
}
|
1311
1569
|
|
1312
1570
|
/* note : this variant can't fail */
|
@@ -1321,28 +1579,38 @@ size_t ZSTD_initDStream(ZSTD_DStream* zds)
|
|
1321
1579
|
* this function cannot fail */
|
1322
1580
|
size_t ZSTD_initDStream_usingDDict(ZSTD_DStream* dctx, const ZSTD_DDict* ddict)
|
1323
1581
|
{
|
1324
|
-
FORWARD_IF_ERROR( ZSTD_DCtx_reset(dctx, ZSTD_reset_session_only) );
|
1325
|
-
FORWARD_IF_ERROR( ZSTD_DCtx_refDDict(dctx, ddict) );
|
1326
|
-
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);
|
1327
1585
|
}
|
1328
1586
|
|
1329
1587
|
/* ZSTD_resetDStream() :
|
1330
|
-
* return : expected size, aka
|
1588
|
+
* return : expected size, aka ZSTD_startingInputLength().
|
1331
1589
|
* this function cannot fail */
|
1332
1590
|
size_t ZSTD_resetDStream(ZSTD_DStream* dctx)
|
1333
1591
|
{
|
1334
|
-
FORWARD_IF_ERROR(ZSTD_DCtx_reset(dctx, ZSTD_reset_session_only));
|
1335
|
-
return
|
1592
|
+
FORWARD_IF_ERROR(ZSTD_DCtx_reset(dctx, ZSTD_reset_session_only), "");
|
1593
|
+
return ZSTD_startingInputLength(dctx->format);
|
1336
1594
|
}
|
1337
1595
|
|
1338
1596
|
|
1339
1597
|
size_t ZSTD_DCtx_refDDict(ZSTD_DCtx* dctx, const ZSTD_DDict* ddict)
|
1340
1598
|
{
|
1341
|
-
RETURN_ERROR_IF(dctx->streamStage != zdss_init, stage_wrong);
|
1599
|
+
RETURN_ERROR_IF(dctx->streamStage != zdss_init, stage_wrong, "");
|
1342
1600
|
ZSTD_clearDict(dctx);
|
1343
1601
|
if (ddict) {
|
1344
1602
|
dctx->ddict = ddict;
|
1345
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
|
+
}
|
1346
1614
|
}
|
1347
1615
|
return 0;
|
1348
1616
|
}
|
@@ -1355,16 +1623,16 @@ size_t ZSTD_DCtx_setMaxWindowSize(ZSTD_DCtx* dctx, size_t maxWindowSize)
|
|
1355
1623
|
ZSTD_bounds const bounds = ZSTD_dParam_getBounds(ZSTD_d_windowLogMax);
|
1356
1624
|
size_t const min = (size_t)1 << bounds.lowerBound;
|
1357
1625
|
size_t const max = (size_t)1 << bounds.upperBound;
|
1358
|
-
RETURN_ERROR_IF(dctx->streamStage != zdss_init, stage_wrong);
|
1359
|
-
RETURN_ERROR_IF(maxWindowSize < min, parameter_outOfBound);
|
1360
|
-
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, "");
|
1361
1629
|
dctx->maxWindowSize = maxWindowSize;
|
1362
1630
|
return 0;
|
1363
1631
|
}
|
1364
1632
|
|
1365
1633
|
size_t ZSTD_DCtx_setFormat(ZSTD_DCtx* dctx, ZSTD_format_e format)
|
1366
1634
|
{
|
1367
|
-
return ZSTD_DCtx_setParameter(dctx, ZSTD_d_format, format);
|
1635
|
+
return ZSTD_DCtx_setParameter(dctx, ZSTD_d_format, (int)format);
|
1368
1636
|
}
|
1369
1637
|
|
1370
1638
|
ZSTD_bounds ZSTD_dParam_getBounds(ZSTD_dParameter dParam)
|
@@ -1380,6 +1648,18 @@ ZSTD_bounds ZSTD_dParam_getBounds(ZSTD_dParameter dParam)
|
|
1380
1648
|
bounds.upperBound = (int)ZSTD_f_zstd1_magicless;
|
1381
1649
|
ZSTD_STATIC_ASSERT(ZSTD_f_zstd1 < ZSTD_f_zstd1_magicless);
|
1382
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;
|
1383
1663
|
default:;
|
1384
1664
|
}
|
1385
1665
|
bounds.error = ERROR(parameter_unsupported);
|
@@ -1399,12 +1679,35 @@ static int ZSTD_dParam_withinBounds(ZSTD_dParameter dParam, int value)
|
|
1399
1679
|
}
|
1400
1680
|
|
1401
1681
|
#define CHECK_DBOUNDS(p,v) { \
|
1402
|
-
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, "");
|
1403
1706
|
}
|
1404
1707
|
|
1405
1708
|
size_t ZSTD_DCtx_setParameter(ZSTD_DCtx* dctx, ZSTD_dParameter dParam, int value)
|
1406
1709
|
{
|
1407
|
-
RETURN_ERROR_IF(dctx->streamStage != zdss_init, stage_wrong);
|
1710
|
+
RETURN_ERROR_IF(dctx->streamStage != zdss_init, stage_wrong, "");
|
1408
1711
|
switch(dParam) {
|
1409
1712
|
case ZSTD_d_windowLogMax:
|
1410
1713
|
if (value == 0) value = ZSTD_WINDOWLOG_LIMIT_DEFAULT;
|
@@ -1415,9 +1718,24 @@ size_t ZSTD_DCtx_setParameter(ZSTD_DCtx* dctx, ZSTD_dParameter dParam, int value
|
|
1415
1718
|
CHECK_DBOUNDS(ZSTD_d_format, value);
|
1416
1719
|
dctx->format = (ZSTD_format_e)value;
|
1417
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;
|
1418
1736
|
default:;
|
1419
1737
|
}
|
1420
|
-
RETURN_ERROR(parameter_unsupported);
|
1738
|
+
RETURN_ERROR(parameter_unsupported, "");
|
1421
1739
|
}
|
1422
1740
|
|
1423
1741
|
size_t ZSTD_DCtx_reset(ZSTD_DCtx* dctx, ZSTD_ResetDirective reset)
|
@@ -1429,10 +1747,9 @@ size_t ZSTD_DCtx_reset(ZSTD_DCtx* dctx, ZSTD_ResetDirective reset)
|
|
1429
1747
|
}
|
1430
1748
|
if ( (reset == ZSTD_reset_parameters)
|
1431
1749
|
|| (reset == ZSTD_reset_session_and_parameters) ) {
|
1432
|
-
RETURN_ERROR_IF(dctx->streamStage != zdss_init, stage_wrong);
|
1750
|
+
RETURN_ERROR_IF(dctx->streamStage != zdss_init, stage_wrong, "");
|
1433
1751
|
ZSTD_clearDict(dctx);
|
1434
|
-
dctx
|
1435
|
-
dctx->maxWindowSize = ZSTD_MAXWINDOWSIZE_DEFAULT;
|
1752
|
+
ZSTD_DCtx_resetParameters(dctx);
|
1436
1753
|
}
|
1437
1754
|
return 0;
|
1438
1755
|
}
|
@@ -1450,7 +1767,7 @@ size_t ZSTD_decodingBufferSize_min(unsigned long long windowSize, unsigned long
|
|
1450
1767
|
unsigned long long const neededSize = MIN(frameContentSize, neededRBSize);
|
1451
1768
|
size_t const minRBSize = (size_t) neededSize;
|
1452
1769
|
RETURN_ERROR_IF((unsigned long long)minRBSize != neededSize,
|
1453
|
-
frameParameter_windowTooLarge);
|
1770
|
+
frameParameter_windowTooLarge, "");
|
1454
1771
|
return minRBSize;
|
1455
1772
|
}
|
1456
1773
|
|
@@ -1468,30 +1785,94 @@ size_t ZSTD_estimateDStreamSize_fromFrame(const void* src, size_t srcSize)
|
|
1468
1785
|
ZSTD_frameHeader zfh;
|
1469
1786
|
size_t const err = ZSTD_getFrameHeader(&zfh, src, srcSize);
|
1470
1787
|
if (ZSTD_isError(err)) return err;
|
1471
|
-
RETURN_ERROR_IF(err>0, srcSize_wrong);
|
1788
|
+
RETURN_ERROR_IF(err>0, srcSize_wrong, "");
|
1472
1789
|
RETURN_ERROR_IF(zfh.windowSize > windowSizeMax,
|
1473
|
-
frameParameter_windowTooLarge);
|
1790
|
+
frameParameter_windowTooLarge, "");
|
1474
1791
|
return ZSTD_estimateDStreamSize((size_t)zfh.windowSize);
|
1475
1792
|
}
|
1476
1793
|
|
1477
1794
|
|
1478
1795
|
/* ***** Decompression ***** */
|
1479
1796
|
|
1480
|
-
|
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)
|
1481
1811
|
{
|
1482
|
-
|
1483
|
-
|
1484
|
-
|
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!");
|
1485
1831
|
}
|
1486
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
|
+
}
|
1487
1866
|
|
1488
1867
|
size_t ZSTD_decompressStream(ZSTD_DStream* zds, ZSTD_outBuffer* output, ZSTD_inBuffer* input)
|
1489
1868
|
{
|
1490
|
-
const char* const
|
1491
|
-
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;
|
1492
1872
|
const char* ip = istart;
|
1493
|
-
char* const
|
1494
|
-
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;
|
1495
1876
|
char* op = ostart;
|
1496
1877
|
U32 someMoreWork = 1;
|
1497
1878
|
|
@@ -1507,6 +1888,7 @@ size_t ZSTD_decompressStream(ZSTD_DStream* zds, ZSTD_outBuffer* output, ZSTD_inB
|
|
1507
1888
|
"forbidden. out: pos: %u vs size: %u",
|
1508
1889
|
(U32)output->pos, (U32)output->size);
|
1509
1890
|
DEBUGLOG(5, "input size : %u", (U32)(input->size - input->pos));
|
1891
|
+
FORWARD_IF_ERROR(ZSTD_checkOutBuffer(zds, output), "");
|
1510
1892
|
|
1511
1893
|
while (someMoreWork) {
|
1512
1894
|
switch(zds->streamStage)
|
@@ -1517,6 +1899,7 @@ size_t ZSTD_decompressStream(ZSTD_DStream* zds, ZSTD_outBuffer* output, ZSTD_inB
|
|
1517
1899
|
zds->lhSize = zds->inPos = zds->outStart = zds->outEnd = 0;
|
1518
1900
|
zds->legacyVersion = 0;
|
1519
1901
|
zds->hostageByte = 0;
|
1902
|
+
zds->expectedOutBuffer = *output;
|
1520
1903
|
/* fall-through */
|
1521
1904
|
|
1522
1905
|
case zdss_loadHeader :
|
@@ -1531,6 +1914,9 @@ size_t ZSTD_decompressStream(ZSTD_DStream* zds, ZSTD_outBuffer* output, ZSTD_inB
|
|
1531
1914
|
} }
|
1532
1915
|
#endif
|
1533
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
|
+
}
|
1534
1920
|
DEBUGLOG(5, "header size : %u", (U32)hSize);
|
1535
1921
|
if (ZSTD_isError(hSize)) {
|
1536
1922
|
#if defined(ZSTD_LEGACY_SUPPORT) && (ZSTD_LEGACY_SUPPORT>=1)
|
@@ -1544,7 +1930,7 @@ size_t ZSTD_decompressStream(ZSTD_DStream* zds, ZSTD_outBuffer* output, ZSTD_inB
|
|
1544
1930
|
"legacy support is incompatible with static dctx");
|
1545
1931
|
FORWARD_IF_ERROR(ZSTD_initLegacyStream(&zds->legacyContext,
|
1546
1932
|
zds->previousLegacyVersion, legacyVersion,
|
1547
|
-
dict, dictSize));
|
1933
|
+
dict, dictSize), "");
|
1548
1934
|
zds->legacyVersion = zds->previousLegacyVersion = legacyVersion;
|
1549
1935
|
{ size_t const hint = ZSTD_decompressLegacyStream(zds->legacyContext, legacyVersion, output, input);
|
1550
1936
|
if (hint==0) zds->streamStage = zdss_init; /* or stay in stage zdss_loadHeader */
|
@@ -1559,24 +1945,25 @@ size_t ZSTD_decompressStream(ZSTD_DStream* zds, ZSTD_outBuffer* output, ZSTD_inB
|
|
1559
1945
|
assert(iend >= ip);
|
1560
1946
|
if (toLoad > remainingInput) { /* not enough input to load full header */
|
1561
1947
|
if (remainingInput > 0) {
|
1562
|
-
|
1948
|
+
ZSTD_memcpy(zds->headerBuffer + zds->lhSize, ip, remainingInput);
|
1563
1949
|
zds->lhSize += remainingInput;
|
1564
1950
|
}
|
1565
1951
|
input->pos = input->size;
|
1566
|
-
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 */
|
1567
1953
|
}
|
1568
1954
|
assert(ip != NULL);
|
1569
|
-
|
1955
|
+
ZSTD_memcpy(zds->headerBuffer + zds->lhSize, ip, toLoad); zds->lhSize = hSize; ip += toLoad;
|
1570
1956
|
break;
|
1571
1957
|
} }
|
1572
1958
|
|
1573
1959
|
/* check for single-pass mode opportunity */
|
1574
|
-
if (zds->fParams.frameContentSize
|
1960
|
+
if (zds->fParams.frameContentSize != ZSTD_CONTENTSIZE_UNKNOWN
|
1961
|
+
&& zds->fParams.frameType != ZSTD_skippableFrame
|
1575
1962
|
&& (U64)(size_t)(oend-op) >= zds->fParams.frameContentSize) {
|
1576
|
-
size_t const cSize = ZSTD_findFrameCompressedSize(istart, iend-istart);
|
1963
|
+
size_t const cSize = ZSTD_findFrameCompressedSize(istart, (size_t)(iend-istart));
|
1577
1964
|
if (cSize <= (size_t)(iend-istart)) {
|
1578
1965
|
/* shortcut : using single-pass mode */
|
1579
|
-
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));
|
1580
1967
|
if (ZSTD_isError(decompressedSize)) return decompressedSize;
|
1581
1968
|
DEBUGLOG(4, "shortcut to single-pass ZSTD_decompress_usingDDict()")
|
1582
1969
|
ip = istart + cSize;
|
@@ -1587,15 +1974,23 @@ size_t ZSTD_decompressStream(ZSTD_DStream* zds, ZSTD_outBuffer* output, ZSTD_inB
|
|
1587
1974
|
break;
|
1588
1975
|
} }
|
1589
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
|
+
|
1590
1985
|
/* Consume header (see ZSTDds_decodeFrameHeader) */
|
1591
1986
|
DEBUGLOG(4, "Consume header");
|
1592
|
-
FORWARD_IF_ERROR(ZSTD_decompressBegin_usingDDict(zds, ZSTD_getDDict(zds)));
|
1987
|
+
FORWARD_IF_ERROR(ZSTD_decompressBegin_usingDDict(zds, ZSTD_getDDict(zds)), "");
|
1593
1988
|
|
1594
1989
|
if ((MEM_readLE32(zds->headerBuffer) & ZSTD_MAGIC_SKIPPABLE_MASK) == ZSTD_MAGIC_SKIPPABLE_START) { /* skippable frame */
|
1595
1990
|
zds->expected = MEM_readLE32(zds->headerBuffer + ZSTD_FRAMEIDSIZE);
|
1596
1991
|
zds->stage = ZSTDds_skipFrame;
|
1597
1992
|
} else {
|
1598
|
-
FORWARD_IF_ERROR(ZSTD_decodeFrameHeader(zds, zds->headerBuffer, zds->lhSize));
|
1993
|
+
FORWARD_IF_ERROR(ZSTD_decodeFrameHeader(zds, zds->headerBuffer, zds->lhSize), "");
|
1599
1994
|
zds->expected = ZSTD_blockHeaderSize;
|
1600
1995
|
zds->stage = ZSTDds_decodeBlockHeader;
|
1601
1996
|
}
|
@@ -1606,40 +2001,48 @@ size_t ZSTD_decompressStream(ZSTD_DStream* zds, ZSTD_outBuffer* output, ZSTD_inB
|
|
1606
2001
|
(U32)(zds->maxWindowSize >> 10) );
|
1607
2002
|
zds->fParams.windowSize = MAX(zds->fParams.windowSize, 1U << ZSTD_WINDOWLOG_ABSOLUTEMIN);
|
1608
2003
|
RETURN_ERROR_IF(zds->fParams.windowSize > zds->maxWindowSize,
|
1609
|
-
frameParameter_windowTooLarge);
|
2004
|
+
frameParameter_windowTooLarge, "");
|
1610
2005
|
|
1611
2006
|
/* Adapt buffer sizes to frame header instructions */
|
1612
2007
|
{ size_t const neededInBuffSize = MAX(zds->fParams.blockSizeMax, 4 /* frame checksum */);
|
1613
|
-
size_t const neededOutBuffSize =
|
1614
|
-
|
1615
|
-
|
1616
|
-
|
1617
|
-
|
1618
|
-
|
1619
|
-
|
1620
|
-
|
1621
|
-
|
1622
|
-
|
1623
|
-
|
1624
|
-
|
1625
|
-
|
1626
|
-
|
1627
|
-
|
1628
|
-
zds->
|
1629
|
-
|
1630
|
-
|
1631
|
-
|
1632
|
-
|
1633
|
-
|
1634
|
-
|
1635
|
-
|
1636
|
-
|
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
|
+
} } }
|
1637
2040
|
zds->streamStage = zdss_read;
|
1638
2041
|
/* fall-through */
|
1639
2042
|
|
1640
2043
|
case zdss_read:
|
1641
2044
|
DEBUGLOG(5, "stage zdss_read");
|
1642
|
-
{ size_t const neededInSize =
|
2045
|
+
{ size_t const neededInSize = ZSTD_nextSrcSizeToDecompressWithInputSize(zds, (size_t)(iend - ip));
|
1643
2046
|
DEBUGLOG(5, "neededInSize = %u", (U32)neededInSize);
|
1644
2047
|
if (neededInSize==0) { /* end of frame */
|
1645
2048
|
zds->streamStage = zdss_init;
|
@@ -1647,15 +2050,9 @@ size_t ZSTD_decompressStream(ZSTD_DStream* zds, ZSTD_outBuffer* output, ZSTD_inB
|
|
1647
2050
|
break;
|
1648
2051
|
}
|
1649
2052
|
if ((size_t)(iend-ip) >= neededInSize) { /* decode directly from src */
|
1650
|
-
|
1651
|
-
size_t const decodedSize = ZSTD_decompressContinue(zds,
|
1652
|
-
zds->outBuff + zds->outStart, (isSkipFrame ? 0 : zds->outBuffSize - zds->outStart),
|
1653
|
-
ip, neededInSize);
|
1654
|
-
if (ZSTD_isError(decodedSize)) return decodedSize;
|
2053
|
+
FORWARD_IF_ERROR(ZSTD_decompressContinueStream(zds, &op, oend, ip, neededInSize), "");
|
1655
2054
|
ip += neededInSize;
|
1656
|
-
|
1657
|
-
zds->outEnd = zds->outStart + decodedSize;
|
1658
|
-
zds->streamStage = zdss_flush;
|
2055
|
+
/* Function modifies the stage so we must break */
|
1659
2056
|
break;
|
1660
2057
|
} }
|
1661
2058
|
if (ip==iend) { someMoreWork = 0; break; } /* no more input */
|
@@ -1667,33 +2064,29 @@ size_t ZSTD_decompressStream(ZSTD_DStream* zds, ZSTD_outBuffer* output, ZSTD_inB
|
|
1667
2064
|
size_t const toLoad = neededInSize - zds->inPos;
|
1668
2065
|
int const isSkipFrame = ZSTD_isSkipFrame(zds);
|
1669
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));
|
1670
2069
|
if (isSkipFrame) {
|
1671
2070
|
loadedSize = MIN(toLoad, (size_t)(iend-ip));
|
1672
2071
|
} else {
|
1673
2072
|
RETURN_ERROR_IF(toLoad > zds->inBuffSize - zds->inPos,
|
1674
2073
|
corruption_detected,
|
1675
2074
|
"should never happen");
|
1676
|
-
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));
|
1677
2076
|
}
|
1678
2077
|
ip += loadedSize;
|
1679
2078
|
zds->inPos += loadedSize;
|
1680
2079
|
if (loadedSize < toLoad) { someMoreWork = 0; break; } /* not enough input, wait for more */
|
1681
2080
|
|
1682
2081
|
/* decode loaded input */
|
1683
|
-
|
1684
|
-
|
1685
|
-
|
1686
|
-
|
1687
|
-
|
1688
|
-
if (!decodedSize && !isSkipFrame) { zds->streamStage = zdss_read; break; } /* this was just a header */
|
1689
|
-
zds->outEnd = zds->outStart + decodedSize;
|
1690
|
-
} }
|
1691
|
-
zds->streamStage = zdss_flush;
|
1692
|
-
/* fall-through */
|
1693
|
-
|
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
|
+
}
|
1694
2087
|
case zdss_flush:
|
1695
2088
|
{ size_t const toFlushSize = zds->outEnd - zds->outStart;
|
1696
|
-
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);
|
1697
2090
|
op += flushedSize;
|
1698
2091
|
zds->outStart += flushedSize;
|
1699
2092
|
if (flushedSize == toFlushSize) { /* flush completed */
|
@@ -1713,17 +2106,21 @@ size_t ZSTD_decompressStream(ZSTD_DStream* zds, ZSTD_outBuffer* output, ZSTD_inB
|
|
1713
2106
|
|
1714
2107
|
default:
|
1715
2108
|
assert(0); /* impossible */
|
1716
|
-
RETURN_ERROR(GENERIC); /* some compiler require default to do something */
|
2109
|
+
RETURN_ERROR(GENERIC, "impossible to reach"); /* some compiler require default to do something */
|
1717
2110
|
} }
|
1718
2111
|
|
1719
2112
|
/* result */
|
1720
2113
|
input->pos = (size_t)(ip - (const char*)(input->src));
|
1721
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
|
+
|
1722
2119
|
if ((ip==istart) && (op==ostart)) { /* no forward progress */
|
1723
2120
|
zds->noForwardProgress ++;
|
1724
2121
|
if (zds->noForwardProgress >= ZSTD_NO_FORWARD_PROGRESS_MAX) {
|
1725
|
-
RETURN_ERROR_IF(op==oend, dstSize_tooSmall);
|
1726
|
-
RETURN_ERROR_IF(ip==iend, srcSize_wrong);
|
2122
|
+
RETURN_ERROR_IF(op==oend, dstSize_tooSmall, "");
|
2123
|
+
RETURN_ERROR_IF(ip==iend, srcSize_wrong, "");
|
1727
2124
|
assert(0);
|
1728
2125
|
}
|
1729
2126
|
} else {
|