zstd-ruby 1.3.8.0 → 1.4.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.travis.yml +6 -5
- data/README.md +1 -1
- data/ext/zstdruby/libzstd/Makefile +133 -61
- data/ext/zstdruby/libzstd/README.md +51 -18
- data/ext/zstdruby/libzstd/common/bitstream.h +38 -39
- data/ext/zstdruby/libzstd/common/compiler.h +41 -6
- data/ext/zstdruby/libzstd/common/cpu.h +1 -1
- data/ext/zstdruby/libzstd/common/debug.c +11 -31
- data/ext/zstdruby/libzstd/common/debug.h +11 -31
- data/ext/zstdruby/libzstd/common/entropy_common.c +13 -33
- data/ext/zstdruby/libzstd/common/error_private.c +2 -1
- data/ext/zstdruby/libzstd/common/error_private.h +6 -2
- data/ext/zstdruby/libzstd/common/fse.h +13 -33
- data/ext/zstdruby/libzstd/common/fse_decompress.c +12 -35
- data/ext/zstdruby/libzstd/common/huf.h +15 -33
- data/ext/zstdruby/libzstd/common/mem.h +75 -2
- data/ext/zstdruby/libzstd/common/pool.c +8 -4
- data/ext/zstdruby/libzstd/common/pool.h +2 -2
- data/ext/zstdruby/libzstd/common/threading.c +52 -6
- data/ext/zstdruby/libzstd/common/threading.h +36 -4
- data/ext/zstdruby/libzstd/common/xxhash.c +25 -37
- data/ext/zstdruby/libzstd/common/xxhash.h +11 -31
- data/ext/zstdruby/libzstd/common/zstd_common.c +1 -1
- data/ext/zstdruby/libzstd/common/zstd_errors.h +2 -1
- data/ext/zstdruby/libzstd/common/zstd_internal.h +203 -22
- data/ext/zstdruby/libzstd/compress/fse_compress.c +19 -42
- data/ext/zstdruby/libzstd/compress/hist.c +15 -35
- data/ext/zstdruby/libzstd/compress/hist.h +12 -32
- data/ext/zstdruby/libzstd/compress/huf_compress.c +92 -92
- data/ext/zstdruby/libzstd/compress/zstd_compress.c +1460 -1472
- data/ext/zstdruby/libzstd/compress/zstd_compress_internal.h +330 -65
- 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 +419 -0
- data/ext/zstdruby/libzstd/compress/zstd_compress_sequences.h +54 -0
- data/ext/zstdruby/libzstd/compress/zstd_compress_superblock.c +845 -0
- data/ext/zstdruby/libzstd/compress/zstd_compress_superblock.h +32 -0
- data/ext/zstdruby/libzstd/compress/zstd_cwksp.h +525 -0
- data/ext/zstdruby/libzstd/compress/zstd_double_fast.c +65 -43
- data/ext/zstdruby/libzstd/compress/zstd_double_fast.h +2 -2
- data/ext/zstdruby/libzstd/compress/zstd_fast.c +264 -159
- data/ext/zstdruby/libzstd/compress/zstd_fast.h +2 -2
- data/ext/zstdruby/libzstd/compress/zstd_lazy.c +74 -42
- data/ext/zstdruby/libzstd/compress/zstd_lazy.h +2 -2
- data/ext/zstdruby/libzstd/compress/zstd_ldm.c +33 -11
- data/ext/zstdruby/libzstd/compress/zstd_ldm.h +7 -2
- data/ext/zstdruby/libzstd/compress/zstd_opt.c +108 -125
- data/ext/zstdruby/libzstd/compress/zstd_opt.h +1 -1
- data/ext/zstdruby/libzstd/compress/zstdmt_compress.c +129 -93
- data/ext/zstdruby/libzstd/compress/zstdmt_compress.h +46 -28
- data/ext/zstdruby/libzstd/decompress/huf_decompress.c +76 -60
- data/ext/zstdruby/libzstd/decompress/zstd_ddict.c +14 -10
- data/ext/zstdruby/libzstd/decompress/zstd_ddict.h +2 -2
- data/ext/zstdruby/libzstd/decompress/zstd_decompress.c +471 -258
- data/ext/zstdruby/libzstd/decompress/zstd_decompress_block.c +471 -346
- data/ext/zstdruby/libzstd/decompress/zstd_decompress_block.h +3 -3
- data/ext/zstdruby/libzstd/decompress/zstd_decompress_internal.h +25 -4
- 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 +220 -65
- data/ext/zstdruby/libzstd/dictBuilder/cover.h +81 -7
- data/ext/zstdruby/libzstd/dictBuilder/fastcover.c +85 -56
- data/ext/zstdruby/libzstd/dictBuilder/zdict.c +43 -19
- data/ext/zstdruby/libzstd/dictBuilder/zdict.h +73 -35
- data/ext/zstdruby/libzstd/dll/example/Makefile +2 -1
- data/ext/zstdruby/libzstd/dll/example/build_package.bat +3 -2
- data/ext/zstdruby/libzstd/legacy/zstd_legacy.h +49 -15
- data/ext/zstdruby/libzstd/legacy/zstd_v01.c +142 -117
- data/ext/zstdruby/libzstd/legacy/zstd_v01.h +13 -8
- data/ext/zstdruby/libzstd/legacy/zstd_v02.c +54 -25
- data/ext/zstdruby/libzstd/legacy/zstd_v02.h +13 -8
- data/ext/zstdruby/libzstd/legacy/zstd_v03.c +55 -25
- data/ext/zstdruby/libzstd/legacy/zstd_v03.h +13 -8
- data/ext/zstdruby/libzstd/legacy/zstd_v04.c +62 -29
- data/ext/zstdruby/libzstd/legacy/zstd_v04.h +13 -8
- data/ext/zstdruby/libzstd/legacy/zstd_v05.c +145 -109
- data/ext/zstdruby/libzstd/legacy/zstd_v05.h +14 -9
- data/ext/zstdruby/libzstd/legacy/zstd_v06.c +56 -26
- data/ext/zstdruby/libzstd/legacy/zstd_v06.h +11 -6
- data/ext/zstdruby/libzstd/legacy/zstd_v07.c +65 -28
- data/ext/zstdruby/libzstd/legacy/zstd_v07.h +11 -6
- data/ext/zstdruby/libzstd/libzstd.pc.in +3 -2
- data/ext/zstdruby/libzstd/zstd.h +921 -597
- data/lib/zstd-ruby/version.rb +1 -1
- data/zstd-ruby.gemspec +2 -2
- metadata +19 -14
- data/ext/zstdruby/libzstd/dll/libzstd.def +0 -87
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/*
|
|
2
|
-
* Copyright (c) 2016-
|
|
2
|
+
* Copyright (c) 2016-2020, 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
|
|
@@ -17,15 +17,30 @@
|
|
|
17
17
|
|
|
18
18
|
|
|
19
19
|
/* Note : This is an internal API.
|
|
20
|
-
*
|
|
20
|
+
* These APIs used to be exposed with ZSTDLIB_API,
|
|
21
21
|
* because it used to be the only way to invoke MT compression.
|
|
22
|
-
* Now, it's recommended to use
|
|
23
|
-
*
|
|
22
|
+
* Now, it's recommended to use ZSTD_compress2 and ZSTD_compressStream2()
|
|
23
|
+
* instead.
|
|
24
|
+
*
|
|
25
|
+
* If you depend on these APIs and can't switch, then define
|
|
26
|
+
* ZSTD_LEGACY_MULTITHREADED_API when making the dynamic library.
|
|
27
|
+
* However, we may completely remove these functions in a future
|
|
28
|
+
* release, so please switch soon.
|
|
29
|
+
*
|
|
30
|
+
* This API requires ZSTD_MULTITHREAD to be defined during compilation,
|
|
31
|
+
* otherwise ZSTDMT_createCCtx*() will fail.
|
|
32
|
+
*/
|
|
33
|
+
|
|
34
|
+
#ifdef ZSTD_LEGACY_MULTITHREADED_API
|
|
35
|
+
# define ZSTDMT_API ZSTDLIB_API
|
|
36
|
+
#else
|
|
37
|
+
# define ZSTDMT_API
|
|
38
|
+
#endif
|
|
24
39
|
|
|
25
40
|
/* === Dependencies === */
|
|
26
41
|
#include <stddef.h> /* size_t */
|
|
27
42
|
#define ZSTD_STATIC_LINKING_ONLY /* ZSTD_parameters */
|
|
28
|
-
#include "zstd.h" /* ZSTD_inBuffer, ZSTD_outBuffer, ZSTDLIB_API */
|
|
43
|
+
#include "../zstd.h" /* ZSTD_inBuffer, ZSTD_outBuffer, ZSTDLIB_API */
|
|
29
44
|
|
|
30
45
|
|
|
31
46
|
/* === Constants === */
|
|
@@ -35,22 +50,25 @@
|
|
|
35
50
|
#ifndef ZSTDMT_JOBSIZE_MIN
|
|
36
51
|
# define ZSTDMT_JOBSIZE_MIN (1 MB)
|
|
37
52
|
#endif
|
|
53
|
+
#define ZSTDMT_JOBLOG_MAX (MEM_32bits() ? 29 : 30)
|
|
38
54
|
#define ZSTDMT_JOBSIZE_MAX (MEM_32bits() ? (512 MB) : (1024 MB))
|
|
39
55
|
|
|
40
56
|
|
|
41
57
|
/* === Memory management === */
|
|
42
58
|
typedef struct ZSTDMT_CCtx_s ZSTDMT_CCtx;
|
|
43
|
-
|
|
44
|
-
|
|
59
|
+
/* Requires ZSTD_MULTITHREAD to be defined during compilation, otherwise it will return NULL. */
|
|
60
|
+
ZSTDMT_API ZSTDMT_CCtx* ZSTDMT_createCCtx(unsigned nbWorkers);
|
|
61
|
+
/* Requires ZSTD_MULTITHREAD to be defined during compilation, otherwise it will return NULL. */
|
|
62
|
+
ZSTDMT_API ZSTDMT_CCtx* ZSTDMT_createCCtx_advanced(unsigned nbWorkers,
|
|
45
63
|
ZSTD_customMem cMem);
|
|
46
|
-
|
|
64
|
+
ZSTDMT_API size_t ZSTDMT_freeCCtx(ZSTDMT_CCtx* mtctx);
|
|
47
65
|
|
|
48
|
-
|
|
66
|
+
ZSTDMT_API size_t ZSTDMT_sizeof_CCtx(ZSTDMT_CCtx* mtctx);
|
|
49
67
|
|
|
50
68
|
|
|
51
69
|
/* === Simple one-pass compression function === */
|
|
52
70
|
|
|
53
|
-
|
|
71
|
+
ZSTDMT_API size_t ZSTDMT_compressCCtx(ZSTDMT_CCtx* mtctx,
|
|
54
72
|
void* dst, size_t dstCapacity,
|
|
55
73
|
const void* src, size_t srcSize,
|
|
56
74
|
int compressionLevel);
|
|
@@ -59,31 +77,31 @@ ZSTDLIB_API size_t ZSTDMT_compressCCtx(ZSTDMT_CCtx* mtctx,
|
|
|
59
77
|
|
|
60
78
|
/* === Streaming functions === */
|
|
61
79
|
|
|
62
|
-
|
|
63
|
-
|
|
80
|
+
ZSTDMT_API size_t ZSTDMT_initCStream(ZSTDMT_CCtx* mtctx, int compressionLevel);
|
|
81
|
+
ZSTDMT_API size_t ZSTDMT_resetCStream(ZSTDMT_CCtx* mtctx, unsigned long long pledgedSrcSize); /**< if srcSize is not known at reset time, use ZSTD_CONTENTSIZE_UNKNOWN. Note: for compatibility with older programs, 0 means the same as ZSTD_CONTENTSIZE_UNKNOWN, but it will change in the future to mean "empty" */
|
|
64
82
|
|
|
65
|
-
|
|
66
|
-
|
|
83
|
+
ZSTDMT_API size_t ZSTDMT_nextInputSizeHint(const ZSTDMT_CCtx* mtctx);
|
|
84
|
+
ZSTDMT_API size_t ZSTDMT_compressStream(ZSTDMT_CCtx* mtctx, ZSTD_outBuffer* output, ZSTD_inBuffer* input);
|
|
67
85
|
|
|
68
|
-
|
|
69
|
-
|
|
86
|
+
ZSTDMT_API size_t ZSTDMT_flushStream(ZSTDMT_CCtx* mtctx, ZSTD_outBuffer* output); /**< @return : 0 == all flushed; >0 : still some data to be flushed; or an error code (ZSTD_isError()) */
|
|
87
|
+
ZSTDMT_API size_t ZSTDMT_endStream(ZSTDMT_CCtx* mtctx, ZSTD_outBuffer* output); /**< @return : 0 == all flushed; >0 : still some data to be flushed; or an error code (ZSTD_isError()) */
|
|
70
88
|
|
|
71
89
|
|
|
72
90
|
/* === Advanced functions and parameters === */
|
|
73
91
|
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
92
|
+
ZSTDMT_API size_t ZSTDMT_compress_advanced(ZSTDMT_CCtx* mtctx,
|
|
93
|
+
void* dst, size_t dstCapacity,
|
|
94
|
+
const void* src, size_t srcSize,
|
|
95
|
+
const ZSTD_CDict* cdict,
|
|
96
|
+
ZSTD_parameters params,
|
|
97
|
+
int overlapLog);
|
|
80
98
|
|
|
81
|
-
|
|
99
|
+
ZSTDMT_API size_t ZSTDMT_initCStream_advanced(ZSTDMT_CCtx* mtctx,
|
|
82
100
|
const void* dict, size_t dictSize, /* dict can be released after init, a local copy is preserved within zcs */
|
|
83
101
|
ZSTD_parameters params,
|
|
84
102
|
unsigned long long pledgedSrcSize); /* pledgedSrcSize is optional and can be zero == unknown */
|
|
85
103
|
|
|
86
|
-
|
|
104
|
+
ZSTDMT_API size_t ZSTDMT_initCStream_usingCDict(ZSTDMT_CCtx* mtctx,
|
|
87
105
|
const ZSTD_CDict* cdict,
|
|
88
106
|
ZSTD_frameParameters fparams,
|
|
89
107
|
unsigned long long pledgedSrcSize); /* note : zero means empty */
|
|
@@ -92,7 +110,7 @@ ZSTDLIB_API size_t ZSTDMT_initCStream_usingCDict(ZSTDMT_CCtx* mtctx,
|
|
|
92
110
|
* List of parameters that can be set using ZSTDMT_setMTCtxParameter() */
|
|
93
111
|
typedef enum {
|
|
94
112
|
ZSTDMT_p_jobSize, /* Each job is compressed in parallel. By default, this value is dynamically determined depending on compression parameters. Can be set explicitly here. */
|
|
95
|
-
ZSTDMT_p_overlapLog, /* Each job may reload a part of previous job to enhance
|
|
113
|
+
ZSTDMT_p_overlapLog, /* Each job may reload a part of previous job to enhance compression ratio; 0 == no overlap, 6(default) == use 1/8th of window, >=9 == use full window. This is a "sticky" parameter : its value will be re-used on next compression job */
|
|
96
114
|
ZSTDMT_p_rsyncable /* Enables rsyncable mode. */
|
|
97
115
|
} ZSTDMT_parameter;
|
|
98
116
|
|
|
@@ -101,12 +119,12 @@ typedef enum {
|
|
|
101
119
|
* The function must be called typically after ZSTD_createCCtx() but __before ZSTDMT_init*() !__
|
|
102
120
|
* Parameters not explicitly reset by ZSTDMT_init*() remain the same in consecutive compression sessions.
|
|
103
121
|
* @return : 0, or an error code (which can be tested using ZSTD_isError()) */
|
|
104
|
-
|
|
122
|
+
ZSTDMT_API size_t ZSTDMT_setMTCtxParameter(ZSTDMT_CCtx* mtctx, ZSTDMT_parameter parameter, int value);
|
|
105
123
|
|
|
106
124
|
/* ZSTDMT_getMTCtxParameter() :
|
|
107
125
|
* Query the ZSTDMT_CCtx for a parameter value.
|
|
108
126
|
* @return : 0, or an error code (which can be tested using ZSTD_isError()) */
|
|
109
|
-
|
|
127
|
+
ZSTDMT_API size_t ZSTDMT_getMTCtxParameter(ZSTDMT_CCtx* mtctx, ZSTDMT_parameter parameter, int* value);
|
|
110
128
|
|
|
111
129
|
|
|
112
130
|
/*! ZSTDMT_compressStream_generic() :
|
|
@@ -116,7 +134,7 @@ ZSTDLIB_API size_t ZSTDMT_getMTCtxParameter(ZSTDMT_CCtx* mtctx, ZSTDMT_parameter
|
|
|
116
134
|
* 0 if fully flushed
|
|
117
135
|
* or an error code
|
|
118
136
|
* note : needs to be init using any ZSTD_initCStream*() variant */
|
|
119
|
-
|
|
137
|
+
ZSTDMT_API size_t ZSTDMT_compressStream_generic(ZSTDMT_CCtx* mtctx,
|
|
120
138
|
ZSTD_outBuffer* output,
|
|
121
139
|
ZSTD_inBuffer* input,
|
|
122
140
|
ZSTD_EndDirective endOp);
|
|
@@ -1,47 +1,27 @@
|
|
|
1
1
|
/* ******************************************************************
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
notice, this list of conditions and the following disclaimer.
|
|
14
|
-
* Redistributions in binary form must reproduce the above
|
|
15
|
-
copyright notice, this list of conditions and the following disclaimer
|
|
16
|
-
in the documentation and/or other materials provided with the
|
|
17
|
-
distribution.
|
|
18
|
-
|
|
19
|
-
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
|
20
|
-
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
|
21
|
-
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
|
22
|
-
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
|
23
|
-
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
|
24
|
-
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
|
25
|
-
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
|
26
|
-
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
|
27
|
-
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
28
|
-
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
|
29
|
-
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
30
|
-
|
|
31
|
-
You can contact the author at :
|
|
32
|
-
- FSE+HUF source repository : https://github.com/Cyan4973/FiniteStateEntropy
|
|
2
|
+
* huff0 huffman decoder,
|
|
3
|
+
* part of Finite State Entropy library
|
|
4
|
+
* Copyright (c) 2013-2020, Yann Collet, Facebook, Inc.
|
|
5
|
+
*
|
|
6
|
+
* You can contact the author at :
|
|
7
|
+
* - FSE+HUF source repository : https://github.com/Cyan4973/FiniteStateEntropy
|
|
8
|
+
*
|
|
9
|
+
* This source code is licensed under both the BSD-style license (found in the
|
|
10
|
+
* LICENSE file in the root directory of this source tree) and the GPLv2 (found
|
|
11
|
+
* in the COPYING file in the root directory of this source tree).
|
|
12
|
+
* You may select, at your option, one of the above-listed licenses.
|
|
33
13
|
****************************************************************** */
|
|
34
14
|
|
|
35
15
|
/* **************************************************************
|
|
36
16
|
* Dependencies
|
|
37
17
|
****************************************************************/
|
|
38
18
|
#include <string.h> /* memcpy, memset */
|
|
39
|
-
#include "compiler.h"
|
|
40
|
-
#include "bitstream.h" /* BIT_* */
|
|
41
|
-
#include "fse.h" /* to compress headers */
|
|
19
|
+
#include "../common/compiler.h"
|
|
20
|
+
#include "../common/bitstream.h" /* BIT_* */
|
|
21
|
+
#include "../common/fse.h" /* to compress headers */
|
|
42
22
|
#define HUF_STATIC_LINKING_ONLY
|
|
43
|
-
#include "huf.h"
|
|
44
|
-
#include "error_private.h"
|
|
23
|
+
#include "../common/huf.h"
|
|
24
|
+
#include "../common/error_private.h"
|
|
45
25
|
|
|
46
26
|
/* **************************************************************
|
|
47
27
|
* Macros
|
|
@@ -61,7 +41,6 @@
|
|
|
61
41
|
* Error Management
|
|
62
42
|
****************************************************************/
|
|
63
43
|
#define HUF_isError ERR_isError
|
|
64
|
-
#define CHECK_F(f) { size_t const err_ = (f); if (HUF_isError(err_)) return err_; }
|
|
65
44
|
|
|
66
45
|
|
|
67
46
|
/* **************************************************************
|
|
@@ -179,17 +158,29 @@ size_t HUF_readDTableX1_wksp(HUF_DTable* DTable, const void* src, size_t srcSize
|
|
|
179
158
|
|
|
180
159
|
/* fill DTable */
|
|
181
160
|
{ U32 n;
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
161
|
+
size_t const nEnd = nbSymbols;
|
|
162
|
+
for (n=0; n<nEnd; n++) {
|
|
163
|
+
size_t const w = huffWeight[n];
|
|
164
|
+
size_t const length = (1 << w) >> 1;
|
|
165
|
+
size_t const uStart = rankVal[w];
|
|
166
|
+
size_t const uEnd = uStart + length;
|
|
167
|
+
size_t u;
|
|
186
168
|
HUF_DEltX1 D;
|
|
187
|
-
D.byte = (BYTE)n;
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
169
|
+
D.byte = (BYTE)n;
|
|
170
|
+
D.nbBits = (BYTE)(tableLog + 1 - w);
|
|
171
|
+
rankVal[w] = (U32)uEnd;
|
|
172
|
+
if (length < 4) {
|
|
173
|
+
/* Use length in the loop bound so the compiler knows it is short. */
|
|
174
|
+
for (u = 0; u < length; ++u)
|
|
175
|
+
dt[uStart + u] = D;
|
|
176
|
+
} else {
|
|
177
|
+
/* Unroll the loop 4 times, we know it is a power of 2. */
|
|
178
|
+
for (u = uStart; u < uEnd; u += 4) {
|
|
179
|
+
dt[u + 0] = D;
|
|
180
|
+
dt[u + 1] = D;
|
|
181
|
+
dt[u + 2] = D;
|
|
182
|
+
dt[u + 3] = D;
|
|
183
|
+
} } } }
|
|
193
184
|
return iSize;
|
|
194
185
|
}
|
|
195
186
|
|
|
@@ -280,6 +271,7 @@ HUF_decompress4X1_usingDTable_internal_body(
|
|
|
280
271
|
{ const BYTE* const istart = (const BYTE*) cSrc;
|
|
281
272
|
BYTE* const ostart = (BYTE*) dst;
|
|
282
273
|
BYTE* const oend = ostart + dstSize;
|
|
274
|
+
BYTE* const olimit = oend - 3;
|
|
283
275
|
const void* const dtPtr = DTable + 1;
|
|
284
276
|
const HUF_DEltX1* const dt = (const HUF_DEltX1*)dtPtr;
|
|
285
277
|
|
|
@@ -304,9 +296,9 @@ HUF_decompress4X1_usingDTable_internal_body(
|
|
|
304
296
|
BYTE* op2 = opStart2;
|
|
305
297
|
BYTE* op3 = opStart3;
|
|
306
298
|
BYTE* op4 = opStart4;
|
|
307
|
-
U32 endSignal = BIT_DStream_unfinished;
|
|
308
299
|
DTableDesc const dtd = HUF_getDTableDesc(DTable);
|
|
309
300
|
U32 const dtLog = dtd.tableLog;
|
|
301
|
+
U32 endSignal = 1;
|
|
310
302
|
|
|
311
303
|
if (length4 > cSrcSize) return ERROR(corruption_detected); /* overflow */
|
|
312
304
|
CHECK_F( BIT_initDStream(&bitD1, istart1, length1) );
|
|
@@ -315,8 +307,7 @@ HUF_decompress4X1_usingDTable_internal_body(
|
|
|
315
307
|
CHECK_F( BIT_initDStream(&bitD4, istart4, length4) );
|
|
316
308
|
|
|
317
309
|
/* up to 16 symbols per loop (4 symbols per stream) in 64-bit mode */
|
|
318
|
-
|
|
319
|
-
while ( (endSignal==BIT_DStream_unfinished) && (op4<(oend-3)) ) {
|
|
310
|
+
for ( ; (endSignal) & (op4 < olimit) ; ) {
|
|
320
311
|
HUF_DECODE_SYMBOLX1_2(op1, &bitD1);
|
|
321
312
|
HUF_DECODE_SYMBOLX1_2(op2, &bitD2);
|
|
322
313
|
HUF_DECODE_SYMBOLX1_2(op3, &bitD3);
|
|
@@ -333,10 +324,10 @@ HUF_decompress4X1_usingDTable_internal_body(
|
|
|
333
324
|
HUF_DECODE_SYMBOLX1_0(op2, &bitD2);
|
|
334
325
|
HUF_DECODE_SYMBOLX1_0(op3, &bitD3);
|
|
335
326
|
HUF_DECODE_SYMBOLX1_0(op4, &bitD4);
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
327
|
+
endSignal &= BIT_reloadDStreamFast(&bitD1) == BIT_DStream_unfinished;
|
|
328
|
+
endSignal &= BIT_reloadDStreamFast(&bitD2) == BIT_DStream_unfinished;
|
|
329
|
+
endSignal &= BIT_reloadDStreamFast(&bitD3) == BIT_DStream_unfinished;
|
|
330
|
+
endSignal &= BIT_reloadDStreamFast(&bitD4) == BIT_DStream_unfinished;
|
|
340
331
|
}
|
|
341
332
|
|
|
342
333
|
/* check corruption */
|
|
@@ -755,7 +746,6 @@ HUF_decompress1X2_usingDTable_internal_body(
|
|
|
755
746
|
return dstSize;
|
|
756
747
|
}
|
|
757
748
|
|
|
758
|
-
|
|
759
749
|
FORCE_INLINE_TEMPLATE size_t
|
|
760
750
|
HUF_decompress4X2_usingDTable_internal_body(
|
|
761
751
|
void* dst, size_t dstSize,
|
|
@@ -767,6 +757,7 @@ HUF_decompress4X2_usingDTable_internal_body(
|
|
|
767
757
|
{ const BYTE* const istart = (const BYTE*) cSrc;
|
|
768
758
|
BYTE* const ostart = (BYTE*) dst;
|
|
769
759
|
BYTE* const oend = ostart + dstSize;
|
|
760
|
+
BYTE* const olimit = oend - (sizeof(size_t)-1);
|
|
770
761
|
const void* const dtPtr = DTable+1;
|
|
771
762
|
const HUF_DEltX2* const dt = (const HUF_DEltX2*)dtPtr;
|
|
772
763
|
|
|
@@ -791,7 +782,7 @@ HUF_decompress4X2_usingDTable_internal_body(
|
|
|
791
782
|
BYTE* op2 = opStart2;
|
|
792
783
|
BYTE* op3 = opStart3;
|
|
793
784
|
BYTE* op4 = opStart4;
|
|
794
|
-
U32 endSignal;
|
|
785
|
+
U32 endSignal = 1;
|
|
795
786
|
DTableDesc const dtd = HUF_getDTableDesc(DTable);
|
|
796
787
|
U32 const dtLog = dtd.tableLog;
|
|
797
788
|
|
|
@@ -802,8 +793,29 @@ HUF_decompress4X2_usingDTable_internal_body(
|
|
|
802
793
|
CHECK_F( BIT_initDStream(&bitD4, istart4, length4) );
|
|
803
794
|
|
|
804
795
|
/* 16-32 symbols per loop (4-8 symbols per stream) */
|
|
805
|
-
|
|
806
|
-
|
|
796
|
+
for ( ; (endSignal) & (op4 < olimit); ) {
|
|
797
|
+
#if defined(__clang__) && (defined(__x86_64__) || defined(__i386__))
|
|
798
|
+
HUF_DECODE_SYMBOLX2_2(op1, &bitD1);
|
|
799
|
+
HUF_DECODE_SYMBOLX2_1(op1, &bitD1);
|
|
800
|
+
HUF_DECODE_SYMBOLX2_2(op1, &bitD1);
|
|
801
|
+
HUF_DECODE_SYMBOLX2_0(op1, &bitD1);
|
|
802
|
+
HUF_DECODE_SYMBOLX2_2(op2, &bitD2);
|
|
803
|
+
HUF_DECODE_SYMBOLX2_1(op2, &bitD2);
|
|
804
|
+
HUF_DECODE_SYMBOLX2_2(op2, &bitD2);
|
|
805
|
+
HUF_DECODE_SYMBOLX2_0(op2, &bitD2);
|
|
806
|
+
endSignal &= BIT_reloadDStreamFast(&bitD1) == BIT_DStream_unfinished;
|
|
807
|
+
endSignal &= BIT_reloadDStreamFast(&bitD2) == BIT_DStream_unfinished;
|
|
808
|
+
HUF_DECODE_SYMBOLX2_2(op3, &bitD3);
|
|
809
|
+
HUF_DECODE_SYMBOLX2_1(op3, &bitD3);
|
|
810
|
+
HUF_DECODE_SYMBOLX2_2(op3, &bitD3);
|
|
811
|
+
HUF_DECODE_SYMBOLX2_0(op3, &bitD3);
|
|
812
|
+
HUF_DECODE_SYMBOLX2_2(op4, &bitD4);
|
|
813
|
+
HUF_DECODE_SYMBOLX2_1(op4, &bitD4);
|
|
814
|
+
HUF_DECODE_SYMBOLX2_2(op4, &bitD4);
|
|
815
|
+
HUF_DECODE_SYMBOLX2_0(op4, &bitD4);
|
|
816
|
+
endSignal &= BIT_reloadDStreamFast(&bitD3) == BIT_DStream_unfinished;
|
|
817
|
+
endSignal &= BIT_reloadDStreamFast(&bitD4) == BIT_DStream_unfinished;
|
|
818
|
+
#else
|
|
807
819
|
HUF_DECODE_SYMBOLX2_2(op1, &bitD1);
|
|
808
820
|
HUF_DECODE_SYMBOLX2_2(op2, &bitD2);
|
|
809
821
|
HUF_DECODE_SYMBOLX2_2(op3, &bitD3);
|
|
@@ -820,8 +832,12 @@ HUF_decompress4X2_usingDTable_internal_body(
|
|
|
820
832
|
HUF_DECODE_SYMBOLX2_0(op2, &bitD2);
|
|
821
833
|
HUF_DECODE_SYMBOLX2_0(op3, &bitD3);
|
|
822
834
|
HUF_DECODE_SYMBOLX2_0(op4, &bitD4);
|
|
823
|
-
|
|
824
|
-
|
|
835
|
+
endSignal = (U32)LIKELY(
|
|
836
|
+
(BIT_reloadDStreamFast(&bitD1) == BIT_DStream_unfinished)
|
|
837
|
+
& (BIT_reloadDStreamFast(&bitD2) == BIT_DStream_unfinished)
|
|
838
|
+
& (BIT_reloadDStreamFast(&bitD3) == BIT_DStream_unfinished)
|
|
839
|
+
& (BIT_reloadDStreamFast(&bitD4) == BIT_DStream_unfinished));
|
|
840
|
+
#endif
|
|
825
841
|
}
|
|
826
842
|
|
|
827
843
|
/* check corruption */
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/*
|
|
2
|
-
* Copyright (c) 2016-
|
|
2
|
+
* Copyright (c) 2016-2020, 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,17 +15,17 @@
|
|
|
15
15
|
* Dependencies
|
|
16
16
|
*********************************************************/
|
|
17
17
|
#include <string.h> /* memcpy, memmove, memset */
|
|
18
|
-
#include "cpu.h" /* bmi2 */
|
|
19
|
-
#include "mem.h" /* low level memory routines */
|
|
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;
|
|
@@ -105,9 +109,9 @@ ZSTD_loadEntropy_intoDDict(ZSTD_DDict* ddict,
|
|
|
105
109
|
ddict->dictID = MEM_readLE32((const char*)ddict->dictContent + ZSTD_FRAMEIDSIZE);
|
|
106
110
|
|
|
107
111
|
/* load entropy tables */
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
112
|
+
RETURN_ERROR_IF(ZSTD_isError(ZSTD_loadDEntropy(
|
|
113
|
+
&ddict->entropy, ddict->dictContent, ddict->dictSize)),
|
|
114
|
+
dictionary_corrupted, "");
|
|
111
115
|
ddict->entropyPresent = 1;
|
|
112
116
|
return 0;
|
|
113
117
|
}
|
|
@@ -133,7 +137,7 @@ static size_t ZSTD_initDDict_internal(ZSTD_DDict* ddict,
|
|
|
133
137
|
ddict->entropy.hufTable[0] = (HUF_DTable)((HufLog)*0x1000001); /* cover both little and big endian */
|
|
134
138
|
|
|
135
139
|
/* parse dictionary content */
|
|
136
|
-
|
|
140
|
+
FORWARD_IF_ERROR( ZSTD_loadEntropy_intoDDict(ddict, dictContentType) , "");
|
|
137
141
|
|
|
138
142
|
return 0;
|
|
139
143
|
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/*
|
|
2
|
-
* Copyright (c) 2016-
|
|
2
|
+
* Copyright (c) 2016-2020, 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
|
|
@@ -16,7 +16,7 @@
|
|
|
16
16
|
* Dependencies
|
|
17
17
|
*********************************************************/
|
|
18
18
|
#include <stddef.h> /* size_t */
|
|
19
|
-
#include "zstd.h" /* ZSTD_DDict, and several public functions */
|
|
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-2020, 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
|
|
@@ -56,19 +56,19 @@
|
|
|
56
56
|
* Dependencies
|
|
57
57
|
*********************************************************/
|
|
58
58
|
#include <string.h> /* memcpy, memmove, memset */
|
|
59
|
-
#include "cpu.h" /* bmi2 */
|
|
60
|
-
#include "mem.h" /* low level memory routines */
|
|
59
|
+
#include "../common/cpu.h" /* bmi2 */
|
|
60
|
+
#include "../common/mem.h" /* low level memory routines */
|
|
61
61
|
#define FSE_STATIC_LINKING_ONLY
|
|
62
|
-
#include "fse.h"
|
|
62
|
+
#include "../common/fse.h"
|
|
63
63
|
#define HUF_STATIC_LINKING_ONLY
|
|
64
|
-
#include "huf.h"
|
|
65
|
-
#include "zstd_internal.h" /* blockProperties_t */
|
|
64
|
+
#include "../common/huf.h"
|
|
65
|
+
#include "../common/zstd_internal.h" /* blockProperties_t */
|
|
66
66
|
#include "zstd_decompress_internal.h" /* ZSTD_DCtx */
|
|
67
67
|
#include "zstd_ddict.h" /* ZSTD_DDictDictContent */
|
|
68
68
|
#include "zstd_decompress_block.h" /* ZSTD_decompressBlock_internal */
|
|
69
69
|
|
|
70
70
|
#if defined(ZSTD_LEGACY_SUPPORT) && (ZSTD_LEGACY_SUPPORT>=1)
|
|
71
|
-
# include "zstd_legacy.h"
|
|
71
|
+
# include "../legacy/zstd_legacy.h"
|
|
72
72
|
#endif
|
|
73
73
|
|
|
74
74
|
|
|
@@ -88,10 +88,7 @@ size_t ZSTD_estimateDCtxSize(void) { return sizeof(ZSTD_DCtx); }
|
|
|
88
88
|
|
|
89
89
|
static size_t ZSTD_startingInputLength(ZSTD_format_e format)
|
|
90
90
|
{
|
|
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);
|
|
91
|
+
size_t const startingInputLength = ZSTD_FRAMEHEADERSIZE_PREFIX(format);
|
|
95
92
|
/* only supports formats ZSTD_f_zstd1 and ZSTD_f_zstd1_magicless */
|
|
96
93
|
assert( (format == ZSTD_f_zstd1) || (format == ZSTD_f_zstd1_magicless) );
|
|
97
94
|
return startingInputLength;
|
|
@@ -106,6 +103,7 @@ static void ZSTD_initDCtx_internal(ZSTD_DCtx* dctx)
|
|
|
106
103
|
dctx->ddictLocal = NULL;
|
|
107
104
|
dctx->dictEnd = NULL;
|
|
108
105
|
dctx->ddictIsCold = 0;
|
|
106
|
+
dctx->dictUses = ZSTD_dont_use;
|
|
109
107
|
dctx->inBuff = NULL;
|
|
110
108
|
dctx->inBuffSize = 0;
|
|
111
109
|
dctx->outBuffSize = 0;
|
|
@@ -113,7 +111,12 @@ static void ZSTD_initDCtx_internal(ZSTD_DCtx* dctx)
|
|
|
113
111
|
dctx->legacyContext = NULL;
|
|
114
112
|
dctx->previousLegacyVersion = 0;
|
|
115
113
|
dctx->noForwardProgress = 0;
|
|
114
|
+
dctx->oversizedDuration = 0;
|
|
116
115
|
dctx->bmi2 = ZSTD_cpuid_bmi2(ZSTD_cpuid());
|
|
116
|
+
dctx->outBufferMode = ZSTD_obm_buffered;
|
|
117
|
+
#ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
|
|
118
|
+
dctx->dictContentEndForFuzzing = NULL;
|
|
119
|
+
#endif
|
|
117
120
|
}
|
|
118
121
|
|
|
119
122
|
ZSTD_DCtx* ZSTD_initStaticDCtx(void *workspace, size_t workspaceSize)
|
|
@@ -147,13 +150,20 @@ ZSTD_DCtx* ZSTD_createDCtx(void)
|
|
|
147
150
|
return ZSTD_createDCtx_advanced(ZSTD_defaultCMem);
|
|
148
151
|
}
|
|
149
152
|
|
|
153
|
+
static void ZSTD_clearDict(ZSTD_DCtx* dctx)
|
|
154
|
+
{
|
|
155
|
+
ZSTD_freeDDict(dctx->ddictLocal);
|
|
156
|
+
dctx->ddictLocal = NULL;
|
|
157
|
+
dctx->ddict = NULL;
|
|
158
|
+
dctx->dictUses = ZSTD_dont_use;
|
|
159
|
+
}
|
|
160
|
+
|
|
150
161
|
size_t ZSTD_freeDCtx(ZSTD_DCtx* dctx)
|
|
151
162
|
{
|
|
152
163
|
if (dctx==NULL) return 0; /* support free on NULL */
|
|
153
|
-
|
|
164
|
+
RETURN_ERROR_IF(dctx->staticSize, memory_allocation, "not compatible with static DCtx");
|
|
154
165
|
{ ZSTD_customMem const cMem = dctx->customMem;
|
|
155
|
-
|
|
156
|
-
dctx->ddictLocal = NULL;
|
|
166
|
+
ZSTD_clearDict(dctx);
|
|
157
167
|
ZSTD_free(dctx->inBuff, cMem);
|
|
158
168
|
dctx->inBuff = NULL;
|
|
159
169
|
#if defined(ZSTD_LEGACY_SUPPORT) && (ZSTD_LEGACY_SUPPORT >= 1)
|
|
@@ -203,7 +213,7 @@ unsigned ZSTD_isFrame(const void* buffer, size_t size)
|
|
|
203
213
|
static size_t ZSTD_frameHeaderSize_internal(const void* src, size_t srcSize, ZSTD_format_e format)
|
|
204
214
|
{
|
|
205
215
|
size_t const minInputSize = ZSTD_startingInputLength(format);
|
|
206
|
-
|
|
216
|
+
RETURN_ERROR_IF(srcSize < minInputSize, srcSize_wrong, "");
|
|
207
217
|
|
|
208
218
|
{ BYTE const fhd = ((const BYTE*)src)[minInputSize-1];
|
|
209
219
|
U32 const dictID= fhd & 3;
|
|
@@ -238,7 +248,7 @@ size_t ZSTD_getFrameHeader_advanced(ZSTD_frameHeader* zfhPtr, const void* src, s
|
|
|
238
248
|
|
|
239
249
|
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 */
|
|
240
250
|
if (srcSize < minInputSize) return minInputSize;
|
|
241
|
-
|
|
251
|
+
RETURN_ERROR_IF(src==NULL, GENERIC, "invalid parameter");
|
|
242
252
|
|
|
243
253
|
if ( (format != ZSTD_f_zstd1_magicless)
|
|
244
254
|
&& (MEM_readLE32(src) != ZSTD_MAGICNUMBER) ) {
|
|
@@ -251,7 +261,7 @@ size_t ZSTD_getFrameHeader_advanced(ZSTD_frameHeader* zfhPtr, const void* src, s
|
|
|
251
261
|
zfhPtr->frameType = ZSTD_skippableFrame;
|
|
252
262
|
return 0;
|
|
253
263
|
}
|
|
254
|
-
|
|
264
|
+
RETURN_ERROR(prefix_unknown, "");
|
|
255
265
|
}
|
|
256
266
|
|
|
257
267
|
/* ensure there is enough `srcSize` to fully read/decode frame header */
|
|
@@ -269,14 +279,13 @@ size_t ZSTD_getFrameHeader_advanced(ZSTD_frameHeader* zfhPtr, const void* src, s
|
|
|
269
279
|
U64 windowSize = 0;
|
|
270
280
|
U32 dictID = 0;
|
|
271
281
|
U64 frameContentSize = ZSTD_CONTENTSIZE_UNKNOWN;
|
|
272
|
-
|
|
273
|
-
|
|
282
|
+
RETURN_ERROR_IF((fhdByte & 0x08) != 0, frameParameter_unsupported,
|
|
283
|
+
"reserved bits, must be zero");
|
|
274
284
|
|
|
275
285
|
if (!singleSegment) {
|
|
276
286
|
BYTE const wlByte = ip[pos++];
|
|
277
287
|
U32 const windowLog = (wlByte >> 3) + ZSTD_WINDOWLOG_ABSOLUTEMIN;
|
|
278
|
-
|
|
279
|
-
return ERROR(frameParameter_windowTooLarge);
|
|
288
|
+
RETURN_ERROR_IF(windowLog > ZSTD_WINDOWLOG_MAX, frameParameter_windowTooLarge, "");
|
|
280
289
|
windowSize = (1ULL << windowLog);
|
|
281
290
|
windowSize += (windowSize >> 3) * (wlByte&7);
|
|
282
291
|
}
|
|
@@ -348,14 +357,16 @@ static size_t readSkippableFrameSize(void const* src, size_t srcSize)
|
|
|
348
357
|
size_t const skippableHeaderSize = ZSTD_SKIPPABLEHEADERSIZE;
|
|
349
358
|
U32 sizeU32;
|
|
350
359
|
|
|
351
|
-
|
|
352
|
-
return ERROR(srcSize_wrong);
|
|
360
|
+
RETURN_ERROR_IF(srcSize < ZSTD_SKIPPABLEHEADERSIZE, srcSize_wrong, "");
|
|
353
361
|
|
|
354
362
|
sizeU32 = MEM_readLE32((BYTE const*)src + ZSTD_FRAMEIDSIZE);
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
363
|
+
RETURN_ERROR_IF((U32)(sizeU32 + ZSTD_SKIPPABLEHEADERSIZE) < sizeU32,
|
|
364
|
+
frameParameter_unsupported, "");
|
|
365
|
+
{
|
|
366
|
+
size_t const skippableSize = skippableHeaderSize + sizeU32;
|
|
367
|
+
RETURN_ERROR_IF(skippableSize > srcSize, srcSize_wrong, "");
|
|
368
|
+
return skippableSize;
|
|
369
|
+
}
|
|
359
370
|
}
|
|
360
371
|
|
|
361
372
|
/** ZSTD_findDecompressedSize() :
|
|
@@ -367,16 +378,15 @@ unsigned long long ZSTD_findDecompressedSize(const void* src, size_t srcSize)
|
|
|
367
378
|
{
|
|
368
379
|
unsigned long long totalDstSize = 0;
|
|
369
380
|
|
|
370
|
-
while (srcSize >=
|
|
381
|
+
while (srcSize >= ZSTD_startingInputLength(ZSTD_f_zstd1)) {
|
|
371
382
|
U32 const magicNumber = MEM_readLE32(src);
|
|
372
383
|
|
|
373
384
|
if ((magicNumber & ZSTD_MAGIC_SKIPPABLE_MASK) == ZSTD_MAGIC_SKIPPABLE_START) {
|
|
374
385
|
size_t const skippableSize = readSkippableFrameSize(src, srcSize);
|
|
375
|
-
if (ZSTD_isError(skippableSize))
|
|
376
|
-
return skippableSize;
|
|
377
|
-
if (srcSize < skippableSize) {
|
|
386
|
+
if (ZSTD_isError(skippableSize)) {
|
|
378
387
|
return ZSTD_CONTENTSIZE_ERROR;
|
|
379
388
|
}
|
|
389
|
+
assert(skippableSize <= srcSize);
|
|
380
390
|
|
|
381
391
|
src = (const BYTE *)src + skippableSize;
|
|
382
392
|
srcSize -= skippableSize;
|
|
@@ -428,88 +438,137 @@ static size_t ZSTD_decodeFrameHeader(ZSTD_DCtx* dctx, const void* src, size_t he
|
|
|
428
438
|
{
|
|
429
439
|
size_t const result = ZSTD_getFrameHeader_advanced(&(dctx->fParams), src, headerSize, dctx->format);
|
|
430
440
|
if (ZSTD_isError(result)) return result; /* invalid header */
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
441
|
+
RETURN_ERROR_IF(result>0, srcSize_wrong, "headerSize too small");
|
|
442
|
+
#ifndef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
|
|
443
|
+
/* Skip the dictID check in fuzzing mode, because it makes the search
|
|
444
|
+
* harder.
|
|
445
|
+
*/
|
|
446
|
+
RETURN_ERROR_IF(dctx->fParams.dictID && (dctx->dictID != dctx->fParams.dictID),
|
|
447
|
+
dictionary_wrong, "");
|
|
448
|
+
#endif
|
|
434
449
|
if (dctx->fParams.checksumFlag) XXH64_reset(&dctx->xxhState, 0);
|
|
435
450
|
return 0;
|
|
436
451
|
}
|
|
437
452
|
|
|
453
|
+
static ZSTD_frameSizeInfo ZSTD_errorFrameSizeInfo(size_t ret)
|
|
454
|
+
{
|
|
455
|
+
ZSTD_frameSizeInfo frameSizeInfo;
|
|
456
|
+
frameSizeInfo.compressedSize = ret;
|
|
457
|
+
frameSizeInfo.decompressedBound = ZSTD_CONTENTSIZE_ERROR;
|
|
458
|
+
return frameSizeInfo;
|
|
459
|
+
}
|
|
438
460
|
|
|
439
|
-
|
|
440
|
-
* compatible with legacy mode
|
|
441
|
-
* `src` must point to the start of a ZSTD frame, ZSTD legacy frame, or skippable frame
|
|
442
|
-
* `srcSize` must be at least as large as the frame contained
|
|
443
|
-
* @return : the compressed size of the frame starting at `src` */
|
|
444
|
-
size_t ZSTD_findFrameCompressedSize(const void *src, size_t srcSize)
|
|
461
|
+
static ZSTD_frameSizeInfo ZSTD_findFrameSizeInfo(const void* src, size_t srcSize)
|
|
445
462
|
{
|
|
463
|
+
ZSTD_frameSizeInfo frameSizeInfo;
|
|
464
|
+
memset(&frameSizeInfo, 0, sizeof(ZSTD_frameSizeInfo));
|
|
465
|
+
|
|
446
466
|
#if defined(ZSTD_LEGACY_SUPPORT) && (ZSTD_LEGACY_SUPPORT >= 1)
|
|
447
467
|
if (ZSTD_isLegacy(src, srcSize))
|
|
448
|
-
return
|
|
468
|
+
return ZSTD_findFrameSizeInfoLegacy(src, srcSize);
|
|
449
469
|
#endif
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
470
|
+
|
|
471
|
+
if ((srcSize >= ZSTD_SKIPPABLEHEADERSIZE)
|
|
472
|
+
&& (MEM_readLE32(src) & ZSTD_MAGIC_SKIPPABLE_MASK) == ZSTD_MAGIC_SKIPPABLE_START) {
|
|
473
|
+
frameSizeInfo.compressedSize = readSkippableFrameSize(src, srcSize);
|
|
474
|
+
assert(ZSTD_isError(frameSizeInfo.compressedSize) ||
|
|
475
|
+
frameSizeInfo.compressedSize <= srcSize);
|
|
476
|
+
return frameSizeInfo;
|
|
453
477
|
} else {
|
|
454
478
|
const BYTE* ip = (const BYTE*)src;
|
|
455
479
|
const BYTE* const ipstart = ip;
|
|
456
480
|
size_t remainingSize = srcSize;
|
|
481
|
+
size_t nbBlocks = 0;
|
|
457
482
|
ZSTD_frameHeader zfh;
|
|
458
483
|
|
|
459
484
|
/* Extract Frame Header */
|
|
460
485
|
{ size_t const ret = ZSTD_getFrameHeader(&zfh, src, srcSize);
|
|
461
|
-
if (ZSTD_isError(ret))
|
|
462
|
-
|
|
486
|
+
if (ZSTD_isError(ret))
|
|
487
|
+
return ZSTD_errorFrameSizeInfo(ret);
|
|
488
|
+
if (ret > 0)
|
|
489
|
+
return ZSTD_errorFrameSizeInfo(ERROR(srcSize_wrong));
|
|
463
490
|
}
|
|
464
491
|
|
|
465
492
|
ip += zfh.headerSize;
|
|
466
493
|
remainingSize -= zfh.headerSize;
|
|
467
494
|
|
|
468
|
-
/*
|
|
495
|
+
/* Iterate over each block */
|
|
469
496
|
while (1) {
|
|
470
497
|
blockProperties_t blockProperties;
|
|
471
498
|
size_t const cBlockSize = ZSTD_getcBlockSize(ip, remainingSize, &blockProperties);
|
|
472
|
-
if (ZSTD_isError(cBlockSize))
|
|
499
|
+
if (ZSTD_isError(cBlockSize))
|
|
500
|
+
return ZSTD_errorFrameSizeInfo(cBlockSize);
|
|
473
501
|
|
|
474
502
|
if (ZSTD_blockHeaderSize + cBlockSize > remainingSize)
|
|
475
|
-
return ERROR(srcSize_wrong);
|
|
503
|
+
return ZSTD_errorFrameSizeInfo(ERROR(srcSize_wrong));
|
|
476
504
|
|
|
477
505
|
ip += ZSTD_blockHeaderSize + cBlockSize;
|
|
478
506
|
remainingSize -= ZSTD_blockHeaderSize + cBlockSize;
|
|
507
|
+
nbBlocks++;
|
|
479
508
|
|
|
480
509
|
if (blockProperties.lastBlock) break;
|
|
481
510
|
}
|
|
482
511
|
|
|
483
|
-
|
|
484
|
-
|
|
512
|
+
/* Final frame content checksum */
|
|
513
|
+
if (zfh.checksumFlag) {
|
|
514
|
+
if (remainingSize < 4)
|
|
515
|
+
return ZSTD_errorFrameSizeInfo(ERROR(srcSize_wrong));
|
|
485
516
|
ip += 4;
|
|
486
517
|
}
|
|
487
518
|
|
|
488
|
-
|
|
519
|
+
frameSizeInfo.compressedSize = ip - ipstart;
|
|
520
|
+
frameSizeInfo.decompressedBound = (zfh.frameContentSize != ZSTD_CONTENTSIZE_UNKNOWN)
|
|
521
|
+
? zfh.frameContentSize
|
|
522
|
+
: nbBlocks * zfh.blockSizeMax;
|
|
523
|
+
return frameSizeInfo;
|
|
489
524
|
}
|
|
490
525
|
}
|
|
491
526
|
|
|
527
|
+
/** ZSTD_findFrameCompressedSize() :
|
|
528
|
+
* compatible with legacy mode
|
|
529
|
+
* `src` must point to the start of a ZSTD frame, ZSTD legacy frame, or skippable frame
|
|
530
|
+
* `srcSize` must be at least as large as the frame contained
|
|
531
|
+
* @return : the compressed size of the frame starting at `src` */
|
|
532
|
+
size_t ZSTD_findFrameCompressedSize(const void *src, size_t srcSize)
|
|
533
|
+
{
|
|
534
|
+
ZSTD_frameSizeInfo const frameSizeInfo = ZSTD_findFrameSizeInfo(src, srcSize);
|
|
535
|
+
return frameSizeInfo.compressedSize;
|
|
536
|
+
}
|
|
537
|
+
|
|
538
|
+
/** ZSTD_decompressBound() :
|
|
539
|
+
* compatible with legacy mode
|
|
540
|
+
* `src` must point to the start of a ZSTD frame or a skippeable frame
|
|
541
|
+
* `srcSize` must be at least as large as the frame contained
|
|
542
|
+
* @return : the maximum decompressed size of the compressed source
|
|
543
|
+
*/
|
|
544
|
+
unsigned long long ZSTD_decompressBound(const void* src, size_t srcSize)
|
|
545
|
+
{
|
|
546
|
+
unsigned long long bound = 0;
|
|
547
|
+
/* Iterate over each frame */
|
|
548
|
+
while (srcSize > 0) {
|
|
549
|
+
ZSTD_frameSizeInfo const frameSizeInfo = ZSTD_findFrameSizeInfo(src, srcSize);
|
|
550
|
+
size_t const compressedSize = frameSizeInfo.compressedSize;
|
|
551
|
+
unsigned long long const decompressedBound = frameSizeInfo.decompressedBound;
|
|
552
|
+
if (ZSTD_isError(compressedSize) || decompressedBound == ZSTD_CONTENTSIZE_ERROR)
|
|
553
|
+
return ZSTD_CONTENTSIZE_ERROR;
|
|
554
|
+
assert(srcSize >= compressedSize);
|
|
555
|
+
src = (const BYTE*)src + compressedSize;
|
|
556
|
+
srcSize -= compressedSize;
|
|
557
|
+
bound += decompressedBound;
|
|
558
|
+
}
|
|
559
|
+
return bound;
|
|
560
|
+
}
|
|
492
561
|
|
|
493
562
|
|
|
494
563
|
/*-*************************************************************
|
|
495
564
|
* Frame decoding
|
|
496
565
|
***************************************************************/
|
|
497
566
|
|
|
498
|
-
|
|
499
|
-
void ZSTD_checkContinuity(ZSTD_DCtx* dctx, const void* dst)
|
|
500
|
-
{
|
|
501
|
-
if (dst != dctx->previousDstEnd) { /* not contiguous */
|
|
502
|
-
dctx->dictEnd = dctx->previousDstEnd;
|
|
503
|
-
dctx->virtualStart = (const char*)dst - ((const char*)(dctx->previousDstEnd) - (const char*)(dctx->prefixStart));
|
|
504
|
-
dctx->prefixStart = dst;
|
|
505
|
-
dctx->previousDstEnd = dst;
|
|
506
|
-
}
|
|
507
|
-
}
|
|
508
|
-
|
|
509
567
|
/** ZSTD_insertBlock() :
|
|
510
|
-
|
|
568
|
+
* insert `src` block into `dctx` history. Useful to track uncompressed blocks. */
|
|
511
569
|
size_t ZSTD_insertBlock(ZSTD_DCtx* dctx, const void* blockStart, size_t blockSize)
|
|
512
570
|
{
|
|
571
|
+
DEBUGLOG(5, "ZSTD_insertBlock: %u bytes", (unsigned)blockSize);
|
|
513
572
|
ZSTD_checkContinuity(dctx, blockStart);
|
|
514
573
|
dctx->previousDstEnd = (const char*)blockStart + blockSize;
|
|
515
574
|
return blockSize;
|
|
@@ -522,9 +581,9 @@ static size_t ZSTD_copyRawBlock(void* dst, size_t dstCapacity,
|
|
|
522
581
|
DEBUGLOG(5, "ZSTD_copyRawBlock");
|
|
523
582
|
if (dst == NULL) {
|
|
524
583
|
if (srcSize == 0) return 0;
|
|
525
|
-
|
|
584
|
+
RETURN_ERROR(dstBuffer_null, "");
|
|
526
585
|
}
|
|
527
|
-
|
|
586
|
+
RETURN_ERROR_IF(srcSize > dstCapacity, dstSize_tooSmall, "");
|
|
528
587
|
memcpy(dst, src, srcSize);
|
|
529
588
|
return srcSize;
|
|
530
589
|
}
|
|
@@ -535,9 +594,9 @@ static size_t ZSTD_setRleBlock(void* dst, size_t dstCapacity,
|
|
|
535
594
|
{
|
|
536
595
|
if (dst == NULL) {
|
|
537
596
|
if (regenSize == 0) return 0;
|
|
538
|
-
|
|
597
|
+
RETURN_ERROR(dstBuffer_null, "");
|
|
539
598
|
}
|
|
540
|
-
|
|
599
|
+
RETURN_ERROR_IF(regenSize > dstCapacity, dstSize_tooSmall, "");
|
|
541
600
|
memset(dst, b, regenSize);
|
|
542
601
|
return regenSize;
|
|
543
602
|
}
|
|
@@ -553,22 +612,24 @@ static size_t ZSTD_decompressFrame(ZSTD_DCtx* dctx,
|
|
|
553
612
|
{
|
|
554
613
|
const BYTE* ip = (const BYTE*)(*srcPtr);
|
|
555
614
|
BYTE* const ostart = (BYTE* const)dst;
|
|
556
|
-
BYTE* const oend = ostart + dstCapacity;
|
|
615
|
+
BYTE* const oend = dstCapacity != 0 ? ostart + dstCapacity : ostart;
|
|
557
616
|
BYTE* op = ostart;
|
|
558
617
|
size_t remainingSrcSize = *srcSizePtr;
|
|
559
618
|
|
|
560
619
|
DEBUGLOG(4, "ZSTD_decompressFrame (srcSize:%i)", (int)*srcSizePtr);
|
|
561
620
|
|
|
562
621
|
/* check */
|
|
563
|
-
|
|
564
|
-
|
|
622
|
+
RETURN_ERROR_IF(
|
|
623
|
+
remainingSrcSize < ZSTD_FRAMEHEADERSIZE_MIN(dctx->format)+ZSTD_blockHeaderSize,
|
|
624
|
+
srcSize_wrong, "");
|
|
565
625
|
|
|
566
626
|
/* Frame Header */
|
|
567
|
-
{ size_t const frameHeaderSize =
|
|
627
|
+
{ size_t const frameHeaderSize = ZSTD_frameHeaderSize_internal(
|
|
628
|
+
ip, ZSTD_FRAMEHEADERSIZE_PREFIX(dctx->format), dctx->format);
|
|
568
629
|
if (ZSTD_isError(frameHeaderSize)) return frameHeaderSize;
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
630
|
+
RETURN_ERROR_IF(remainingSrcSize < frameHeaderSize+ZSTD_blockHeaderSize,
|
|
631
|
+
srcSize_wrong, "");
|
|
632
|
+
FORWARD_IF_ERROR( ZSTD_decodeFrameHeader(dctx, ip, frameHeaderSize) , "");
|
|
572
633
|
ip += frameHeaderSize; remainingSrcSize -= frameHeaderSize;
|
|
573
634
|
}
|
|
574
635
|
|
|
@@ -581,7 +642,7 @@ static size_t ZSTD_decompressFrame(ZSTD_DCtx* dctx,
|
|
|
581
642
|
|
|
582
643
|
ip += ZSTD_blockHeaderSize;
|
|
583
644
|
remainingSrcSize -= ZSTD_blockHeaderSize;
|
|
584
|
-
|
|
645
|
+
RETURN_ERROR_IF(cBlockSize > remainingSrcSize, srcSize_wrong, "");
|
|
585
646
|
|
|
586
647
|
switch(blockProperties.blockType)
|
|
587
648
|
{
|
|
@@ -596,28 +657,30 @@ static size_t ZSTD_decompressFrame(ZSTD_DCtx* dctx,
|
|
|
596
657
|
break;
|
|
597
658
|
case bt_reserved :
|
|
598
659
|
default:
|
|
599
|
-
|
|
660
|
+
RETURN_ERROR(corruption_detected, "invalid block type");
|
|
600
661
|
}
|
|
601
662
|
|
|
602
663
|
if (ZSTD_isError(decodedSize)) return decodedSize;
|
|
603
664
|
if (dctx->fParams.checksumFlag)
|
|
604
665
|
XXH64_update(&dctx->xxhState, op, decodedSize);
|
|
605
|
-
|
|
666
|
+
if (decodedSize != 0)
|
|
667
|
+
op += decodedSize;
|
|
668
|
+
assert(ip != NULL);
|
|
606
669
|
ip += cBlockSize;
|
|
607
670
|
remainingSrcSize -= cBlockSize;
|
|
608
671
|
if (blockProperties.lastBlock) break;
|
|
609
672
|
}
|
|
610
673
|
|
|
611
674
|
if (dctx->fParams.frameContentSize != ZSTD_CONTENTSIZE_UNKNOWN) {
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
}
|
|
675
|
+
RETURN_ERROR_IF((U64)(op-ostart) != dctx->fParams.frameContentSize,
|
|
676
|
+
corruption_detected, "");
|
|
677
|
+
}
|
|
615
678
|
if (dctx->fParams.checksumFlag) { /* Frame content checksum verification */
|
|
616
679
|
U32 const checkCalc = (U32)XXH64_digest(&dctx->xxhState);
|
|
617
680
|
U32 checkRead;
|
|
618
|
-
|
|
681
|
+
RETURN_ERROR_IF(remainingSrcSize<4, checksum_wrong, "");
|
|
619
682
|
checkRead = MEM_readLE32(ip);
|
|
620
|
-
|
|
683
|
+
RETURN_ERROR_IF(checkRead != checkCalc, checksum_wrong, "");
|
|
621
684
|
ip += 4;
|
|
622
685
|
remainingSrcSize -= 4;
|
|
623
686
|
}
|
|
@@ -645,15 +708,15 @@ static size_t ZSTD_decompressMultiFrame(ZSTD_DCtx* dctx,
|
|
|
645
708
|
dictSize = ZSTD_DDict_dictSize(ddict);
|
|
646
709
|
}
|
|
647
710
|
|
|
648
|
-
while (srcSize >=
|
|
711
|
+
while (srcSize >= ZSTD_startingInputLength(dctx->format)) {
|
|
649
712
|
|
|
650
713
|
#if defined(ZSTD_LEGACY_SUPPORT) && (ZSTD_LEGACY_SUPPORT >= 1)
|
|
651
714
|
if (ZSTD_isLegacy(src, srcSize)) {
|
|
652
715
|
size_t decodedSize;
|
|
653
716
|
size_t const frameSize = ZSTD_findFrameCompressedSizeLegacy(src, srcSize);
|
|
654
717
|
if (ZSTD_isError(frameSize)) return frameSize;
|
|
655
|
-
|
|
656
|
-
|
|
718
|
+
RETURN_ERROR_IF(dctx->staticSize, memory_allocation,
|
|
719
|
+
"legacy support is not compatible with static dctx");
|
|
657
720
|
|
|
658
721
|
decodedSize = ZSTD_decompressLegacy(dst, dstCapacity, src, frameSize, dict, dictSize);
|
|
659
722
|
if (ZSTD_isError(decodedSize)) return decodedSize;
|
|
@@ -674,9 +737,8 @@ static size_t ZSTD_decompressMultiFrame(ZSTD_DCtx* dctx,
|
|
|
674
737
|
(unsigned)magicNumber, ZSTD_MAGICNUMBER);
|
|
675
738
|
if ((magicNumber & ZSTD_MAGIC_SKIPPABLE_MASK) == ZSTD_MAGIC_SKIPPABLE_START) {
|
|
676
739
|
size_t const skippableSize = readSkippableFrameSize(src, srcSize);
|
|
677
|
-
|
|
678
|
-
|
|
679
|
-
if (srcSize < skippableSize) return ERROR(srcSize_wrong);
|
|
740
|
+
FORWARD_IF_ERROR(skippableSize, "readSkippableFrameSize failed");
|
|
741
|
+
assert(skippableSize <= srcSize);
|
|
680
742
|
|
|
681
743
|
src = (const BYTE *)src + skippableSize;
|
|
682
744
|
srcSize -= skippableSize;
|
|
@@ -685,38 +747,39 @@ static size_t ZSTD_decompressMultiFrame(ZSTD_DCtx* dctx,
|
|
|
685
747
|
|
|
686
748
|
if (ddict) {
|
|
687
749
|
/* we were called from ZSTD_decompress_usingDDict */
|
|
688
|
-
|
|
750
|
+
FORWARD_IF_ERROR(ZSTD_decompressBegin_usingDDict(dctx, ddict), "");
|
|
689
751
|
} else {
|
|
690
752
|
/* this will initialize correctly with no dict if dict == NULL, so
|
|
691
753
|
* use this in all cases but ddict */
|
|
692
|
-
|
|
754
|
+
FORWARD_IF_ERROR(ZSTD_decompressBegin_usingDict(dctx, dict, dictSize), "");
|
|
693
755
|
}
|
|
694
756
|
ZSTD_checkContinuity(dctx, dst);
|
|
695
757
|
|
|
696
758
|
{ const size_t res = ZSTD_decompressFrame(dctx, dst, dstCapacity,
|
|
697
759
|
&src, &srcSize);
|
|
698
|
-
|
|
699
|
-
|
|
700
|
-
|
|
701
|
-
|
|
702
|
-
|
|
703
|
-
|
|
704
|
-
|
|
705
|
-
|
|
706
|
-
|
|
707
|
-
|
|
708
|
-
|
|
709
|
-
|
|
710
|
-
|
|
760
|
+
RETURN_ERROR_IF(
|
|
761
|
+
(ZSTD_getErrorCode(res) == ZSTD_error_prefix_unknown)
|
|
762
|
+
&& (moreThan1Frame==1),
|
|
763
|
+
srcSize_wrong,
|
|
764
|
+
"at least one frame successfully completed, but following "
|
|
765
|
+
"bytes are garbage: it's more likely to be a srcSize error, "
|
|
766
|
+
"specifying more bytes than compressed size of frame(s). This "
|
|
767
|
+
"error message replaces ERROR(prefix_unknown), which would be "
|
|
768
|
+
"confusing, as the first header is actually correct. Note that "
|
|
769
|
+
"one could be unlucky, it might be a corruption error instead, "
|
|
770
|
+
"happening right at the place where we expect zstd magic "
|
|
771
|
+
"bytes. But this is _much_ less likely than a srcSize field "
|
|
772
|
+
"error.");
|
|
711
773
|
if (ZSTD_isError(res)) return res;
|
|
712
774
|
assert(res <= dstCapacity);
|
|
713
|
-
|
|
775
|
+
if (res != 0)
|
|
776
|
+
dst = (BYTE*)dst + res;
|
|
714
777
|
dstCapacity -= res;
|
|
715
778
|
}
|
|
716
779
|
moreThan1Frame = 1;
|
|
717
780
|
} /* while (srcSize >= ZSTD_frameHeaderSize_prefix) */
|
|
718
781
|
|
|
719
|
-
|
|
782
|
+
RETURN_ERROR_IF(srcSize, srcSize_wrong, "input not entirely consumed");
|
|
720
783
|
|
|
721
784
|
return (BYTE*)dst - (BYTE*)dststart;
|
|
722
785
|
}
|
|
@@ -730,9 +793,26 @@ size_t ZSTD_decompress_usingDict(ZSTD_DCtx* dctx,
|
|
|
730
793
|
}
|
|
731
794
|
|
|
732
795
|
|
|
796
|
+
static ZSTD_DDict const* ZSTD_getDDict(ZSTD_DCtx* dctx)
|
|
797
|
+
{
|
|
798
|
+
switch (dctx->dictUses) {
|
|
799
|
+
default:
|
|
800
|
+
assert(0 /* Impossible */);
|
|
801
|
+
/* fall-through */
|
|
802
|
+
case ZSTD_dont_use:
|
|
803
|
+
ZSTD_clearDict(dctx);
|
|
804
|
+
return NULL;
|
|
805
|
+
case ZSTD_use_indefinitely:
|
|
806
|
+
return dctx->ddict;
|
|
807
|
+
case ZSTD_use_once:
|
|
808
|
+
dctx->dictUses = ZSTD_dont_use;
|
|
809
|
+
return dctx->ddict;
|
|
810
|
+
}
|
|
811
|
+
}
|
|
812
|
+
|
|
733
813
|
size_t ZSTD_decompressDCtx(ZSTD_DCtx* dctx, void* dst, size_t dstCapacity, const void* src, size_t srcSize)
|
|
734
814
|
{
|
|
735
|
-
return
|
|
815
|
+
return ZSTD_decompress_usingDDict(dctx, dst, dstCapacity, src, srcSize, ZSTD_getDDict(dctx));
|
|
736
816
|
}
|
|
737
817
|
|
|
738
818
|
|
|
@@ -741,7 +821,7 @@ size_t ZSTD_decompress(void* dst, size_t dstCapacity, const void* src, size_t sr
|
|
|
741
821
|
#if defined(ZSTD_HEAPMODE) && (ZSTD_HEAPMODE>=1)
|
|
742
822
|
size_t regenSize;
|
|
743
823
|
ZSTD_DCtx* const dctx = ZSTD_createDCtx();
|
|
744
|
-
|
|
824
|
+
RETURN_ERROR_IF(dctx==NULL, memory_allocation, "NULL pointer!");
|
|
745
825
|
regenSize = ZSTD_decompressDCtx(dctx, dst, dstCapacity, src, srcSize);
|
|
746
826
|
ZSTD_freeDCtx(dctx);
|
|
747
827
|
return regenSize;
|
|
@@ -759,6 +839,24 @@ size_t ZSTD_decompress(void* dst, size_t dstCapacity, const void* src, size_t sr
|
|
|
759
839
|
****************************************/
|
|
760
840
|
size_t ZSTD_nextSrcSizeToDecompress(ZSTD_DCtx* dctx) { return dctx->expected; }
|
|
761
841
|
|
|
842
|
+
/**
|
|
843
|
+
* Similar to ZSTD_nextSrcSizeToDecompress(), but when when a block input can be streamed,
|
|
844
|
+
* we allow taking a partial block as the input. Currently only raw uncompressed blocks can
|
|
845
|
+
* be streamed.
|
|
846
|
+
*
|
|
847
|
+
* For blocks that can be streamed, this allows us to reduce the latency until we produce
|
|
848
|
+
* output, and avoid copying the input.
|
|
849
|
+
*
|
|
850
|
+
* @param inputSize - The total amount of input that the caller currently has.
|
|
851
|
+
*/
|
|
852
|
+
static size_t ZSTD_nextSrcSizeToDecompressWithInputSize(ZSTD_DCtx* dctx, size_t inputSize) {
|
|
853
|
+
if (!(dctx->stage == ZSTDds_decompressBlock || dctx->stage == ZSTDds_decompressLastBlock))
|
|
854
|
+
return dctx->expected;
|
|
855
|
+
if (dctx->bType != bt_raw)
|
|
856
|
+
return dctx->expected;
|
|
857
|
+
return MIN(MAX(inputSize, 1), dctx->expected);
|
|
858
|
+
}
|
|
859
|
+
|
|
762
860
|
ZSTD_nextInputType_e ZSTD_nextInputType(ZSTD_DCtx* dctx) {
|
|
763
861
|
switch(dctx->stage)
|
|
764
862
|
{
|
|
@@ -791,8 +889,7 @@ size_t ZSTD_decompressContinue(ZSTD_DCtx* dctx, void* dst, size_t dstCapacity, c
|
|
|
791
889
|
{
|
|
792
890
|
DEBUGLOG(5, "ZSTD_decompressContinue (srcSize:%u)", (unsigned)srcSize);
|
|
793
891
|
/* Sanity check */
|
|
794
|
-
|
|
795
|
-
return ERROR(srcSize_wrong); /* not allowed */
|
|
892
|
+
RETURN_ERROR_IF(srcSize != ZSTD_nextSrcSizeToDecompressWithInputSize(dctx, srcSize), srcSize_wrong, "not allowed");
|
|
796
893
|
if (dstCapacity) ZSTD_checkContinuity(dctx, dst);
|
|
797
894
|
|
|
798
895
|
switch (dctx->stage)
|
|
@@ -817,7 +914,7 @@ size_t ZSTD_decompressContinue(ZSTD_DCtx* dctx, void* dst, size_t dstCapacity, c
|
|
|
817
914
|
case ZSTDds_decodeFrameHeader:
|
|
818
915
|
assert(src != NULL);
|
|
819
916
|
memcpy(dctx->headerBuffer + (dctx->headerSize - srcSize), src, srcSize);
|
|
820
|
-
|
|
917
|
+
FORWARD_IF_ERROR(ZSTD_decodeFrameHeader(dctx, dctx->headerBuffer, dctx->headerSize), "");
|
|
821
918
|
dctx->expected = ZSTD_blockHeaderSize;
|
|
822
919
|
dctx->stage = ZSTDds_decodeBlockHeader;
|
|
823
920
|
return 0;
|
|
@@ -826,6 +923,7 @@ size_t ZSTD_decompressContinue(ZSTD_DCtx* dctx, void* dst, size_t dstCapacity, c
|
|
|
826
923
|
{ blockProperties_t bp;
|
|
827
924
|
size_t const cBlockSize = ZSTD_getcBlockSize(src, ZSTD_blockHeaderSize, &bp);
|
|
828
925
|
if (ZSTD_isError(cBlockSize)) return cBlockSize;
|
|
926
|
+
RETURN_ERROR_IF(cBlockSize > dctx->fParams.blockSizeMax, corruption_detected, "Block Size Exceeds Maximum");
|
|
829
927
|
dctx->expected = cBlockSize;
|
|
830
928
|
dctx->bType = bp.blockType;
|
|
831
929
|
dctx->rleSize = bp.origSize;
|
|
@@ -858,28 +956,41 @@ size_t ZSTD_decompressContinue(ZSTD_DCtx* dctx, void* dst, size_t dstCapacity, c
|
|
|
858
956
|
case bt_compressed:
|
|
859
957
|
DEBUGLOG(5, "ZSTD_decompressContinue: case bt_compressed");
|
|
860
958
|
rSize = ZSTD_decompressBlock_internal(dctx, dst, dstCapacity, src, srcSize, /* frame */ 1);
|
|
959
|
+
dctx->expected = 0; /* Streaming not supported */
|
|
861
960
|
break;
|
|
862
961
|
case bt_raw :
|
|
962
|
+
assert(srcSize <= dctx->expected);
|
|
863
963
|
rSize = ZSTD_copyRawBlock(dst, dstCapacity, src, srcSize);
|
|
964
|
+
FORWARD_IF_ERROR(rSize, "ZSTD_copyRawBlock failed");
|
|
965
|
+
assert(rSize == srcSize);
|
|
966
|
+
dctx->expected -= rSize;
|
|
864
967
|
break;
|
|
865
968
|
case bt_rle :
|
|
866
969
|
rSize = ZSTD_setRleBlock(dst, dstCapacity, *(const BYTE*)src, dctx->rleSize);
|
|
970
|
+
dctx->expected = 0; /* Streaming not supported */
|
|
867
971
|
break;
|
|
868
972
|
case bt_reserved : /* should never happen */
|
|
869
973
|
default:
|
|
870
|
-
|
|
974
|
+
RETURN_ERROR(corruption_detected, "invalid block type");
|
|
871
975
|
}
|
|
872
|
-
|
|
976
|
+
FORWARD_IF_ERROR(rSize, "");
|
|
977
|
+
RETURN_ERROR_IF(rSize > dctx->fParams.blockSizeMax, corruption_detected, "Decompressed Block Size Exceeds Maximum");
|
|
873
978
|
DEBUGLOG(5, "ZSTD_decompressContinue: decoded size from block : %u", (unsigned)rSize);
|
|
874
979
|
dctx->decodedSize += rSize;
|
|
875
980
|
if (dctx->fParams.checksumFlag) XXH64_update(&dctx->xxhState, dst, rSize);
|
|
981
|
+
dctx->previousDstEnd = (char*)dst + rSize;
|
|
982
|
+
|
|
983
|
+
/* Stay on the same stage until we are finished streaming the block. */
|
|
984
|
+
if (dctx->expected > 0) {
|
|
985
|
+
return rSize;
|
|
986
|
+
}
|
|
876
987
|
|
|
877
988
|
if (dctx->stage == ZSTDds_decompressLastBlock) { /* end of frame */
|
|
878
989
|
DEBUGLOG(4, "ZSTD_decompressContinue: decoded size from frame : %u", (unsigned)dctx->decodedSize);
|
|
879
|
-
|
|
880
|
-
|
|
881
|
-
|
|
882
|
-
|
|
990
|
+
RETURN_ERROR_IF(
|
|
991
|
+
dctx->fParams.frameContentSize != ZSTD_CONTENTSIZE_UNKNOWN
|
|
992
|
+
&& dctx->decodedSize != dctx->fParams.frameContentSize,
|
|
993
|
+
corruption_detected, "");
|
|
883
994
|
if (dctx->fParams.checksumFlag) { /* another round for frame checksum */
|
|
884
995
|
dctx->expected = 4;
|
|
885
996
|
dctx->stage = ZSTDds_checkChecksum;
|
|
@@ -890,7 +1001,6 @@ size_t ZSTD_decompressContinue(ZSTD_DCtx* dctx, void* dst, size_t dstCapacity, c
|
|
|
890
1001
|
} else {
|
|
891
1002
|
dctx->stage = ZSTDds_decodeBlockHeader;
|
|
892
1003
|
dctx->expected = ZSTD_blockHeaderSize;
|
|
893
|
-
dctx->previousDstEnd = (char*)dst + rSize;
|
|
894
1004
|
}
|
|
895
1005
|
return rSize;
|
|
896
1006
|
}
|
|
@@ -900,7 +1010,7 @@ size_t ZSTD_decompressContinue(ZSTD_DCtx* dctx, void* dst, size_t dstCapacity, c
|
|
|
900
1010
|
{ U32 const h32 = (U32)XXH64_digest(&dctx->xxhState);
|
|
901
1011
|
U32 const check32 = MEM_readLE32(src);
|
|
902
1012
|
DEBUGLOG(4, "ZSTD_decompressContinue: checksum : calculated %08X :: %08X read", (unsigned)h32, (unsigned)check32);
|
|
903
|
-
|
|
1013
|
+
RETURN_ERROR_IF(check32 != h32, checksum_wrong, "");
|
|
904
1014
|
dctx->expected = 0;
|
|
905
1015
|
dctx->stage = ZSTDds_getFrameHeaderSize;
|
|
906
1016
|
return 0;
|
|
@@ -921,7 +1031,7 @@ size_t ZSTD_decompressContinue(ZSTD_DCtx* dctx, void* dst, size_t dstCapacity, c
|
|
|
921
1031
|
|
|
922
1032
|
default:
|
|
923
1033
|
assert(0); /* impossible */
|
|
924
|
-
|
|
1034
|
+
RETURN_ERROR(GENERIC, "impossible to reach"); /* some compiler require default to do something */
|
|
925
1035
|
}
|
|
926
1036
|
}
|
|
927
1037
|
|
|
@@ -932,6 +1042,10 @@ static size_t ZSTD_refDictContent(ZSTD_DCtx* dctx, const void* dict, size_t dict
|
|
|
932
1042
|
dctx->virtualStart = (const char*)dict - ((const char*)(dctx->previousDstEnd) - (const char*)(dctx->prefixStart));
|
|
933
1043
|
dctx->prefixStart = dict;
|
|
934
1044
|
dctx->previousDstEnd = (const char*)dict + dictSize;
|
|
1045
|
+
#ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
|
|
1046
|
+
dctx->dictContentBeginForFuzzing = dctx->prefixStart;
|
|
1047
|
+
dctx->dictContentEndForFuzzing = dctx->previousDstEnd;
|
|
1048
|
+
#endif
|
|
935
1049
|
return 0;
|
|
936
1050
|
}
|
|
937
1051
|
|
|
@@ -945,7 +1059,7 @@ ZSTD_loadDEntropy(ZSTD_entropyDTables_t* entropy,
|
|
|
945
1059
|
const BYTE* dictPtr = (const BYTE*)dict;
|
|
946
1060
|
const BYTE* const dictEnd = dictPtr + dictSize;
|
|
947
1061
|
|
|
948
|
-
|
|
1062
|
+
RETURN_ERROR_IF(dictSize <= 8, dictionary_corrupted, "dict is too small");
|
|
949
1063
|
assert(MEM_readLE32(dict) == ZSTD_MAGIC_DICTIONARY); /* dict must be valid */
|
|
950
1064
|
dictPtr += 8; /* skip header = magic + dictID */
|
|
951
1065
|
|
|
@@ -964,16 +1078,16 @@ ZSTD_loadDEntropy(ZSTD_entropyDTables_t* entropy,
|
|
|
964
1078
|
dictPtr, dictEnd - dictPtr,
|
|
965
1079
|
workspace, workspaceSize);
|
|
966
1080
|
#endif
|
|
967
|
-
|
|
1081
|
+
RETURN_ERROR_IF(HUF_isError(hSize), dictionary_corrupted, "");
|
|
968
1082
|
dictPtr += hSize;
|
|
969
1083
|
}
|
|
970
1084
|
|
|
971
1085
|
{ short offcodeNCount[MaxOff+1];
|
|
972
1086
|
unsigned offcodeMaxValue = MaxOff, offcodeLog;
|
|
973
1087
|
size_t const offcodeHeaderSize = FSE_readNCount(offcodeNCount, &offcodeMaxValue, &offcodeLog, dictPtr, dictEnd-dictPtr);
|
|
974
|
-
|
|
975
|
-
|
|
976
|
-
|
|
1088
|
+
RETURN_ERROR_IF(FSE_isError(offcodeHeaderSize), dictionary_corrupted, "");
|
|
1089
|
+
RETURN_ERROR_IF(offcodeMaxValue > MaxOff, dictionary_corrupted, "");
|
|
1090
|
+
RETURN_ERROR_IF(offcodeLog > OffFSELog, dictionary_corrupted, "");
|
|
977
1091
|
ZSTD_buildFSETable( entropy->OFTable,
|
|
978
1092
|
offcodeNCount, offcodeMaxValue,
|
|
979
1093
|
OF_base, OF_bits,
|
|
@@ -984,9 +1098,9 @@ ZSTD_loadDEntropy(ZSTD_entropyDTables_t* entropy,
|
|
|
984
1098
|
{ short matchlengthNCount[MaxML+1];
|
|
985
1099
|
unsigned matchlengthMaxValue = MaxML, matchlengthLog;
|
|
986
1100
|
size_t const matchlengthHeaderSize = FSE_readNCount(matchlengthNCount, &matchlengthMaxValue, &matchlengthLog, dictPtr, dictEnd-dictPtr);
|
|
987
|
-
|
|
988
|
-
|
|
989
|
-
|
|
1101
|
+
RETURN_ERROR_IF(FSE_isError(matchlengthHeaderSize), dictionary_corrupted, "");
|
|
1102
|
+
RETURN_ERROR_IF(matchlengthMaxValue > MaxML, dictionary_corrupted, "");
|
|
1103
|
+
RETURN_ERROR_IF(matchlengthLog > MLFSELog, dictionary_corrupted, "");
|
|
990
1104
|
ZSTD_buildFSETable( entropy->MLTable,
|
|
991
1105
|
matchlengthNCount, matchlengthMaxValue,
|
|
992
1106
|
ML_base, ML_bits,
|
|
@@ -997,9 +1111,9 @@ ZSTD_loadDEntropy(ZSTD_entropyDTables_t* entropy,
|
|
|
997
1111
|
{ short litlengthNCount[MaxLL+1];
|
|
998
1112
|
unsigned litlengthMaxValue = MaxLL, litlengthLog;
|
|
999
1113
|
size_t const litlengthHeaderSize = FSE_readNCount(litlengthNCount, &litlengthMaxValue, &litlengthLog, dictPtr, dictEnd-dictPtr);
|
|
1000
|
-
|
|
1001
|
-
|
|
1002
|
-
|
|
1114
|
+
RETURN_ERROR_IF(FSE_isError(litlengthHeaderSize), dictionary_corrupted, "");
|
|
1115
|
+
RETURN_ERROR_IF(litlengthMaxValue > MaxLL, dictionary_corrupted, "");
|
|
1116
|
+
RETURN_ERROR_IF(litlengthLog > LLFSELog, dictionary_corrupted, "");
|
|
1003
1117
|
ZSTD_buildFSETable( entropy->LLTable,
|
|
1004
1118
|
litlengthNCount, litlengthMaxValue,
|
|
1005
1119
|
LL_base, LL_bits,
|
|
@@ -1007,12 +1121,13 @@ ZSTD_loadDEntropy(ZSTD_entropyDTables_t* entropy,
|
|
|
1007
1121
|
dictPtr += litlengthHeaderSize;
|
|
1008
1122
|
}
|
|
1009
1123
|
|
|
1010
|
-
|
|
1124
|
+
RETURN_ERROR_IF(dictPtr+12 > dictEnd, dictionary_corrupted, "");
|
|
1011
1125
|
{ int i;
|
|
1012
1126
|
size_t const dictContentSize = (size_t)(dictEnd - (dictPtr+12));
|
|
1013
1127
|
for (i=0; i<3; i++) {
|
|
1014
1128
|
U32 const rep = MEM_readLE32(dictPtr); dictPtr += 4;
|
|
1015
|
-
|
|
1129
|
+
RETURN_ERROR_IF(rep==0 || rep > dictContentSize,
|
|
1130
|
+
dictionary_corrupted, "");
|
|
1016
1131
|
entropy->rep[i] = rep;
|
|
1017
1132
|
} }
|
|
1018
1133
|
|
|
@@ -1030,7 +1145,7 @@ static size_t ZSTD_decompress_insertDictionary(ZSTD_DCtx* dctx, const void* dict
|
|
|
1030
1145
|
|
|
1031
1146
|
/* load entropy tables */
|
|
1032
1147
|
{ size_t const eSize = ZSTD_loadDEntropy(&dctx->entropy, dict, dictSize);
|
|
1033
|
-
|
|
1148
|
+
RETURN_ERROR_IF(ZSTD_isError(eSize), dictionary_corrupted, "");
|
|
1034
1149
|
dict = (const char*)dict + eSize;
|
|
1035
1150
|
dictSize -= eSize;
|
|
1036
1151
|
}
|
|
@@ -1053,6 +1168,7 @@ size_t ZSTD_decompressBegin(ZSTD_DCtx* dctx)
|
|
|
1053
1168
|
dctx->entropy.hufTable[0] = (HUF_DTable)((HufLog)*0x1000001); /* cover both little and big endian */
|
|
1054
1169
|
dctx->litEntropy = dctx->fseEntropy = 0;
|
|
1055
1170
|
dctx->dictID = 0;
|
|
1171
|
+
dctx->bType = bt_reserved;
|
|
1056
1172
|
ZSTD_STATIC_ASSERT(sizeof(dctx->entropy.rep) == sizeof(repStartValue));
|
|
1057
1173
|
memcpy(dctx->entropy.rep, repStartValue, sizeof(repStartValue)); /* initial repcodes */
|
|
1058
1174
|
dctx->LLTptr = dctx->entropy.LLTable;
|
|
@@ -1064,9 +1180,11 @@ size_t ZSTD_decompressBegin(ZSTD_DCtx* dctx)
|
|
|
1064
1180
|
|
|
1065
1181
|
size_t ZSTD_decompressBegin_usingDict(ZSTD_DCtx* dctx, const void* dict, size_t dictSize)
|
|
1066
1182
|
{
|
|
1067
|
-
|
|
1183
|
+
FORWARD_IF_ERROR( ZSTD_decompressBegin(dctx) , "");
|
|
1068
1184
|
if (dict && dictSize)
|
|
1069
|
-
|
|
1185
|
+
RETURN_ERROR_IF(
|
|
1186
|
+
ZSTD_isError(ZSTD_decompress_insertDictionary(dctx, dict, dictSize)),
|
|
1187
|
+
dictionary_corrupted, "");
|
|
1070
1188
|
return 0;
|
|
1071
1189
|
}
|
|
1072
1190
|
|
|
@@ -1085,7 +1203,7 @@ size_t ZSTD_decompressBegin_usingDDict(ZSTD_DCtx* dctx, const ZSTD_DDict* ddict)
|
|
|
1085
1203
|
DEBUGLOG(4, "DDict is %s",
|
|
1086
1204
|
dctx->ddictIsCold ? "~cold~" : "hot!");
|
|
1087
1205
|
}
|
|
1088
|
-
|
|
1206
|
+
FORWARD_IF_ERROR( ZSTD_decompressBegin(dctx) , "");
|
|
1089
1207
|
if (ddict) { /* NULL ddict is equivalent to no dictionary */
|
|
1090
1208
|
ZSTD_copyDDictParameters(dctx, ddict);
|
|
1091
1209
|
}
|
|
@@ -1104,7 +1222,7 @@ unsigned ZSTD_getDictID_fromDict(const void* dict, size_t dictSize)
|
|
|
1104
1222
|
}
|
|
1105
1223
|
|
|
1106
1224
|
/*! ZSTD_getDictID_fromFrame() :
|
|
1107
|
-
* Provides the dictID required to
|
|
1225
|
+
* Provides the dictID required to decompress frame stored within `src`.
|
|
1108
1226
|
* If @return == 0, the dictID could not be decoded.
|
|
1109
1227
|
* This could for one of the following reasons :
|
|
1110
1228
|
* - The frame does not require a dictionary (most common case).
|
|
@@ -1176,15 +1294,14 @@ size_t ZSTD_DCtx_loadDictionary_advanced(ZSTD_DCtx* dctx,
|
|
|
1176
1294
|
ZSTD_dictLoadMethod_e dictLoadMethod,
|
|
1177
1295
|
ZSTD_dictContentType_e dictContentType)
|
|
1178
1296
|
{
|
|
1179
|
-
|
|
1180
|
-
|
|
1181
|
-
if (dict && dictSize
|
|
1297
|
+
RETURN_ERROR_IF(dctx->streamStage != zdss_init, stage_wrong, "");
|
|
1298
|
+
ZSTD_clearDict(dctx);
|
|
1299
|
+
if (dict && dictSize != 0) {
|
|
1182
1300
|
dctx->ddictLocal = ZSTD_createDDict_advanced(dict, dictSize, dictLoadMethod, dictContentType, dctx->customMem);
|
|
1183
|
-
|
|
1184
|
-
|
|
1185
|
-
dctx->
|
|
1301
|
+
RETURN_ERROR_IF(dctx->ddictLocal == NULL, memory_allocation, "NULL pointer!");
|
|
1302
|
+
dctx->ddict = dctx->ddictLocal;
|
|
1303
|
+
dctx->dictUses = ZSTD_use_indefinitely;
|
|
1186
1304
|
}
|
|
1187
|
-
dctx->ddict = dctx->ddictLocal;
|
|
1188
1305
|
return 0;
|
|
1189
1306
|
}
|
|
1190
1307
|
|
|
@@ -1200,7 +1317,9 @@ size_t ZSTD_DCtx_loadDictionary(ZSTD_DCtx* dctx, const void* dict, size_t dictSi
|
|
|
1200
1317
|
|
|
1201
1318
|
size_t ZSTD_DCtx_refPrefix_advanced(ZSTD_DCtx* dctx, const void* prefix, size_t prefixSize, ZSTD_dictContentType_e dictContentType)
|
|
1202
1319
|
{
|
|
1203
|
-
|
|
1320
|
+
FORWARD_IF_ERROR(ZSTD_DCtx_loadDictionary_advanced(dctx, prefix, prefixSize, ZSTD_dlm_byRef, dictContentType), "");
|
|
1321
|
+
dctx->dictUses = ZSTD_use_once;
|
|
1322
|
+
return 0;
|
|
1204
1323
|
}
|
|
1205
1324
|
|
|
1206
1325
|
size_t ZSTD_DCtx_refPrefix(ZSTD_DCtx* dctx, const void* prefix, size_t prefixSize)
|
|
@@ -1210,22 +1329,21 @@ size_t ZSTD_DCtx_refPrefix(ZSTD_DCtx* dctx, const void* prefix, size_t prefixSiz
|
|
|
1210
1329
|
|
|
1211
1330
|
|
|
1212
1331
|
/* ZSTD_initDStream_usingDict() :
|
|
1213
|
-
* return : expected size, aka
|
|
1332
|
+
* return : expected size, aka ZSTD_startingInputLength().
|
|
1214
1333
|
* this function cannot fail */
|
|
1215
1334
|
size_t ZSTD_initDStream_usingDict(ZSTD_DStream* zds, const void* dict, size_t dictSize)
|
|
1216
1335
|
{
|
|
1217
1336
|
DEBUGLOG(4, "ZSTD_initDStream_usingDict");
|
|
1218
|
-
zds
|
|
1219
|
-
zds
|
|
1220
|
-
|
|
1221
|
-
return ZSTD_FRAMEHEADERSIZE_PREFIX;
|
|
1337
|
+
FORWARD_IF_ERROR( ZSTD_DCtx_reset(zds, ZSTD_reset_session_only) , "");
|
|
1338
|
+
FORWARD_IF_ERROR( ZSTD_DCtx_loadDictionary(zds, dict, dictSize) , "");
|
|
1339
|
+
return ZSTD_startingInputLength(zds->format);
|
|
1222
1340
|
}
|
|
1223
1341
|
|
|
1224
1342
|
/* note : this variant can't fail */
|
|
1225
1343
|
size_t ZSTD_initDStream(ZSTD_DStream* zds)
|
|
1226
1344
|
{
|
|
1227
1345
|
DEBUGLOG(4, "ZSTD_initDStream");
|
|
1228
|
-
return
|
|
1346
|
+
return ZSTD_initDStream_usingDDict(zds, NULL);
|
|
1229
1347
|
}
|
|
1230
1348
|
|
|
1231
1349
|
/* ZSTD_initDStream_usingDDict() :
|
|
@@ -1233,29 +1351,29 @@ size_t ZSTD_initDStream(ZSTD_DStream* zds)
|
|
|
1233
1351
|
* this function cannot fail */
|
|
1234
1352
|
size_t ZSTD_initDStream_usingDDict(ZSTD_DStream* dctx, const ZSTD_DDict* ddict)
|
|
1235
1353
|
{
|
|
1236
|
-
|
|
1237
|
-
dctx
|
|
1238
|
-
return
|
|
1354
|
+
FORWARD_IF_ERROR( ZSTD_DCtx_reset(dctx, ZSTD_reset_session_only) , "");
|
|
1355
|
+
FORWARD_IF_ERROR( ZSTD_DCtx_refDDict(dctx, ddict) , "");
|
|
1356
|
+
return ZSTD_startingInputLength(dctx->format);
|
|
1239
1357
|
}
|
|
1240
1358
|
|
|
1241
1359
|
/* ZSTD_resetDStream() :
|
|
1242
|
-
* return : expected size, aka
|
|
1360
|
+
* return : expected size, aka ZSTD_startingInputLength().
|
|
1243
1361
|
* this function cannot fail */
|
|
1244
1362
|
size_t ZSTD_resetDStream(ZSTD_DStream* dctx)
|
|
1245
1363
|
{
|
|
1246
|
-
|
|
1247
|
-
dctx->
|
|
1248
|
-
dctx->lhSize = dctx->inPos = dctx->outStart = dctx->outEnd = 0;
|
|
1249
|
-
dctx->legacyVersion = 0;
|
|
1250
|
-
dctx->hostageByte = 0;
|
|
1251
|
-
return ZSTD_FRAMEHEADERSIZE_PREFIX;
|
|
1364
|
+
FORWARD_IF_ERROR(ZSTD_DCtx_reset(dctx, ZSTD_reset_session_only), "");
|
|
1365
|
+
return ZSTD_startingInputLength(dctx->format);
|
|
1252
1366
|
}
|
|
1253
1367
|
|
|
1254
1368
|
|
|
1255
1369
|
size_t ZSTD_DCtx_refDDict(ZSTD_DCtx* dctx, const ZSTD_DDict* ddict)
|
|
1256
1370
|
{
|
|
1257
|
-
|
|
1258
|
-
dctx
|
|
1371
|
+
RETURN_ERROR_IF(dctx->streamStage != zdss_init, stage_wrong, "");
|
|
1372
|
+
ZSTD_clearDict(dctx);
|
|
1373
|
+
if (ddict) {
|
|
1374
|
+
dctx->ddict = ddict;
|
|
1375
|
+
dctx->dictUses = ZSTD_use_indefinitely;
|
|
1376
|
+
}
|
|
1259
1377
|
return 0;
|
|
1260
1378
|
}
|
|
1261
1379
|
|
|
@@ -1267,9 +1385,9 @@ size_t ZSTD_DCtx_setMaxWindowSize(ZSTD_DCtx* dctx, size_t maxWindowSize)
|
|
|
1267
1385
|
ZSTD_bounds const bounds = ZSTD_dParam_getBounds(ZSTD_d_windowLogMax);
|
|
1268
1386
|
size_t const min = (size_t)1 << bounds.lowerBound;
|
|
1269
1387
|
size_t const max = (size_t)1 << bounds.upperBound;
|
|
1270
|
-
|
|
1271
|
-
|
|
1272
|
-
|
|
1388
|
+
RETURN_ERROR_IF(dctx->streamStage != zdss_init, stage_wrong, "");
|
|
1389
|
+
RETURN_ERROR_IF(maxWindowSize < min, parameter_outOfBound, "");
|
|
1390
|
+
RETURN_ERROR_IF(maxWindowSize > max, parameter_outOfBound, "");
|
|
1273
1391
|
dctx->maxWindowSize = maxWindowSize;
|
|
1274
1392
|
return 0;
|
|
1275
1393
|
}
|
|
@@ -1292,6 +1410,10 @@ ZSTD_bounds ZSTD_dParam_getBounds(ZSTD_dParameter dParam)
|
|
|
1292
1410
|
bounds.upperBound = (int)ZSTD_f_zstd1_magicless;
|
|
1293
1411
|
ZSTD_STATIC_ASSERT(ZSTD_f_zstd1 < ZSTD_f_zstd1_magicless);
|
|
1294
1412
|
return bounds;
|
|
1413
|
+
case ZSTD_d_stableOutBuffer:
|
|
1414
|
+
bounds.lowerBound = (int)ZSTD_obm_buffered;
|
|
1415
|
+
bounds.upperBound = (int)ZSTD_obm_stable;
|
|
1416
|
+
return bounds;
|
|
1295
1417
|
default:;
|
|
1296
1418
|
}
|
|
1297
1419
|
bounds.error = ERROR(parameter_unsupported);
|
|
@@ -1311,15 +1433,15 @@ static int ZSTD_dParam_withinBounds(ZSTD_dParameter dParam, int value)
|
|
|
1311
1433
|
}
|
|
1312
1434
|
|
|
1313
1435
|
#define CHECK_DBOUNDS(p,v) { \
|
|
1314
|
-
|
|
1315
|
-
return ERROR(parameter_outOfBound); \
|
|
1436
|
+
RETURN_ERROR_IF(!ZSTD_dParam_withinBounds(p, v), parameter_outOfBound, ""); \
|
|
1316
1437
|
}
|
|
1317
1438
|
|
|
1318
1439
|
size_t ZSTD_DCtx_setParameter(ZSTD_DCtx* dctx, ZSTD_dParameter dParam, int value)
|
|
1319
1440
|
{
|
|
1320
|
-
|
|
1441
|
+
RETURN_ERROR_IF(dctx->streamStage != zdss_init, stage_wrong, "");
|
|
1321
1442
|
switch(dParam) {
|
|
1322
1443
|
case ZSTD_d_windowLogMax:
|
|
1444
|
+
if (value == 0) value = ZSTD_WINDOWLOG_LIMIT_DEFAULT;
|
|
1323
1445
|
CHECK_DBOUNDS(ZSTD_d_windowLogMax, value);
|
|
1324
1446
|
dctx->maxWindowSize = ((size_t)1) << value;
|
|
1325
1447
|
return 0;
|
|
@@ -1327,21 +1449,26 @@ size_t ZSTD_DCtx_setParameter(ZSTD_DCtx* dctx, ZSTD_dParameter dParam, int value
|
|
|
1327
1449
|
CHECK_DBOUNDS(ZSTD_d_format, value);
|
|
1328
1450
|
dctx->format = (ZSTD_format_e)value;
|
|
1329
1451
|
return 0;
|
|
1452
|
+
case ZSTD_d_stableOutBuffer:
|
|
1453
|
+
CHECK_DBOUNDS(ZSTD_d_stableOutBuffer, value);
|
|
1454
|
+
dctx->outBufferMode = (ZSTD_outBufferMode_e)value;
|
|
1455
|
+
return 0;
|
|
1330
1456
|
default:;
|
|
1331
1457
|
}
|
|
1332
|
-
|
|
1458
|
+
RETURN_ERROR(parameter_unsupported, "");
|
|
1333
1459
|
}
|
|
1334
1460
|
|
|
1335
1461
|
size_t ZSTD_DCtx_reset(ZSTD_DCtx* dctx, ZSTD_ResetDirective reset)
|
|
1336
1462
|
{
|
|
1337
1463
|
if ( (reset == ZSTD_reset_session_only)
|
|
1338
1464
|
|| (reset == ZSTD_reset_session_and_parameters) ) {
|
|
1339
|
-
|
|
1465
|
+
dctx->streamStage = zdss_init;
|
|
1466
|
+
dctx->noForwardProgress = 0;
|
|
1340
1467
|
}
|
|
1341
1468
|
if ( (reset == ZSTD_reset_parameters)
|
|
1342
1469
|
|| (reset == ZSTD_reset_session_and_parameters) ) {
|
|
1343
|
-
|
|
1344
|
-
|
|
1470
|
+
RETURN_ERROR_IF(dctx->streamStage != zdss_init, stage_wrong, "");
|
|
1471
|
+
ZSTD_clearDict(dctx);
|
|
1345
1472
|
dctx->format = ZSTD_f_zstd1;
|
|
1346
1473
|
dctx->maxWindowSize = ZSTD_MAXWINDOWSIZE_DEFAULT;
|
|
1347
1474
|
}
|
|
@@ -1360,7 +1487,8 @@ size_t ZSTD_decodingBufferSize_min(unsigned long long windowSize, unsigned long
|
|
|
1360
1487
|
unsigned long long const neededRBSize = windowSize + blockSize + (WILDCOPY_OVERLENGTH * 2);
|
|
1361
1488
|
unsigned long long const neededSize = MIN(frameContentSize, neededRBSize);
|
|
1362
1489
|
size_t const minRBSize = (size_t) neededSize;
|
|
1363
|
-
|
|
1490
|
+
RETURN_ERROR_IF((unsigned long long)minRBSize != neededSize,
|
|
1491
|
+
frameParameter_windowTooLarge, "");
|
|
1364
1492
|
return minRBSize;
|
|
1365
1493
|
}
|
|
1366
1494
|
|
|
@@ -1378,60 +1506,129 @@ size_t ZSTD_estimateDStreamSize_fromFrame(const void* src, size_t srcSize)
|
|
|
1378
1506
|
ZSTD_frameHeader zfh;
|
|
1379
1507
|
size_t const err = ZSTD_getFrameHeader(&zfh, src, srcSize);
|
|
1380
1508
|
if (ZSTD_isError(err)) return err;
|
|
1381
|
-
|
|
1382
|
-
|
|
1383
|
-
|
|
1509
|
+
RETURN_ERROR_IF(err>0, srcSize_wrong, "");
|
|
1510
|
+
RETURN_ERROR_IF(zfh.windowSize > windowSizeMax,
|
|
1511
|
+
frameParameter_windowTooLarge, "");
|
|
1384
1512
|
return ZSTD_estimateDStreamSize((size_t)zfh.windowSize);
|
|
1385
1513
|
}
|
|
1386
1514
|
|
|
1387
1515
|
|
|
1388
1516
|
/* ***** Decompression ***** */
|
|
1389
1517
|
|
|
1390
|
-
|
|
1518
|
+
static int ZSTD_DCtx_isOverflow(ZSTD_DStream* zds, size_t const neededInBuffSize, size_t const neededOutBuffSize)
|
|
1391
1519
|
{
|
|
1392
|
-
|
|
1393
|
-
|
|
1394
|
-
|
|
1520
|
+
return (zds->inBuffSize + zds->outBuffSize) >= (neededInBuffSize + neededOutBuffSize) * ZSTD_WORKSPACETOOLARGE_FACTOR;
|
|
1521
|
+
}
|
|
1522
|
+
|
|
1523
|
+
static void ZSTD_DCtx_updateOversizedDuration(ZSTD_DStream* zds, size_t const neededInBuffSize, size_t const neededOutBuffSize)
|
|
1524
|
+
{
|
|
1525
|
+
if (ZSTD_DCtx_isOverflow(zds, neededInBuffSize, neededOutBuffSize))
|
|
1526
|
+
zds->oversizedDuration++;
|
|
1527
|
+
else
|
|
1528
|
+
zds->oversizedDuration = 0;
|
|
1529
|
+
}
|
|
1530
|
+
|
|
1531
|
+
static int ZSTD_DCtx_isOversizedTooLong(ZSTD_DStream* zds)
|
|
1532
|
+
{
|
|
1533
|
+
return zds->oversizedDuration >= ZSTD_WORKSPACETOOLARGE_MAXDURATION;
|
|
1534
|
+
}
|
|
1535
|
+
|
|
1536
|
+
/* Checks that the output buffer hasn't changed if ZSTD_obm_stable is used. */
|
|
1537
|
+
static size_t ZSTD_checkOutBuffer(ZSTD_DStream const* zds, ZSTD_outBuffer const* output)
|
|
1538
|
+
{
|
|
1539
|
+
ZSTD_outBuffer const expect = zds->expectedOutBuffer;
|
|
1540
|
+
/* No requirement when ZSTD_obm_stable is not enabled. */
|
|
1541
|
+
if (zds->outBufferMode != ZSTD_obm_stable)
|
|
1542
|
+
return 0;
|
|
1543
|
+
/* Any buffer is allowed in zdss_init, this must be the same for every other call until
|
|
1544
|
+
* the context is reset.
|
|
1545
|
+
*/
|
|
1546
|
+
if (zds->streamStage == zdss_init)
|
|
1547
|
+
return 0;
|
|
1548
|
+
/* The buffer must match our expectation exactly. */
|
|
1549
|
+
if (expect.dst == output->dst && expect.pos == output->pos && expect.size == output->size)
|
|
1550
|
+
return 0;
|
|
1551
|
+
RETURN_ERROR(dstBuffer_wrong, "ZSTD_obm_stable enabled but output differs!");
|
|
1395
1552
|
}
|
|
1396
1553
|
|
|
1554
|
+
/* Calls ZSTD_decompressContinue() with the right parameters for ZSTD_decompressStream()
|
|
1555
|
+
* and updates the stage and the output buffer state. This call is extracted so it can be
|
|
1556
|
+
* used both when reading directly from the ZSTD_inBuffer, and in buffered input mode.
|
|
1557
|
+
* NOTE: You must break after calling this function since the streamStage is modified.
|
|
1558
|
+
*/
|
|
1559
|
+
static size_t ZSTD_decompressContinueStream(
|
|
1560
|
+
ZSTD_DStream* zds, char** op, char* oend,
|
|
1561
|
+
void const* src, size_t srcSize) {
|
|
1562
|
+
int const isSkipFrame = ZSTD_isSkipFrame(zds);
|
|
1563
|
+
if (zds->outBufferMode == ZSTD_obm_buffered) {
|
|
1564
|
+
size_t const dstSize = isSkipFrame ? 0 : zds->outBuffSize - zds->outStart;
|
|
1565
|
+
size_t const decodedSize = ZSTD_decompressContinue(zds,
|
|
1566
|
+
zds->outBuff + zds->outStart, dstSize, src, srcSize);
|
|
1567
|
+
FORWARD_IF_ERROR(decodedSize, "");
|
|
1568
|
+
if (!decodedSize && !isSkipFrame) {
|
|
1569
|
+
zds->streamStage = zdss_read;
|
|
1570
|
+
} else {
|
|
1571
|
+
zds->outEnd = zds->outStart + decodedSize;
|
|
1572
|
+
zds->streamStage = zdss_flush;
|
|
1573
|
+
}
|
|
1574
|
+
} else {
|
|
1575
|
+
/* Write directly into the output buffer */
|
|
1576
|
+
size_t const dstSize = isSkipFrame ? 0 : oend - *op;
|
|
1577
|
+
size_t const decodedSize = ZSTD_decompressContinue(zds, *op, dstSize, src, srcSize);
|
|
1578
|
+
FORWARD_IF_ERROR(decodedSize, "");
|
|
1579
|
+
*op += decodedSize;
|
|
1580
|
+
/* Flushing is not needed. */
|
|
1581
|
+
zds->streamStage = zdss_read;
|
|
1582
|
+
assert(*op <= oend);
|
|
1583
|
+
assert(zds->outBufferMode == ZSTD_obm_stable);
|
|
1584
|
+
}
|
|
1585
|
+
return 0;
|
|
1586
|
+
}
|
|
1397
1587
|
|
|
1398
1588
|
size_t ZSTD_decompressStream(ZSTD_DStream* zds, ZSTD_outBuffer* output, ZSTD_inBuffer* input)
|
|
1399
1589
|
{
|
|
1400
|
-
const char* const
|
|
1401
|
-
const char* const
|
|
1590
|
+
const char* const src = (const char*)input->src;
|
|
1591
|
+
const char* const istart = input->pos != 0 ? src + input->pos : src;
|
|
1592
|
+
const char* const iend = input->size != 0 ? src + input->size : src;
|
|
1402
1593
|
const char* ip = istart;
|
|
1403
|
-
char* const
|
|
1404
|
-
char* const
|
|
1594
|
+
char* const dst = (char*)output->dst;
|
|
1595
|
+
char* const ostart = output->pos != 0 ? dst + output->pos : dst;
|
|
1596
|
+
char* const oend = output->size != 0 ? dst + output->size : dst;
|
|
1405
1597
|
char* op = ostart;
|
|
1406
1598
|
U32 someMoreWork = 1;
|
|
1407
1599
|
|
|
1408
1600
|
DEBUGLOG(5, "ZSTD_decompressStream");
|
|
1409
|
-
|
|
1410
|
-
|
|
1411
|
-
|
|
1412
|
-
|
|
1413
|
-
|
|
1414
|
-
|
|
1415
|
-
|
|
1416
|
-
|
|
1417
|
-
|
|
1418
|
-
|
|
1601
|
+
RETURN_ERROR_IF(
|
|
1602
|
+
input->pos > input->size,
|
|
1603
|
+
srcSize_wrong,
|
|
1604
|
+
"forbidden. in: pos: %u vs size: %u",
|
|
1605
|
+
(U32)input->pos, (U32)input->size);
|
|
1606
|
+
RETURN_ERROR_IF(
|
|
1607
|
+
output->pos > output->size,
|
|
1608
|
+
dstSize_tooSmall,
|
|
1609
|
+
"forbidden. out: pos: %u vs size: %u",
|
|
1610
|
+
(U32)output->pos, (U32)output->size);
|
|
1419
1611
|
DEBUGLOG(5, "input size : %u", (U32)(input->size - input->pos));
|
|
1612
|
+
FORWARD_IF_ERROR(ZSTD_checkOutBuffer(zds, output), "");
|
|
1420
1613
|
|
|
1421
1614
|
while (someMoreWork) {
|
|
1422
1615
|
switch(zds->streamStage)
|
|
1423
1616
|
{
|
|
1424
1617
|
case zdss_init :
|
|
1425
1618
|
DEBUGLOG(5, "stage zdss_init => transparent reset ");
|
|
1426
|
-
|
|
1619
|
+
zds->streamStage = zdss_loadHeader;
|
|
1620
|
+
zds->lhSize = zds->inPos = zds->outStart = zds->outEnd = 0;
|
|
1621
|
+
zds->legacyVersion = 0;
|
|
1622
|
+
zds->hostageByte = 0;
|
|
1623
|
+
zds->expectedOutBuffer = *output;
|
|
1427
1624
|
/* fall-through */
|
|
1428
1625
|
|
|
1429
1626
|
case zdss_loadHeader :
|
|
1430
1627
|
DEBUGLOG(5, "stage zdss_loadHeader (srcSize : %u)", (U32)(iend - ip));
|
|
1431
1628
|
#if defined(ZSTD_LEGACY_SUPPORT) && (ZSTD_LEGACY_SUPPORT>=1)
|
|
1432
1629
|
if (zds->legacyVersion) {
|
|
1433
|
-
|
|
1434
|
-
|
|
1630
|
+
RETURN_ERROR_IF(zds->staticSize, memory_allocation,
|
|
1631
|
+
"legacy support is incompatible with static dctx");
|
|
1435
1632
|
{ size_t const hint = ZSTD_decompressLegacyStream(zds->legacyContext, zds->legacyVersion, output, input);
|
|
1436
1633
|
if (hint==0) zds->streamStage = zdss_init;
|
|
1437
1634
|
return hint;
|
|
@@ -1443,14 +1640,15 @@ size_t ZSTD_decompressStream(ZSTD_DStream* zds, ZSTD_outBuffer* output, ZSTD_inB
|
|
|
1443
1640
|
#if defined(ZSTD_LEGACY_SUPPORT) && (ZSTD_LEGACY_SUPPORT>=1)
|
|
1444
1641
|
U32 const legacyVersion = ZSTD_isLegacy(istart, iend-istart);
|
|
1445
1642
|
if (legacyVersion) {
|
|
1446
|
-
const
|
|
1447
|
-
|
|
1643
|
+
ZSTD_DDict const* const ddict = ZSTD_getDDict(zds);
|
|
1644
|
+
const void* const dict = ddict ? ZSTD_DDict_dictContent(ddict) : NULL;
|
|
1645
|
+
size_t const dictSize = ddict ? ZSTD_DDict_dictSize(ddict) : 0;
|
|
1448
1646
|
DEBUGLOG(5, "ZSTD_decompressStream: detected legacy version v0.%u", legacyVersion);
|
|
1449
|
-
|
|
1450
|
-
|
|
1451
|
-
|
|
1647
|
+
RETURN_ERROR_IF(zds->staticSize, memory_allocation,
|
|
1648
|
+
"legacy support is incompatible with static dctx");
|
|
1649
|
+
FORWARD_IF_ERROR(ZSTD_initLegacyStream(&zds->legacyContext,
|
|
1452
1650
|
zds->previousLegacyVersion, legacyVersion,
|
|
1453
|
-
dict, dictSize));
|
|
1651
|
+
dict, dictSize), "");
|
|
1454
1652
|
zds->legacyVersion = zds->previousLegacyVersion = legacyVersion;
|
|
1455
1653
|
{ size_t const hint = ZSTD_decompressLegacyStream(zds->legacyContext, legacyVersion, output, input);
|
|
1456
1654
|
if (hint==0) zds->streamStage = zdss_init; /* or stay in stage zdss_loadHeader */
|
|
@@ -1469,7 +1667,7 @@ size_t ZSTD_decompressStream(ZSTD_DStream* zds, ZSTD_outBuffer* output, ZSTD_inB
|
|
|
1469
1667
|
zds->lhSize += remainingInput;
|
|
1470
1668
|
}
|
|
1471
1669
|
input->pos = input->size;
|
|
1472
|
-
return (MAX(ZSTD_FRAMEHEADERSIZE_MIN, hSize) - zds->lhSize) + ZSTD_blockHeaderSize; /* remaining header bytes + next block header */
|
|
1670
|
+
return (MAX((size_t)ZSTD_FRAMEHEADERSIZE_MIN(zds->format), hSize) - zds->lhSize) + ZSTD_blockHeaderSize; /* remaining header bytes + next block header */
|
|
1473
1671
|
}
|
|
1474
1672
|
assert(ip != NULL);
|
|
1475
1673
|
memcpy(zds->headerBuffer + zds->lhSize, ip, toLoad); zds->lhSize = hSize; ip += toLoad;
|
|
@@ -1477,12 +1675,13 @@ size_t ZSTD_decompressStream(ZSTD_DStream* zds, ZSTD_outBuffer* output, ZSTD_inB
|
|
|
1477
1675
|
} }
|
|
1478
1676
|
|
|
1479
1677
|
/* check for single-pass mode opportunity */
|
|
1480
|
-
if (zds->fParams.frameContentSize
|
|
1678
|
+
if (zds->fParams.frameContentSize != ZSTD_CONTENTSIZE_UNKNOWN
|
|
1679
|
+
&& zds->fParams.frameType != ZSTD_skippableFrame
|
|
1481
1680
|
&& (U64)(size_t)(oend-op) >= zds->fParams.frameContentSize) {
|
|
1482
1681
|
size_t const cSize = ZSTD_findFrameCompressedSize(istart, iend-istart);
|
|
1483
1682
|
if (cSize <= (size_t)(iend-istart)) {
|
|
1484
1683
|
/* shortcut : using single-pass mode */
|
|
1485
|
-
size_t const decompressedSize = ZSTD_decompress_usingDDict(zds, op, oend-op, istart, cSize, zds
|
|
1684
|
+
size_t const decompressedSize = ZSTD_decompress_usingDDict(zds, op, oend-op, istart, cSize, ZSTD_getDDict(zds));
|
|
1486
1685
|
if (ZSTD_isError(decompressedSize)) return decompressedSize;
|
|
1487
1686
|
DEBUGLOG(4, "shortcut to single-pass ZSTD_decompress_usingDDict()")
|
|
1488
1687
|
ip = istart + cSize;
|
|
@@ -1493,15 +1692,23 @@ size_t ZSTD_decompressStream(ZSTD_DStream* zds, ZSTD_outBuffer* output, ZSTD_inB
|
|
|
1493
1692
|
break;
|
|
1494
1693
|
} }
|
|
1495
1694
|
|
|
1695
|
+
/* Check output buffer is large enough for ZSTD_odm_stable. */
|
|
1696
|
+
if (zds->outBufferMode == ZSTD_obm_stable
|
|
1697
|
+
&& zds->fParams.frameType != ZSTD_skippableFrame
|
|
1698
|
+
&& zds->fParams.frameContentSize != ZSTD_CONTENTSIZE_UNKNOWN
|
|
1699
|
+
&& (U64)(size_t)(oend-op) < zds->fParams.frameContentSize) {
|
|
1700
|
+
RETURN_ERROR(dstSize_tooSmall, "ZSTD_obm_stable passed but ZSTD_outBuffer is too small");
|
|
1701
|
+
}
|
|
1702
|
+
|
|
1496
1703
|
/* Consume header (see ZSTDds_decodeFrameHeader) */
|
|
1497
1704
|
DEBUGLOG(4, "Consume header");
|
|
1498
|
-
|
|
1705
|
+
FORWARD_IF_ERROR(ZSTD_decompressBegin_usingDDict(zds, ZSTD_getDDict(zds)), "");
|
|
1499
1706
|
|
|
1500
1707
|
if ((MEM_readLE32(zds->headerBuffer) & ZSTD_MAGIC_SKIPPABLE_MASK) == ZSTD_MAGIC_SKIPPABLE_START) { /* skippable frame */
|
|
1501
1708
|
zds->expected = MEM_readLE32(zds->headerBuffer + ZSTD_FRAMEIDSIZE);
|
|
1502
1709
|
zds->stage = ZSTDds_skipFrame;
|
|
1503
1710
|
} else {
|
|
1504
|
-
|
|
1711
|
+
FORWARD_IF_ERROR(ZSTD_decodeFrameHeader(zds, zds->headerBuffer, zds->lhSize), "");
|
|
1505
1712
|
zds->expected = ZSTD_blockHeaderSize;
|
|
1506
1713
|
zds->stage = ZSTDds_decodeBlockHeader;
|
|
1507
1714
|
}
|
|
@@ -1511,39 +1718,49 @@ size_t ZSTD_decompressStream(ZSTD_DStream* zds, ZSTD_outBuffer* output, ZSTD_inB
|
|
|
1511
1718
|
(U32)(zds->fParams.windowSize >>10),
|
|
1512
1719
|
(U32)(zds->maxWindowSize >> 10) );
|
|
1513
1720
|
zds->fParams.windowSize = MAX(zds->fParams.windowSize, 1U << ZSTD_WINDOWLOG_ABSOLUTEMIN);
|
|
1514
|
-
|
|
1721
|
+
RETURN_ERROR_IF(zds->fParams.windowSize > zds->maxWindowSize,
|
|
1722
|
+
frameParameter_windowTooLarge, "");
|
|
1515
1723
|
|
|
1516
1724
|
/* Adapt buffer sizes to frame header instructions */
|
|
1517
1725
|
{ size_t const neededInBuffSize = MAX(zds->fParams.blockSizeMax, 4 /* frame checksum */);
|
|
1518
|
-
size_t const neededOutBuffSize =
|
|
1519
|
-
|
|
1520
|
-
|
|
1521
|
-
|
|
1522
|
-
|
|
1523
|
-
|
|
1524
|
-
|
|
1525
|
-
|
|
1526
|
-
|
|
1527
|
-
|
|
1528
|
-
|
|
1529
|
-
|
|
1530
|
-
|
|
1531
|
-
|
|
1532
|
-
|
|
1533
|
-
zds->
|
|
1534
|
-
|
|
1535
|
-
|
|
1536
|
-
|
|
1537
|
-
|
|
1538
|
-
|
|
1539
|
-
|
|
1540
|
-
|
|
1726
|
+
size_t const neededOutBuffSize = zds->outBufferMode == ZSTD_obm_buffered
|
|
1727
|
+
? ZSTD_decodingBufferSize_min(zds->fParams.windowSize, zds->fParams.frameContentSize)
|
|
1728
|
+
: 0;
|
|
1729
|
+
|
|
1730
|
+
ZSTD_DCtx_updateOversizedDuration(zds, neededInBuffSize, neededOutBuffSize);
|
|
1731
|
+
|
|
1732
|
+
{ int const tooSmall = (zds->inBuffSize < neededInBuffSize) || (zds->outBuffSize < neededOutBuffSize);
|
|
1733
|
+
int const tooLarge = ZSTD_DCtx_isOversizedTooLong(zds);
|
|
1734
|
+
|
|
1735
|
+
if (tooSmall || tooLarge) {
|
|
1736
|
+
size_t const bufferSize = neededInBuffSize + neededOutBuffSize;
|
|
1737
|
+
DEBUGLOG(4, "inBuff : from %u to %u",
|
|
1738
|
+
(U32)zds->inBuffSize, (U32)neededInBuffSize);
|
|
1739
|
+
DEBUGLOG(4, "outBuff : from %u to %u",
|
|
1740
|
+
(U32)zds->outBuffSize, (U32)neededOutBuffSize);
|
|
1741
|
+
if (zds->staticSize) { /* static DCtx */
|
|
1742
|
+
DEBUGLOG(4, "staticSize : %u", (U32)zds->staticSize);
|
|
1743
|
+
assert(zds->staticSize >= sizeof(ZSTD_DCtx)); /* controlled at init */
|
|
1744
|
+
RETURN_ERROR_IF(
|
|
1745
|
+
bufferSize > zds->staticSize - sizeof(ZSTD_DCtx),
|
|
1746
|
+
memory_allocation, "");
|
|
1747
|
+
} else {
|
|
1748
|
+
ZSTD_free(zds->inBuff, zds->customMem);
|
|
1749
|
+
zds->inBuffSize = 0;
|
|
1750
|
+
zds->outBuffSize = 0;
|
|
1751
|
+
zds->inBuff = (char*)ZSTD_malloc(bufferSize, zds->customMem);
|
|
1752
|
+
RETURN_ERROR_IF(zds->inBuff == NULL, memory_allocation, "");
|
|
1753
|
+
}
|
|
1754
|
+
zds->inBuffSize = neededInBuffSize;
|
|
1755
|
+
zds->outBuff = zds->inBuff + zds->inBuffSize;
|
|
1756
|
+
zds->outBuffSize = neededOutBuffSize;
|
|
1757
|
+
} } }
|
|
1541
1758
|
zds->streamStage = zdss_read;
|
|
1542
1759
|
/* fall-through */
|
|
1543
1760
|
|
|
1544
1761
|
case zdss_read:
|
|
1545
1762
|
DEBUGLOG(5, "stage zdss_read");
|
|
1546
|
-
{ size_t const neededInSize =
|
|
1763
|
+
{ size_t const neededInSize = ZSTD_nextSrcSizeToDecompressWithInputSize(zds, iend - ip);
|
|
1547
1764
|
DEBUGLOG(5, "neededInSize = %u", (U32)neededInSize);
|
|
1548
1765
|
if (neededInSize==0) { /* end of frame */
|
|
1549
1766
|
zds->streamStage = zdss_init;
|
|
@@ -1551,15 +1768,9 @@ size_t ZSTD_decompressStream(ZSTD_DStream* zds, ZSTD_outBuffer* output, ZSTD_inB
|
|
|
1551
1768
|
break;
|
|
1552
1769
|
}
|
|
1553
1770
|
if ((size_t)(iend-ip) >= neededInSize) { /* decode directly from src */
|
|
1554
|
-
|
|
1555
|
-
size_t const decodedSize = ZSTD_decompressContinue(zds,
|
|
1556
|
-
zds->outBuff + zds->outStart, (isSkipFrame ? 0 : zds->outBuffSize - zds->outStart),
|
|
1557
|
-
ip, neededInSize);
|
|
1558
|
-
if (ZSTD_isError(decodedSize)) return decodedSize;
|
|
1771
|
+
FORWARD_IF_ERROR(ZSTD_decompressContinueStream(zds, &op, oend, ip, neededInSize), "");
|
|
1559
1772
|
ip += neededInSize;
|
|
1560
|
-
|
|
1561
|
-
zds->outEnd = zds->outStart + decodedSize;
|
|
1562
|
-
zds->streamStage = zdss_flush;
|
|
1773
|
+
/* Function modifies the stage so we must break */
|
|
1563
1774
|
break;
|
|
1564
1775
|
} }
|
|
1565
1776
|
if (ip==iend) { someMoreWork = 0; break; } /* no more input */
|
|
@@ -1571,10 +1782,14 @@ size_t ZSTD_decompressStream(ZSTD_DStream* zds, ZSTD_outBuffer* output, ZSTD_inB
|
|
|
1571
1782
|
size_t const toLoad = neededInSize - zds->inPos;
|
|
1572
1783
|
int const isSkipFrame = ZSTD_isSkipFrame(zds);
|
|
1573
1784
|
size_t loadedSize;
|
|
1785
|
+
/* At this point we shouldn't be decompressing a block that we can stream. */
|
|
1786
|
+
assert(neededInSize == ZSTD_nextSrcSizeToDecompressWithInputSize(zds, iend - ip));
|
|
1574
1787
|
if (isSkipFrame) {
|
|
1575
1788
|
loadedSize = MIN(toLoad, (size_t)(iend-ip));
|
|
1576
1789
|
} else {
|
|
1577
|
-
|
|
1790
|
+
RETURN_ERROR_IF(toLoad > zds->inBuffSize - zds->inPos,
|
|
1791
|
+
corruption_detected,
|
|
1792
|
+
"should never happen");
|
|
1578
1793
|
loadedSize = ZSTD_limitCopy(zds->inBuff + zds->inPos, toLoad, ip, iend-ip);
|
|
1579
1794
|
}
|
|
1580
1795
|
ip += loadedSize;
|
|
@@ -1582,17 +1797,11 @@ size_t ZSTD_decompressStream(ZSTD_DStream* zds, ZSTD_outBuffer* output, ZSTD_inB
|
|
|
1582
1797
|
if (loadedSize < toLoad) { someMoreWork = 0; break; } /* not enough input, wait for more */
|
|
1583
1798
|
|
|
1584
1799
|
/* decode loaded input */
|
|
1585
|
-
|
|
1586
|
-
|
|
1587
|
-
|
|
1588
|
-
|
|
1589
|
-
|
|
1590
|
-
if (!decodedSize && !isSkipFrame) { zds->streamStage = zdss_read; break; } /* this was just a header */
|
|
1591
|
-
zds->outEnd = zds->outStart + decodedSize;
|
|
1592
|
-
} }
|
|
1593
|
-
zds->streamStage = zdss_flush;
|
|
1594
|
-
/* fall-through */
|
|
1595
|
-
|
|
1800
|
+
zds->inPos = 0; /* input is consumed */
|
|
1801
|
+
FORWARD_IF_ERROR(ZSTD_decompressContinueStream(zds, &op, oend, zds->inBuff, neededInSize), "");
|
|
1802
|
+
/* Function modifies the stage so we must break */
|
|
1803
|
+
break;
|
|
1804
|
+
}
|
|
1596
1805
|
case zdss_flush:
|
|
1597
1806
|
{ size_t const toFlushSize = zds->outEnd - zds->outStart;
|
|
1598
1807
|
size_t const flushedSize = ZSTD_limitCopy(op, oend-op, zds->outBuff + zds->outStart, toFlushSize);
|
|
@@ -1615,17 +1824,21 @@ size_t ZSTD_decompressStream(ZSTD_DStream* zds, ZSTD_outBuffer* output, ZSTD_inB
|
|
|
1615
1824
|
|
|
1616
1825
|
default:
|
|
1617
1826
|
assert(0); /* impossible */
|
|
1618
|
-
|
|
1827
|
+
RETURN_ERROR(GENERIC, "impossible to reach"); /* some compiler require default to do something */
|
|
1619
1828
|
} }
|
|
1620
1829
|
|
|
1621
1830
|
/* result */
|
|
1622
1831
|
input->pos = (size_t)(ip - (const char*)(input->src));
|
|
1623
1832
|
output->pos = (size_t)(op - (char*)(output->dst));
|
|
1833
|
+
|
|
1834
|
+
/* Update the expected output buffer for ZSTD_obm_stable. */
|
|
1835
|
+
zds->expectedOutBuffer = *output;
|
|
1836
|
+
|
|
1624
1837
|
if ((ip==istart) && (op==ostart)) { /* no forward progress */
|
|
1625
1838
|
zds->noForwardProgress ++;
|
|
1626
1839
|
if (zds->noForwardProgress >= ZSTD_NO_FORWARD_PROGRESS_MAX) {
|
|
1627
|
-
|
|
1628
|
-
|
|
1840
|
+
RETURN_ERROR_IF(op==oend, dstSize_tooSmall, "");
|
|
1841
|
+
RETURN_ERROR_IF(ip==iend, srcSize_wrong, "");
|
|
1629
1842
|
assert(0);
|
|
1630
1843
|
}
|
|
1631
1844
|
} else {
|