zstdlib 0.6.0-x86-mingw32 → 0.9.0-x86-mingw32
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGES.md +20 -0
- data/README.md +7 -1
- data/Rakefile +38 -8
- data/ext/{zstdlib → zstdlib_c}/extconf.rb +10 -5
- data/ext/{zstdlib → zstdlib_c}/ruby/zlib-2.2/zstdlib.c +2 -2
- data/ext/{zstdlib → zstdlib_c}/ruby/zlib-2.3/zstdlib.c +2 -2
- data/ext/{zstdlib → zstdlib_c}/ruby/zlib-2.4/zstdlib.c +2 -2
- data/ext/{zstdlib → zstdlib_c}/ruby/zlib-2.5/zstdlib.c +2 -2
- data/ext/{zstdlib → zstdlib_c}/ruby/zlib-2.6/zstdlib.c +2 -2
- data/ext/{zstdlib → zstdlib_c}/ruby/zlib-2.7/zstdlib.c +2 -2
- data/ext/zstdlib_c/ruby/zlib-3.0/zstdlib.c +4994 -0
- data/ext/zstdlib_c/ruby/zlib-3.1/zstdlib.c +5076 -0
- data/ext/{zstdlib → zstdlib_c}/zlib-1.2.11/adler32.c +0 -0
- data/ext/{zstdlib → zstdlib_c}/zlib-1.2.11/compress.c +0 -0
- data/ext/{zstdlib → zstdlib_c}/zlib-1.2.11/crc32.c +0 -0
- data/ext/{zstdlib → zstdlib_c}/zlib-1.2.11/crc32.h +0 -0
- data/ext/{zstdlib → zstdlib_c}/zlib-1.2.11/deflate.c +0 -0
- data/ext/{zstdlib → zstdlib_c}/zlib-1.2.11/deflate.h +0 -0
- data/ext/{zstdlib → zstdlib_c}/zlib-1.2.11/gzclose.c +0 -0
- data/ext/{zstdlib → zstdlib_c}/zlib-1.2.11/gzguts.h +0 -0
- data/ext/{zstdlib → zstdlib_c}/zlib-1.2.11/gzlib.c +0 -0
- data/ext/{zstdlib → zstdlib_c}/zlib-1.2.11/gzread.c +0 -0
- data/ext/{zstdlib → zstdlib_c}/zlib-1.2.11/gzwrite.c +0 -0
- data/ext/{zstdlib → zstdlib_c}/zlib-1.2.11/infback.c +0 -0
- data/ext/{zstdlib → zstdlib_c}/zlib-1.2.11/inffast.c +0 -0
- data/ext/{zstdlib → zstdlib_c}/zlib-1.2.11/inffast.h +0 -0
- data/ext/{zstdlib → zstdlib_c}/zlib-1.2.11/inffixed.h +0 -0
- data/ext/{zstdlib → zstdlib_c}/zlib-1.2.11/inflate.c +0 -0
- data/ext/{zstdlib → zstdlib_c}/zlib-1.2.11/inflate.h +0 -0
- data/ext/{zstdlib → zstdlib_c}/zlib-1.2.11/inftrees.c +0 -0
- data/ext/{zstdlib → zstdlib_c}/zlib-1.2.11/inftrees.h +0 -0
- data/ext/{zstdlib → zstdlib_c}/zlib-1.2.11/trees.c +0 -0
- data/ext/{zstdlib → zstdlib_c}/zlib-1.2.11/trees.h +0 -0
- data/ext/{zstdlib → zstdlib_c}/zlib-1.2.11/uncompr.c +0 -0
- data/ext/{zstdlib → zstdlib_c}/zlib-1.2.11/zconf.h +0 -0
- data/ext/{zstdlib → zstdlib_c}/zlib-1.2.11/zlib.h +0 -0
- data/ext/{zstdlib → zstdlib_c}/zlib-1.2.11/zutil.c +0 -0
- data/ext/{zstdlib → zstdlib_c}/zlib-1.2.11/zutil.h +0 -0
- data/ext/{zstdlib → zstdlib_c}/zlib.mk +0 -0
- data/ext/{zstdlib → zstdlib_c}/zlibwrapper/zlibwrapper.c +1 -5
- data/ext/{zstdlib → zstdlib_c}/zlibwrapper.mk +0 -0
- data/ext/{zstdlib/zstd-1.4.4 → zstdlib_c/zstd-1.5.2}/lib/common/bitstream.h +75 -57
- data/ext/zstdlib_c/zstd-1.5.2/lib/common/compiler.h +335 -0
- data/ext/{zstdlib/zstd-1.4.4 → zstdlib_c/zstd-1.5.2}/lib/common/cpu.h +1 -3
- data/ext/zstdlib_c/zstd-1.5.2/lib/common/debug.c +24 -0
- data/ext/{zstdlib/zstd-1.4.4 → zstdlib_c/zstd-1.5.2}/lib/common/debug.h +22 -49
- data/ext/zstdlib_c/zstd-1.5.2/lib/common/entropy_common.c +368 -0
- data/ext/{zstdlib/zstd-1.4.4 → zstdlib_c/zstd-1.5.2}/lib/common/error_private.c +3 -1
- data/ext/zstdlib_c/zstd-1.5.2/lib/common/error_private.h +159 -0
- data/ext/{zstdlib/zstd-1.4.4 → zstdlib_c/zstd-1.5.2}/lib/common/fse.h +51 -42
- data/ext/{zstdlib/zstd-1.4.4 → zstdlib_c/zstd-1.5.2}/lib/common/fse_decompress.c +149 -57
- data/ext/{zstdlib/zstd-1.4.4 → zstdlib_c/zstd-1.5.2}/lib/common/huf.h +60 -54
- data/ext/{zstdlib/zstd-1.4.4 → zstdlib_c/zstd-1.5.2}/lib/common/mem.h +87 -98
- data/ext/{zstdlib/zstd-1.4.4 → zstdlib_c/zstd-1.5.2}/lib/common/pool.c +34 -23
- data/ext/{zstdlib/zstd-1.4.4 → zstdlib_c/zstd-1.5.2}/lib/common/pool.h +5 -5
- data/ext/zstdlib_c/zstd-1.5.2/lib/common/portability_macros.h +137 -0
- data/ext/{zstdlib/zstd-1.4.4 → zstdlib_c/zstd-1.5.2}/lib/common/threading.c +10 -8
- data/ext/{zstdlib/zstd-1.4.4 → zstdlib_c/zstd-1.5.2}/lib/common/threading.h +4 -3
- data/ext/zstdlib_c/zstd-1.5.2/lib/common/xxhash.c +24 -0
- data/ext/zstdlib_c/zstd-1.5.2/lib/common/xxhash.h +5686 -0
- data/ext/{zstdlib/zstd-1.4.4 → zstdlib_c/zstd-1.5.2}/lib/common/zstd_common.c +10 -10
- data/ext/zstdlib_c/zstd-1.5.2/lib/common/zstd_deps.h +111 -0
- data/ext/zstdlib_c/zstd-1.5.2/lib/common/zstd_internal.h +493 -0
- data/ext/zstdlib_c/zstd-1.5.2/lib/common/zstd_trace.h +163 -0
- data/ext/zstdlib_c/zstd-1.5.2/lib/compress/clevels.h +134 -0
- data/ext/{zstdlib/zstd-1.4.4 → zstdlib_c/zstd-1.5.2}/lib/compress/fse_compress.c +105 -85
- data/ext/{zstdlib/zstd-1.4.4 → zstdlib_c/zstd-1.5.2}/lib/compress/hist.c +41 -63
- data/ext/{zstdlib/zstd-1.4.4 → zstdlib_c/zstd-1.5.2}/lib/compress/hist.h +13 -33
- data/ext/zstdlib_c/zstd-1.5.2/lib/compress/huf_compress.c +1370 -0
- data/ext/zstdlib_c/zstd-1.5.2/lib/compress/zstd_compress.c +6327 -0
- data/ext/{zstdlib/zstd-1.4.4 → zstdlib_c/zstd-1.5.2}/lib/compress/zstd_compress_internal.h +537 -82
- data/ext/{zstdlib/zstd-1.4.4 → zstdlib_c/zstd-1.5.2}/lib/compress/zstd_compress_literals.c +21 -16
- data/ext/{zstdlib/zstd-1.4.4 → zstdlib_c/zstd-1.5.2}/lib/compress/zstd_compress_literals.h +4 -2
- data/ext/{zstdlib/zstd-1.4.4 → zstdlib_c/zstd-1.5.2}/lib/compress/zstd_compress_sequences.c +61 -34
- data/ext/{zstdlib/zstd-1.4.4 → zstdlib_c/zstd-1.5.2}/lib/compress/zstd_compress_sequences.h +10 -3
- data/ext/zstdlib_c/zstd-1.5.2/lib/compress/zstd_compress_superblock.c +573 -0
- data/ext/zstdlib_c/zstd-1.5.2/lib/compress/zstd_compress_superblock.h +32 -0
- data/ext/{zstdlib/zstd-1.4.4 → zstdlib_c/zstd-1.5.2}/lib/compress/zstd_cwksp.h +236 -95
- data/ext/{zstdlib/zstd-1.4.4 → zstdlib_c/zstd-1.5.2}/lib/compress/zstd_double_fast.c +321 -143
- data/ext/{zstdlib/zstd-1.4.4 → zstdlib_c/zstd-1.5.2}/lib/compress/zstd_double_fast.h +2 -2
- data/ext/{zstdlib/zstd-1.4.4 → zstdlib_c/zstd-1.5.2}/lib/compress/zstd_fast.c +328 -137
- data/ext/{zstdlib/zstd-1.4.4 → zstdlib_c/zstd-1.5.2}/lib/compress/zstd_fast.h +2 -2
- data/ext/zstdlib_c/zstd-1.5.2/lib/compress/zstd_lazy.c +2104 -0
- data/ext/zstdlib_c/zstd-1.5.2/lib/compress/zstd_lazy.h +125 -0
- data/ext/{zstdlib/zstd-1.4.4 → zstdlib_c/zstd-1.5.2}/lib/compress/zstd_ldm.c +336 -209
- data/ext/{zstdlib/zstd-1.4.4 → zstdlib_c/zstd-1.5.2}/lib/compress/zstd_ldm.h +15 -3
- data/ext/zstdlib_c/zstd-1.5.2/lib/compress/zstd_ldm_geartab.h +106 -0
- data/ext/{zstdlib/zstd-1.4.4 → zstdlib_c/zstd-1.5.2}/lib/compress/zstd_opt.c +439 -239
- data/ext/{zstdlib/zstd-1.4.4 → zstdlib_c/zstd-1.5.2}/lib/compress/zstd_opt.h +1 -1
- data/ext/{zstdlib/zstd-1.4.4 → zstdlib_c/zstd-1.5.2}/lib/compress/zstdmt_compress.c +205 -462
- data/ext/zstdlib_c/zstd-1.5.2/lib/compress/zstdmt_compress.h +113 -0
- data/ext/zstdlib_c/zstd-1.5.2/lib/decompress/huf_decompress.c +1889 -0
- data/ext/zstdlib_c/zstd-1.5.2/lib/decompress/huf_decompress_amd64.S +585 -0
- data/ext/{zstdlib/zstd-1.4.4 → zstdlib_c/zstd-1.5.2}/lib/decompress/zstd_ddict.c +20 -16
- data/ext/{zstdlib/zstd-1.4.4 → zstdlib_c/zstd-1.5.2}/lib/decompress/zstd_ddict.h +3 -3
- data/ext/{zstdlib/zstd-1.4.4 → zstdlib_c/zstd-1.5.2}/lib/decompress/zstd_decompress.c +691 -230
- data/ext/zstdlib_c/zstd-1.5.2/lib/decompress/zstd_decompress_block.c +2072 -0
- data/ext/{zstdlib/zstd-1.4.4 → zstdlib_c/zstd-1.5.2}/lib/decompress/zstd_decompress_block.h +16 -7
- data/ext/{zstdlib/zstd-1.4.4 → zstdlib_c/zstd-1.5.2}/lib/decompress/zstd_decompress_internal.h +71 -10
- data/ext/zstdlib_c/zstd-1.5.2/lib/zdict.h +452 -0
- data/ext/{zstdlib/zstd-1.4.4 → zstdlib_c/zstd-1.5.2}/lib/zstd.h +760 -234
- data/ext/{zstdlib/zstd-1.4.4/lib/common → zstdlib_c/zstd-1.5.2/lib}/zstd_errors.h +3 -1
- data/ext/{zstdlib/zstd-1.4.4 → zstdlib_c/zstd-1.5.2}/zlibWrapper/gzclose.c +0 -0
- data/ext/{zstdlib/zstd-1.4.4 → zstdlib_c/zstd-1.5.2}/zlibWrapper/gzcompatibility.h +1 -1
- data/ext/{zstdlib/zstd-1.4.4 → zstdlib_c/zstd-1.5.2}/zlibWrapper/gzguts.h +0 -0
- data/ext/{zstdlib/zstd-1.4.4 → zstdlib_c/zstd-1.5.2}/zlibWrapper/gzlib.c +0 -0
- data/ext/{zstdlib/zstd-1.4.4 → zstdlib_c/zstd-1.5.2}/zlibWrapper/gzread.c +0 -0
- data/ext/{zstdlib/zstd-1.4.4 → zstdlib_c/zstd-1.5.2}/zlibWrapper/gzwrite.c +0 -0
- data/ext/{zstdlib/zstd-1.4.4 → zstdlib_c/zstd-1.5.2}/zlibWrapper/zstd_zlibwrapper.c +133 -44
- data/ext/{zstdlib/zstd-1.4.4 → zstdlib_c/zstd-1.5.2}/zlibWrapper/zstd_zlibwrapper.h +1 -1
- data/ext/zstdlib_c/zstd.mk +15 -0
- data/lib/2.4/zstdlib_c.so +0 -0
- data/lib/2.5/zstdlib_c.so +0 -0
- data/lib/2.6/zstdlib_c.so +0 -0
- data/lib/2.7/zstdlib_c.so +0 -0
- data/lib/3.0/zstdlib_c.so +0 -0
- data/lib/3.1/zstdlib_c.so +0 -0
- data/lib/zstdlib.rb +2 -2
- metadata +125 -114
- data/ext/zstdlib/zstd-1.4.4/lib/common/compiler.h +0 -159
- data/ext/zstdlib/zstd-1.4.4/lib/common/debug.c +0 -44
- data/ext/zstdlib/zstd-1.4.4/lib/common/entropy_common.c +0 -236
- data/ext/zstdlib/zstd-1.4.4/lib/common/error_private.h +0 -76
- data/ext/zstdlib/zstd-1.4.4/lib/common/xxhash.c +0 -882
- data/ext/zstdlib/zstd-1.4.4/lib/common/xxhash.h +0 -305
- data/ext/zstdlib/zstd-1.4.4/lib/common/zstd_internal.h +0 -350
- data/ext/zstdlib/zstd-1.4.4/lib/compress/huf_compress.c +0 -798
- data/ext/zstdlib/zstd-1.4.4/lib/compress/zstd_compress.c +0 -4103
- data/ext/zstdlib/zstd-1.4.4/lib/compress/zstd_lazy.c +0 -1115
- data/ext/zstdlib/zstd-1.4.4/lib/compress/zstd_lazy.h +0 -67
- data/ext/zstdlib/zstd-1.4.4/lib/compress/zstdmt_compress.h +0 -192
- data/ext/zstdlib/zstd-1.4.4/lib/decompress/huf_decompress.c +0 -1234
- data/ext/zstdlib/zstd-1.4.4/lib/decompress/zstd_decompress_block.c +0 -1323
- data/ext/zstdlib/zstd.mk +0 -14
- data/lib/2.2/zstdlib.so +0 -0
- data/lib/2.3/zstdlib.so +0 -0
- data/lib/2.4/zstdlib.so +0 -0
- data/lib/2.5/zstdlib.so +0 -0
- data/lib/2.6/zstdlib.so +0 -0
- data/lib/2.7/zstdlib.so +0 -0
@@ -1,5 +1,5 @@
|
|
1
1
|
/*
|
2
|
-
* Copyright (c)
|
2
|
+
* Copyright (c) Yann Collet, Facebook, Inc.
|
3
3
|
* All rights reserved.
|
4
4
|
*
|
5
5
|
* This source code is licensed under both the BSD-style license (found in the
|
@@ -55,23 +55,164 @@
|
|
55
55
|
/*-*******************************************************
|
56
56
|
* Dependencies
|
57
57
|
*********************************************************/
|
58
|
-
#include
|
59
|
-
#include "
|
60
|
-
#include "mem.h" /* low level memory routines */
|
58
|
+
#include "../common/zstd_deps.h" /* ZSTD_memcpy, ZSTD_memmove, ZSTD_memset */
|
59
|
+
#include "../common/mem.h" /* low level memory routines */
|
61
60
|
#define FSE_STATIC_LINKING_ONLY
|
62
|
-
#include "fse.h"
|
61
|
+
#include "../common/fse.h"
|
63
62
|
#define HUF_STATIC_LINKING_ONLY
|
64
|
-
#include "huf.h"
|
65
|
-
#include "
|
63
|
+
#include "../common/huf.h"
|
64
|
+
#include "../common/xxhash.h" /* XXH64_reset, XXH64_update, XXH64_digest, XXH64 */
|
65
|
+
#include "../common/zstd_internal.h" /* blockProperties_t */
|
66
66
|
#include "zstd_decompress_internal.h" /* ZSTD_DCtx */
|
67
67
|
#include "zstd_ddict.h" /* ZSTD_DDictDictContent */
|
68
68
|
#include "zstd_decompress_block.h" /* ZSTD_decompressBlock_internal */
|
69
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
|
|
75
|
+
|
76
|
+
/*************************************
|
77
|
+
* Multiple DDicts Hashset internals *
|
78
|
+
*************************************/
|
79
|
+
|
80
|
+
#define DDICT_HASHSET_MAX_LOAD_FACTOR_COUNT_MULT 4
|
81
|
+
#define DDICT_HASHSET_MAX_LOAD_FACTOR_SIZE_MULT 3 /* These two constants represent SIZE_MULT/COUNT_MULT load factor without using a float.
|
82
|
+
* Currently, that means a 0.75 load factor.
|
83
|
+
* So, if count * COUNT_MULT / size * SIZE_MULT != 0, then we've exceeded
|
84
|
+
* the load factor of the ddict hash set.
|
85
|
+
*/
|
86
|
+
|
87
|
+
#define DDICT_HASHSET_TABLE_BASE_SIZE 64
|
88
|
+
#define DDICT_HASHSET_RESIZE_FACTOR 2
|
89
|
+
|
90
|
+
/* Hash function to determine starting position of dict insertion within the table
|
91
|
+
* Returns an index between [0, hashSet->ddictPtrTableSize]
|
92
|
+
*/
|
93
|
+
static size_t ZSTD_DDictHashSet_getIndex(const ZSTD_DDictHashSet* hashSet, U32 dictID) {
|
94
|
+
const U64 hash = XXH64(&dictID, sizeof(U32), 0);
|
95
|
+
/* DDict ptr table size is a multiple of 2, use size - 1 as mask to get index within [0, hashSet->ddictPtrTableSize) */
|
96
|
+
return hash & (hashSet->ddictPtrTableSize - 1);
|
97
|
+
}
|
98
|
+
|
99
|
+
/* Adds DDict to a hashset without resizing it.
|
100
|
+
* If inserting a DDict with a dictID that already exists in the set, replaces the one in the set.
|
101
|
+
* Returns 0 if successful, or a zstd error code if something went wrong.
|
102
|
+
*/
|
103
|
+
static size_t ZSTD_DDictHashSet_emplaceDDict(ZSTD_DDictHashSet* hashSet, const ZSTD_DDict* ddict) {
|
104
|
+
const U32 dictID = ZSTD_getDictID_fromDDict(ddict);
|
105
|
+
size_t idx = ZSTD_DDictHashSet_getIndex(hashSet, dictID);
|
106
|
+
const size_t idxRangeMask = hashSet->ddictPtrTableSize - 1;
|
107
|
+
RETURN_ERROR_IF(hashSet->ddictPtrCount == hashSet->ddictPtrTableSize, GENERIC, "Hash set is full!");
|
108
|
+
DEBUGLOG(4, "Hashed index: for dictID: %u is %zu", dictID, idx);
|
109
|
+
while (hashSet->ddictPtrTable[idx] != NULL) {
|
110
|
+
/* Replace existing ddict if inserting ddict with same dictID */
|
111
|
+
if (ZSTD_getDictID_fromDDict(hashSet->ddictPtrTable[idx]) == dictID) {
|
112
|
+
DEBUGLOG(4, "DictID already exists, replacing rather than adding");
|
113
|
+
hashSet->ddictPtrTable[idx] = ddict;
|
114
|
+
return 0;
|
115
|
+
}
|
116
|
+
idx &= idxRangeMask;
|
117
|
+
idx++;
|
118
|
+
}
|
119
|
+
DEBUGLOG(4, "Final idx after probing for dictID %u is: %zu", dictID, idx);
|
120
|
+
hashSet->ddictPtrTable[idx] = ddict;
|
121
|
+
hashSet->ddictPtrCount++;
|
122
|
+
return 0;
|
123
|
+
}
|
124
|
+
|
125
|
+
/* Expands hash table by factor of DDICT_HASHSET_RESIZE_FACTOR and
|
126
|
+
* rehashes all values, allocates new table, frees old table.
|
127
|
+
* Returns 0 on success, otherwise a zstd error code.
|
128
|
+
*/
|
129
|
+
static size_t ZSTD_DDictHashSet_expand(ZSTD_DDictHashSet* hashSet, ZSTD_customMem customMem) {
|
130
|
+
size_t newTableSize = hashSet->ddictPtrTableSize * DDICT_HASHSET_RESIZE_FACTOR;
|
131
|
+
const ZSTD_DDict** newTable = (const ZSTD_DDict**)ZSTD_customCalloc(sizeof(ZSTD_DDict*) * newTableSize, customMem);
|
132
|
+
const ZSTD_DDict** oldTable = hashSet->ddictPtrTable;
|
133
|
+
size_t oldTableSize = hashSet->ddictPtrTableSize;
|
134
|
+
size_t i;
|
135
|
+
|
136
|
+
DEBUGLOG(4, "Expanding DDict hash table! Old size: %zu new size: %zu", oldTableSize, newTableSize);
|
137
|
+
RETURN_ERROR_IF(!newTable, memory_allocation, "Expanded hashset allocation failed!");
|
138
|
+
hashSet->ddictPtrTable = newTable;
|
139
|
+
hashSet->ddictPtrTableSize = newTableSize;
|
140
|
+
hashSet->ddictPtrCount = 0;
|
141
|
+
for (i = 0; i < oldTableSize; ++i) {
|
142
|
+
if (oldTable[i] != NULL) {
|
143
|
+
FORWARD_IF_ERROR(ZSTD_DDictHashSet_emplaceDDict(hashSet, oldTable[i]), "");
|
144
|
+
}
|
145
|
+
}
|
146
|
+
ZSTD_customFree((void*)oldTable, customMem);
|
147
|
+
DEBUGLOG(4, "Finished re-hash");
|
148
|
+
return 0;
|
149
|
+
}
|
150
|
+
|
151
|
+
/* Fetches a DDict with the given dictID
|
152
|
+
* Returns the ZSTD_DDict* with the requested dictID. If it doesn't exist, then returns NULL.
|
153
|
+
*/
|
154
|
+
static const ZSTD_DDict* ZSTD_DDictHashSet_getDDict(ZSTD_DDictHashSet* hashSet, U32 dictID) {
|
155
|
+
size_t idx = ZSTD_DDictHashSet_getIndex(hashSet, dictID);
|
156
|
+
const size_t idxRangeMask = hashSet->ddictPtrTableSize - 1;
|
157
|
+
DEBUGLOG(4, "Hashed index: for dictID: %u is %zu", dictID, idx);
|
158
|
+
for (;;) {
|
159
|
+
size_t currDictID = ZSTD_getDictID_fromDDict(hashSet->ddictPtrTable[idx]);
|
160
|
+
if (currDictID == dictID || currDictID == 0) {
|
161
|
+
/* currDictID == 0 implies a NULL ddict entry */
|
162
|
+
break;
|
163
|
+
} else {
|
164
|
+
idx &= idxRangeMask; /* Goes to start of table when we reach the end */
|
165
|
+
idx++;
|
166
|
+
}
|
167
|
+
}
|
168
|
+
DEBUGLOG(4, "Final idx after probing for dictID %u is: %zu", dictID, idx);
|
169
|
+
return hashSet->ddictPtrTable[idx];
|
170
|
+
}
|
171
|
+
|
172
|
+
/* Allocates space for and returns a ddict hash set
|
173
|
+
* The hash set's ZSTD_DDict* table has all values automatically set to NULL to begin with.
|
174
|
+
* Returns NULL if allocation failed.
|
175
|
+
*/
|
176
|
+
static ZSTD_DDictHashSet* ZSTD_createDDictHashSet(ZSTD_customMem customMem) {
|
177
|
+
ZSTD_DDictHashSet* ret = (ZSTD_DDictHashSet*)ZSTD_customMalloc(sizeof(ZSTD_DDictHashSet), customMem);
|
178
|
+
DEBUGLOG(4, "Allocating new hash set");
|
179
|
+
if (!ret)
|
180
|
+
return NULL;
|
181
|
+
ret->ddictPtrTable = (const ZSTD_DDict**)ZSTD_customCalloc(DDICT_HASHSET_TABLE_BASE_SIZE * sizeof(ZSTD_DDict*), customMem);
|
182
|
+
if (!ret->ddictPtrTable) {
|
183
|
+
ZSTD_customFree(ret, customMem);
|
184
|
+
return NULL;
|
185
|
+
}
|
186
|
+
ret->ddictPtrTableSize = DDICT_HASHSET_TABLE_BASE_SIZE;
|
187
|
+
ret->ddictPtrCount = 0;
|
188
|
+
return ret;
|
189
|
+
}
|
190
|
+
|
191
|
+
/* Frees the table of ZSTD_DDict* within a hashset, then frees the hashset itself.
|
192
|
+
* Note: The ZSTD_DDict* within the table are NOT freed.
|
193
|
+
*/
|
194
|
+
static void ZSTD_freeDDictHashSet(ZSTD_DDictHashSet* hashSet, ZSTD_customMem customMem) {
|
195
|
+
DEBUGLOG(4, "Freeing ddict hash set");
|
196
|
+
if (hashSet && hashSet->ddictPtrTable) {
|
197
|
+
ZSTD_customFree((void*)hashSet->ddictPtrTable, customMem);
|
198
|
+
}
|
199
|
+
if (hashSet) {
|
200
|
+
ZSTD_customFree(hashSet, customMem);
|
201
|
+
}
|
202
|
+
}
|
203
|
+
|
204
|
+
/* Public function: Adds a DDict into the ZSTD_DDictHashSet, possibly triggering a resize of the hash set.
|
205
|
+
* Returns 0 on success, or a ZSTD error.
|
206
|
+
*/
|
207
|
+
static size_t ZSTD_DDictHashSet_addDDict(ZSTD_DDictHashSet* hashSet, const ZSTD_DDict* ddict, ZSTD_customMem customMem) {
|
208
|
+
DEBUGLOG(4, "Adding dict ID: %u to hashset with - Count: %zu Tablesize: %zu", ZSTD_getDictID_fromDDict(ddict), hashSet->ddictPtrCount, hashSet->ddictPtrTableSize);
|
209
|
+
if (hashSet->ddictPtrCount * DDICT_HASHSET_MAX_LOAD_FACTOR_COUNT_MULT / hashSet->ddictPtrTableSize * DDICT_HASHSET_MAX_LOAD_FACTOR_SIZE_MULT != 0) {
|
210
|
+
FORWARD_IF_ERROR(ZSTD_DDictHashSet_expand(hashSet, customMem), "");
|
211
|
+
}
|
212
|
+
FORWARD_IF_ERROR(ZSTD_DDictHashSet_emplaceDDict(hashSet, ddict), "");
|
213
|
+
return 0;
|
214
|
+
}
|
215
|
+
|
75
216
|
/*-*************************************************************
|
76
217
|
* Context management
|
77
218
|
***************************************************************/
|
@@ -94,11 +235,19 @@ static size_t ZSTD_startingInputLength(ZSTD_format_e format)
|
|
94
235
|
return startingInputLength;
|
95
236
|
}
|
96
237
|
|
238
|
+
static void ZSTD_DCtx_resetParameters(ZSTD_DCtx* dctx)
|
239
|
+
{
|
240
|
+
assert(dctx->streamStage == zdss_init);
|
241
|
+
dctx->format = ZSTD_f_zstd1;
|
242
|
+
dctx->maxWindowSize = ZSTD_MAXWINDOWSIZE_DEFAULT;
|
243
|
+
dctx->outBufferMode = ZSTD_bm_buffered;
|
244
|
+
dctx->forceIgnoreChecksum = ZSTD_d_validateChecksum;
|
245
|
+
dctx->refMultipleDDicts = ZSTD_rmd_refSingleDDict;
|
246
|
+
}
|
247
|
+
|
97
248
|
static void ZSTD_initDCtx_internal(ZSTD_DCtx* dctx)
|
98
249
|
{
|
99
|
-
dctx->format = ZSTD_f_zstd1; /* ZSTD_decompressBegin() invokes ZSTD_startingInputLength() with argument dctx->format */
|
100
250
|
dctx->staticSize = 0;
|
101
|
-
dctx->maxWindowSize = ZSTD_MAXWINDOWSIZE_DEFAULT;
|
102
251
|
dctx->ddict = NULL;
|
103
252
|
dctx->ddictLocal = NULL;
|
104
253
|
dctx->dictEnd = NULL;
|
@@ -108,10 +257,20 @@ static void ZSTD_initDCtx_internal(ZSTD_DCtx* dctx)
|
|
108
257
|
dctx->inBuffSize = 0;
|
109
258
|
dctx->outBuffSize = 0;
|
110
259
|
dctx->streamStage = zdss_init;
|
260
|
+
#if defined(ZSTD_LEGACY_SUPPORT) && (ZSTD_LEGACY_SUPPORT>=1)
|
111
261
|
dctx->legacyContext = NULL;
|
112
262
|
dctx->previousLegacyVersion = 0;
|
263
|
+
#endif
|
113
264
|
dctx->noForwardProgress = 0;
|
114
|
-
dctx->
|
265
|
+
dctx->oversizedDuration = 0;
|
266
|
+
#if DYNAMIC_BMI2
|
267
|
+
dctx->bmi2 = ZSTD_cpuSupportsBmi2();
|
268
|
+
#endif
|
269
|
+
dctx->ddictSet = NULL;
|
270
|
+
ZSTD_DCtx_resetParameters(dctx);
|
271
|
+
#ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
|
272
|
+
dctx->dictContentEndForFuzzing = NULL;
|
273
|
+
#endif
|
115
274
|
}
|
116
275
|
|
117
276
|
ZSTD_DCtx* ZSTD_initStaticDCtx(void *workspace, size_t workspaceSize)
|
@@ -127,11 +286,10 @@ ZSTD_DCtx* ZSTD_initStaticDCtx(void *workspace, size_t workspaceSize)
|
|
127
286
|
return dctx;
|
128
287
|
}
|
129
288
|
|
130
|
-
ZSTD_DCtx*
|
131
|
-
|
132
|
-
if (!customMem.customAlloc ^ !customMem.customFree) return NULL;
|
289
|
+
static ZSTD_DCtx* ZSTD_createDCtx_internal(ZSTD_customMem customMem) {
|
290
|
+
if ((!customMem.customAlloc) ^ (!customMem.customFree)) return NULL;
|
133
291
|
|
134
|
-
{ ZSTD_DCtx* const dctx = (ZSTD_DCtx*)
|
292
|
+
{ ZSTD_DCtx* const dctx = (ZSTD_DCtx*)ZSTD_customMalloc(sizeof(*dctx), customMem);
|
135
293
|
if (!dctx) return NULL;
|
136
294
|
dctx->customMem = customMem;
|
137
295
|
ZSTD_initDCtx_internal(dctx);
|
@@ -139,10 +297,15 @@ ZSTD_DCtx* ZSTD_createDCtx_advanced(ZSTD_customMem customMem)
|
|
139
297
|
}
|
140
298
|
}
|
141
299
|
|
300
|
+
ZSTD_DCtx* ZSTD_createDCtx_advanced(ZSTD_customMem customMem)
|
301
|
+
{
|
302
|
+
return ZSTD_createDCtx_internal(customMem);
|
303
|
+
}
|
304
|
+
|
142
305
|
ZSTD_DCtx* ZSTD_createDCtx(void)
|
143
306
|
{
|
144
307
|
DEBUGLOG(3, "ZSTD_createDCtx");
|
145
|
-
return
|
308
|
+
return ZSTD_createDCtx_internal(ZSTD_defaultCMem);
|
146
309
|
}
|
147
310
|
|
148
311
|
static void ZSTD_clearDict(ZSTD_DCtx* dctx)
|
@@ -159,13 +322,17 @@ size_t ZSTD_freeDCtx(ZSTD_DCtx* dctx)
|
|
159
322
|
RETURN_ERROR_IF(dctx->staticSize, memory_allocation, "not compatible with static DCtx");
|
160
323
|
{ ZSTD_customMem const cMem = dctx->customMem;
|
161
324
|
ZSTD_clearDict(dctx);
|
162
|
-
|
325
|
+
ZSTD_customFree(dctx->inBuff, cMem);
|
163
326
|
dctx->inBuff = NULL;
|
164
327
|
#if defined(ZSTD_LEGACY_SUPPORT) && (ZSTD_LEGACY_SUPPORT >= 1)
|
165
328
|
if (dctx->legacyContext)
|
166
329
|
ZSTD_freeLegacyStreamContext(dctx->legacyContext, dctx->previousLegacyVersion);
|
167
330
|
#endif
|
168
|
-
|
331
|
+
if (dctx->ddictSet) {
|
332
|
+
ZSTD_freeDDictHashSet(dctx->ddictSet, cMem);
|
333
|
+
dctx->ddictSet = NULL;
|
334
|
+
}
|
335
|
+
ZSTD_customFree(dctx, cMem);
|
169
336
|
return 0;
|
170
337
|
}
|
171
338
|
}
|
@@ -174,7 +341,30 @@ size_t ZSTD_freeDCtx(ZSTD_DCtx* dctx)
|
|
174
341
|
void ZSTD_copyDCtx(ZSTD_DCtx* dstDCtx, const ZSTD_DCtx* srcDCtx)
|
175
342
|
{
|
176
343
|
size_t const toCopy = (size_t)((char*)(&dstDCtx->inBuff) - (char*)dstDCtx);
|
177
|
-
|
344
|
+
ZSTD_memcpy(dstDCtx, srcDCtx, toCopy); /* no need to copy workspace */
|
345
|
+
}
|
346
|
+
|
347
|
+
/* Given a dctx with a digested frame params, re-selects the correct ZSTD_DDict based on
|
348
|
+
* the requested dict ID from the frame. If there exists a reference to the correct ZSTD_DDict, then
|
349
|
+
* accordingly sets the ddict to be used to decompress the frame.
|
350
|
+
*
|
351
|
+
* If no DDict is found, then no action is taken, and the ZSTD_DCtx::ddict remains as-is.
|
352
|
+
*
|
353
|
+
* ZSTD_d_refMultipleDDicts must be enabled for this function to be called.
|
354
|
+
*/
|
355
|
+
static void ZSTD_DCtx_selectFrameDDict(ZSTD_DCtx* dctx) {
|
356
|
+
assert(dctx->refMultipleDDicts && dctx->ddictSet);
|
357
|
+
DEBUGLOG(4, "Adjusting DDict based on requested dict ID from frame");
|
358
|
+
if (dctx->ddict) {
|
359
|
+
const ZSTD_DDict* frameDDict = ZSTD_DDictHashSet_getDDict(dctx->ddictSet, dctx->fParams.dictID);
|
360
|
+
if (frameDDict) {
|
361
|
+
DEBUGLOG(4, "DDict found!");
|
362
|
+
ZSTD_clearDict(dctx);
|
363
|
+
dctx->dictID = dctx->fParams.dictID;
|
364
|
+
dctx->ddict = frameDDict;
|
365
|
+
dctx->dictUses = ZSTD_use_indefinitely;
|
366
|
+
}
|
367
|
+
}
|
178
368
|
}
|
179
369
|
|
180
370
|
|
@@ -200,6 +390,19 @@ unsigned ZSTD_isFrame(const void* buffer, size_t size)
|
|
200
390
|
return 0;
|
201
391
|
}
|
202
392
|
|
393
|
+
/*! ZSTD_isSkippableFrame() :
|
394
|
+
* Tells if the content of `buffer` starts with a valid Frame Identifier for a skippable frame.
|
395
|
+
* Note : Frame Identifier is 4 bytes. If `size < 4`, @return will always be 0.
|
396
|
+
*/
|
397
|
+
unsigned ZSTD_isSkippableFrame(const void* buffer, size_t size)
|
398
|
+
{
|
399
|
+
if (size < ZSTD_FRAMEIDSIZE) return 0;
|
400
|
+
{ U32 const magic = MEM_readLE32(buffer);
|
401
|
+
if ((magic & ZSTD_MAGIC_SKIPPABLE_MASK) == ZSTD_MAGIC_SKIPPABLE_START) return 1;
|
402
|
+
}
|
403
|
+
return 0;
|
404
|
+
}
|
405
|
+
|
203
406
|
/** ZSTD_frameHeaderSize_internal() :
|
204
407
|
* srcSize must be large enough to reach header size fields.
|
205
408
|
* note : only works for formats ZSTD_f_zstd1 and ZSTD_f_zstd1_magicless.
|
@@ -208,7 +411,7 @@ unsigned ZSTD_isFrame(const void* buffer, size_t size)
|
|
208
411
|
static size_t ZSTD_frameHeaderSize_internal(const void* src, size_t srcSize, ZSTD_format_e format)
|
209
412
|
{
|
210
413
|
size_t const minInputSize = ZSTD_startingInputLength(format);
|
211
|
-
RETURN_ERROR_IF(srcSize < minInputSize, srcSize_wrong);
|
414
|
+
RETURN_ERROR_IF(srcSize < minInputSize, srcSize_wrong, "");
|
212
415
|
|
213
416
|
{ BYTE const fhd = ((const BYTE*)src)[minInputSize-1];
|
214
417
|
U32 const dictID= fhd & 3;
|
@@ -241,7 +444,7 @@ size_t ZSTD_getFrameHeader_advanced(ZSTD_frameHeader* zfhPtr, const void* src, s
|
|
241
444
|
const BYTE* ip = (const BYTE*)src;
|
242
445
|
size_t const minInputSize = ZSTD_startingInputLength(format);
|
243
446
|
|
244
|
-
|
447
|
+
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 */
|
245
448
|
if (srcSize < minInputSize) return minInputSize;
|
246
449
|
RETURN_ERROR_IF(src==NULL, GENERIC, "invalid parameter");
|
247
450
|
|
@@ -251,12 +454,12 @@ size_t ZSTD_getFrameHeader_advanced(ZSTD_frameHeader* zfhPtr, const void* src, s
|
|
251
454
|
/* skippable frame */
|
252
455
|
if (srcSize < ZSTD_SKIPPABLEHEADERSIZE)
|
253
456
|
return ZSTD_SKIPPABLEHEADERSIZE; /* magic number + frame length */
|
254
|
-
|
457
|
+
ZSTD_memset(zfhPtr, 0, sizeof(*zfhPtr));
|
255
458
|
zfhPtr->frameContentSize = MEM_readLE32((const char *)src + ZSTD_FRAMEIDSIZE);
|
256
459
|
zfhPtr->frameType = ZSTD_skippableFrame;
|
257
460
|
return 0;
|
258
461
|
}
|
259
|
-
RETURN_ERROR(prefix_unknown);
|
462
|
+
RETURN_ERROR(prefix_unknown, "");
|
260
463
|
}
|
261
464
|
|
262
465
|
/* ensure there is enough `srcSize` to fully read/decode frame header */
|
@@ -280,13 +483,15 @@ size_t ZSTD_getFrameHeader_advanced(ZSTD_frameHeader* zfhPtr, const void* src, s
|
|
280
483
|
if (!singleSegment) {
|
281
484
|
BYTE const wlByte = ip[pos++];
|
282
485
|
U32 const windowLog = (wlByte >> 3) + ZSTD_WINDOWLOG_ABSOLUTEMIN;
|
283
|
-
RETURN_ERROR_IF(windowLog > ZSTD_WINDOWLOG_MAX, frameParameter_windowTooLarge);
|
486
|
+
RETURN_ERROR_IF(windowLog > ZSTD_WINDOWLOG_MAX, frameParameter_windowTooLarge, "");
|
284
487
|
windowSize = (1ULL << windowLog);
|
285
488
|
windowSize += (windowSize >> 3) * (wlByte&7);
|
286
489
|
}
|
287
490
|
switch(dictIDSizeCode)
|
288
491
|
{
|
289
|
-
default:
|
492
|
+
default:
|
493
|
+
assert(0); /* impossible */
|
494
|
+
ZSTD_FALLTHROUGH;
|
290
495
|
case 0 : break;
|
291
496
|
case 1 : dictID = ip[pos]; pos++; break;
|
292
497
|
case 2 : dictID = MEM_readLE16(ip+pos); pos+=2; break;
|
@@ -294,7 +499,9 @@ size_t ZSTD_getFrameHeader_advanced(ZSTD_frameHeader* zfhPtr, const void* src, s
|
|
294
499
|
}
|
295
500
|
switch(fcsID)
|
296
501
|
{
|
297
|
-
default:
|
502
|
+
default:
|
503
|
+
assert(0); /* impossible */
|
504
|
+
ZSTD_FALLTHROUGH;
|
298
505
|
case 0 : if (singleSegment) frameContentSize = ip[pos]; break;
|
299
506
|
case 1 : frameContentSize = MEM_readLE16(ip+pos)+256; break;
|
300
507
|
case 2 : frameContentSize = MEM_readLE32(ip+pos); break;
|
@@ -323,7 +530,6 @@ size_t ZSTD_getFrameHeader(ZSTD_frameHeader* zfhPtr, const void* src, size_t src
|
|
323
530
|
return ZSTD_getFrameHeader_advanced(zfhPtr, src, srcSize, ZSTD_f_zstd1);
|
324
531
|
}
|
325
532
|
|
326
|
-
|
327
533
|
/** ZSTD_getFrameContentSize() :
|
328
534
|
* compatible with legacy mode
|
329
535
|
* @return : decompressed size of the single frame pointed to be `src` if known, otherwise
|
@@ -352,18 +558,49 @@ static size_t readSkippableFrameSize(void const* src, size_t srcSize)
|
|
352
558
|
size_t const skippableHeaderSize = ZSTD_SKIPPABLEHEADERSIZE;
|
353
559
|
U32 sizeU32;
|
354
560
|
|
355
|
-
RETURN_ERROR_IF(srcSize < ZSTD_SKIPPABLEHEADERSIZE, srcSize_wrong);
|
561
|
+
RETURN_ERROR_IF(srcSize < ZSTD_SKIPPABLEHEADERSIZE, srcSize_wrong, "");
|
356
562
|
|
357
563
|
sizeU32 = MEM_readLE32((BYTE const*)src + ZSTD_FRAMEIDSIZE);
|
358
564
|
RETURN_ERROR_IF((U32)(sizeU32 + ZSTD_SKIPPABLEHEADERSIZE) < sizeU32,
|
359
|
-
frameParameter_unsupported);
|
565
|
+
frameParameter_unsupported, "");
|
360
566
|
{
|
361
567
|
size_t const skippableSize = skippableHeaderSize + sizeU32;
|
362
|
-
RETURN_ERROR_IF(skippableSize > srcSize, srcSize_wrong);
|
568
|
+
RETURN_ERROR_IF(skippableSize > srcSize, srcSize_wrong, "");
|
363
569
|
return skippableSize;
|
364
570
|
}
|
365
571
|
}
|
366
572
|
|
573
|
+
/*! ZSTD_readSkippableFrame() :
|
574
|
+
* Retrieves a zstd skippable frame containing data given by src, and writes it to dst buffer.
|
575
|
+
*
|
576
|
+
* The parameter magicVariant will receive the magicVariant that was supplied when the frame was written,
|
577
|
+
* i.e. magicNumber - ZSTD_MAGIC_SKIPPABLE_START. This can be NULL if the caller is not interested
|
578
|
+
* in the magicVariant.
|
579
|
+
*
|
580
|
+
* Returns an error if destination buffer is not large enough, or if the frame is not skippable.
|
581
|
+
*
|
582
|
+
* @return : number of bytes written or a ZSTD error.
|
583
|
+
*/
|
584
|
+
ZSTDLIB_API size_t ZSTD_readSkippableFrame(void* dst, size_t dstCapacity, unsigned* magicVariant,
|
585
|
+
const void* src, size_t srcSize)
|
586
|
+
{
|
587
|
+
U32 const magicNumber = MEM_readLE32(src);
|
588
|
+
size_t skippableFrameSize = readSkippableFrameSize(src, srcSize);
|
589
|
+
size_t skippableContentSize = skippableFrameSize - ZSTD_SKIPPABLEHEADERSIZE;
|
590
|
+
|
591
|
+
/* check input validity */
|
592
|
+
RETURN_ERROR_IF(!ZSTD_isSkippableFrame(src, srcSize), frameParameter_unsupported, "");
|
593
|
+
RETURN_ERROR_IF(skippableFrameSize < ZSTD_SKIPPABLEHEADERSIZE || skippableFrameSize > srcSize, srcSize_wrong, "");
|
594
|
+
RETURN_ERROR_IF(skippableContentSize > dstCapacity, dstSize_tooSmall, "");
|
595
|
+
|
596
|
+
/* deliver payload */
|
597
|
+
if (skippableContentSize > 0 && dst != NULL)
|
598
|
+
ZSTD_memcpy(dst, (const BYTE *)src + ZSTD_SKIPPABLEHEADERSIZE, skippableContentSize);
|
599
|
+
if (magicVariant != NULL)
|
600
|
+
*magicVariant = magicNumber - ZSTD_MAGIC_SKIPPABLE_START;
|
601
|
+
return skippableContentSize;
|
602
|
+
}
|
603
|
+
|
367
604
|
/** ZSTD_findDecompressedSize() :
|
368
605
|
* compatible with legacy mode
|
369
606
|
* `srcSize` must be the exact length of some number of ZSTD compressed and/or
|
@@ -428,20 +665,29 @@ unsigned long long ZSTD_getDecompressedSize(const void* src, size_t srcSize)
|
|
428
665
|
|
429
666
|
/** ZSTD_decodeFrameHeader() :
|
430
667
|
* `headerSize` must be the size provided by ZSTD_frameHeaderSize().
|
668
|
+
* If multiple DDict references are enabled, also will choose the correct DDict to use.
|
431
669
|
* @return : 0 if success, or an error code, which can be tested using ZSTD_isError() */
|
432
670
|
static size_t ZSTD_decodeFrameHeader(ZSTD_DCtx* dctx, const void* src, size_t headerSize)
|
433
671
|
{
|
434
672
|
size_t const result = ZSTD_getFrameHeader_advanced(&(dctx->fParams), src, headerSize, dctx->format);
|
435
673
|
if (ZSTD_isError(result)) return result; /* invalid header */
|
436
674
|
RETURN_ERROR_IF(result>0, srcSize_wrong, "headerSize too small");
|
675
|
+
|
676
|
+
/* Reference DDict requested by frame if dctx references multiple ddicts */
|
677
|
+
if (dctx->refMultipleDDicts == ZSTD_rmd_refMultipleDDicts && dctx->ddictSet) {
|
678
|
+
ZSTD_DCtx_selectFrameDDict(dctx);
|
679
|
+
}
|
680
|
+
|
437
681
|
#ifndef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
|
438
682
|
/* Skip the dictID check in fuzzing mode, because it makes the search
|
439
683
|
* harder.
|
440
684
|
*/
|
441
685
|
RETURN_ERROR_IF(dctx->fParams.dictID && (dctx->dictID != dctx->fParams.dictID),
|
442
|
-
dictionary_wrong);
|
686
|
+
dictionary_wrong, "");
|
443
687
|
#endif
|
444
|
-
|
688
|
+
dctx->validateChecksum = (dctx->fParams.checksumFlag && !dctx->forceIgnoreChecksum) ? 1 : 0;
|
689
|
+
if (dctx->validateChecksum) XXH64_reset(&dctx->xxhState, 0);
|
690
|
+
dctx->processedCSize += headerSize;
|
445
691
|
return 0;
|
446
692
|
}
|
447
693
|
|
@@ -456,7 +702,7 @@ static ZSTD_frameSizeInfo ZSTD_errorFrameSizeInfo(size_t ret)
|
|
456
702
|
static ZSTD_frameSizeInfo ZSTD_findFrameSizeInfo(const void* src, size_t srcSize)
|
457
703
|
{
|
458
704
|
ZSTD_frameSizeInfo frameSizeInfo;
|
459
|
-
|
705
|
+
ZSTD_memset(&frameSizeInfo, 0, sizeof(ZSTD_frameSizeInfo));
|
460
706
|
|
461
707
|
#if defined(ZSTD_LEGACY_SUPPORT) && (ZSTD_LEGACY_SUPPORT >= 1)
|
462
708
|
if (ZSTD_isLegacy(src, srcSize))
|
@@ -511,7 +757,7 @@ static ZSTD_frameSizeInfo ZSTD_findFrameSizeInfo(const void* src, size_t srcSize
|
|
511
757
|
ip += 4;
|
512
758
|
}
|
513
759
|
|
514
|
-
frameSizeInfo.compressedSize = ip - ipstart;
|
760
|
+
frameSizeInfo.compressedSize = (size_t)(ip - ipstart);
|
515
761
|
frameSizeInfo.decompressedBound = (zfh.frameContentSize != ZSTD_CONTENTSIZE_UNKNOWN)
|
516
762
|
? zfh.frameContentSize
|
517
763
|
: nbBlocks * zfh.blockSizeMax;
|
@@ -559,23 +805,12 @@ unsigned long long ZSTD_decompressBound(const void* src, size_t srcSize)
|
|
559
805
|
* Frame decoding
|
560
806
|
***************************************************************/
|
561
807
|
|
562
|
-
|
563
|
-
void ZSTD_checkContinuity(ZSTD_DCtx* dctx, const void* dst)
|
564
|
-
{
|
565
|
-
if (dst != dctx->previousDstEnd) { /* not contiguous */
|
566
|
-
dctx->dictEnd = dctx->previousDstEnd;
|
567
|
-
dctx->virtualStart = (const char*)dst - ((const char*)(dctx->previousDstEnd) - (const char*)(dctx->prefixStart));
|
568
|
-
dctx->prefixStart = dst;
|
569
|
-
dctx->previousDstEnd = dst;
|
570
|
-
}
|
571
|
-
}
|
572
|
-
|
573
808
|
/** ZSTD_insertBlock() :
|
574
809
|
* insert `src` block into `dctx` history. Useful to track uncompressed blocks. */
|
575
810
|
size_t ZSTD_insertBlock(ZSTD_DCtx* dctx, const void* blockStart, size_t blockSize)
|
576
811
|
{
|
577
812
|
DEBUGLOG(5, "ZSTD_insertBlock: %u bytes", (unsigned)blockSize);
|
578
|
-
ZSTD_checkContinuity(dctx, blockStart);
|
813
|
+
ZSTD_checkContinuity(dctx, blockStart, blockSize);
|
579
814
|
dctx->previousDstEnd = (const char*)blockStart + blockSize;
|
580
815
|
return blockSize;
|
581
816
|
}
|
@@ -585,12 +820,12 @@ static size_t ZSTD_copyRawBlock(void* dst, size_t dstCapacity,
|
|
585
820
|
const void* src, size_t srcSize)
|
586
821
|
{
|
587
822
|
DEBUGLOG(5, "ZSTD_copyRawBlock");
|
823
|
+
RETURN_ERROR_IF(srcSize > dstCapacity, dstSize_tooSmall, "");
|
588
824
|
if (dst == NULL) {
|
589
825
|
if (srcSize == 0) return 0;
|
590
|
-
RETURN_ERROR(dstBuffer_null);
|
826
|
+
RETURN_ERROR(dstBuffer_null, "");
|
591
827
|
}
|
592
|
-
|
593
|
-
memcpy(dst, src, srcSize);
|
828
|
+
ZSTD_memcpy(dst, src, srcSize);
|
594
829
|
return srcSize;
|
595
830
|
}
|
596
831
|
|
@@ -598,15 +833,41 @@ static size_t ZSTD_setRleBlock(void* dst, size_t dstCapacity,
|
|
598
833
|
BYTE b,
|
599
834
|
size_t regenSize)
|
600
835
|
{
|
836
|
+
RETURN_ERROR_IF(regenSize > dstCapacity, dstSize_tooSmall, "");
|
601
837
|
if (dst == NULL) {
|
602
838
|
if (regenSize == 0) return 0;
|
603
|
-
RETURN_ERROR(dstBuffer_null);
|
839
|
+
RETURN_ERROR(dstBuffer_null, "");
|
604
840
|
}
|
605
|
-
|
606
|
-
memset(dst, b, regenSize);
|
841
|
+
ZSTD_memset(dst, b, regenSize);
|
607
842
|
return regenSize;
|
608
843
|
}
|
609
844
|
|
845
|
+
static void ZSTD_DCtx_trace_end(ZSTD_DCtx const* dctx, U64 uncompressedSize, U64 compressedSize, unsigned streaming)
|
846
|
+
{
|
847
|
+
#if ZSTD_TRACE
|
848
|
+
if (dctx->traceCtx && ZSTD_trace_decompress_end != NULL) {
|
849
|
+
ZSTD_Trace trace;
|
850
|
+
ZSTD_memset(&trace, 0, sizeof(trace));
|
851
|
+
trace.version = ZSTD_VERSION_NUMBER;
|
852
|
+
trace.streaming = streaming;
|
853
|
+
if (dctx->ddict) {
|
854
|
+
trace.dictionaryID = ZSTD_getDictID_fromDDict(dctx->ddict);
|
855
|
+
trace.dictionarySize = ZSTD_DDict_dictSize(dctx->ddict);
|
856
|
+
trace.dictionaryIsCold = dctx->ddictIsCold;
|
857
|
+
}
|
858
|
+
trace.uncompressedSize = (size_t)uncompressedSize;
|
859
|
+
trace.compressedSize = (size_t)compressedSize;
|
860
|
+
trace.dctx = dctx;
|
861
|
+
ZSTD_trace_decompress_end(dctx->traceCtx, &trace);
|
862
|
+
}
|
863
|
+
#else
|
864
|
+
(void)dctx;
|
865
|
+
(void)uncompressedSize;
|
866
|
+
(void)compressedSize;
|
867
|
+
(void)streaming;
|
868
|
+
#endif
|
869
|
+
}
|
870
|
+
|
610
871
|
|
611
872
|
/*! ZSTD_decompressFrame() :
|
612
873
|
* @dctx must be properly initialized
|
@@ -616,9 +877,10 @@ static size_t ZSTD_decompressFrame(ZSTD_DCtx* dctx,
|
|
616
877
|
void* dst, size_t dstCapacity,
|
617
878
|
const void** srcPtr, size_t *srcSizePtr)
|
618
879
|
{
|
619
|
-
const BYTE*
|
620
|
-
BYTE*
|
621
|
-
BYTE* const
|
880
|
+
const BYTE* const istart = (const BYTE*)(*srcPtr);
|
881
|
+
const BYTE* ip = istart;
|
882
|
+
BYTE* const ostart = (BYTE*)dst;
|
883
|
+
BYTE* const oend = dstCapacity != 0 ? ostart + dstCapacity : ostart;
|
622
884
|
BYTE* op = ostart;
|
623
885
|
size_t remainingSrcSize = *srcSizePtr;
|
624
886
|
|
@@ -627,15 +889,15 @@ static size_t ZSTD_decompressFrame(ZSTD_DCtx* dctx,
|
|
627
889
|
/* check */
|
628
890
|
RETURN_ERROR_IF(
|
629
891
|
remainingSrcSize < ZSTD_FRAMEHEADERSIZE_MIN(dctx->format)+ZSTD_blockHeaderSize,
|
630
|
-
srcSize_wrong);
|
892
|
+
srcSize_wrong, "");
|
631
893
|
|
632
894
|
/* Frame Header */
|
633
895
|
{ size_t const frameHeaderSize = ZSTD_frameHeaderSize_internal(
|
634
896
|
ip, ZSTD_FRAMEHEADERSIZE_PREFIX(dctx->format), dctx->format);
|
635
897
|
if (ZSTD_isError(frameHeaderSize)) return frameHeaderSize;
|
636
898
|
RETURN_ERROR_IF(remainingSrcSize < frameHeaderSize+ZSTD_blockHeaderSize,
|
637
|
-
srcSize_wrong);
|
638
|
-
FORWARD_IF_ERROR( ZSTD_decodeFrameHeader(dctx, ip, frameHeaderSize) );
|
899
|
+
srcSize_wrong, "");
|
900
|
+
FORWARD_IF_ERROR( ZSTD_decodeFrameHeader(dctx, ip, frameHeaderSize) , "");
|
639
901
|
ip += frameHeaderSize; remainingSrcSize -= frameHeaderSize;
|
640
902
|
}
|
641
903
|
|
@@ -648,28 +910,30 @@ static size_t ZSTD_decompressFrame(ZSTD_DCtx* dctx,
|
|
648
910
|
|
649
911
|
ip += ZSTD_blockHeaderSize;
|
650
912
|
remainingSrcSize -= ZSTD_blockHeaderSize;
|
651
|
-
RETURN_ERROR_IF(cBlockSize > remainingSrcSize, srcSize_wrong);
|
913
|
+
RETURN_ERROR_IF(cBlockSize > remainingSrcSize, srcSize_wrong, "");
|
652
914
|
|
653
915
|
switch(blockProperties.blockType)
|
654
916
|
{
|
655
917
|
case bt_compressed:
|
656
|
-
decodedSize = ZSTD_decompressBlock_internal(dctx, op, oend-op, ip, cBlockSize, /* frame */ 1);
|
918
|
+
decodedSize = ZSTD_decompressBlock_internal(dctx, op, (size_t)(oend-op), ip, cBlockSize, /* frame */ 1, not_streaming);
|
657
919
|
break;
|
658
920
|
case bt_raw :
|
659
|
-
decodedSize = ZSTD_copyRawBlock(op, oend-op, ip, cBlockSize);
|
921
|
+
decodedSize = ZSTD_copyRawBlock(op, (size_t)(oend-op), ip, cBlockSize);
|
660
922
|
break;
|
661
923
|
case bt_rle :
|
662
|
-
decodedSize = ZSTD_setRleBlock(op, oend-op, *ip, blockProperties.origSize);
|
924
|
+
decodedSize = ZSTD_setRleBlock(op, (size_t)(oend-op), *ip, blockProperties.origSize);
|
663
925
|
break;
|
664
926
|
case bt_reserved :
|
665
927
|
default:
|
666
|
-
RETURN_ERROR(corruption_detected);
|
928
|
+
RETURN_ERROR(corruption_detected, "invalid block type");
|
667
929
|
}
|
668
930
|
|
669
931
|
if (ZSTD_isError(decodedSize)) return decodedSize;
|
670
|
-
if (dctx->
|
932
|
+
if (dctx->validateChecksum)
|
671
933
|
XXH64_update(&dctx->xxhState, op, decodedSize);
|
672
|
-
|
934
|
+
if (decodedSize != 0)
|
935
|
+
op += decodedSize;
|
936
|
+
assert(ip != NULL);
|
673
937
|
ip += cBlockSize;
|
674
938
|
remainingSrcSize -= cBlockSize;
|
675
939
|
if (blockProperties.lastBlock) break;
|
@@ -677,22 +941,24 @@ static size_t ZSTD_decompressFrame(ZSTD_DCtx* dctx,
|
|
677
941
|
|
678
942
|
if (dctx->fParams.frameContentSize != ZSTD_CONTENTSIZE_UNKNOWN) {
|
679
943
|
RETURN_ERROR_IF((U64)(op-ostart) != dctx->fParams.frameContentSize,
|
680
|
-
corruption_detected);
|
944
|
+
corruption_detected, "");
|
681
945
|
}
|
682
946
|
if (dctx->fParams.checksumFlag) { /* Frame content checksum verification */
|
683
|
-
|
684
|
-
|
685
|
-
|
686
|
-
|
687
|
-
|
947
|
+
RETURN_ERROR_IF(remainingSrcSize<4, checksum_wrong, "");
|
948
|
+
if (!dctx->forceIgnoreChecksum) {
|
949
|
+
U32 const checkCalc = (U32)XXH64_digest(&dctx->xxhState);
|
950
|
+
U32 checkRead;
|
951
|
+
checkRead = MEM_readLE32(ip);
|
952
|
+
RETURN_ERROR_IF(checkRead != checkCalc, checksum_wrong, "");
|
953
|
+
}
|
688
954
|
ip += 4;
|
689
955
|
remainingSrcSize -= 4;
|
690
956
|
}
|
691
|
-
|
957
|
+
ZSTD_DCtx_trace_end(dctx, (U64)(op-ostart), (U64)(ip-istart), /* streaming */ 0);
|
692
958
|
/* Allow caller to get size read */
|
693
959
|
*srcPtr = ip;
|
694
960
|
*srcSizePtr = remainingSrcSize;
|
695
|
-
return op-ostart;
|
961
|
+
return (size_t)(op-ostart);
|
696
962
|
}
|
697
963
|
|
698
964
|
static size_t ZSTD_decompressMultiFrame(ZSTD_DCtx* dctx,
|
@@ -725,7 +991,7 @@ static size_t ZSTD_decompressMultiFrame(ZSTD_DCtx* dctx,
|
|
725
991
|
decodedSize = ZSTD_decompressLegacy(dst, dstCapacity, src, frameSize, dict, dictSize);
|
726
992
|
if (ZSTD_isError(decodedSize)) return decodedSize;
|
727
993
|
|
728
|
-
assert(decodedSize
|
994
|
+
assert(decodedSize <= dstCapacity);
|
729
995
|
dst = (BYTE*)dst + decodedSize;
|
730
996
|
dstCapacity -= decodedSize;
|
731
997
|
|
@@ -741,7 +1007,7 @@ static size_t ZSTD_decompressMultiFrame(ZSTD_DCtx* dctx,
|
|
741
1007
|
(unsigned)magicNumber, ZSTD_MAGICNUMBER);
|
742
1008
|
if ((magicNumber & ZSTD_MAGIC_SKIPPABLE_MASK) == ZSTD_MAGIC_SKIPPABLE_START) {
|
743
1009
|
size_t const skippableSize = readSkippableFrameSize(src, srcSize);
|
744
|
-
FORWARD_IF_ERROR(skippableSize);
|
1010
|
+
FORWARD_IF_ERROR(skippableSize, "readSkippableFrameSize failed");
|
745
1011
|
assert(skippableSize <= srcSize);
|
746
1012
|
|
747
1013
|
src = (const BYTE *)src + skippableSize;
|
@@ -751,13 +1017,13 @@ static size_t ZSTD_decompressMultiFrame(ZSTD_DCtx* dctx,
|
|
751
1017
|
|
752
1018
|
if (ddict) {
|
753
1019
|
/* we were called from ZSTD_decompress_usingDDict */
|
754
|
-
FORWARD_IF_ERROR(ZSTD_decompressBegin_usingDDict(dctx, ddict));
|
1020
|
+
FORWARD_IF_ERROR(ZSTD_decompressBegin_usingDDict(dctx, ddict), "");
|
755
1021
|
} else {
|
756
1022
|
/* this will initialize correctly with no dict if dict == NULL, so
|
757
1023
|
* use this in all cases but ddict */
|
758
|
-
FORWARD_IF_ERROR(ZSTD_decompressBegin_usingDict(dctx, dict, dictSize));
|
1024
|
+
FORWARD_IF_ERROR(ZSTD_decompressBegin_usingDict(dctx, dict, dictSize), "");
|
759
1025
|
}
|
760
|
-
ZSTD_checkContinuity(dctx, dst);
|
1026
|
+
ZSTD_checkContinuity(dctx, dst, dstCapacity);
|
761
1027
|
|
762
1028
|
{ const size_t res = ZSTD_decompressFrame(dctx, dst, dstCapacity,
|
763
1029
|
&src, &srcSize);
|
@@ -765,18 +1031,17 @@ static size_t ZSTD_decompressMultiFrame(ZSTD_DCtx* dctx,
|
|
765
1031
|
(ZSTD_getErrorCode(res) == ZSTD_error_prefix_unknown)
|
766
1032
|
&& (moreThan1Frame==1),
|
767
1033
|
srcSize_wrong,
|
768
|
-
"
|
769
|
-
"bytes are garbage:
|
770
|
-
"
|
771
|
-
"
|
772
|
-
"
|
773
|
-
"
|
774
|
-
"
|
775
|
-
"bytes. But this is _much_ less likely than a srcSize field "
|
776
|
-
"error.");
|
1034
|
+
"At least one frame successfully completed, "
|
1035
|
+
"but following bytes are garbage: "
|
1036
|
+
"it's more likely to be a srcSize error, "
|
1037
|
+
"specifying more input bytes than size of frame(s). "
|
1038
|
+
"Note: one could be unlucky, it might be a corruption error instead, "
|
1039
|
+
"happening right at the place where we expect zstd magic bytes. "
|
1040
|
+
"But this is _much_ less likely than a srcSize field error.");
|
777
1041
|
if (ZSTD_isError(res)) return res;
|
778
1042
|
assert(res <= dstCapacity);
|
779
|
-
|
1043
|
+
if (res != 0)
|
1044
|
+
dst = (BYTE*)dst + res;
|
780
1045
|
dstCapacity -= res;
|
781
1046
|
}
|
782
1047
|
moreThan1Frame = 1;
|
@@ -784,7 +1049,7 @@ static size_t ZSTD_decompressMultiFrame(ZSTD_DCtx* dctx,
|
|
784
1049
|
|
785
1050
|
RETURN_ERROR_IF(srcSize, srcSize_wrong, "input not entirely consumed");
|
786
1051
|
|
787
|
-
return (BYTE*)dst - (BYTE*)dststart;
|
1052
|
+
return (size_t)((BYTE*)dst - (BYTE*)dststart);
|
788
1053
|
}
|
789
1054
|
|
790
1055
|
size_t ZSTD_decompress_usingDict(ZSTD_DCtx* dctx,
|
@@ -801,7 +1066,7 @@ static ZSTD_DDict const* ZSTD_getDDict(ZSTD_DCtx* dctx)
|
|
801
1066
|
switch (dctx->dictUses) {
|
802
1067
|
default:
|
803
1068
|
assert(0 /* Impossible */);
|
804
|
-
|
1069
|
+
ZSTD_FALLTHROUGH;
|
805
1070
|
case ZSTD_dont_use:
|
806
1071
|
ZSTD_clearDict(dctx);
|
807
1072
|
return NULL;
|
@@ -823,8 +1088,8 @@ size_t ZSTD_decompress(void* dst, size_t dstCapacity, const void* src, size_t sr
|
|
823
1088
|
{
|
824
1089
|
#if defined(ZSTD_HEAPMODE) && (ZSTD_HEAPMODE>=1)
|
825
1090
|
size_t regenSize;
|
826
|
-
ZSTD_DCtx* const dctx =
|
827
|
-
RETURN_ERROR_IF(dctx==NULL, memory_allocation);
|
1091
|
+
ZSTD_DCtx* const dctx = ZSTD_createDCtx_internal(ZSTD_defaultCMem);
|
1092
|
+
RETURN_ERROR_IF(dctx==NULL, memory_allocation, "NULL pointer!");
|
828
1093
|
regenSize = ZSTD_decompressDCtx(dctx, dst, dstCapacity, src, srcSize);
|
829
1094
|
ZSTD_freeDCtx(dctx);
|
830
1095
|
return regenSize;
|
@@ -842,12 +1107,32 @@ size_t ZSTD_decompress(void* dst, size_t dstCapacity, const void* src, size_t sr
|
|
842
1107
|
****************************************/
|
843
1108
|
size_t ZSTD_nextSrcSizeToDecompress(ZSTD_DCtx* dctx) { return dctx->expected; }
|
844
1109
|
|
1110
|
+
/**
|
1111
|
+
* Similar to ZSTD_nextSrcSizeToDecompress(), but when when a block input can be streamed,
|
1112
|
+
* we allow taking a partial block as the input. Currently only raw uncompressed blocks can
|
1113
|
+
* be streamed.
|
1114
|
+
*
|
1115
|
+
* For blocks that can be streamed, this allows us to reduce the latency until we produce
|
1116
|
+
* output, and avoid copying the input.
|
1117
|
+
*
|
1118
|
+
* @param inputSize - The total amount of input that the caller currently has.
|
1119
|
+
*/
|
1120
|
+
static size_t ZSTD_nextSrcSizeToDecompressWithInputSize(ZSTD_DCtx* dctx, size_t inputSize) {
|
1121
|
+
if (!(dctx->stage == ZSTDds_decompressBlock || dctx->stage == ZSTDds_decompressLastBlock))
|
1122
|
+
return dctx->expected;
|
1123
|
+
if (dctx->bType != bt_raw)
|
1124
|
+
return dctx->expected;
|
1125
|
+
return BOUNDED(1, inputSize, dctx->expected);
|
1126
|
+
}
|
1127
|
+
|
845
1128
|
ZSTD_nextInputType_e ZSTD_nextInputType(ZSTD_DCtx* dctx) {
|
846
1129
|
switch(dctx->stage)
|
847
1130
|
{
|
848
1131
|
default: /* should not happen */
|
849
1132
|
assert(0);
|
1133
|
+
ZSTD_FALLTHROUGH;
|
850
1134
|
case ZSTDds_getFrameHeaderSize:
|
1135
|
+
ZSTD_FALLTHROUGH;
|
851
1136
|
case ZSTDds_decodeFrameHeader:
|
852
1137
|
return ZSTDnit_frameHeader;
|
853
1138
|
case ZSTDds_decodeBlockHeader:
|
@@ -859,6 +1144,7 @@ ZSTD_nextInputType_e ZSTD_nextInputType(ZSTD_DCtx* dctx) {
|
|
859
1144
|
case ZSTDds_checkChecksum:
|
860
1145
|
return ZSTDnit_checksum;
|
861
1146
|
case ZSTDds_decodeSkippableHeader:
|
1147
|
+
ZSTD_FALLTHROUGH;
|
862
1148
|
case ZSTDds_skipFrame:
|
863
1149
|
return ZSTDnit_skippableFrame;
|
864
1150
|
}
|
@@ -874,8 +1160,10 @@ size_t ZSTD_decompressContinue(ZSTD_DCtx* dctx, void* dst, size_t dstCapacity, c
|
|
874
1160
|
{
|
875
1161
|
DEBUGLOG(5, "ZSTD_decompressContinue (srcSize:%u)", (unsigned)srcSize);
|
876
1162
|
/* Sanity check */
|
877
|
-
RETURN_ERROR_IF(srcSize != dctx
|
878
|
-
|
1163
|
+
RETURN_ERROR_IF(srcSize != ZSTD_nextSrcSizeToDecompressWithInputSize(dctx, srcSize), srcSize_wrong, "not allowed");
|
1164
|
+
ZSTD_checkContinuity(dctx, dst, dstCapacity);
|
1165
|
+
|
1166
|
+
dctx->processedCSize += srcSize;
|
879
1167
|
|
880
1168
|
switch (dctx->stage)
|
881
1169
|
{
|
@@ -884,22 +1172,22 @@ size_t ZSTD_decompressContinue(ZSTD_DCtx* dctx, void* dst, size_t dstCapacity, c
|
|
884
1172
|
if (dctx->format == ZSTD_f_zstd1) { /* allows header */
|
885
1173
|
assert(srcSize >= ZSTD_FRAMEIDSIZE); /* to read skippable magic number */
|
886
1174
|
if ((MEM_readLE32(src) & ZSTD_MAGIC_SKIPPABLE_MASK) == ZSTD_MAGIC_SKIPPABLE_START) { /* skippable frame */
|
887
|
-
|
1175
|
+
ZSTD_memcpy(dctx->headerBuffer, src, srcSize);
|
888
1176
|
dctx->expected = ZSTD_SKIPPABLEHEADERSIZE - srcSize; /* remaining to load to get full skippable frame header */
|
889
1177
|
dctx->stage = ZSTDds_decodeSkippableHeader;
|
890
1178
|
return 0;
|
891
1179
|
} }
|
892
1180
|
dctx->headerSize = ZSTD_frameHeaderSize_internal(src, srcSize, dctx->format);
|
893
1181
|
if (ZSTD_isError(dctx->headerSize)) return dctx->headerSize;
|
894
|
-
|
1182
|
+
ZSTD_memcpy(dctx->headerBuffer, src, srcSize);
|
895
1183
|
dctx->expected = dctx->headerSize - srcSize;
|
896
1184
|
dctx->stage = ZSTDds_decodeFrameHeader;
|
897
1185
|
return 0;
|
898
1186
|
|
899
1187
|
case ZSTDds_decodeFrameHeader:
|
900
1188
|
assert(src != NULL);
|
901
|
-
|
902
|
-
FORWARD_IF_ERROR(ZSTD_decodeFrameHeader(dctx, dctx->headerBuffer, dctx->headerSize));
|
1189
|
+
ZSTD_memcpy(dctx->headerBuffer + (dctx->headerSize - srcSize), src, srcSize);
|
1190
|
+
FORWARD_IF_ERROR(ZSTD_decodeFrameHeader(dctx, dctx->headerBuffer, dctx->headerSize), "");
|
903
1191
|
dctx->expected = ZSTD_blockHeaderSize;
|
904
1192
|
dctx->stage = ZSTDds_decodeBlockHeader;
|
905
1193
|
return 0;
|
@@ -940,51 +1228,67 @@ size_t ZSTD_decompressContinue(ZSTD_DCtx* dctx, void* dst, size_t dstCapacity, c
|
|
940
1228
|
{
|
941
1229
|
case bt_compressed:
|
942
1230
|
DEBUGLOG(5, "ZSTD_decompressContinue: case bt_compressed");
|
943
|
-
rSize = ZSTD_decompressBlock_internal(dctx, dst, dstCapacity, src, srcSize, /* frame */ 1);
|
1231
|
+
rSize = ZSTD_decompressBlock_internal(dctx, dst, dstCapacity, src, srcSize, /* frame */ 1, is_streaming);
|
1232
|
+
dctx->expected = 0; /* Streaming not supported */
|
944
1233
|
break;
|
945
1234
|
case bt_raw :
|
1235
|
+
assert(srcSize <= dctx->expected);
|
946
1236
|
rSize = ZSTD_copyRawBlock(dst, dstCapacity, src, srcSize);
|
1237
|
+
FORWARD_IF_ERROR(rSize, "ZSTD_copyRawBlock failed");
|
1238
|
+
assert(rSize == srcSize);
|
1239
|
+
dctx->expected -= rSize;
|
947
1240
|
break;
|
948
1241
|
case bt_rle :
|
949
1242
|
rSize = ZSTD_setRleBlock(dst, dstCapacity, *(const BYTE*)src, dctx->rleSize);
|
1243
|
+
dctx->expected = 0; /* Streaming not supported */
|
950
1244
|
break;
|
951
1245
|
case bt_reserved : /* should never happen */
|
952
1246
|
default:
|
953
|
-
RETURN_ERROR(corruption_detected);
|
1247
|
+
RETURN_ERROR(corruption_detected, "invalid block type");
|
954
1248
|
}
|
955
|
-
|
1249
|
+
FORWARD_IF_ERROR(rSize, "");
|
956
1250
|
RETURN_ERROR_IF(rSize > dctx->fParams.blockSizeMax, corruption_detected, "Decompressed Block Size Exceeds Maximum");
|
957
1251
|
DEBUGLOG(5, "ZSTD_decompressContinue: decoded size from block : %u", (unsigned)rSize);
|
958
1252
|
dctx->decodedSize += rSize;
|
959
|
-
if (dctx->
|
1253
|
+
if (dctx->validateChecksum) XXH64_update(&dctx->xxhState, dst, rSize);
|
1254
|
+
dctx->previousDstEnd = (char*)dst + rSize;
|
1255
|
+
|
1256
|
+
/* Stay on the same stage until we are finished streaming the block. */
|
1257
|
+
if (dctx->expected > 0) {
|
1258
|
+
return rSize;
|
1259
|
+
}
|
960
1260
|
|
961
1261
|
if (dctx->stage == ZSTDds_decompressLastBlock) { /* end of frame */
|
962
1262
|
DEBUGLOG(4, "ZSTD_decompressContinue: decoded size from frame : %u", (unsigned)dctx->decodedSize);
|
963
1263
|
RETURN_ERROR_IF(
|
964
1264
|
dctx->fParams.frameContentSize != ZSTD_CONTENTSIZE_UNKNOWN
|
965
1265
|
&& dctx->decodedSize != dctx->fParams.frameContentSize,
|
966
|
-
corruption_detected);
|
1266
|
+
corruption_detected, "");
|
967
1267
|
if (dctx->fParams.checksumFlag) { /* another round for frame checksum */
|
968
1268
|
dctx->expected = 4;
|
969
1269
|
dctx->stage = ZSTDds_checkChecksum;
|
970
1270
|
} else {
|
1271
|
+
ZSTD_DCtx_trace_end(dctx, dctx->decodedSize, dctx->processedCSize, /* streaming */ 1);
|
971
1272
|
dctx->expected = 0; /* ends here */
|
972
1273
|
dctx->stage = ZSTDds_getFrameHeaderSize;
|
973
1274
|
}
|
974
1275
|
} else {
|
975
1276
|
dctx->stage = ZSTDds_decodeBlockHeader;
|
976
1277
|
dctx->expected = ZSTD_blockHeaderSize;
|
977
|
-
dctx->previousDstEnd = (char*)dst + rSize;
|
978
1278
|
}
|
979
1279
|
return rSize;
|
980
1280
|
}
|
981
1281
|
|
982
1282
|
case ZSTDds_checkChecksum:
|
983
1283
|
assert(srcSize == 4); /* guaranteed by dctx->expected */
|
984
|
-
{
|
985
|
-
|
986
|
-
|
987
|
-
|
1284
|
+
{
|
1285
|
+
if (dctx->validateChecksum) {
|
1286
|
+
U32 const h32 = (U32)XXH64_digest(&dctx->xxhState);
|
1287
|
+
U32 const check32 = MEM_readLE32(src);
|
1288
|
+
DEBUGLOG(4, "ZSTD_decompressContinue: checksum : calculated %08X :: %08X read", (unsigned)h32, (unsigned)check32);
|
1289
|
+
RETURN_ERROR_IF(check32 != h32, checksum_wrong, "");
|
1290
|
+
}
|
1291
|
+
ZSTD_DCtx_trace_end(dctx, dctx->decodedSize, dctx->processedCSize, /* streaming */ 1);
|
988
1292
|
dctx->expected = 0;
|
989
1293
|
dctx->stage = ZSTDds_getFrameHeaderSize;
|
990
1294
|
return 0;
|
@@ -993,7 +1297,7 @@ size_t ZSTD_decompressContinue(ZSTD_DCtx* dctx, void* dst, size_t dstCapacity, c
|
|
993
1297
|
case ZSTDds_decodeSkippableHeader:
|
994
1298
|
assert(src != NULL);
|
995
1299
|
assert(srcSize <= ZSTD_SKIPPABLEHEADERSIZE);
|
996
|
-
|
1300
|
+
ZSTD_memcpy(dctx->headerBuffer + (ZSTD_SKIPPABLEHEADERSIZE - srcSize), src, srcSize); /* complete skippable header */
|
997
1301
|
dctx->expected = MEM_readLE32(dctx->headerBuffer + ZSTD_FRAMEIDSIZE); /* note : dctx->expected can grow seriously large, beyond local buffer size */
|
998
1302
|
dctx->stage = ZSTDds_skipFrame;
|
999
1303
|
return 0;
|
@@ -1005,7 +1309,7 @@ size_t ZSTD_decompressContinue(ZSTD_DCtx* dctx, void* dst, size_t dstCapacity, c
|
|
1005
1309
|
|
1006
1310
|
default:
|
1007
1311
|
assert(0); /* impossible */
|
1008
|
-
RETURN_ERROR(GENERIC); /* some compiler require default to do something */
|
1312
|
+
RETURN_ERROR(GENERIC, "impossible to reach"); /* some compiler require default to do something */
|
1009
1313
|
}
|
1010
1314
|
}
|
1011
1315
|
|
@@ -1016,6 +1320,10 @@ static size_t ZSTD_refDictContent(ZSTD_DCtx* dctx, const void* dict, size_t dict
|
|
1016
1320
|
dctx->virtualStart = (const char*)dict - ((const char*)(dctx->previousDstEnd) - (const char*)(dctx->prefixStart));
|
1017
1321
|
dctx->prefixStart = dict;
|
1018
1322
|
dctx->previousDstEnd = (const char*)dict + dictSize;
|
1323
|
+
#ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
|
1324
|
+
dctx->dictContentBeginForFuzzing = dctx->prefixStart;
|
1325
|
+
dctx->dictContentEndForFuzzing = dctx->previousDstEnd;
|
1326
|
+
#endif
|
1019
1327
|
return 0;
|
1020
1328
|
}
|
1021
1329
|
|
@@ -1029,7 +1337,7 @@ ZSTD_loadDEntropy(ZSTD_entropyDTables_t* entropy,
|
|
1029
1337
|
const BYTE* dictPtr = (const BYTE*)dict;
|
1030
1338
|
const BYTE* const dictEnd = dictPtr + dictSize;
|
1031
1339
|
|
1032
|
-
RETURN_ERROR_IF(dictSize <= 8, dictionary_corrupted);
|
1340
|
+
RETURN_ERROR_IF(dictSize <= 8, dictionary_corrupted, "dict is too small");
|
1033
1341
|
assert(MEM_readLE32(dict) == ZSTD_MAGIC_DICTIONARY); /* dict must be valid */
|
1034
1342
|
dictPtr += 8; /* skip header = magic + dictID */
|
1035
1343
|
|
@@ -1045,63 +1353,69 @@ ZSTD_loadDEntropy(ZSTD_entropyDTables_t* entropy,
|
|
1045
1353
|
workspace, workspaceSize);
|
1046
1354
|
#else
|
1047
1355
|
size_t const hSize = HUF_readDTableX2_wksp(entropy->hufTable,
|
1048
|
-
dictPtr, dictEnd - dictPtr,
|
1356
|
+
dictPtr, (size_t)(dictEnd - dictPtr),
|
1049
1357
|
workspace, workspaceSize);
|
1050
1358
|
#endif
|
1051
|
-
RETURN_ERROR_IF(HUF_isError(hSize), dictionary_corrupted);
|
1359
|
+
RETURN_ERROR_IF(HUF_isError(hSize), dictionary_corrupted, "");
|
1052
1360
|
dictPtr += hSize;
|
1053
1361
|
}
|
1054
1362
|
|
1055
1363
|
{ short offcodeNCount[MaxOff+1];
|
1056
1364
|
unsigned offcodeMaxValue = MaxOff, offcodeLog;
|
1057
|
-
size_t const offcodeHeaderSize = FSE_readNCount(offcodeNCount, &offcodeMaxValue, &offcodeLog, dictPtr, dictEnd-dictPtr);
|
1058
|
-
RETURN_ERROR_IF(FSE_isError(offcodeHeaderSize), dictionary_corrupted);
|
1059
|
-
RETURN_ERROR_IF(offcodeMaxValue > MaxOff, dictionary_corrupted);
|
1060
|
-
RETURN_ERROR_IF(offcodeLog > OffFSELog, dictionary_corrupted);
|
1365
|
+
size_t const offcodeHeaderSize = FSE_readNCount(offcodeNCount, &offcodeMaxValue, &offcodeLog, dictPtr, (size_t)(dictEnd-dictPtr));
|
1366
|
+
RETURN_ERROR_IF(FSE_isError(offcodeHeaderSize), dictionary_corrupted, "");
|
1367
|
+
RETURN_ERROR_IF(offcodeMaxValue > MaxOff, dictionary_corrupted, "");
|
1368
|
+
RETURN_ERROR_IF(offcodeLog > OffFSELog, dictionary_corrupted, "");
|
1061
1369
|
ZSTD_buildFSETable( entropy->OFTable,
|
1062
1370
|
offcodeNCount, offcodeMaxValue,
|
1063
1371
|
OF_base, OF_bits,
|
1064
|
-
offcodeLog
|
1372
|
+
offcodeLog,
|
1373
|
+
entropy->workspace, sizeof(entropy->workspace),
|
1374
|
+
/* bmi2 */0);
|
1065
1375
|
dictPtr += offcodeHeaderSize;
|
1066
1376
|
}
|
1067
1377
|
|
1068
1378
|
{ short matchlengthNCount[MaxML+1];
|
1069
1379
|
unsigned matchlengthMaxValue = MaxML, matchlengthLog;
|
1070
|
-
size_t const matchlengthHeaderSize = FSE_readNCount(matchlengthNCount, &matchlengthMaxValue, &matchlengthLog, dictPtr, dictEnd-dictPtr);
|
1071
|
-
RETURN_ERROR_IF(FSE_isError(matchlengthHeaderSize), dictionary_corrupted);
|
1072
|
-
RETURN_ERROR_IF(matchlengthMaxValue > MaxML, dictionary_corrupted);
|
1073
|
-
RETURN_ERROR_IF(matchlengthLog > MLFSELog, dictionary_corrupted);
|
1380
|
+
size_t const matchlengthHeaderSize = FSE_readNCount(matchlengthNCount, &matchlengthMaxValue, &matchlengthLog, dictPtr, (size_t)(dictEnd-dictPtr));
|
1381
|
+
RETURN_ERROR_IF(FSE_isError(matchlengthHeaderSize), dictionary_corrupted, "");
|
1382
|
+
RETURN_ERROR_IF(matchlengthMaxValue > MaxML, dictionary_corrupted, "");
|
1383
|
+
RETURN_ERROR_IF(matchlengthLog > MLFSELog, dictionary_corrupted, "");
|
1074
1384
|
ZSTD_buildFSETable( entropy->MLTable,
|
1075
1385
|
matchlengthNCount, matchlengthMaxValue,
|
1076
1386
|
ML_base, ML_bits,
|
1077
|
-
matchlengthLog
|
1387
|
+
matchlengthLog,
|
1388
|
+
entropy->workspace, sizeof(entropy->workspace),
|
1389
|
+
/* bmi2 */ 0);
|
1078
1390
|
dictPtr += matchlengthHeaderSize;
|
1079
1391
|
}
|
1080
1392
|
|
1081
1393
|
{ short litlengthNCount[MaxLL+1];
|
1082
1394
|
unsigned litlengthMaxValue = MaxLL, litlengthLog;
|
1083
|
-
size_t const litlengthHeaderSize = FSE_readNCount(litlengthNCount, &litlengthMaxValue, &litlengthLog, dictPtr, dictEnd-dictPtr);
|
1084
|
-
RETURN_ERROR_IF(FSE_isError(litlengthHeaderSize), dictionary_corrupted);
|
1085
|
-
RETURN_ERROR_IF(litlengthMaxValue > MaxLL, dictionary_corrupted);
|
1086
|
-
RETURN_ERROR_IF(litlengthLog > LLFSELog, dictionary_corrupted);
|
1395
|
+
size_t const litlengthHeaderSize = FSE_readNCount(litlengthNCount, &litlengthMaxValue, &litlengthLog, dictPtr, (size_t)(dictEnd-dictPtr));
|
1396
|
+
RETURN_ERROR_IF(FSE_isError(litlengthHeaderSize), dictionary_corrupted, "");
|
1397
|
+
RETURN_ERROR_IF(litlengthMaxValue > MaxLL, dictionary_corrupted, "");
|
1398
|
+
RETURN_ERROR_IF(litlengthLog > LLFSELog, dictionary_corrupted, "");
|
1087
1399
|
ZSTD_buildFSETable( entropy->LLTable,
|
1088
1400
|
litlengthNCount, litlengthMaxValue,
|
1089
1401
|
LL_base, LL_bits,
|
1090
|
-
litlengthLog
|
1402
|
+
litlengthLog,
|
1403
|
+
entropy->workspace, sizeof(entropy->workspace),
|
1404
|
+
/* bmi2 */ 0);
|
1091
1405
|
dictPtr += litlengthHeaderSize;
|
1092
1406
|
}
|
1093
1407
|
|
1094
|
-
RETURN_ERROR_IF(dictPtr+12 > dictEnd, dictionary_corrupted);
|
1408
|
+
RETURN_ERROR_IF(dictPtr+12 > dictEnd, dictionary_corrupted, "");
|
1095
1409
|
{ int i;
|
1096
1410
|
size_t const dictContentSize = (size_t)(dictEnd - (dictPtr+12));
|
1097
1411
|
for (i=0; i<3; i++) {
|
1098
1412
|
U32 const rep = MEM_readLE32(dictPtr); dictPtr += 4;
|
1099
1413
|
RETURN_ERROR_IF(rep==0 || rep > dictContentSize,
|
1100
|
-
dictionary_corrupted);
|
1414
|
+
dictionary_corrupted, "");
|
1101
1415
|
entropy->rep[i] = rep;
|
1102
1416
|
} }
|
1103
1417
|
|
1104
|
-
return dictPtr - (const BYTE*)dict;
|
1418
|
+
return (size_t)(dictPtr - (const BYTE*)dict);
|
1105
1419
|
}
|
1106
1420
|
|
1107
1421
|
static size_t ZSTD_decompress_insertDictionary(ZSTD_DCtx* dctx, const void* dict, size_t dictSize)
|
@@ -1115,7 +1429,7 @@ static size_t ZSTD_decompress_insertDictionary(ZSTD_DCtx* dctx, const void* dict
|
|
1115
1429
|
|
1116
1430
|
/* load entropy tables */
|
1117
1431
|
{ size_t const eSize = ZSTD_loadDEntropy(&dctx->entropy, dict, dictSize);
|
1118
|
-
RETURN_ERROR_IF(ZSTD_isError(eSize), dictionary_corrupted);
|
1432
|
+
RETURN_ERROR_IF(ZSTD_isError(eSize), dictionary_corrupted, "");
|
1119
1433
|
dict = (const char*)dict + eSize;
|
1120
1434
|
dictSize -= eSize;
|
1121
1435
|
}
|
@@ -1128,8 +1442,12 @@ static size_t ZSTD_decompress_insertDictionary(ZSTD_DCtx* dctx, const void* dict
|
|
1128
1442
|
size_t ZSTD_decompressBegin(ZSTD_DCtx* dctx)
|
1129
1443
|
{
|
1130
1444
|
assert(dctx != NULL);
|
1445
|
+
#if ZSTD_TRACE
|
1446
|
+
dctx->traceCtx = (ZSTD_trace_decompress_begin != NULL) ? ZSTD_trace_decompress_begin(dctx) : 0;
|
1447
|
+
#endif
|
1131
1448
|
dctx->expected = ZSTD_startingInputLength(dctx->format); /* dctx->format must be properly set */
|
1132
1449
|
dctx->stage = ZSTDds_getFrameHeaderSize;
|
1450
|
+
dctx->processedCSize = 0;
|
1133
1451
|
dctx->decodedSize = 0;
|
1134
1452
|
dctx->previousDstEnd = NULL;
|
1135
1453
|
dctx->prefixStart = NULL;
|
@@ -1138,8 +1456,9 @@ size_t ZSTD_decompressBegin(ZSTD_DCtx* dctx)
|
|
1138
1456
|
dctx->entropy.hufTable[0] = (HUF_DTable)((HufLog)*0x1000001); /* cover both little and big endian */
|
1139
1457
|
dctx->litEntropy = dctx->fseEntropy = 0;
|
1140
1458
|
dctx->dictID = 0;
|
1459
|
+
dctx->bType = bt_reserved;
|
1141
1460
|
ZSTD_STATIC_ASSERT(sizeof(dctx->entropy.rep) == sizeof(repStartValue));
|
1142
|
-
|
1461
|
+
ZSTD_memcpy(dctx->entropy.rep, repStartValue, sizeof(repStartValue)); /* initial repcodes */
|
1143
1462
|
dctx->LLTptr = dctx->entropy.LLTable;
|
1144
1463
|
dctx->MLTptr = dctx->entropy.MLTable;
|
1145
1464
|
dctx->OFTptr = dctx->entropy.OFTable;
|
@@ -1149,11 +1468,11 @@ size_t ZSTD_decompressBegin(ZSTD_DCtx* dctx)
|
|
1149
1468
|
|
1150
1469
|
size_t ZSTD_decompressBegin_usingDict(ZSTD_DCtx* dctx, const void* dict, size_t dictSize)
|
1151
1470
|
{
|
1152
|
-
FORWARD_IF_ERROR( ZSTD_decompressBegin(dctx) );
|
1471
|
+
FORWARD_IF_ERROR( ZSTD_decompressBegin(dctx) , "");
|
1153
1472
|
if (dict && dictSize)
|
1154
1473
|
RETURN_ERROR_IF(
|
1155
1474
|
ZSTD_isError(ZSTD_decompress_insertDictionary(dctx, dict, dictSize)),
|
1156
|
-
dictionary_corrupted);
|
1475
|
+
dictionary_corrupted, "");
|
1157
1476
|
return 0;
|
1158
1477
|
}
|
1159
1478
|
|
@@ -1172,7 +1491,7 @@ size_t ZSTD_decompressBegin_usingDDict(ZSTD_DCtx* dctx, const ZSTD_DDict* ddict)
|
|
1172
1491
|
DEBUGLOG(4, "DDict is %s",
|
1173
1492
|
dctx->ddictIsCold ? "~cold~" : "hot!");
|
1174
1493
|
}
|
1175
|
-
FORWARD_IF_ERROR( ZSTD_decompressBegin(dctx) );
|
1494
|
+
FORWARD_IF_ERROR( ZSTD_decompressBegin(dctx) , "");
|
1176
1495
|
if (ddict) { /* NULL ddict is equivalent to no dictionary */
|
1177
1496
|
ZSTD_copyDDictParameters(dctx, ddict);
|
1178
1497
|
}
|
@@ -1234,7 +1553,7 @@ size_t ZSTD_decompress_usingDDict(ZSTD_DCtx* dctx,
|
|
1234
1553
|
ZSTD_DStream* ZSTD_createDStream(void)
|
1235
1554
|
{
|
1236
1555
|
DEBUGLOG(3, "ZSTD_createDStream");
|
1237
|
-
return
|
1556
|
+
return ZSTD_createDCtx_internal(ZSTD_defaultCMem);
|
1238
1557
|
}
|
1239
1558
|
|
1240
1559
|
ZSTD_DStream* ZSTD_initStaticDStream(void *workspace, size_t workspaceSize)
|
@@ -1244,7 +1563,7 @@ ZSTD_DStream* ZSTD_initStaticDStream(void *workspace, size_t workspaceSize)
|
|
1244
1563
|
|
1245
1564
|
ZSTD_DStream* ZSTD_createDStream_advanced(ZSTD_customMem customMem)
|
1246
1565
|
{
|
1247
|
-
return
|
1566
|
+
return ZSTD_createDCtx_internal(customMem);
|
1248
1567
|
}
|
1249
1568
|
|
1250
1569
|
size_t ZSTD_freeDStream(ZSTD_DStream* zds)
|
@@ -1263,11 +1582,11 @@ size_t ZSTD_DCtx_loadDictionary_advanced(ZSTD_DCtx* dctx,
|
|
1263
1582
|
ZSTD_dictLoadMethod_e dictLoadMethod,
|
1264
1583
|
ZSTD_dictContentType_e dictContentType)
|
1265
1584
|
{
|
1266
|
-
RETURN_ERROR_IF(dctx->streamStage != zdss_init, stage_wrong);
|
1585
|
+
RETURN_ERROR_IF(dctx->streamStage != zdss_init, stage_wrong, "");
|
1267
1586
|
ZSTD_clearDict(dctx);
|
1268
1587
|
if (dict && dictSize != 0) {
|
1269
1588
|
dctx->ddictLocal = ZSTD_createDDict_advanced(dict, dictSize, dictLoadMethod, dictContentType, dctx->customMem);
|
1270
|
-
RETURN_ERROR_IF(dctx->ddictLocal == NULL, memory_allocation);
|
1589
|
+
RETURN_ERROR_IF(dctx->ddictLocal == NULL, memory_allocation, "NULL pointer!");
|
1271
1590
|
dctx->ddict = dctx->ddictLocal;
|
1272
1591
|
dctx->dictUses = ZSTD_use_indefinitely;
|
1273
1592
|
}
|
@@ -1286,7 +1605,7 @@ size_t ZSTD_DCtx_loadDictionary(ZSTD_DCtx* dctx, const void* dict, size_t dictSi
|
|
1286
1605
|
|
1287
1606
|
size_t ZSTD_DCtx_refPrefix_advanced(ZSTD_DCtx* dctx, const void* prefix, size_t prefixSize, ZSTD_dictContentType_e dictContentType)
|
1288
1607
|
{
|
1289
|
-
FORWARD_IF_ERROR(ZSTD_DCtx_loadDictionary_advanced(dctx, prefix, prefixSize, ZSTD_dlm_byRef, dictContentType));
|
1608
|
+
FORWARD_IF_ERROR(ZSTD_DCtx_loadDictionary_advanced(dctx, prefix, prefixSize, ZSTD_dlm_byRef, dictContentType), "");
|
1290
1609
|
dctx->dictUses = ZSTD_use_once;
|
1291
1610
|
return 0;
|
1292
1611
|
}
|
@@ -1303,8 +1622,8 @@ size_t ZSTD_DCtx_refPrefix(ZSTD_DCtx* dctx, const void* prefix, size_t prefixSiz
|
|
1303
1622
|
size_t ZSTD_initDStream_usingDict(ZSTD_DStream* zds, const void* dict, size_t dictSize)
|
1304
1623
|
{
|
1305
1624
|
DEBUGLOG(4, "ZSTD_initDStream_usingDict");
|
1306
|
-
FORWARD_IF_ERROR( ZSTD_DCtx_reset(zds, ZSTD_reset_session_only) );
|
1307
|
-
FORWARD_IF_ERROR( ZSTD_DCtx_loadDictionary(zds, dict, dictSize) );
|
1625
|
+
FORWARD_IF_ERROR( ZSTD_DCtx_reset(zds, ZSTD_reset_session_only) , "");
|
1626
|
+
FORWARD_IF_ERROR( ZSTD_DCtx_loadDictionary(zds, dict, dictSize) , "");
|
1308
1627
|
return ZSTD_startingInputLength(zds->format);
|
1309
1628
|
}
|
1310
1629
|
|
@@ -1320,8 +1639,8 @@ size_t ZSTD_initDStream(ZSTD_DStream* zds)
|
|
1320
1639
|
* this function cannot fail */
|
1321
1640
|
size_t ZSTD_initDStream_usingDDict(ZSTD_DStream* dctx, const ZSTD_DDict* ddict)
|
1322
1641
|
{
|
1323
|
-
FORWARD_IF_ERROR( ZSTD_DCtx_reset(dctx, ZSTD_reset_session_only) );
|
1324
|
-
FORWARD_IF_ERROR( ZSTD_DCtx_refDDict(dctx, ddict) );
|
1642
|
+
FORWARD_IF_ERROR( ZSTD_DCtx_reset(dctx, ZSTD_reset_session_only) , "");
|
1643
|
+
FORWARD_IF_ERROR( ZSTD_DCtx_refDDict(dctx, ddict) , "");
|
1325
1644
|
return ZSTD_startingInputLength(dctx->format);
|
1326
1645
|
}
|
1327
1646
|
|
@@ -1330,18 +1649,28 @@ size_t ZSTD_initDStream_usingDDict(ZSTD_DStream* dctx, const ZSTD_DDict* ddict)
|
|
1330
1649
|
* this function cannot fail */
|
1331
1650
|
size_t ZSTD_resetDStream(ZSTD_DStream* dctx)
|
1332
1651
|
{
|
1333
|
-
FORWARD_IF_ERROR(ZSTD_DCtx_reset(dctx, ZSTD_reset_session_only));
|
1652
|
+
FORWARD_IF_ERROR(ZSTD_DCtx_reset(dctx, ZSTD_reset_session_only), "");
|
1334
1653
|
return ZSTD_startingInputLength(dctx->format);
|
1335
1654
|
}
|
1336
1655
|
|
1337
1656
|
|
1338
1657
|
size_t ZSTD_DCtx_refDDict(ZSTD_DCtx* dctx, const ZSTD_DDict* ddict)
|
1339
1658
|
{
|
1340
|
-
RETURN_ERROR_IF(dctx->streamStage != zdss_init, stage_wrong);
|
1659
|
+
RETURN_ERROR_IF(dctx->streamStage != zdss_init, stage_wrong, "");
|
1341
1660
|
ZSTD_clearDict(dctx);
|
1342
1661
|
if (ddict) {
|
1343
1662
|
dctx->ddict = ddict;
|
1344
1663
|
dctx->dictUses = ZSTD_use_indefinitely;
|
1664
|
+
if (dctx->refMultipleDDicts == ZSTD_rmd_refMultipleDDicts) {
|
1665
|
+
if (dctx->ddictSet == NULL) {
|
1666
|
+
dctx->ddictSet = ZSTD_createDDictHashSet(dctx->customMem);
|
1667
|
+
if (!dctx->ddictSet) {
|
1668
|
+
RETURN_ERROR(memory_allocation, "Failed to allocate memory for hash set!");
|
1669
|
+
}
|
1670
|
+
}
|
1671
|
+
assert(!dctx->staticSize); /* Impossible: ddictSet cannot have been allocated if static dctx */
|
1672
|
+
FORWARD_IF_ERROR(ZSTD_DDictHashSet_addDDict(dctx->ddictSet, ddict, dctx->customMem), "");
|
1673
|
+
}
|
1345
1674
|
}
|
1346
1675
|
return 0;
|
1347
1676
|
}
|
@@ -1354,16 +1683,16 @@ size_t ZSTD_DCtx_setMaxWindowSize(ZSTD_DCtx* dctx, size_t maxWindowSize)
|
|
1354
1683
|
ZSTD_bounds const bounds = ZSTD_dParam_getBounds(ZSTD_d_windowLogMax);
|
1355
1684
|
size_t const min = (size_t)1 << bounds.lowerBound;
|
1356
1685
|
size_t const max = (size_t)1 << bounds.upperBound;
|
1357
|
-
RETURN_ERROR_IF(dctx->streamStage != zdss_init, stage_wrong);
|
1358
|
-
RETURN_ERROR_IF(maxWindowSize < min, parameter_outOfBound);
|
1359
|
-
RETURN_ERROR_IF(maxWindowSize > max, parameter_outOfBound);
|
1686
|
+
RETURN_ERROR_IF(dctx->streamStage != zdss_init, stage_wrong, "");
|
1687
|
+
RETURN_ERROR_IF(maxWindowSize < min, parameter_outOfBound, "");
|
1688
|
+
RETURN_ERROR_IF(maxWindowSize > max, parameter_outOfBound, "");
|
1360
1689
|
dctx->maxWindowSize = maxWindowSize;
|
1361
1690
|
return 0;
|
1362
1691
|
}
|
1363
1692
|
|
1364
1693
|
size_t ZSTD_DCtx_setFormat(ZSTD_DCtx* dctx, ZSTD_format_e format)
|
1365
1694
|
{
|
1366
|
-
return ZSTD_DCtx_setParameter(dctx, ZSTD_d_format, format);
|
1695
|
+
return ZSTD_DCtx_setParameter(dctx, ZSTD_d_format, (int)format);
|
1367
1696
|
}
|
1368
1697
|
|
1369
1698
|
ZSTD_bounds ZSTD_dParam_getBounds(ZSTD_dParameter dParam)
|
@@ -1379,6 +1708,18 @@ ZSTD_bounds ZSTD_dParam_getBounds(ZSTD_dParameter dParam)
|
|
1379
1708
|
bounds.upperBound = (int)ZSTD_f_zstd1_magicless;
|
1380
1709
|
ZSTD_STATIC_ASSERT(ZSTD_f_zstd1 < ZSTD_f_zstd1_magicless);
|
1381
1710
|
return bounds;
|
1711
|
+
case ZSTD_d_stableOutBuffer:
|
1712
|
+
bounds.lowerBound = (int)ZSTD_bm_buffered;
|
1713
|
+
bounds.upperBound = (int)ZSTD_bm_stable;
|
1714
|
+
return bounds;
|
1715
|
+
case ZSTD_d_forceIgnoreChecksum:
|
1716
|
+
bounds.lowerBound = (int)ZSTD_d_validateChecksum;
|
1717
|
+
bounds.upperBound = (int)ZSTD_d_ignoreChecksum;
|
1718
|
+
return bounds;
|
1719
|
+
case ZSTD_d_refMultipleDDicts:
|
1720
|
+
bounds.lowerBound = (int)ZSTD_rmd_refSingleDDict;
|
1721
|
+
bounds.upperBound = (int)ZSTD_rmd_refMultipleDDicts;
|
1722
|
+
return bounds;
|
1382
1723
|
default:;
|
1383
1724
|
}
|
1384
1725
|
bounds.error = ERROR(parameter_unsupported);
|
@@ -1398,12 +1739,35 @@ static int ZSTD_dParam_withinBounds(ZSTD_dParameter dParam, int value)
|
|
1398
1739
|
}
|
1399
1740
|
|
1400
1741
|
#define CHECK_DBOUNDS(p,v) { \
|
1401
|
-
RETURN_ERROR_IF(!ZSTD_dParam_withinBounds(p, v), parameter_outOfBound); \
|
1742
|
+
RETURN_ERROR_IF(!ZSTD_dParam_withinBounds(p, v), parameter_outOfBound, ""); \
|
1743
|
+
}
|
1744
|
+
|
1745
|
+
size_t ZSTD_DCtx_getParameter(ZSTD_DCtx* dctx, ZSTD_dParameter param, int* value)
|
1746
|
+
{
|
1747
|
+
switch (param) {
|
1748
|
+
case ZSTD_d_windowLogMax:
|
1749
|
+
*value = (int)ZSTD_highbit32((U32)dctx->maxWindowSize);
|
1750
|
+
return 0;
|
1751
|
+
case ZSTD_d_format:
|
1752
|
+
*value = (int)dctx->format;
|
1753
|
+
return 0;
|
1754
|
+
case ZSTD_d_stableOutBuffer:
|
1755
|
+
*value = (int)dctx->outBufferMode;
|
1756
|
+
return 0;
|
1757
|
+
case ZSTD_d_forceIgnoreChecksum:
|
1758
|
+
*value = (int)dctx->forceIgnoreChecksum;
|
1759
|
+
return 0;
|
1760
|
+
case ZSTD_d_refMultipleDDicts:
|
1761
|
+
*value = (int)dctx->refMultipleDDicts;
|
1762
|
+
return 0;
|
1763
|
+
default:;
|
1764
|
+
}
|
1765
|
+
RETURN_ERROR(parameter_unsupported, "");
|
1402
1766
|
}
|
1403
1767
|
|
1404
1768
|
size_t ZSTD_DCtx_setParameter(ZSTD_DCtx* dctx, ZSTD_dParameter dParam, int value)
|
1405
1769
|
{
|
1406
|
-
RETURN_ERROR_IF(dctx->streamStage != zdss_init, stage_wrong);
|
1770
|
+
RETURN_ERROR_IF(dctx->streamStage != zdss_init, stage_wrong, "");
|
1407
1771
|
switch(dParam) {
|
1408
1772
|
case ZSTD_d_windowLogMax:
|
1409
1773
|
if (value == 0) value = ZSTD_WINDOWLOG_LIMIT_DEFAULT;
|
@@ -1414,9 +1778,24 @@ size_t ZSTD_DCtx_setParameter(ZSTD_DCtx* dctx, ZSTD_dParameter dParam, int value
|
|
1414
1778
|
CHECK_DBOUNDS(ZSTD_d_format, value);
|
1415
1779
|
dctx->format = (ZSTD_format_e)value;
|
1416
1780
|
return 0;
|
1781
|
+
case ZSTD_d_stableOutBuffer:
|
1782
|
+
CHECK_DBOUNDS(ZSTD_d_stableOutBuffer, value);
|
1783
|
+
dctx->outBufferMode = (ZSTD_bufferMode_e)value;
|
1784
|
+
return 0;
|
1785
|
+
case ZSTD_d_forceIgnoreChecksum:
|
1786
|
+
CHECK_DBOUNDS(ZSTD_d_forceIgnoreChecksum, value);
|
1787
|
+
dctx->forceIgnoreChecksum = (ZSTD_forceIgnoreChecksum_e)value;
|
1788
|
+
return 0;
|
1789
|
+
case ZSTD_d_refMultipleDDicts:
|
1790
|
+
CHECK_DBOUNDS(ZSTD_d_refMultipleDDicts, value);
|
1791
|
+
if (dctx->staticSize != 0) {
|
1792
|
+
RETURN_ERROR(parameter_unsupported, "Static dctx does not support multiple DDicts!");
|
1793
|
+
}
|
1794
|
+
dctx->refMultipleDDicts = (ZSTD_refMultipleDDicts_e)value;
|
1795
|
+
return 0;
|
1417
1796
|
default:;
|
1418
1797
|
}
|
1419
|
-
RETURN_ERROR(parameter_unsupported);
|
1798
|
+
RETURN_ERROR(parameter_unsupported, "");
|
1420
1799
|
}
|
1421
1800
|
|
1422
1801
|
size_t ZSTD_DCtx_reset(ZSTD_DCtx* dctx, ZSTD_ResetDirective reset)
|
@@ -1428,10 +1807,9 @@ size_t ZSTD_DCtx_reset(ZSTD_DCtx* dctx, ZSTD_ResetDirective reset)
|
|
1428
1807
|
}
|
1429
1808
|
if ( (reset == ZSTD_reset_parameters)
|
1430
1809
|
|| (reset == ZSTD_reset_session_and_parameters) ) {
|
1431
|
-
RETURN_ERROR_IF(dctx->streamStage != zdss_init, stage_wrong);
|
1810
|
+
RETURN_ERROR_IF(dctx->streamStage != zdss_init, stage_wrong, "");
|
1432
1811
|
ZSTD_clearDict(dctx);
|
1433
|
-
dctx
|
1434
|
-
dctx->maxWindowSize = ZSTD_MAXWINDOWSIZE_DEFAULT;
|
1812
|
+
ZSTD_DCtx_resetParameters(dctx);
|
1435
1813
|
}
|
1436
1814
|
return 0;
|
1437
1815
|
}
|
@@ -1445,11 +1823,12 @@ size_t ZSTD_sizeof_DStream(const ZSTD_DStream* dctx)
|
|
1445
1823
|
size_t ZSTD_decodingBufferSize_min(unsigned long long windowSize, unsigned long long frameContentSize)
|
1446
1824
|
{
|
1447
1825
|
size_t const blockSize = (size_t) MIN(windowSize, ZSTD_BLOCKSIZE_MAX);
|
1448
|
-
|
1826
|
+
/* space is needed to store the litbuffer after the output of a given block without stomping the extDict of a previous run, as well as to cover both windows against wildcopy*/
|
1827
|
+
unsigned long long const neededRBSize = windowSize + blockSize + ZSTD_BLOCKSIZE_MAX + (WILDCOPY_OVERLENGTH * 2);
|
1449
1828
|
unsigned long long const neededSize = MIN(frameContentSize, neededRBSize);
|
1450
1829
|
size_t const minRBSize = (size_t) neededSize;
|
1451
1830
|
RETURN_ERROR_IF((unsigned long long)minRBSize != neededSize,
|
1452
|
-
frameParameter_windowTooLarge);
|
1831
|
+
frameParameter_windowTooLarge, "");
|
1453
1832
|
return minRBSize;
|
1454
1833
|
}
|
1455
1834
|
|
@@ -1467,30 +1846,94 @@ size_t ZSTD_estimateDStreamSize_fromFrame(const void* src, size_t srcSize)
|
|
1467
1846
|
ZSTD_frameHeader zfh;
|
1468
1847
|
size_t const err = ZSTD_getFrameHeader(&zfh, src, srcSize);
|
1469
1848
|
if (ZSTD_isError(err)) return err;
|
1470
|
-
RETURN_ERROR_IF(err>0, srcSize_wrong);
|
1849
|
+
RETURN_ERROR_IF(err>0, srcSize_wrong, "");
|
1471
1850
|
RETURN_ERROR_IF(zfh.windowSize > windowSizeMax,
|
1472
|
-
frameParameter_windowTooLarge);
|
1851
|
+
frameParameter_windowTooLarge, "");
|
1473
1852
|
return ZSTD_estimateDStreamSize((size_t)zfh.windowSize);
|
1474
1853
|
}
|
1475
1854
|
|
1476
1855
|
|
1477
1856
|
/* ***** Decompression ***** */
|
1478
1857
|
|
1479
|
-
|
1858
|
+
static int ZSTD_DCtx_isOverflow(ZSTD_DStream* zds, size_t const neededInBuffSize, size_t const neededOutBuffSize)
|
1859
|
+
{
|
1860
|
+
return (zds->inBuffSize + zds->outBuffSize) >= (neededInBuffSize + neededOutBuffSize) * ZSTD_WORKSPACETOOLARGE_FACTOR;
|
1861
|
+
}
|
1862
|
+
|
1863
|
+
static void ZSTD_DCtx_updateOversizedDuration(ZSTD_DStream* zds, size_t const neededInBuffSize, size_t const neededOutBuffSize)
|
1864
|
+
{
|
1865
|
+
if (ZSTD_DCtx_isOverflow(zds, neededInBuffSize, neededOutBuffSize))
|
1866
|
+
zds->oversizedDuration++;
|
1867
|
+
else
|
1868
|
+
zds->oversizedDuration = 0;
|
1869
|
+
}
|
1870
|
+
|
1871
|
+
static int ZSTD_DCtx_isOversizedTooLong(ZSTD_DStream* zds)
|
1480
1872
|
{
|
1481
|
-
|
1482
|
-
memcpy(dst, src, length);
|
1483
|
-
return length;
|
1873
|
+
return zds->oversizedDuration >= ZSTD_WORKSPACETOOLARGE_MAXDURATION;
|
1484
1874
|
}
|
1485
1875
|
|
1876
|
+
/* Checks that the output buffer hasn't changed if ZSTD_obm_stable is used. */
|
1877
|
+
static size_t ZSTD_checkOutBuffer(ZSTD_DStream const* zds, ZSTD_outBuffer const* output)
|
1878
|
+
{
|
1879
|
+
ZSTD_outBuffer const expect = zds->expectedOutBuffer;
|
1880
|
+
/* No requirement when ZSTD_obm_stable is not enabled. */
|
1881
|
+
if (zds->outBufferMode != ZSTD_bm_stable)
|
1882
|
+
return 0;
|
1883
|
+
/* Any buffer is allowed in zdss_init, this must be the same for every other call until
|
1884
|
+
* the context is reset.
|
1885
|
+
*/
|
1886
|
+
if (zds->streamStage == zdss_init)
|
1887
|
+
return 0;
|
1888
|
+
/* The buffer must match our expectation exactly. */
|
1889
|
+
if (expect.dst == output->dst && expect.pos == output->pos && expect.size == output->size)
|
1890
|
+
return 0;
|
1891
|
+
RETURN_ERROR(dstBuffer_wrong, "ZSTD_d_stableOutBuffer enabled but output differs!");
|
1892
|
+
}
|
1893
|
+
|
1894
|
+
/* Calls ZSTD_decompressContinue() with the right parameters for ZSTD_decompressStream()
|
1895
|
+
* and updates the stage and the output buffer state. This call is extracted so it can be
|
1896
|
+
* used both when reading directly from the ZSTD_inBuffer, and in buffered input mode.
|
1897
|
+
* NOTE: You must break after calling this function since the streamStage is modified.
|
1898
|
+
*/
|
1899
|
+
static size_t ZSTD_decompressContinueStream(
|
1900
|
+
ZSTD_DStream* zds, char** op, char* oend,
|
1901
|
+
void const* src, size_t srcSize) {
|
1902
|
+
int const isSkipFrame = ZSTD_isSkipFrame(zds);
|
1903
|
+
if (zds->outBufferMode == ZSTD_bm_buffered) {
|
1904
|
+
size_t const dstSize = isSkipFrame ? 0 : zds->outBuffSize - zds->outStart;
|
1905
|
+
size_t const decodedSize = ZSTD_decompressContinue(zds,
|
1906
|
+
zds->outBuff + zds->outStart, dstSize, src, srcSize);
|
1907
|
+
FORWARD_IF_ERROR(decodedSize, "");
|
1908
|
+
if (!decodedSize && !isSkipFrame) {
|
1909
|
+
zds->streamStage = zdss_read;
|
1910
|
+
} else {
|
1911
|
+
zds->outEnd = zds->outStart + decodedSize;
|
1912
|
+
zds->streamStage = zdss_flush;
|
1913
|
+
}
|
1914
|
+
} else {
|
1915
|
+
/* Write directly into the output buffer */
|
1916
|
+
size_t const dstSize = isSkipFrame ? 0 : (size_t)(oend - *op);
|
1917
|
+
size_t const decodedSize = ZSTD_decompressContinue(zds, *op, dstSize, src, srcSize);
|
1918
|
+
FORWARD_IF_ERROR(decodedSize, "");
|
1919
|
+
*op += decodedSize;
|
1920
|
+
/* Flushing is not needed. */
|
1921
|
+
zds->streamStage = zdss_read;
|
1922
|
+
assert(*op <= oend);
|
1923
|
+
assert(zds->outBufferMode == ZSTD_bm_stable);
|
1924
|
+
}
|
1925
|
+
return 0;
|
1926
|
+
}
|
1486
1927
|
|
1487
1928
|
size_t ZSTD_decompressStream(ZSTD_DStream* zds, ZSTD_outBuffer* output, ZSTD_inBuffer* input)
|
1488
1929
|
{
|
1489
|
-
const char* const
|
1490
|
-
const char* const
|
1930
|
+
const char* const src = (const char*)input->src;
|
1931
|
+
const char* const istart = input->pos != 0 ? src + input->pos : src;
|
1932
|
+
const char* const iend = input->size != 0 ? src + input->size : src;
|
1491
1933
|
const char* ip = istart;
|
1492
|
-
char* const
|
1493
|
-
char* const
|
1934
|
+
char* const dst = (char*)output->dst;
|
1935
|
+
char* const ostart = output->pos != 0 ? dst + output->pos : dst;
|
1936
|
+
char* const oend = output->size != 0 ? dst + output->size : dst;
|
1494
1937
|
char* op = ostart;
|
1495
1938
|
U32 someMoreWork = 1;
|
1496
1939
|
|
@@ -1506,6 +1949,7 @@ size_t ZSTD_decompressStream(ZSTD_DStream* zds, ZSTD_outBuffer* output, ZSTD_inB
|
|
1506
1949
|
"forbidden. out: pos: %u vs size: %u",
|
1507
1950
|
(U32)output->pos, (U32)output->size);
|
1508
1951
|
DEBUGLOG(5, "input size : %u", (U32)(input->size - input->pos));
|
1952
|
+
FORWARD_IF_ERROR(ZSTD_checkOutBuffer(zds, output), "");
|
1509
1953
|
|
1510
1954
|
while (someMoreWork) {
|
1511
1955
|
switch(zds->streamStage)
|
@@ -1514,9 +1958,12 @@ size_t ZSTD_decompressStream(ZSTD_DStream* zds, ZSTD_outBuffer* output, ZSTD_inB
|
|
1514
1958
|
DEBUGLOG(5, "stage zdss_init => transparent reset ");
|
1515
1959
|
zds->streamStage = zdss_loadHeader;
|
1516
1960
|
zds->lhSize = zds->inPos = zds->outStart = zds->outEnd = 0;
|
1961
|
+
#if defined(ZSTD_LEGACY_SUPPORT) && (ZSTD_LEGACY_SUPPORT>=1)
|
1517
1962
|
zds->legacyVersion = 0;
|
1963
|
+
#endif
|
1518
1964
|
zds->hostageByte = 0;
|
1519
|
-
|
1965
|
+
zds->expectedOutBuffer = *output;
|
1966
|
+
ZSTD_FALLTHROUGH;
|
1520
1967
|
|
1521
1968
|
case zdss_loadHeader :
|
1522
1969
|
DEBUGLOG(5, "stage zdss_loadHeader (srcSize : %u)", (U32)(iend - ip));
|
@@ -1530,6 +1977,9 @@ size_t ZSTD_decompressStream(ZSTD_DStream* zds, ZSTD_outBuffer* output, ZSTD_inB
|
|
1530
1977
|
} }
|
1531
1978
|
#endif
|
1532
1979
|
{ size_t const hSize = ZSTD_getFrameHeader_advanced(&zds->fParams, zds->headerBuffer, zds->lhSize, zds->format);
|
1980
|
+
if (zds->refMultipleDDicts && zds->ddictSet) {
|
1981
|
+
ZSTD_DCtx_selectFrameDDict(zds);
|
1982
|
+
}
|
1533
1983
|
DEBUGLOG(5, "header size : %u", (U32)hSize);
|
1534
1984
|
if (ZSTD_isError(hSize)) {
|
1535
1985
|
#if defined(ZSTD_LEGACY_SUPPORT) && (ZSTD_LEGACY_SUPPORT>=1)
|
@@ -1543,7 +1993,7 @@ size_t ZSTD_decompressStream(ZSTD_DStream* zds, ZSTD_outBuffer* output, ZSTD_inB
|
|
1543
1993
|
"legacy support is incompatible with static dctx");
|
1544
1994
|
FORWARD_IF_ERROR(ZSTD_initLegacyStream(&zds->legacyContext,
|
1545
1995
|
zds->previousLegacyVersion, legacyVersion,
|
1546
|
-
dict, dictSize));
|
1996
|
+
dict, dictSize), "");
|
1547
1997
|
zds->legacyVersion = zds->previousLegacyVersion = legacyVersion;
|
1548
1998
|
{ size_t const hint = ZSTD_decompressLegacyStream(zds->legacyContext, legacyVersion, output, input);
|
1549
1999
|
if (hint==0) zds->streamStage = zdss_init; /* or stay in stage zdss_loadHeader */
|
@@ -1558,24 +2008,25 @@ size_t ZSTD_decompressStream(ZSTD_DStream* zds, ZSTD_outBuffer* output, ZSTD_inB
|
|
1558
2008
|
assert(iend >= ip);
|
1559
2009
|
if (toLoad > remainingInput) { /* not enough input to load full header */
|
1560
2010
|
if (remainingInput > 0) {
|
1561
|
-
|
2011
|
+
ZSTD_memcpy(zds->headerBuffer + zds->lhSize, ip, remainingInput);
|
1562
2012
|
zds->lhSize += remainingInput;
|
1563
2013
|
}
|
1564
2014
|
input->pos = input->size;
|
1565
2015
|
return (MAX((size_t)ZSTD_FRAMEHEADERSIZE_MIN(zds->format), hSize) - zds->lhSize) + ZSTD_blockHeaderSize; /* remaining header bytes + next block header */
|
1566
2016
|
}
|
1567
2017
|
assert(ip != NULL);
|
1568
|
-
|
2018
|
+
ZSTD_memcpy(zds->headerBuffer + zds->lhSize, ip, toLoad); zds->lhSize = hSize; ip += toLoad;
|
1569
2019
|
break;
|
1570
2020
|
} }
|
1571
2021
|
|
1572
2022
|
/* check for single-pass mode opportunity */
|
1573
|
-
if (zds->fParams.frameContentSize
|
2023
|
+
if (zds->fParams.frameContentSize != ZSTD_CONTENTSIZE_UNKNOWN
|
2024
|
+
&& zds->fParams.frameType != ZSTD_skippableFrame
|
1574
2025
|
&& (U64)(size_t)(oend-op) >= zds->fParams.frameContentSize) {
|
1575
|
-
size_t const cSize = ZSTD_findFrameCompressedSize(istart, iend-istart);
|
2026
|
+
size_t const cSize = ZSTD_findFrameCompressedSize(istart, (size_t)(iend-istart));
|
1576
2027
|
if (cSize <= (size_t)(iend-istart)) {
|
1577
2028
|
/* shortcut : using single-pass mode */
|
1578
|
-
size_t const decompressedSize = ZSTD_decompress_usingDDict(zds, op, oend-op, istart, cSize, ZSTD_getDDict(zds));
|
2029
|
+
size_t const decompressedSize = ZSTD_decompress_usingDDict(zds, op, (size_t)(oend-op), istart, cSize, ZSTD_getDDict(zds));
|
1579
2030
|
if (ZSTD_isError(decompressedSize)) return decompressedSize;
|
1580
2031
|
DEBUGLOG(4, "shortcut to single-pass ZSTD_decompress_usingDDict()")
|
1581
2032
|
ip = istart + cSize;
|
@@ -1586,15 +2037,23 @@ size_t ZSTD_decompressStream(ZSTD_DStream* zds, ZSTD_outBuffer* output, ZSTD_inB
|
|
1586
2037
|
break;
|
1587
2038
|
} }
|
1588
2039
|
|
2040
|
+
/* Check output buffer is large enough for ZSTD_odm_stable. */
|
2041
|
+
if (zds->outBufferMode == ZSTD_bm_stable
|
2042
|
+
&& zds->fParams.frameType != ZSTD_skippableFrame
|
2043
|
+
&& zds->fParams.frameContentSize != ZSTD_CONTENTSIZE_UNKNOWN
|
2044
|
+
&& (U64)(size_t)(oend-op) < zds->fParams.frameContentSize) {
|
2045
|
+
RETURN_ERROR(dstSize_tooSmall, "ZSTD_obm_stable passed but ZSTD_outBuffer is too small");
|
2046
|
+
}
|
2047
|
+
|
1589
2048
|
/* Consume header (see ZSTDds_decodeFrameHeader) */
|
1590
2049
|
DEBUGLOG(4, "Consume header");
|
1591
|
-
FORWARD_IF_ERROR(ZSTD_decompressBegin_usingDDict(zds, ZSTD_getDDict(zds)));
|
2050
|
+
FORWARD_IF_ERROR(ZSTD_decompressBegin_usingDDict(zds, ZSTD_getDDict(zds)), "");
|
1592
2051
|
|
1593
2052
|
if ((MEM_readLE32(zds->headerBuffer) & ZSTD_MAGIC_SKIPPABLE_MASK) == ZSTD_MAGIC_SKIPPABLE_START) { /* skippable frame */
|
1594
2053
|
zds->expected = MEM_readLE32(zds->headerBuffer + ZSTD_FRAMEIDSIZE);
|
1595
2054
|
zds->stage = ZSTDds_skipFrame;
|
1596
2055
|
} else {
|
1597
|
-
FORWARD_IF_ERROR(ZSTD_decodeFrameHeader(zds, zds->headerBuffer, zds->lhSize));
|
2056
|
+
FORWARD_IF_ERROR(ZSTD_decodeFrameHeader(zds, zds->headerBuffer, zds->lhSize), "");
|
1598
2057
|
zds->expected = ZSTD_blockHeaderSize;
|
1599
2058
|
zds->stage = ZSTDds_decodeBlockHeader;
|
1600
2059
|
}
|
@@ -1605,40 +2064,48 @@ size_t ZSTD_decompressStream(ZSTD_DStream* zds, ZSTD_outBuffer* output, ZSTD_inB
|
|
1605
2064
|
(U32)(zds->maxWindowSize >> 10) );
|
1606
2065
|
zds->fParams.windowSize = MAX(zds->fParams.windowSize, 1U << ZSTD_WINDOWLOG_ABSOLUTEMIN);
|
1607
2066
|
RETURN_ERROR_IF(zds->fParams.windowSize > zds->maxWindowSize,
|
1608
|
-
frameParameter_windowTooLarge);
|
2067
|
+
frameParameter_windowTooLarge, "");
|
1609
2068
|
|
1610
2069
|
/* Adapt buffer sizes to frame header instructions */
|
1611
2070
|
{ size_t const neededInBuffSize = MAX(zds->fParams.blockSizeMax, 4 /* frame checksum */);
|
1612
|
-
size_t const neededOutBuffSize =
|
1613
|
-
|
1614
|
-
|
1615
|
-
|
1616
|
-
|
1617
|
-
|
1618
|
-
|
1619
|
-
|
1620
|
-
|
1621
|
-
|
1622
|
-
|
1623
|
-
|
1624
|
-
|
1625
|
-
|
1626
|
-
|
1627
|
-
zds->
|
1628
|
-
|
1629
|
-
|
1630
|
-
|
1631
|
-
|
1632
|
-
|
1633
|
-
|
1634
|
-
|
1635
|
-
|
2071
|
+
size_t const neededOutBuffSize = zds->outBufferMode == ZSTD_bm_buffered
|
2072
|
+
? ZSTD_decodingBufferSize_min(zds->fParams.windowSize, zds->fParams.frameContentSize)
|
2073
|
+
: 0;
|
2074
|
+
|
2075
|
+
ZSTD_DCtx_updateOversizedDuration(zds, neededInBuffSize, neededOutBuffSize);
|
2076
|
+
|
2077
|
+
{ int const tooSmall = (zds->inBuffSize < neededInBuffSize) || (zds->outBuffSize < neededOutBuffSize);
|
2078
|
+
int const tooLarge = ZSTD_DCtx_isOversizedTooLong(zds);
|
2079
|
+
|
2080
|
+
if (tooSmall || tooLarge) {
|
2081
|
+
size_t const bufferSize = neededInBuffSize + neededOutBuffSize;
|
2082
|
+
DEBUGLOG(4, "inBuff : from %u to %u",
|
2083
|
+
(U32)zds->inBuffSize, (U32)neededInBuffSize);
|
2084
|
+
DEBUGLOG(4, "outBuff : from %u to %u",
|
2085
|
+
(U32)zds->outBuffSize, (U32)neededOutBuffSize);
|
2086
|
+
if (zds->staticSize) { /* static DCtx */
|
2087
|
+
DEBUGLOG(4, "staticSize : %u", (U32)zds->staticSize);
|
2088
|
+
assert(zds->staticSize >= sizeof(ZSTD_DCtx)); /* controlled at init */
|
2089
|
+
RETURN_ERROR_IF(
|
2090
|
+
bufferSize > zds->staticSize - sizeof(ZSTD_DCtx),
|
2091
|
+
memory_allocation, "");
|
2092
|
+
} else {
|
2093
|
+
ZSTD_customFree(zds->inBuff, zds->customMem);
|
2094
|
+
zds->inBuffSize = 0;
|
2095
|
+
zds->outBuffSize = 0;
|
2096
|
+
zds->inBuff = (char*)ZSTD_customMalloc(bufferSize, zds->customMem);
|
2097
|
+
RETURN_ERROR_IF(zds->inBuff == NULL, memory_allocation, "");
|
2098
|
+
}
|
2099
|
+
zds->inBuffSize = neededInBuffSize;
|
2100
|
+
zds->outBuff = zds->inBuff + zds->inBuffSize;
|
2101
|
+
zds->outBuffSize = neededOutBuffSize;
|
2102
|
+
} } }
|
1636
2103
|
zds->streamStage = zdss_read;
|
1637
|
-
|
2104
|
+
ZSTD_FALLTHROUGH;
|
1638
2105
|
|
1639
2106
|
case zdss_read:
|
1640
2107
|
DEBUGLOG(5, "stage zdss_read");
|
1641
|
-
{ size_t const neededInSize =
|
2108
|
+
{ size_t const neededInSize = ZSTD_nextSrcSizeToDecompressWithInputSize(zds, (size_t)(iend - ip));
|
1642
2109
|
DEBUGLOG(5, "neededInSize = %u", (U32)neededInSize);
|
1643
2110
|
if (neededInSize==0) { /* end of frame */
|
1644
2111
|
zds->streamStage = zdss_init;
|
@@ -1646,53 +2113,43 @@ size_t ZSTD_decompressStream(ZSTD_DStream* zds, ZSTD_outBuffer* output, ZSTD_inB
|
|
1646
2113
|
break;
|
1647
2114
|
}
|
1648
2115
|
if ((size_t)(iend-ip) >= neededInSize) { /* decode directly from src */
|
1649
|
-
|
1650
|
-
size_t const decodedSize = ZSTD_decompressContinue(zds,
|
1651
|
-
zds->outBuff + zds->outStart, (isSkipFrame ? 0 : zds->outBuffSize - zds->outStart),
|
1652
|
-
ip, neededInSize);
|
1653
|
-
if (ZSTD_isError(decodedSize)) return decodedSize;
|
2116
|
+
FORWARD_IF_ERROR(ZSTD_decompressContinueStream(zds, &op, oend, ip, neededInSize), "");
|
1654
2117
|
ip += neededInSize;
|
1655
|
-
|
1656
|
-
zds->outEnd = zds->outStart + decodedSize;
|
1657
|
-
zds->streamStage = zdss_flush;
|
2118
|
+
/* Function modifies the stage so we must break */
|
1658
2119
|
break;
|
1659
2120
|
} }
|
1660
2121
|
if (ip==iend) { someMoreWork = 0; break; } /* no more input */
|
1661
2122
|
zds->streamStage = zdss_load;
|
1662
|
-
|
2123
|
+
ZSTD_FALLTHROUGH;
|
1663
2124
|
|
1664
2125
|
case zdss_load:
|
1665
2126
|
{ size_t const neededInSize = ZSTD_nextSrcSizeToDecompress(zds);
|
1666
2127
|
size_t const toLoad = neededInSize - zds->inPos;
|
1667
2128
|
int const isSkipFrame = ZSTD_isSkipFrame(zds);
|
1668
2129
|
size_t loadedSize;
|
2130
|
+
/* At this point we shouldn't be decompressing a block that we can stream. */
|
2131
|
+
assert(neededInSize == ZSTD_nextSrcSizeToDecompressWithInputSize(zds, iend - ip));
|
1669
2132
|
if (isSkipFrame) {
|
1670
2133
|
loadedSize = MIN(toLoad, (size_t)(iend-ip));
|
1671
2134
|
} else {
|
1672
2135
|
RETURN_ERROR_IF(toLoad > zds->inBuffSize - zds->inPos,
|
1673
2136
|
corruption_detected,
|
1674
2137
|
"should never happen");
|
1675
|
-
loadedSize = ZSTD_limitCopy(zds->inBuff + zds->inPos, toLoad, ip, iend-ip);
|
2138
|
+
loadedSize = ZSTD_limitCopy(zds->inBuff + zds->inPos, toLoad, ip, (size_t)(iend-ip));
|
1676
2139
|
}
|
1677
2140
|
ip += loadedSize;
|
1678
2141
|
zds->inPos += loadedSize;
|
1679
2142
|
if (loadedSize < toLoad) { someMoreWork = 0; break; } /* not enough input, wait for more */
|
1680
2143
|
|
1681
2144
|
/* decode loaded input */
|
1682
|
-
|
1683
|
-
|
1684
|
-
|
1685
|
-
|
1686
|
-
|
1687
|
-
if (!decodedSize && !isSkipFrame) { zds->streamStage = zdss_read; break; } /* this was just a header */
|
1688
|
-
zds->outEnd = zds->outStart + decodedSize;
|
1689
|
-
} }
|
1690
|
-
zds->streamStage = zdss_flush;
|
1691
|
-
/* fall-through */
|
1692
|
-
|
2145
|
+
zds->inPos = 0; /* input is consumed */
|
2146
|
+
FORWARD_IF_ERROR(ZSTD_decompressContinueStream(zds, &op, oend, zds->inBuff, neededInSize), "");
|
2147
|
+
/* Function modifies the stage so we must break */
|
2148
|
+
break;
|
2149
|
+
}
|
1693
2150
|
case zdss_flush:
|
1694
2151
|
{ size_t const toFlushSize = zds->outEnd - zds->outStart;
|
1695
|
-
size_t const flushedSize = ZSTD_limitCopy(op, oend-op, zds->outBuff + zds->outStart, toFlushSize);
|
2152
|
+
size_t const flushedSize = ZSTD_limitCopy(op, (size_t)(oend-op), zds->outBuff + zds->outStart, toFlushSize);
|
1696
2153
|
op += flushedSize;
|
1697
2154
|
zds->outStart += flushedSize;
|
1698
2155
|
if (flushedSize == toFlushSize) { /* flush completed */
|
@@ -1712,17 +2169,21 @@ size_t ZSTD_decompressStream(ZSTD_DStream* zds, ZSTD_outBuffer* output, ZSTD_inB
|
|
1712
2169
|
|
1713
2170
|
default:
|
1714
2171
|
assert(0); /* impossible */
|
1715
|
-
RETURN_ERROR(GENERIC); /* some compiler require default to do something */
|
2172
|
+
RETURN_ERROR(GENERIC, "impossible to reach"); /* some compiler require default to do something */
|
1716
2173
|
} }
|
1717
2174
|
|
1718
2175
|
/* result */
|
1719
2176
|
input->pos = (size_t)(ip - (const char*)(input->src));
|
1720
2177
|
output->pos = (size_t)(op - (char*)(output->dst));
|
2178
|
+
|
2179
|
+
/* Update the expected output buffer for ZSTD_obm_stable. */
|
2180
|
+
zds->expectedOutBuffer = *output;
|
2181
|
+
|
1721
2182
|
if ((ip==istart) && (op==ostart)) { /* no forward progress */
|
1722
2183
|
zds->noForwardProgress ++;
|
1723
2184
|
if (zds->noForwardProgress >= ZSTD_NO_FORWARD_PROGRESS_MAX) {
|
1724
|
-
RETURN_ERROR_IF(op==oend, dstSize_tooSmall);
|
1725
|
-
RETURN_ERROR_IF(ip==iend, srcSize_wrong);
|
2185
|
+
RETURN_ERROR_IF(op==oend, dstSize_tooSmall, "");
|
2186
|
+
RETURN_ERROR_IF(ip==iend, srcSize_wrong, "");
|
1726
2187
|
assert(0);
|
1727
2188
|
}
|
1728
2189
|
} else {
|