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