zstdlib 0.13.0-x86-linux

Sign up to get free protection for your applications and to get access to all the features.
Files changed (129) hide show
  1. checksums.yaml +7 -0
  2. data/.yardopts +6 -0
  3. data/CHANGES.md +107 -0
  4. data/Gemfile +3 -0
  5. data/README.md +107 -0
  6. data/Rakefile +59 -0
  7. data/ext/zstdlib_c/extconf.rb +59 -0
  8. data/ext/zstdlib_c/ruby/zlib-2.2/zstdlib.c +4675 -0
  9. data/ext/zstdlib_c/ruby/zlib-2.3/zstdlib.c +4702 -0
  10. data/ext/zstdlib_c/ruby/zlib-2.4/zstdlib.c +4859 -0
  11. data/ext/zstdlib_c/ruby/zlib-2.5/zstdlib.c +4864 -0
  12. data/ext/zstdlib_c/ruby/zlib-2.6/zstdlib.c +4906 -0
  13. data/ext/zstdlib_c/ruby/zlib-2.7/zstdlib.c +4895 -0
  14. data/ext/zstdlib_c/ruby/zlib-3.0/zstdlib.c +4994 -0
  15. data/ext/zstdlib_c/ruby/zlib-3.1/zstdlib.c +5076 -0
  16. data/ext/zstdlib_c/ruby/zlib-3.2/zstdlib.c +5090 -0
  17. data/ext/zstdlib_c/ruby/zlib-3.3/zstdlib.c +5090 -0
  18. data/ext/zstdlib_c/zlib-1.3.1/adler32.c +164 -0
  19. data/ext/zstdlib_c/zlib-1.3.1/compress.c +75 -0
  20. data/ext/zstdlib_c/zlib-1.3.1/crc32.c +1049 -0
  21. data/ext/zstdlib_c/zlib-1.3.1/crc32.h +9446 -0
  22. data/ext/zstdlib_c/zlib-1.3.1/deflate.c +2139 -0
  23. data/ext/zstdlib_c/zlib-1.3.1/deflate.h +377 -0
  24. data/ext/zstdlib_c/zlib-1.3.1/gzclose.c +23 -0
  25. data/ext/zstdlib_c/zlib-1.3.1/gzguts.h +214 -0
  26. data/ext/zstdlib_c/zlib-1.3.1/gzlib.c +582 -0
  27. data/ext/zstdlib_c/zlib-1.3.1/gzread.c +602 -0
  28. data/ext/zstdlib_c/zlib-1.3.1/gzwrite.c +631 -0
  29. data/ext/zstdlib_c/zlib-1.3.1/infback.c +628 -0
  30. data/ext/zstdlib_c/zlib-1.3.1/inffast.c +320 -0
  31. data/ext/zstdlib_c/zlib-1.3.1/inffast.h +11 -0
  32. data/ext/zstdlib_c/zlib-1.3.1/inffixed.h +94 -0
  33. data/ext/zstdlib_c/zlib-1.3.1/inflate.c +1526 -0
  34. data/ext/zstdlib_c/zlib-1.3.1/inflate.h +126 -0
  35. data/ext/zstdlib_c/zlib-1.3.1/inftrees.c +299 -0
  36. data/ext/zstdlib_c/zlib-1.3.1/inftrees.h +62 -0
  37. data/ext/zstdlib_c/zlib-1.3.1/trees.c +1117 -0
  38. data/ext/zstdlib_c/zlib-1.3.1/trees.h +128 -0
  39. data/ext/zstdlib_c/zlib-1.3.1/uncompr.c +85 -0
  40. data/ext/zstdlib_c/zlib-1.3.1/zconf.h +543 -0
  41. data/ext/zstdlib_c/zlib-1.3.1/zlib.h +1938 -0
  42. data/ext/zstdlib_c/zlib-1.3.1/zutil.c +299 -0
  43. data/ext/zstdlib_c/zlib-1.3.1/zutil.h +254 -0
  44. data/ext/zstdlib_c/zlib.mk +14 -0
  45. data/ext/zstdlib_c/zlibwrapper/zlibwrapper.c +10 -0
  46. data/ext/zstdlib_c/zlibwrapper.mk +14 -0
  47. data/ext/zstdlib_c/zstd-1.5.6/lib/common/allocations.h +55 -0
  48. data/ext/zstdlib_c/zstd-1.5.6/lib/common/bits.h +200 -0
  49. data/ext/zstdlib_c/zstd-1.5.6/lib/common/bitstream.h +457 -0
  50. data/ext/zstdlib_c/zstd-1.5.6/lib/common/compiler.h +450 -0
  51. data/ext/zstdlib_c/zstd-1.5.6/lib/common/cpu.h +249 -0
  52. data/ext/zstdlib_c/zstd-1.5.6/lib/common/debug.c +30 -0
  53. data/ext/zstdlib_c/zstd-1.5.6/lib/common/debug.h +116 -0
  54. data/ext/zstdlib_c/zstd-1.5.6/lib/common/entropy_common.c +340 -0
  55. data/ext/zstdlib_c/zstd-1.5.6/lib/common/error_private.c +63 -0
  56. data/ext/zstdlib_c/zstd-1.5.6/lib/common/error_private.h +168 -0
  57. data/ext/zstdlib_c/zstd-1.5.6/lib/common/fse.h +640 -0
  58. data/ext/zstdlib_c/zstd-1.5.6/lib/common/fse_decompress.c +313 -0
  59. data/ext/zstdlib_c/zstd-1.5.6/lib/common/huf.h +286 -0
  60. data/ext/zstdlib_c/zstd-1.5.6/lib/common/mem.h +426 -0
  61. data/ext/zstdlib_c/zstd-1.5.6/lib/common/pool.c +371 -0
  62. data/ext/zstdlib_c/zstd-1.5.6/lib/common/pool.h +90 -0
  63. data/ext/zstdlib_c/zstd-1.5.6/lib/common/portability_macros.h +158 -0
  64. data/ext/zstdlib_c/zstd-1.5.6/lib/common/threading.c +182 -0
  65. data/ext/zstdlib_c/zstd-1.5.6/lib/common/threading.h +150 -0
  66. data/ext/zstdlib_c/zstd-1.5.6/lib/common/xxhash.c +18 -0
  67. data/ext/zstdlib_c/zstd-1.5.6/lib/common/xxhash.h +7020 -0
  68. data/ext/zstdlib_c/zstd-1.5.6/lib/common/zstd_common.c +48 -0
  69. data/ext/zstdlib_c/zstd-1.5.6/lib/common/zstd_deps.h +111 -0
  70. data/ext/zstdlib_c/zstd-1.5.6/lib/common/zstd_internal.h +392 -0
  71. data/ext/zstdlib_c/zstd-1.5.6/lib/common/zstd_trace.h +163 -0
  72. data/ext/zstdlib_c/zstd-1.5.6/lib/compress/clevels.h +134 -0
  73. data/ext/zstdlib_c/zstd-1.5.6/lib/compress/fse_compress.c +625 -0
  74. data/ext/zstdlib_c/zstd-1.5.6/lib/compress/hist.c +181 -0
  75. data/ext/zstdlib_c/zstd-1.5.6/lib/compress/hist.h +75 -0
  76. data/ext/zstdlib_c/zstd-1.5.6/lib/compress/huf_compress.c +1464 -0
  77. data/ext/zstdlib_c/zstd-1.5.6/lib/compress/zstd_compress.c +7153 -0
  78. data/ext/zstdlib_c/zstd-1.5.6/lib/compress/zstd_compress_internal.h +1534 -0
  79. data/ext/zstdlib_c/zstd-1.5.6/lib/compress/zstd_compress_literals.c +235 -0
  80. data/ext/zstdlib_c/zstd-1.5.6/lib/compress/zstd_compress_literals.h +39 -0
  81. data/ext/zstdlib_c/zstd-1.5.6/lib/compress/zstd_compress_sequences.c +442 -0
  82. data/ext/zstdlib_c/zstd-1.5.6/lib/compress/zstd_compress_sequences.h +54 -0
  83. data/ext/zstdlib_c/zstd-1.5.6/lib/compress/zstd_compress_superblock.c +688 -0
  84. data/ext/zstdlib_c/zstd-1.5.6/lib/compress/zstd_compress_superblock.h +32 -0
  85. data/ext/zstdlib_c/zstd-1.5.6/lib/compress/zstd_cwksp.h +748 -0
  86. data/ext/zstdlib_c/zstd-1.5.6/lib/compress/zstd_double_fast.c +770 -0
  87. data/ext/zstdlib_c/zstd-1.5.6/lib/compress/zstd_double_fast.h +50 -0
  88. data/ext/zstdlib_c/zstd-1.5.6/lib/compress/zstd_fast.c +968 -0
  89. data/ext/zstdlib_c/zstd-1.5.6/lib/compress/zstd_fast.h +38 -0
  90. data/ext/zstdlib_c/zstd-1.5.6/lib/compress/zstd_lazy.c +2199 -0
  91. data/ext/zstdlib_c/zstd-1.5.6/lib/compress/zstd_lazy.h +202 -0
  92. data/ext/zstdlib_c/zstd-1.5.6/lib/compress/zstd_ldm.c +730 -0
  93. data/ext/zstdlib_c/zstd-1.5.6/lib/compress/zstd_ldm.h +117 -0
  94. data/ext/zstdlib_c/zstd-1.5.6/lib/compress/zstd_ldm_geartab.h +106 -0
  95. data/ext/zstdlib_c/zstd-1.5.6/lib/compress/zstd_opt.c +1576 -0
  96. data/ext/zstdlib_c/zstd-1.5.6/lib/compress/zstd_opt.h +80 -0
  97. data/ext/zstdlib_c/zstd-1.5.6/lib/compress/zstdmt_compress.c +1882 -0
  98. data/ext/zstdlib_c/zstd-1.5.6/lib/compress/zstdmt_compress.h +113 -0
  99. data/ext/zstdlib_c/zstd-1.5.6/lib/decompress/huf_decompress.c +1944 -0
  100. data/ext/zstdlib_c/zstd-1.5.6/lib/decompress/huf_decompress_amd64.S +595 -0
  101. data/ext/zstdlib_c/zstd-1.5.6/lib/decompress/zstd_ddict.c +244 -0
  102. data/ext/zstdlib_c/zstd-1.5.6/lib/decompress/zstd_ddict.h +44 -0
  103. data/ext/zstdlib_c/zstd-1.5.6/lib/decompress/zstd_decompress.c +2407 -0
  104. data/ext/zstdlib_c/zstd-1.5.6/lib/decompress/zstd_decompress_block.c +2215 -0
  105. data/ext/zstdlib_c/zstd-1.5.6/lib/decompress/zstd_decompress_block.h +73 -0
  106. data/ext/zstdlib_c/zstd-1.5.6/lib/decompress/zstd_decompress_internal.h +240 -0
  107. data/ext/zstdlib_c/zstd-1.5.6/lib/zdict.h +474 -0
  108. data/ext/zstdlib_c/zstd-1.5.6/lib/zstd.h +3089 -0
  109. data/ext/zstdlib_c/zstd-1.5.6/lib/zstd_errors.h +114 -0
  110. data/ext/zstdlib_c/zstd-1.5.6/zlibWrapper/gzclose.c +26 -0
  111. data/ext/zstdlib_c/zstd-1.5.6/zlibWrapper/gzcompatibility.h +68 -0
  112. data/ext/zstdlib_c/zstd-1.5.6/zlibWrapper/gzguts.h +229 -0
  113. data/ext/zstdlib_c/zstd-1.5.6/zlibWrapper/gzlib.c +587 -0
  114. data/ext/zstdlib_c/zstd-1.5.6/zlibWrapper/gzread.c +637 -0
  115. data/ext/zstdlib_c/zstd-1.5.6/zlibWrapper/gzwrite.c +631 -0
  116. data/ext/zstdlib_c/zstd-1.5.6/zlibWrapper/zstd_zlibwrapper.c +1200 -0
  117. data/ext/zstdlib_c/zstd-1.5.6/zlibWrapper/zstd_zlibwrapper.h +91 -0
  118. data/ext/zstdlib_c/zstd.mk +15 -0
  119. data/lib/2.4/zstdlib_c.so +0 -0
  120. data/lib/2.5/zstdlib_c.so +0 -0
  121. data/lib/2.6/zstdlib_c.so +0 -0
  122. data/lib/2.7/zstdlib_c.so +0 -0
  123. data/lib/3.0/zstdlib_c.so +0 -0
  124. data/lib/3.1/zstdlib_c.so +0 -0
  125. data/lib/3.2/zstdlib_c.so +0 -0
  126. data/lib/3.3/zstdlib_c.so +0 -0
  127. data/lib/zstdlib.rb +6 -0
  128. data/test/zstdlib_test.rb +21 -0
  129. metadata +243 -0
@@ -0,0 +1,2407 @@
1
+ /*
2
+ * Copyright (c) Meta Platforms, Inc. and affiliates.
3
+ * All rights reserved.
4
+ *
5
+ * This source code is licensed under both the BSD-style license (found in the
6
+ * LICENSE file in the root directory of this source tree) and the GPLv2 (found
7
+ * in the COPYING file in the root directory of this source tree).
8
+ * You may select, at your option, one of the above-listed licenses.
9
+ */
10
+
11
+
12
+ /* ***************************************************************
13
+ * Tuning parameters
14
+ *****************************************************************/
15
+ /*!
16
+ * HEAPMODE :
17
+ * Select how default decompression function ZSTD_decompress() allocates its context,
18
+ * on stack (0), or into heap (1, default; requires malloc()).
19
+ * Note that functions with explicit context such as ZSTD_decompressDCtx() are unaffected.
20
+ */
21
+ #ifndef ZSTD_HEAPMODE
22
+ # define ZSTD_HEAPMODE 1
23
+ #endif
24
+
25
+ /*!
26
+ * LEGACY_SUPPORT :
27
+ * if set to 1+, ZSTD_decompress() can decode older formats (v0.1+)
28
+ */
29
+ #ifndef ZSTD_LEGACY_SUPPORT
30
+ # define ZSTD_LEGACY_SUPPORT 0
31
+ #endif
32
+
33
+ /*!
34
+ * MAXWINDOWSIZE_DEFAULT :
35
+ * maximum window size accepted by DStream __by default__.
36
+ * Frames requiring more memory will be rejected.
37
+ * It's possible to set a different limit using ZSTD_DCtx_setMaxWindowSize().
38
+ */
39
+ #ifndef ZSTD_MAXWINDOWSIZE_DEFAULT
40
+ # define ZSTD_MAXWINDOWSIZE_DEFAULT (((U32)1 << ZSTD_WINDOWLOG_LIMIT_DEFAULT) + 1)
41
+ #endif
42
+
43
+ /*!
44
+ * NO_FORWARD_PROGRESS_MAX :
45
+ * maximum allowed nb of calls to ZSTD_decompressStream()
46
+ * without any forward progress
47
+ * (defined as: no byte read from input, and no byte flushed to output)
48
+ * before triggering an error.
49
+ */
50
+ #ifndef ZSTD_NO_FORWARD_PROGRESS_MAX
51
+ # define ZSTD_NO_FORWARD_PROGRESS_MAX 16
52
+ #endif
53
+
54
+
55
+ /*-*******************************************************
56
+ * Dependencies
57
+ *********************************************************/
58
+ #include "../common/zstd_deps.h" /* ZSTD_memcpy, ZSTD_memmove, ZSTD_memset */
59
+ #include "../common/allocations.h" /* ZSTD_customMalloc, ZSTD_customCalloc, ZSTD_customFree */
60
+ #include "../common/error_private.h"
61
+ #include "../common/zstd_internal.h" /* blockProperties_t */
62
+ #include "../common/mem.h" /* low level memory routines */
63
+ #include "../common/bits.h" /* ZSTD_highbit32 */
64
+ #define FSE_STATIC_LINKING_ONLY
65
+ #include "../common/fse.h"
66
+ #include "../common/huf.h"
67
+ #include "../common/xxhash.h" /* XXH64_reset, XXH64_update, XXH64_digest, XXH64 */
68
+ #include "zstd_decompress_internal.h" /* ZSTD_DCtx */
69
+ #include "zstd_ddict.h" /* ZSTD_DDictDictContent */
70
+ #include "zstd_decompress_block.h" /* ZSTD_decompressBlock_internal */
71
+
72
+ #if defined(ZSTD_LEGACY_SUPPORT) && (ZSTD_LEGACY_SUPPORT>=1)
73
+ # include "../legacy/zstd_legacy.h"
74
+ #endif
75
+
76
+
77
+
78
+ /*************************************
79
+ * Multiple DDicts Hashset internals *
80
+ *************************************/
81
+
82
+ #define DDICT_HASHSET_MAX_LOAD_FACTOR_COUNT_MULT 4
83
+ #define DDICT_HASHSET_MAX_LOAD_FACTOR_SIZE_MULT 3 /* These two constants represent SIZE_MULT/COUNT_MULT load factor without using a float.
84
+ * Currently, that means a 0.75 load factor.
85
+ * So, if count * COUNT_MULT / size * SIZE_MULT != 0, then we've exceeded
86
+ * the load factor of the ddict hash set.
87
+ */
88
+
89
+ #define DDICT_HASHSET_TABLE_BASE_SIZE 64
90
+ #define DDICT_HASHSET_RESIZE_FACTOR 2
91
+
92
+ /* Hash function to determine starting position of dict insertion within the table
93
+ * Returns an index between [0, hashSet->ddictPtrTableSize]
94
+ */
95
+ static size_t ZSTD_DDictHashSet_getIndex(const ZSTD_DDictHashSet* hashSet, U32 dictID) {
96
+ const U64 hash = XXH64(&dictID, sizeof(U32), 0);
97
+ /* DDict ptr table size is a multiple of 2, use size - 1 as mask to get index within [0, hashSet->ddictPtrTableSize) */
98
+ return hash & (hashSet->ddictPtrTableSize - 1);
99
+ }
100
+
101
+ /* Adds DDict to a hashset without resizing it.
102
+ * If inserting a DDict with a dictID that already exists in the set, replaces the one in the set.
103
+ * Returns 0 if successful, or a zstd error code if something went wrong.
104
+ */
105
+ static size_t ZSTD_DDictHashSet_emplaceDDict(ZSTD_DDictHashSet* hashSet, const ZSTD_DDict* ddict) {
106
+ const U32 dictID = ZSTD_getDictID_fromDDict(ddict);
107
+ size_t idx = ZSTD_DDictHashSet_getIndex(hashSet, dictID);
108
+ const size_t idxRangeMask = hashSet->ddictPtrTableSize - 1;
109
+ RETURN_ERROR_IF(hashSet->ddictPtrCount == hashSet->ddictPtrTableSize, GENERIC, "Hash set is full!");
110
+ DEBUGLOG(4, "Hashed index: for dictID: %u is %zu", dictID, idx);
111
+ while (hashSet->ddictPtrTable[idx] != NULL) {
112
+ /* Replace existing ddict if inserting ddict with same dictID */
113
+ if (ZSTD_getDictID_fromDDict(hashSet->ddictPtrTable[idx]) == dictID) {
114
+ DEBUGLOG(4, "DictID already exists, replacing rather than adding");
115
+ hashSet->ddictPtrTable[idx] = ddict;
116
+ return 0;
117
+ }
118
+ idx &= idxRangeMask;
119
+ idx++;
120
+ }
121
+ DEBUGLOG(4, "Final idx after probing for dictID %u is: %zu", dictID, idx);
122
+ hashSet->ddictPtrTable[idx] = ddict;
123
+ hashSet->ddictPtrCount++;
124
+ return 0;
125
+ }
126
+
127
+ /* Expands hash table by factor of DDICT_HASHSET_RESIZE_FACTOR and
128
+ * rehashes all values, allocates new table, frees old table.
129
+ * Returns 0 on success, otherwise a zstd error code.
130
+ */
131
+ static size_t ZSTD_DDictHashSet_expand(ZSTD_DDictHashSet* hashSet, ZSTD_customMem customMem) {
132
+ size_t newTableSize = hashSet->ddictPtrTableSize * DDICT_HASHSET_RESIZE_FACTOR;
133
+ const ZSTD_DDict** newTable = (const ZSTD_DDict**)ZSTD_customCalloc(sizeof(ZSTD_DDict*) * newTableSize, customMem);
134
+ const ZSTD_DDict** oldTable = hashSet->ddictPtrTable;
135
+ size_t oldTableSize = hashSet->ddictPtrTableSize;
136
+ size_t i;
137
+
138
+ DEBUGLOG(4, "Expanding DDict hash table! Old size: %zu new size: %zu", oldTableSize, newTableSize);
139
+ RETURN_ERROR_IF(!newTable, memory_allocation, "Expanded hashset allocation failed!");
140
+ hashSet->ddictPtrTable = newTable;
141
+ hashSet->ddictPtrTableSize = newTableSize;
142
+ hashSet->ddictPtrCount = 0;
143
+ for (i = 0; i < oldTableSize; ++i) {
144
+ if (oldTable[i] != NULL) {
145
+ FORWARD_IF_ERROR(ZSTD_DDictHashSet_emplaceDDict(hashSet, oldTable[i]), "");
146
+ }
147
+ }
148
+ ZSTD_customFree((void*)oldTable, customMem);
149
+ DEBUGLOG(4, "Finished re-hash");
150
+ return 0;
151
+ }
152
+
153
+ /* Fetches a DDict with the given dictID
154
+ * Returns the ZSTD_DDict* with the requested dictID. If it doesn't exist, then returns NULL.
155
+ */
156
+ static const ZSTD_DDict* ZSTD_DDictHashSet_getDDict(ZSTD_DDictHashSet* hashSet, U32 dictID) {
157
+ size_t idx = ZSTD_DDictHashSet_getIndex(hashSet, dictID);
158
+ const size_t idxRangeMask = hashSet->ddictPtrTableSize - 1;
159
+ DEBUGLOG(4, "Hashed index: for dictID: %u is %zu", dictID, idx);
160
+ for (;;) {
161
+ size_t currDictID = ZSTD_getDictID_fromDDict(hashSet->ddictPtrTable[idx]);
162
+ if (currDictID == dictID || currDictID == 0) {
163
+ /* currDictID == 0 implies a NULL ddict entry */
164
+ break;
165
+ } else {
166
+ idx &= idxRangeMask; /* Goes to start of table when we reach the end */
167
+ idx++;
168
+ }
169
+ }
170
+ DEBUGLOG(4, "Final idx after probing for dictID %u is: %zu", dictID, idx);
171
+ return hashSet->ddictPtrTable[idx];
172
+ }
173
+
174
+ /* Allocates space for and returns a ddict hash set
175
+ * The hash set's ZSTD_DDict* table has all values automatically set to NULL to begin with.
176
+ * Returns NULL if allocation failed.
177
+ */
178
+ static ZSTD_DDictHashSet* ZSTD_createDDictHashSet(ZSTD_customMem customMem) {
179
+ ZSTD_DDictHashSet* ret = (ZSTD_DDictHashSet*)ZSTD_customMalloc(sizeof(ZSTD_DDictHashSet), customMem);
180
+ DEBUGLOG(4, "Allocating new hash set");
181
+ if (!ret)
182
+ return NULL;
183
+ ret->ddictPtrTable = (const ZSTD_DDict**)ZSTD_customCalloc(DDICT_HASHSET_TABLE_BASE_SIZE * sizeof(ZSTD_DDict*), customMem);
184
+ if (!ret->ddictPtrTable) {
185
+ ZSTD_customFree(ret, customMem);
186
+ return NULL;
187
+ }
188
+ ret->ddictPtrTableSize = DDICT_HASHSET_TABLE_BASE_SIZE;
189
+ ret->ddictPtrCount = 0;
190
+ return ret;
191
+ }
192
+
193
+ /* Frees the table of ZSTD_DDict* within a hashset, then frees the hashset itself.
194
+ * Note: The ZSTD_DDict* within the table are NOT freed.
195
+ */
196
+ static void ZSTD_freeDDictHashSet(ZSTD_DDictHashSet* hashSet, ZSTD_customMem customMem) {
197
+ DEBUGLOG(4, "Freeing ddict hash set");
198
+ if (hashSet && hashSet->ddictPtrTable) {
199
+ ZSTD_customFree((void*)hashSet->ddictPtrTable, customMem);
200
+ }
201
+ if (hashSet) {
202
+ ZSTD_customFree(hashSet, customMem);
203
+ }
204
+ }
205
+
206
+ /* Public function: Adds a DDict into the ZSTD_DDictHashSet, possibly triggering a resize of the hash set.
207
+ * Returns 0 on success, or a ZSTD error.
208
+ */
209
+ static size_t ZSTD_DDictHashSet_addDDict(ZSTD_DDictHashSet* hashSet, const ZSTD_DDict* ddict, ZSTD_customMem customMem) {
210
+ DEBUGLOG(4, "Adding dict ID: %u to hashset with - Count: %zu Tablesize: %zu", ZSTD_getDictID_fromDDict(ddict), hashSet->ddictPtrCount, hashSet->ddictPtrTableSize);
211
+ if (hashSet->ddictPtrCount * DDICT_HASHSET_MAX_LOAD_FACTOR_COUNT_MULT / hashSet->ddictPtrTableSize * DDICT_HASHSET_MAX_LOAD_FACTOR_SIZE_MULT != 0) {
212
+ FORWARD_IF_ERROR(ZSTD_DDictHashSet_expand(hashSet, customMem), "");
213
+ }
214
+ FORWARD_IF_ERROR(ZSTD_DDictHashSet_emplaceDDict(hashSet, ddict), "");
215
+ return 0;
216
+ }
217
+
218
+ /*-*************************************************************
219
+ * Context management
220
+ ***************************************************************/
221
+ size_t ZSTD_sizeof_DCtx (const ZSTD_DCtx* dctx)
222
+ {
223
+ if (dctx==NULL) return 0; /* support sizeof NULL */
224
+ return sizeof(*dctx)
225
+ + ZSTD_sizeof_DDict(dctx->ddictLocal)
226
+ + dctx->inBuffSize + dctx->outBuffSize;
227
+ }
228
+
229
+ size_t ZSTD_estimateDCtxSize(void) { return sizeof(ZSTD_DCtx); }
230
+
231
+
232
+ static size_t ZSTD_startingInputLength(ZSTD_format_e format)
233
+ {
234
+ size_t const startingInputLength = ZSTD_FRAMEHEADERSIZE_PREFIX(format);
235
+ /* only supports formats ZSTD_f_zstd1 and ZSTD_f_zstd1_magicless */
236
+ assert( (format == ZSTD_f_zstd1) || (format == ZSTD_f_zstd1_magicless) );
237
+ return startingInputLength;
238
+ }
239
+
240
+ static void ZSTD_DCtx_resetParameters(ZSTD_DCtx* dctx)
241
+ {
242
+ assert(dctx->streamStage == zdss_init);
243
+ dctx->format = ZSTD_f_zstd1;
244
+ dctx->maxWindowSize = ZSTD_MAXWINDOWSIZE_DEFAULT;
245
+ dctx->outBufferMode = ZSTD_bm_buffered;
246
+ dctx->forceIgnoreChecksum = ZSTD_d_validateChecksum;
247
+ dctx->refMultipleDDicts = ZSTD_rmd_refSingleDDict;
248
+ dctx->disableHufAsm = 0;
249
+ dctx->maxBlockSizeParam = 0;
250
+ }
251
+
252
+ static void ZSTD_initDCtx_internal(ZSTD_DCtx* dctx)
253
+ {
254
+ dctx->staticSize = 0;
255
+ dctx->ddict = NULL;
256
+ dctx->ddictLocal = NULL;
257
+ dctx->dictEnd = NULL;
258
+ dctx->ddictIsCold = 0;
259
+ dctx->dictUses = ZSTD_dont_use;
260
+ dctx->inBuff = NULL;
261
+ dctx->inBuffSize = 0;
262
+ dctx->outBuffSize = 0;
263
+ dctx->streamStage = zdss_init;
264
+ #if defined(ZSTD_LEGACY_SUPPORT) && (ZSTD_LEGACY_SUPPORT>=1)
265
+ dctx->legacyContext = NULL;
266
+ dctx->previousLegacyVersion = 0;
267
+ #endif
268
+ dctx->noForwardProgress = 0;
269
+ dctx->oversizedDuration = 0;
270
+ dctx->isFrameDecompression = 1;
271
+ #if DYNAMIC_BMI2
272
+ dctx->bmi2 = ZSTD_cpuSupportsBmi2();
273
+ #endif
274
+ dctx->ddictSet = NULL;
275
+ ZSTD_DCtx_resetParameters(dctx);
276
+ #ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
277
+ dctx->dictContentEndForFuzzing = NULL;
278
+ #endif
279
+ }
280
+
281
+ ZSTD_DCtx* ZSTD_initStaticDCtx(void *workspace, size_t workspaceSize)
282
+ {
283
+ ZSTD_DCtx* const dctx = (ZSTD_DCtx*) workspace;
284
+
285
+ if ((size_t)workspace & 7) return NULL; /* 8-aligned */
286
+ if (workspaceSize < sizeof(ZSTD_DCtx)) return NULL; /* minimum size */
287
+
288
+ ZSTD_initDCtx_internal(dctx);
289
+ dctx->staticSize = workspaceSize;
290
+ dctx->inBuff = (char*)(dctx+1);
291
+ return dctx;
292
+ }
293
+
294
+ static ZSTD_DCtx* ZSTD_createDCtx_internal(ZSTD_customMem customMem) {
295
+ if ((!customMem.customAlloc) ^ (!customMem.customFree)) return NULL;
296
+
297
+ { ZSTD_DCtx* const dctx = (ZSTD_DCtx*)ZSTD_customMalloc(sizeof(*dctx), customMem);
298
+ if (!dctx) return NULL;
299
+ dctx->customMem = customMem;
300
+ ZSTD_initDCtx_internal(dctx);
301
+ return dctx;
302
+ }
303
+ }
304
+
305
+ ZSTD_DCtx* ZSTD_createDCtx_advanced(ZSTD_customMem customMem)
306
+ {
307
+ return ZSTD_createDCtx_internal(customMem);
308
+ }
309
+
310
+ ZSTD_DCtx* ZSTD_createDCtx(void)
311
+ {
312
+ DEBUGLOG(3, "ZSTD_createDCtx");
313
+ return ZSTD_createDCtx_internal(ZSTD_defaultCMem);
314
+ }
315
+
316
+ static void ZSTD_clearDict(ZSTD_DCtx* dctx)
317
+ {
318
+ ZSTD_freeDDict(dctx->ddictLocal);
319
+ dctx->ddictLocal = NULL;
320
+ dctx->ddict = NULL;
321
+ dctx->dictUses = ZSTD_dont_use;
322
+ }
323
+
324
+ size_t ZSTD_freeDCtx(ZSTD_DCtx* dctx)
325
+ {
326
+ if (dctx==NULL) return 0; /* support free on NULL */
327
+ RETURN_ERROR_IF(dctx->staticSize, memory_allocation, "not compatible with static DCtx");
328
+ { ZSTD_customMem const cMem = dctx->customMem;
329
+ ZSTD_clearDict(dctx);
330
+ ZSTD_customFree(dctx->inBuff, cMem);
331
+ dctx->inBuff = NULL;
332
+ #if defined(ZSTD_LEGACY_SUPPORT) && (ZSTD_LEGACY_SUPPORT >= 1)
333
+ if (dctx->legacyContext)
334
+ ZSTD_freeLegacyStreamContext(dctx->legacyContext, dctx->previousLegacyVersion);
335
+ #endif
336
+ if (dctx->ddictSet) {
337
+ ZSTD_freeDDictHashSet(dctx->ddictSet, cMem);
338
+ dctx->ddictSet = NULL;
339
+ }
340
+ ZSTD_customFree(dctx, cMem);
341
+ return 0;
342
+ }
343
+ }
344
+
345
+ /* no longer useful */
346
+ void ZSTD_copyDCtx(ZSTD_DCtx* dstDCtx, const ZSTD_DCtx* srcDCtx)
347
+ {
348
+ size_t const toCopy = (size_t)((char*)(&dstDCtx->inBuff) - (char*)dstDCtx);
349
+ ZSTD_memcpy(dstDCtx, srcDCtx, toCopy); /* no need to copy workspace */
350
+ }
351
+
352
+ /* Given a dctx with a digested frame params, re-selects the correct ZSTD_DDict based on
353
+ * the requested dict ID from the frame. If there exists a reference to the correct ZSTD_DDict, then
354
+ * accordingly sets the ddict to be used to decompress the frame.
355
+ *
356
+ * If no DDict is found, then no action is taken, and the ZSTD_DCtx::ddict remains as-is.
357
+ *
358
+ * ZSTD_d_refMultipleDDicts must be enabled for this function to be called.
359
+ */
360
+ static void ZSTD_DCtx_selectFrameDDict(ZSTD_DCtx* dctx) {
361
+ assert(dctx->refMultipleDDicts && dctx->ddictSet);
362
+ DEBUGLOG(4, "Adjusting DDict based on requested dict ID from frame");
363
+ if (dctx->ddict) {
364
+ const ZSTD_DDict* frameDDict = ZSTD_DDictHashSet_getDDict(dctx->ddictSet, dctx->fParams.dictID);
365
+ if (frameDDict) {
366
+ DEBUGLOG(4, "DDict found!");
367
+ ZSTD_clearDict(dctx);
368
+ dctx->dictID = dctx->fParams.dictID;
369
+ dctx->ddict = frameDDict;
370
+ dctx->dictUses = ZSTD_use_indefinitely;
371
+ }
372
+ }
373
+ }
374
+
375
+
376
+ /*-*************************************************************
377
+ * Frame header decoding
378
+ ***************************************************************/
379
+
380
+ /*! ZSTD_isFrame() :
381
+ * Tells if the content of `buffer` starts with a valid Frame Identifier.
382
+ * Note : Frame Identifier is 4 bytes. If `size < 4`, @return will always be 0.
383
+ * Note 2 : Legacy Frame Identifiers are considered valid only if Legacy Support is enabled.
384
+ * Note 3 : Skippable Frame Identifiers are considered valid. */
385
+ unsigned ZSTD_isFrame(const void* buffer, size_t size)
386
+ {
387
+ if (size < ZSTD_FRAMEIDSIZE) return 0;
388
+ { U32 const magic = MEM_readLE32(buffer);
389
+ if (magic == ZSTD_MAGICNUMBER) return 1;
390
+ if ((magic & ZSTD_MAGIC_SKIPPABLE_MASK) == ZSTD_MAGIC_SKIPPABLE_START) return 1;
391
+ }
392
+ #if defined(ZSTD_LEGACY_SUPPORT) && (ZSTD_LEGACY_SUPPORT >= 1)
393
+ if (ZSTD_isLegacy(buffer, size)) return 1;
394
+ #endif
395
+ return 0;
396
+ }
397
+
398
+ /*! ZSTD_isSkippableFrame() :
399
+ * Tells if the content of `buffer` starts with a valid Frame Identifier for a skippable frame.
400
+ * Note : Frame Identifier is 4 bytes. If `size < 4`, @return will always be 0.
401
+ */
402
+ unsigned ZSTD_isSkippableFrame(const void* buffer, size_t size)
403
+ {
404
+ if (size < ZSTD_FRAMEIDSIZE) return 0;
405
+ { U32 const magic = MEM_readLE32(buffer);
406
+ if ((magic & ZSTD_MAGIC_SKIPPABLE_MASK) == ZSTD_MAGIC_SKIPPABLE_START) return 1;
407
+ }
408
+ return 0;
409
+ }
410
+
411
+ /** ZSTD_frameHeaderSize_internal() :
412
+ * srcSize must be large enough to reach header size fields.
413
+ * note : only works for formats ZSTD_f_zstd1 and ZSTD_f_zstd1_magicless.
414
+ * @return : size of the Frame Header
415
+ * or an error code, which can be tested with ZSTD_isError() */
416
+ static size_t ZSTD_frameHeaderSize_internal(const void* src, size_t srcSize, ZSTD_format_e format)
417
+ {
418
+ size_t const minInputSize = ZSTD_startingInputLength(format);
419
+ RETURN_ERROR_IF(srcSize < minInputSize, srcSize_wrong, "");
420
+
421
+ { BYTE const fhd = ((const BYTE*)src)[minInputSize-1];
422
+ U32 const dictID= fhd & 3;
423
+ U32 const singleSegment = (fhd >> 5) & 1;
424
+ U32 const fcsId = fhd >> 6;
425
+ return minInputSize + !singleSegment
426
+ + ZSTD_did_fieldSize[dictID] + ZSTD_fcs_fieldSize[fcsId]
427
+ + (singleSegment && !fcsId);
428
+ }
429
+ }
430
+
431
+ /** ZSTD_frameHeaderSize() :
432
+ * srcSize must be >= ZSTD_frameHeaderSize_prefix.
433
+ * @return : size of the Frame Header,
434
+ * or an error code (if srcSize is too small) */
435
+ size_t ZSTD_frameHeaderSize(const void* src, size_t srcSize)
436
+ {
437
+ return ZSTD_frameHeaderSize_internal(src, srcSize, ZSTD_f_zstd1);
438
+ }
439
+
440
+
441
+ /** ZSTD_getFrameHeader_advanced() :
442
+ * decode Frame Header, or require larger `srcSize`.
443
+ * note : only works for formats ZSTD_f_zstd1 and ZSTD_f_zstd1_magicless
444
+ * @return : 0, `zfhPtr` is correctly filled,
445
+ * >0, `srcSize` is too small, value is wanted `srcSize` amount,
446
+ ** or an error code, which can be tested using ZSTD_isError() */
447
+ size_t ZSTD_getFrameHeader_advanced(ZSTD_frameHeader* zfhPtr, const void* src, size_t srcSize, ZSTD_format_e format)
448
+ {
449
+ const BYTE* ip = (const BYTE*)src;
450
+ size_t const minInputSize = ZSTD_startingInputLength(format);
451
+
452
+ DEBUGLOG(5, "ZSTD_getFrameHeader_advanced: minInputSize = %zu, srcSize = %zu", minInputSize, srcSize);
453
+
454
+ if (srcSize > 0) {
455
+ /* note : technically could be considered an assert(), since it's an invalid entry */
456
+ RETURN_ERROR_IF(src==NULL, GENERIC, "invalid parameter : src==NULL, but srcSize>0");
457
+ }
458
+ if (srcSize < minInputSize) {
459
+ if (srcSize > 0 && format != ZSTD_f_zstd1_magicless) {
460
+ /* when receiving less than @minInputSize bytes,
461
+ * control these bytes at least correspond to a supported magic number
462
+ * in order to error out early if they don't.
463
+ **/
464
+ size_t const toCopy = MIN(4, srcSize);
465
+ unsigned char hbuf[4]; MEM_writeLE32(hbuf, ZSTD_MAGICNUMBER);
466
+ assert(src != NULL);
467
+ ZSTD_memcpy(hbuf, src, toCopy);
468
+ if ( MEM_readLE32(hbuf) != ZSTD_MAGICNUMBER ) {
469
+ /* not a zstd frame : let's check if it's a skippable frame */
470
+ MEM_writeLE32(hbuf, ZSTD_MAGIC_SKIPPABLE_START);
471
+ ZSTD_memcpy(hbuf, src, toCopy);
472
+ if ((MEM_readLE32(hbuf) & ZSTD_MAGIC_SKIPPABLE_MASK) != ZSTD_MAGIC_SKIPPABLE_START) {
473
+ RETURN_ERROR(prefix_unknown,
474
+ "first bytes don't correspond to any supported magic number");
475
+ } } }
476
+ return minInputSize;
477
+ }
478
+
479
+ ZSTD_memset(zfhPtr, 0, sizeof(*zfhPtr)); /* not strictly necessary, but static analyzers may not understand that zfhPtr will be read only if return value is zero, since they are 2 different signals */
480
+ if ( (format != ZSTD_f_zstd1_magicless)
481
+ && (MEM_readLE32(src) != ZSTD_MAGICNUMBER) ) {
482
+ if ((MEM_readLE32(src) & ZSTD_MAGIC_SKIPPABLE_MASK) == ZSTD_MAGIC_SKIPPABLE_START) {
483
+ /* skippable frame */
484
+ if (srcSize < ZSTD_SKIPPABLEHEADERSIZE)
485
+ return ZSTD_SKIPPABLEHEADERSIZE; /* magic number + frame length */
486
+ ZSTD_memset(zfhPtr, 0, sizeof(*zfhPtr));
487
+ zfhPtr->frameContentSize = MEM_readLE32((const char *)src + ZSTD_FRAMEIDSIZE);
488
+ zfhPtr->frameType = ZSTD_skippableFrame;
489
+ return 0;
490
+ }
491
+ RETURN_ERROR(prefix_unknown, "");
492
+ }
493
+
494
+ /* ensure there is enough `srcSize` to fully read/decode frame header */
495
+ { size_t const fhsize = ZSTD_frameHeaderSize_internal(src, srcSize, format);
496
+ if (srcSize < fhsize) return fhsize;
497
+ zfhPtr->headerSize = (U32)fhsize;
498
+ }
499
+
500
+ { BYTE const fhdByte = ip[minInputSize-1];
501
+ size_t pos = minInputSize;
502
+ U32 const dictIDSizeCode = fhdByte&3;
503
+ U32 const checksumFlag = (fhdByte>>2)&1;
504
+ U32 const singleSegment = (fhdByte>>5)&1;
505
+ U32 const fcsID = fhdByte>>6;
506
+ U64 windowSize = 0;
507
+ U32 dictID = 0;
508
+ U64 frameContentSize = ZSTD_CONTENTSIZE_UNKNOWN;
509
+ RETURN_ERROR_IF((fhdByte & 0x08) != 0, frameParameter_unsupported,
510
+ "reserved bits, must be zero");
511
+
512
+ if (!singleSegment) {
513
+ BYTE const wlByte = ip[pos++];
514
+ U32 const windowLog = (wlByte >> 3) + ZSTD_WINDOWLOG_ABSOLUTEMIN;
515
+ RETURN_ERROR_IF(windowLog > ZSTD_WINDOWLOG_MAX, frameParameter_windowTooLarge, "");
516
+ windowSize = (1ULL << windowLog);
517
+ windowSize += (windowSize >> 3) * (wlByte&7);
518
+ }
519
+ switch(dictIDSizeCode)
520
+ {
521
+ default:
522
+ assert(0); /* impossible */
523
+ ZSTD_FALLTHROUGH;
524
+ case 0 : break;
525
+ case 1 : dictID = ip[pos]; pos++; break;
526
+ case 2 : dictID = MEM_readLE16(ip+pos); pos+=2; break;
527
+ case 3 : dictID = MEM_readLE32(ip+pos); pos+=4; break;
528
+ }
529
+ switch(fcsID)
530
+ {
531
+ default:
532
+ assert(0); /* impossible */
533
+ ZSTD_FALLTHROUGH;
534
+ case 0 : if (singleSegment) frameContentSize = ip[pos]; break;
535
+ case 1 : frameContentSize = MEM_readLE16(ip+pos)+256; break;
536
+ case 2 : frameContentSize = MEM_readLE32(ip+pos); break;
537
+ case 3 : frameContentSize = MEM_readLE64(ip+pos); break;
538
+ }
539
+ if (singleSegment) windowSize = frameContentSize;
540
+
541
+ zfhPtr->frameType = ZSTD_frame;
542
+ zfhPtr->frameContentSize = frameContentSize;
543
+ zfhPtr->windowSize = windowSize;
544
+ zfhPtr->blockSizeMax = (unsigned) MIN(windowSize, ZSTD_BLOCKSIZE_MAX);
545
+ zfhPtr->dictID = dictID;
546
+ zfhPtr->checksumFlag = checksumFlag;
547
+ }
548
+ return 0;
549
+ }
550
+
551
+ /** ZSTD_getFrameHeader() :
552
+ * decode Frame Header, or require larger `srcSize`.
553
+ * note : this function does not consume input, it only reads it.
554
+ * @return : 0, `zfhPtr` is correctly filled,
555
+ * >0, `srcSize` is too small, value is wanted `srcSize` amount,
556
+ * or an error code, which can be tested using ZSTD_isError() */
557
+ size_t ZSTD_getFrameHeader(ZSTD_frameHeader* zfhPtr, const void* src, size_t srcSize)
558
+ {
559
+ return ZSTD_getFrameHeader_advanced(zfhPtr, src, srcSize, ZSTD_f_zstd1);
560
+ }
561
+
562
+ /** ZSTD_getFrameContentSize() :
563
+ * compatible with legacy mode
564
+ * @return : decompressed size of the single frame pointed to be `src` if known, otherwise
565
+ * - ZSTD_CONTENTSIZE_UNKNOWN if the size cannot be determined
566
+ * - ZSTD_CONTENTSIZE_ERROR if an error occurred (e.g. invalid magic number, srcSize too small) */
567
+ unsigned long long ZSTD_getFrameContentSize(const void *src, size_t srcSize)
568
+ {
569
+ #if defined(ZSTD_LEGACY_SUPPORT) && (ZSTD_LEGACY_SUPPORT >= 1)
570
+ if (ZSTD_isLegacy(src, srcSize)) {
571
+ unsigned long long const ret = ZSTD_getDecompressedSize_legacy(src, srcSize);
572
+ return ret == 0 ? ZSTD_CONTENTSIZE_UNKNOWN : ret;
573
+ }
574
+ #endif
575
+ { ZSTD_frameHeader zfh;
576
+ if (ZSTD_getFrameHeader(&zfh, src, srcSize) != 0)
577
+ return ZSTD_CONTENTSIZE_ERROR;
578
+ if (zfh.frameType == ZSTD_skippableFrame) {
579
+ return 0;
580
+ } else {
581
+ return zfh.frameContentSize;
582
+ } }
583
+ }
584
+
585
+ static size_t readSkippableFrameSize(void const* src, size_t srcSize)
586
+ {
587
+ size_t const skippableHeaderSize = ZSTD_SKIPPABLEHEADERSIZE;
588
+ U32 sizeU32;
589
+
590
+ RETURN_ERROR_IF(srcSize < ZSTD_SKIPPABLEHEADERSIZE, srcSize_wrong, "");
591
+
592
+ sizeU32 = MEM_readLE32((BYTE const*)src + ZSTD_FRAMEIDSIZE);
593
+ RETURN_ERROR_IF((U32)(sizeU32 + ZSTD_SKIPPABLEHEADERSIZE) < sizeU32,
594
+ frameParameter_unsupported, "");
595
+ { size_t const skippableSize = skippableHeaderSize + sizeU32;
596
+ RETURN_ERROR_IF(skippableSize > srcSize, srcSize_wrong, "");
597
+ return skippableSize;
598
+ }
599
+ }
600
+
601
+ /*! ZSTD_readSkippableFrame() :
602
+ * Retrieves content of a skippable frame, and writes it to dst buffer.
603
+ *
604
+ * The parameter magicVariant will receive the magicVariant that was supplied when the frame was written,
605
+ * i.e. magicNumber - ZSTD_MAGIC_SKIPPABLE_START. This can be NULL if the caller is not interested
606
+ * in the magicVariant.
607
+ *
608
+ * Returns an error if destination buffer is not large enough, or if this is not a valid skippable frame.
609
+ *
610
+ * @return : number of bytes written or a ZSTD error.
611
+ */
612
+ size_t ZSTD_readSkippableFrame(void* dst, size_t dstCapacity,
613
+ unsigned* magicVariant, /* optional, can be NULL */
614
+ const void* src, size_t srcSize)
615
+ {
616
+ RETURN_ERROR_IF(srcSize < ZSTD_SKIPPABLEHEADERSIZE, srcSize_wrong, "");
617
+
618
+ { U32 const magicNumber = MEM_readLE32(src);
619
+ size_t skippableFrameSize = readSkippableFrameSize(src, srcSize);
620
+ size_t skippableContentSize = skippableFrameSize - ZSTD_SKIPPABLEHEADERSIZE;
621
+
622
+ /* check input validity */
623
+ RETURN_ERROR_IF(!ZSTD_isSkippableFrame(src, srcSize), frameParameter_unsupported, "");
624
+ RETURN_ERROR_IF(skippableFrameSize < ZSTD_SKIPPABLEHEADERSIZE || skippableFrameSize > srcSize, srcSize_wrong, "");
625
+ RETURN_ERROR_IF(skippableContentSize > dstCapacity, dstSize_tooSmall, "");
626
+
627
+ /* deliver payload */
628
+ if (skippableContentSize > 0 && dst != NULL)
629
+ ZSTD_memcpy(dst, (const BYTE *)src + ZSTD_SKIPPABLEHEADERSIZE, skippableContentSize);
630
+ if (magicVariant != NULL)
631
+ *magicVariant = magicNumber - ZSTD_MAGIC_SKIPPABLE_START;
632
+ return skippableContentSize;
633
+ }
634
+ }
635
+
636
+ /** ZSTD_findDecompressedSize() :
637
+ * `srcSize` must be the exact length of some number of ZSTD compressed and/or
638
+ * skippable frames
639
+ * note: compatible with legacy mode
640
+ * @return : decompressed size of the frames contained */
641
+ unsigned long long ZSTD_findDecompressedSize(const void* src, size_t srcSize)
642
+ {
643
+ unsigned long long totalDstSize = 0;
644
+
645
+ while (srcSize >= ZSTD_startingInputLength(ZSTD_f_zstd1)) {
646
+ U32 const magicNumber = MEM_readLE32(src);
647
+
648
+ if ((magicNumber & ZSTD_MAGIC_SKIPPABLE_MASK) == ZSTD_MAGIC_SKIPPABLE_START) {
649
+ size_t const skippableSize = readSkippableFrameSize(src, srcSize);
650
+ if (ZSTD_isError(skippableSize)) return ZSTD_CONTENTSIZE_ERROR;
651
+ assert(skippableSize <= srcSize);
652
+
653
+ src = (const BYTE *)src + skippableSize;
654
+ srcSize -= skippableSize;
655
+ continue;
656
+ }
657
+
658
+ { unsigned long long const fcs = ZSTD_getFrameContentSize(src, srcSize);
659
+ if (fcs >= ZSTD_CONTENTSIZE_ERROR) return fcs;
660
+
661
+ if (totalDstSize + fcs < totalDstSize)
662
+ return ZSTD_CONTENTSIZE_ERROR; /* check for overflow */
663
+ totalDstSize += fcs;
664
+ }
665
+ /* skip to next frame */
666
+ { size_t const frameSrcSize = ZSTD_findFrameCompressedSize(src, srcSize);
667
+ if (ZSTD_isError(frameSrcSize)) return ZSTD_CONTENTSIZE_ERROR;
668
+ assert(frameSrcSize <= srcSize);
669
+
670
+ src = (const BYTE *)src + frameSrcSize;
671
+ srcSize -= frameSrcSize;
672
+ }
673
+ } /* while (srcSize >= ZSTD_frameHeaderSize_prefix) */
674
+
675
+ if (srcSize) return ZSTD_CONTENTSIZE_ERROR;
676
+
677
+ return totalDstSize;
678
+ }
679
+
680
+ /** ZSTD_getDecompressedSize() :
681
+ * compatible with legacy mode
682
+ * @return : decompressed size if known, 0 otherwise
683
+ note : 0 can mean any of the following :
684
+ - frame content is empty
685
+ - decompressed size field is not present in frame header
686
+ - frame header unknown / not supported
687
+ - frame header not complete (`srcSize` too small) */
688
+ unsigned long long ZSTD_getDecompressedSize(const void* src, size_t srcSize)
689
+ {
690
+ unsigned long long const ret = ZSTD_getFrameContentSize(src, srcSize);
691
+ ZSTD_STATIC_ASSERT(ZSTD_CONTENTSIZE_ERROR < ZSTD_CONTENTSIZE_UNKNOWN);
692
+ return (ret >= ZSTD_CONTENTSIZE_ERROR) ? 0 : ret;
693
+ }
694
+
695
+
696
+ /** ZSTD_decodeFrameHeader() :
697
+ * `headerSize` must be the size provided by ZSTD_frameHeaderSize().
698
+ * If multiple DDict references are enabled, also will choose the correct DDict to use.
699
+ * @return : 0 if success, or an error code, which can be tested using ZSTD_isError() */
700
+ static size_t ZSTD_decodeFrameHeader(ZSTD_DCtx* dctx, const void* src, size_t headerSize)
701
+ {
702
+ size_t const result = ZSTD_getFrameHeader_advanced(&(dctx->fParams), src, headerSize, dctx->format);
703
+ if (ZSTD_isError(result)) return result; /* invalid header */
704
+ RETURN_ERROR_IF(result>0, srcSize_wrong, "headerSize too small");
705
+
706
+ /* Reference DDict requested by frame if dctx references multiple ddicts */
707
+ if (dctx->refMultipleDDicts == ZSTD_rmd_refMultipleDDicts && dctx->ddictSet) {
708
+ ZSTD_DCtx_selectFrameDDict(dctx);
709
+ }
710
+
711
+ #ifndef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
712
+ /* Skip the dictID check in fuzzing mode, because it makes the search
713
+ * harder.
714
+ */
715
+ RETURN_ERROR_IF(dctx->fParams.dictID && (dctx->dictID != dctx->fParams.dictID),
716
+ dictionary_wrong, "");
717
+ #endif
718
+ dctx->validateChecksum = (dctx->fParams.checksumFlag && !dctx->forceIgnoreChecksum) ? 1 : 0;
719
+ if (dctx->validateChecksum) XXH64_reset(&dctx->xxhState, 0);
720
+ dctx->processedCSize += headerSize;
721
+ return 0;
722
+ }
723
+
724
+ static ZSTD_frameSizeInfo ZSTD_errorFrameSizeInfo(size_t ret)
725
+ {
726
+ ZSTD_frameSizeInfo frameSizeInfo;
727
+ frameSizeInfo.compressedSize = ret;
728
+ frameSizeInfo.decompressedBound = ZSTD_CONTENTSIZE_ERROR;
729
+ return frameSizeInfo;
730
+ }
731
+
732
+ static ZSTD_frameSizeInfo ZSTD_findFrameSizeInfo(const void* src, size_t srcSize, ZSTD_format_e format)
733
+ {
734
+ ZSTD_frameSizeInfo frameSizeInfo;
735
+ ZSTD_memset(&frameSizeInfo, 0, sizeof(ZSTD_frameSizeInfo));
736
+
737
+ #if defined(ZSTD_LEGACY_SUPPORT) && (ZSTD_LEGACY_SUPPORT >= 1)
738
+ if (format == ZSTD_f_zstd1 && ZSTD_isLegacy(src, srcSize))
739
+ return ZSTD_findFrameSizeInfoLegacy(src, srcSize);
740
+ #endif
741
+
742
+ if (format == ZSTD_f_zstd1 && (srcSize >= ZSTD_SKIPPABLEHEADERSIZE)
743
+ && (MEM_readLE32(src) & ZSTD_MAGIC_SKIPPABLE_MASK) == ZSTD_MAGIC_SKIPPABLE_START) {
744
+ frameSizeInfo.compressedSize = readSkippableFrameSize(src, srcSize);
745
+ assert(ZSTD_isError(frameSizeInfo.compressedSize) ||
746
+ frameSizeInfo.compressedSize <= srcSize);
747
+ return frameSizeInfo;
748
+ } else {
749
+ const BYTE* ip = (const BYTE*)src;
750
+ const BYTE* const ipstart = ip;
751
+ size_t remainingSize = srcSize;
752
+ size_t nbBlocks = 0;
753
+ ZSTD_frameHeader zfh;
754
+
755
+ /* Extract Frame Header */
756
+ { size_t const ret = ZSTD_getFrameHeader_advanced(&zfh, src, srcSize, format);
757
+ if (ZSTD_isError(ret))
758
+ return ZSTD_errorFrameSizeInfo(ret);
759
+ if (ret > 0)
760
+ return ZSTD_errorFrameSizeInfo(ERROR(srcSize_wrong));
761
+ }
762
+
763
+ ip += zfh.headerSize;
764
+ remainingSize -= zfh.headerSize;
765
+
766
+ /* Iterate over each block */
767
+ while (1) {
768
+ blockProperties_t blockProperties;
769
+ size_t const cBlockSize = ZSTD_getcBlockSize(ip, remainingSize, &blockProperties);
770
+ if (ZSTD_isError(cBlockSize))
771
+ return ZSTD_errorFrameSizeInfo(cBlockSize);
772
+
773
+ if (ZSTD_blockHeaderSize + cBlockSize > remainingSize)
774
+ return ZSTD_errorFrameSizeInfo(ERROR(srcSize_wrong));
775
+
776
+ ip += ZSTD_blockHeaderSize + cBlockSize;
777
+ remainingSize -= ZSTD_blockHeaderSize + cBlockSize;
778
+ nbBlocks++;
779
+
780
+ if (blockProperties.lastBlock) break;
781
+ }
782
+
783
+ /* Final frame content checksum */
784
+ if (zfh.checksumFlag) {
785
+ if (remainingSize < 4)
786
+ return ZSTD_errorFrameSizeInfo(ERROR(srcSize_wrong));
787
+ ip += 4;
788
+ }
789
+
790
+ frameSizeInfo.nbBlocks = nbBlocks;
791
+ frameSizeInfo.compressedSize = (size_t)(ip - ipstart);
792
+ frameSizeInfo.decompressedBound = (zfh.frameContentSize != ZSTD_CONTENTSIZE_UNKNOWN)
793
+ ? zfh.frameContentSize
794
+ : (unsigned long long)nbBlocks * zfh.blockSizeMax;
795
+ return frameSizeInfo;
796
+ }
797
+ }
798
+
799
+ static size_t ZSTD_findFrameCompressedSize_advanced(const void *src, size_t srcSize, ZSTD_format_e format) {
800
+ ZSTD_frameSizeInfo const frameSizeInfo = ZSTD_findFrameSizeInfo(src, srcSize, format);
801
+ return frameSizeInfo.compressedSize;
802
+ }
803
+
804
+ /** ZSTD_findFrameCompressedSize() :
805
+ * See docs in zstd.h
806
+ * Note: compatible with legacy mode */
807
+ size_t ZSTD_findFrameCompressedSize(const void *src, size_t srcSize)
808
+ {
809
+ return ZSTD_findFrameCompressedSize_advanced(src, srcSize, ZSTD_f_zstd1);
810
+ }
811
+
812
+ /** ZSTD_decompressBound() :
813
+ * compatible with legacy mode
814
+ * `src` must point to the start of a ZSTD frame or a skippeable frame
815
+ * `srcSize` must be at least as large as the frame contained
816
+ * @return : the maximum decompressed size of the compressed source
817
+ */
818
+ unsigned long long ZSTD_decompressBound(const void* src, size_t srcSize)
819
+ {
820
+ unsigned long long bound = 0;
821
+ /* Iterate over each frame */
822
+ while (srcSize > 0) {
823
+ ZSTD_frameSizeInfo const frameSizeInfo = ZSTD_findFrameSizeInfo(src, srcSize, ZSTD_f_zstd1);
824
+ size_t const compressedSize = frameSizeInfo.compressedSize;
825
+ unsigned long long const decompressedBound = frameSizeInfo.decompressedBound;
826
+ if (ZSTD_isError(compressedSize) || decompressedBound == ZSTD_CONTENTSIZE_ERROR)
827
+ return ZSTD_CONTENTSIZE_ERROR;
828
+ assert(srcSize >= compressedSize);
829
+ src = (const BYTE*)src + compressedSize;
830
+ srcSize -= compressedSize;
831
+ bound += decompressedBound;
832
+ }
833
+ return bound;
834
+ }
835
+
836
+ size_t ZSTD_decompressionMargin(void const* src, size_t srcSize)
837
+ {
838
+ size_t margin = 0;
839
+ unsigned maxBlockSize = 0;
840
+
841
+ /* Iterate over each frame */
842
+ while (srcSize > 0) {
843
+ ZSTD_frameSizeInfo const frameSizeInfo = ZSTD_findFrameSizeInfo(src, srcSize, ZSTD_f_zstd1);
844
+ size_t const compressedSize = frameSizeInfo.compressedSize;
845
+ unsigned long long const decompressedBound = frameSizeInfo.decompressedBound;
846
+ ZSTD_frameHeader zfh;
847
+
848
+ FORWARD_IF_ERROR(ZSTD_getFrameHeader(&zfh, src, srcSize), "");
849
+ if (ZSTD_isError(compressedSize) || decompressedBound == ZSTD_CONTENTSIZE_ERROR)
850
+ return ERROR(corruption_detected);
851
+
852
+ if (zfh.frameType == ZSTD_frame) {
853
+ /* Add the frame header to our margin */
854
+ margin += zfh.headerSize;
855
+ /* Add the checksum to our margin */
856
+ margin += zfh.checksumFlag ? 4 : 0;
857
+ /* Add 3 bytes per block */
858
+ margin += 3 * frameSizeInfo.nbBlocks;
859
+
860
+ /* Compute the max block size */
861
+ maxBlockSize = MAX(maxBlockSize, zfh.blockSizeMax);
862
+ } else {
863
+ assert(zfh.frameType == ZSTD_skippableFrame);
864
+ /* Add the entire skippable frame size to our margin. */
865
+ margin += compressedSize;
866
+ }
867
+
868
+ assert(srcSize >= compressedSize);
869
+ src = (const BYTE*)src + compressedSize;
870
+ srcSize -= compressedSize;
871
+ }
872
+
873
+ /* Add the max block size back to the margin. */
874
+ margin += maxBlockSize;
875
+
876
+ return margin;
877
+ }
878
+
879
+ /*-*************************************************************
880
+ * Frame decoding
881
+ ***************************************************************/
882
+
883
+ /** ZSTD_insertBlock() :
884
+ * insert `src` block into `dctx` history. Useful to track uncompressed blocks. */
885
+ size_t ZSTD_insertBlock(ZSTD_DCtx* dctx, const void* blockStart, size_t blockSize)
886
+ {
887
+ DEBUGLOG(5, "ZSTD_insertBlock: %u bytes", (unsigned)blockSize);
888
+ ZSTD_checkContinuity(dctx, blockStart, blockSize);
889
+ dctx->previousDstEnd = (const char*)blockStart + blockSize;
890
+ return blockSize;
891
+ }
892
+
893
+
894
+ static size_t ZSTD_copyRawBlock(void* dst, size_t dstCapacity,
895
+ const void* src, size_t srcSize)
896
+ {
897
+ DEBUGLOG(5, "ZSTD_copyRawBlock");
898
+ RETURN_ERROR_IF(srcSize > dstCapacity, dstSize_tooSmall, "");
899
+ if (dst == NULL) {
900
+ if (srcSize == 0) return 0;
901
+ RETURN_ERROR(dstBuffer_null, "");
902
+ }
903
+ ZSTD_memmove(dst, src, srcSize);
904
+ return srcSize;
905
+ }
906
+
907
+ static size_t ZSTD_setRleBlock(void* dst, size_t dstCapacity,
908
+ BYTE b,
909
+ size_t regenSize)
910
+ {
911
+ RETURN_ERROR_IF(regenSize > dstCapacity, dstSize_tooSmall, "");
912
+ if (dst == NULL) {
913
+ if (regenSize == 0) return 0;
914
+ RETURN_ERROR(dstBuffer_null, "");
915
+ }
916
+ ZSTD_memset(dst, b, regenSize);
917
+ return regenSize;
918
+ }
919
+
920
+ static void ZSTD_DCtx_trace_end(ZSTD_DCtx const* dctx, U64 uncompressedSize, U64 compressedSize, unsigned streaming)
921
+ {
922
+ #if ZSTD_TRACE
923
+ if (dctx->traceCtx && ZSTD_trace_decompress_end != NULL) {
924
+ ZSTD_Trace trace;
925
+ ZSTD_memset(&trace, 0, sizeof(trace));
926
+ trace.version = ZSTD_VERSION_NUMBER;
927
+ trace.streaming = streaming;
928
+ if (dctx->ddict) {
929
+ trace.dictionaryID = ZSTD_getDictID_fromDDict(dctx->ddict);
930
+ trace.dictionarySize = ZSTD_DDict_dictSize(dctx->ddict);
931
+ trace.dictionaryIsCold = dctx->ddictIsCold;
932
+ }
933
+ trace.uncompressedSize = (size_t)uncompressedSize;
934
+ trace.compressedSize = (size_t)compressedSize;
935
+ trace.dctx = dctx;
936
+ ZSTD_trace_decompress_end(dctx->traceCtx, &trace);
937
+ }
938
+ #else
939
+ (void)dctx;
940
+ (void)uncompressedSize;
941
+ (void)compressedSize;
942
+ (void)streaming;
943
+ #endif
944
+ }
945
+
946
+
947
+ /*! ZSTD_decompressFrame() :
948
+ * @dctx must be properly initialized
949
+ * will update *srcPtr and *srcSizePtr,
950
+ * to make *srcPtr progress by one frame. */
951
+ static size_t ZSTD_decompressFrame(ZSTD_DCtx* dctx,
952
+ void* dst, size_t dstCapacity,
953
+ const void** srcPtr, size_t *srcSizePtr)
954
+ {
955
+ const BYTE* const istart = (const BYTE*)(*srcPtr);
956
+ const BYTE* ip = istart;
957
+ BYTE* const ostart = (BYTE*)dst;
958
+ BYTE* const oend = dstCapacity != 0 ? ostart + dstCapacity : ostart;
959
+ BYTE* op = ostart;
960
+ size_t remainingSrcSize = *srcSizePtr;
961
+
962
+ DEBUGLOG(4, "ZSTD_decompressFrame (srcSize:%i)", (int)*srcSizePtr);
963
+
964
+ /* check */
965
+ RETURN_ERROR_IF(
966
+ remainingSrcSize < ZSTD_FRAMEHEADERSIZE_MIN(dctx->format)+ZSTD_blockHeaderSize,
967
+ srcSize_wrong, "");
968
+
969
+ /* Frame Header */
970
+ { size_t const frameHeaderSize = ZSTD_frameHeaderSize_internal(
971
+ ip, ZSTD_FRAMEHEADERSIZE_PREFIX(dctx->format), dctx->format);
972
+ if (ZSTD_isError(frameHeaderSize)) return frameHeaderSize;
973
+ RETURN_ERROR_IF(remainingSrcSize < frameHeaderSize+ZSTD_blockHeaderSize,
974
+ srcSize_wrong, "");
975
+ FORWARD_IF_ERROR( ZSTD_decodeFrameHeader(dctx, ip, frameHeaderSize) , "");
976
+ ip += frameHeaderSize; remainingSrcSize -= frameHeaderSize;
977
+ }
978
+
979
+ /* Shrink the blockSizeMax if enabled */
980
+ if (dctx->maxBlockSizeParam != 0)
981
+ dctx->fParams.blockSizeMax = MIN(dctx->fParams.blockSizeMax, (unsigned)dctx->maxBlockSizeParam);
982
+
983
+ /* Loop on each block */
984
+ while (1) {
985
+ BYTE* oBlockEnd = oend;
986
+ size_t decodedSize;
987
+ blockProperties_t blockProperties;
988
+ size_t const cBlockSize = ZSTD_getcBlockSize(ip, remainingSrcSize, &blockProperties);
989
+ if (ZSTD_isError(cBlockSize)) return cBlockSize;
990
+
991
+ ip += ZSTD_blockHeaderSize;
992
+ remainingSrcSize -= ZSTD_blockHeaderSize;
993
+ RETURN_ERROR_IF(cBlockSize > remainingSrcSize, srcSize_wrong, "");
994
+
995
+ if (ip >= op && ip < oBlockEnd) {
996
+ /* We are decompressing in-place. Limit the output pointer so that we
997
+ * don't overwrite the block that we are currently reading. This will
998
+ * fail decompression if the input & output pointers aren't spaced
999
+ * far enough apart.
1000
+ *
1001
+ * This is important to set, even when the pointers are far enough
1002
+ * apart, because ZSTD_decompressBlock_internal() can decide to store
1003
+ * literals in the output buffer, after the block it is decompressing.
1004
+ * Since we don't want anything to overwrite our input, we have to tell
1005
+ * ZSTD_decompressBlock_internal to never write past ip.
1006
+ *
1007
+ * See ZSTD_allocateLiteralsBuffer() for reference.
1008
+ */
1009
+ oBlockEnd = op + (ip - op);
1010
+ }
1011
+
1012
+ switch(blockProperties.blockType)
1013
+ {
1014
+ case bt_compressed:
1015
+ assert(dctx->isFrameDecompression == 1);
1016
+ decodedSize = ZSTD_decompressBlock_internal(dctx, op, (size_t)(oBlockEnd-op), ip, cBlockSize, not_streaming);
1017
+ break;
1018
+ case bt_raw :
1019
+ /* Use oend instead of oBlockEnd because this function is safe to overlap. It uses memmove. */
1020
+ decodedSize = ZSTD_copyRawBlock(op, (size_t)(oend-op), ip, cBlockSize);
1021
+ break;
1022
+ case bt_rle :
1023
+ decodedSize = ZSTD_setRleBlock(op, (size_t)(oBlockEnd-op), *ip, blockProperties.origSize);
1024
+ break;
1025
+ case bt_reserved :
1026
+ default:
1027
+ RETURN_ERROR(corruption_detected, "invalid block type");
1028
+ }
1029
+ FORWARD_IF_ERROR(decodedSize, "Block decompression failure");
1030
+ DEBUGLOG(5, "Decompressed block of dSize = %u", (unsigned)decodedSize);
1031
+ if (dctx->validateChecksum) {
1032
+ XXH64_update(&dctx->xxhState, op, decodedSize);
1033
+ }
1034
+ if (decodedSize) /* support dst = NULL,0 */ {
1035
+ op += decodedSize;
1036
+ }
1037
+ assert(ip != NULL);
1038
+ ip += cBlockSize;
1039
+ remainingSrcSize -= cBlockSize;
1040
+ if (blockProperties.lastBlock) break;
1041
+ }
1042
+
1043
+ if (dctx->fParams.frameContentSize != ZSTD_CONTENTSIZE_UNKNOWN) {
1044
+ RETURN_ERROR_IF((U64)(op-ostart) != dctx->fParams.frameContentSize,
1045
+ corruption_detected, "");
1046
+ }
1047
+ if (dctx->fParams.checksumFlag) { /* Frame content checksum verification */
1048
+ RETURN_ERROR_IF(remainingSrcSize<4, checksum_wrong, "");
1049
+ if (!dctx->forceIgnoreChecksum) {
1050
+ U32 const checkCalc = (U32)XXH64_digest(&dctx->xxhState);
1051
+ U32 checkRead;
1052
+ checkRead = MEM_readLE32(ip);
1053
+ RETURN_ERROR_IF(checkRead != checkCalc, checksum_wrong, "");
1054
+ }
1055
+ ip += 4;
1056
+ remainingSrcSize -= 4;
1057
+ }
1058
+ ZSTD_DCtx_trace_end(dctx, (U64)(op-ostart), (U64)(ip-istart), /* streaming */ 0);
1059
+ /* Allow caller to get size read */
1060
+ DEBUGLOG(4, "ZSTD_decompressFrame: decompressed frame of size %zi, consuming %zi bytes of input", op-ostart, ip - (const BYTE*)*srcPtr);
1061
+ *srcPtr = ip;
1062
+ *srcSizePtr = remainingSrcSize;
1063
+ return (size_t)(op-ostart);
1064
+ }
1065
+
1066
+ static
1067
+ ZSTD_ALLOW_POINTER_OVERFLOW_ATTR
1068
+ size_t ZSTD_decompressMultiFrame(ZSTD_DCtx* dctx,
1069
+ void* dst, size_t dstCapacity,
1070
+ const void* src, size_t srcSize,
1071
+ const void* dict, size_t dictSize,
1072
+ const ZSTD_DDict* ddict)
1073
+ {
1074
+ void* const dststart = dst;
1075
+ int moreThan1Frame = 0;
1076
+
1077
+ DEBUGLOG(5, "ZSTD_decompressMultiFrame");
1078
+ assert(dict==NULL || ddict==NULL); /* either dict or ddict set, not both */
1079
+
1080
+ if (ddict) {
1081
+ dict = ZSTD_DDict_dictContent(ddict);
1082
+ dictSize = ZSTD_DDict_dictSize(ddict);
1083
+ }
1084
+
1085
+ while (srcSize >= ZSTD_startingInputLength(dctx->format)) {
1086
+
1087
+ #if defined(ZSTD_LEGACY_SUPPORT) && (ZSTD_LEGACY_SUPPORT >= 1)
1088
+ if (dctx->format == ZSTD_f_zstd1 && ZSTD_isLegacy(src, srcSize)) {
1089
+ size_t decodedSize;
1090
+ size_t const frameSize = ZSTD_findFrameCompressedSizeLegacy(src, srcSize);
1091
+ if (ZSTD_isError(frameSize)) return frameSize;
1092
+ RETURN_ERROR_IF(dctx->staticSize, memory_allocation,
1093
+ "legacy support is not compatible with static dctx");
1094
+
1095
+ decodedSize = ZSTD_decompressLegacy(dst, dstCapacity, src, frameSize, dict, dictSize);
1096
+ if (ZSTD_isError(decodedSize)) return decodedSize;
1097
+
1098
+ {
1099
+ unsigned long long const expectedSize = ZSTD_getFrameContentSize(src, srcSize);
1100
+ RETURN_ERROR_IF(expectedSize == ZSTD_CONTENTSIZE_ERROR, corruption_detected, "Corrupted frame header!");
1101
+ if (expectedSize != ZSTD_CONTENTSIZE_UNKNOWN) {
1102
+ RETURN_ERROR_IF(expectedSize != decodedSize, corruption_detected,
1103
+ "Frame header size does not match decoded size!");
1104
+ }
1105
+ }
1106
+
1107
+ assert(decodedSize <= dstCapacity);
1108
+ dst = (BYTE*)dst + decodedSize;
1109
+ dstCapacity -= decodedSize;
1110
+
1111
+ src = (const BYTE*)src + frameSize;
1112
+ srcSize -= frameSize;
1113
+
1114
+ continue;
1115
+ }
1116
+ #endif
1117
+
1118
+ if (dctx->format == ZSTD_f_zstd1 && srcSize >= 4) {
1119
+ U32 const magicNumber = MEM_readLE32(src);
1120
+ DEBUGLOG(5, "reading magic number %08X", (unsigned)magicNumber);
1121
+ if ((magicNumber & ZSTD_MAGIC_SKIPPABLE_MASK) == ZSTD_MAGIC_SKIPPABLE_START) {
1122
+ /* skippable frame detected : skip it */
1123
+ size_t const skippableSize = readSkippableFrameSize(src, srcSize);
1124
+ FORWARD_IF_ERROR(skippableSize, "invalid skippable frame");
1125
+ assert(skippableSize <= srcSize);
1126
+
1127
+ src = (const BYTE *)src + skippableSize;
1128
+ srcSize -= skippableSize;
1129
+ continue; /* check next frame */
1130
+ } }
1131
+
1132
+ if (ddict) {
1133
+ /* we were called from ZSTD_decompress_usingDDict */
1134
+ FORWARD_IF_ERROR(ZSTD_decompressBegin_usingDDict(dctx, ddict), "");
1135
+ } else {
1136
+ /* this will initialize correctly with no dict if dict == NULL, so
1137
+ * use this in all cases but ddict */
1138
+ FORWARD_IF_ERROR(ZSTD_decompressBegin_usingDict(dctx, dict, dictSize), "");
1139
+ }
1140
+ ZSTD_checkContinuity(dctx, dst, dstCapacity);
1141
+
1142
+ { const size_t res = ZSTD_decompressFrame(dctx, dst, dstCapacity,
1143
+ &src, &srcSize);
1144
+ RETURN_ERROR_IF(
1145
+ (ZSTD_getErrorCode(res) == ZSTD_error_prefix_unknown)
1146
+ && (moreThan1Frame==1),
1147
+ srcSize_wrong,
1148
+ "At least one frame successfully completed, "
1149
+ "but following bytes are garbage: "
1150
+ "it's more likely to be a srcSize error, "
1151
+ "specifying more input bytes than size of frame(s). "
1152
+ "Note: one could be unlucky, it might be a corruption error instead, "
1153
+ "happening right at the place where we expect zstd magic bytes. "
1154
+ "But this is _much_ less likely than a srcSize field error.");
1155
+ if (ZSTD_isError(res)) return res;
1156
+ assert(res <= dstCapacity);
1157
+ if (res != 0)
1158
+ dst = (BYTE*)dst + res;
1159
+ dstCapacity -= res;
1160
+ }
1161
+ moreThan1Frame = 1;
1162
+ } /* while (srcSize >= ZSTD_frameHeaderSize_prefix) */
1163
+
1164
+ RETURN_ERROR_IF(srcSize, srcSize_wrong, "input not entirely consumed");
1165
+
1166
+ return (size_t)((BYTE*)dst - (BYTE*)dststart);
1167
+ }
1168
+
1169
+ size_t ZSTD_decompress_usingDict(ZSTD_DCtx* dctx,
1170
+ void* dst, size_t dstCapacity,
1171
+ const void* src, size_t srcSize,
1172
+ const void* dict, size_t dictSize)
1173
+ {
1174
+ return ZSTD_decompressMultiFrame(dctx, dst, dstCapacity, src, srcSize, dict, dictSize, NULL);
1175
+ }
1176
+
1177
+
1178
+ static ZSTD_DDict const* ZSTD_getDDict(ZSTD_DCtx* dctx)
1179
+ {
1180
+ switch (dctx->dictUses) {
1181
+ default:
1182
+ assert(0 /* Impossible */);
1183
+ ZSTD_FALLTHROUGH;
1184
+ case ZSTD_dont_use:
1185
+ ZSTD_clearDict(dctx);
1186
+ return NULL;
1187
+ case ZSTD_use_indefinitely:
1188
+ return dctx->ddict;
1189
+ case ZSTD_use_once:
1190
+ dctx->dictUses = ZSTD_dont_use;
1191
+ return dctx->ddict;
1192
+ }
1193
+ }
1194
+
1195
+ size_t ZSTD_decompressDCtx(ZSTD_DCtx* dctx, void* dst, size_t dstCapacity, const void* src, size_t srcSize)
1196
+ {
1197
+ return ZSTD_decompress_usingDDict(dctx, dst, dstCapacity, src, srcSize, ZSTD_getDDict(dctx));
1198
+ }
1199
+
1200
+
1201
+ size_t ZSTD_decompress(void* dst, size_t dstCapacity, const void* src, size_t srcSize)
1202
+ {
1203
+ #if defined(ZSTD_HEAPMODE) && (ZSTD_HEAPMODE>=1)
1204
+ size_t regenSize;
1205
+ ZSTD_DCtx* const dctx = ZSTD_createDCtx_internal(ZSTD_defaultCMem);
1206
+ RETURN_ERROR_IF(dctx==NULL, memory_allocation, "NULL pointer!");
1207
+ regenSize = ZSTD_decompressDCtx(dctx, dst, dstCapacity, src, srcSize);
1208
+ ZSTD_freeDCtx(dctx);
1209
+ return regenSize;
1210
+ #else /* stack mode */
1211
+ ZSTD_DCtx dctx;
1212
+ ZSTD_initDCtx_internal(&dctx);
1213
+ return ZSTD_decompressDCtx(&dctx, dst, dstCapacity, src, srcSize);
1214
+ #endif
1215
+ }
1216
+
1217
+
1218
+ /*-**************************************
1219
+ * Advanced Streaming Decompression API
1220
+ * Bufferless and synchronous
1221
+ ****************************************/
1222
+ size_t ZSTD_nextSrcSizeToDecompress(ZSTD_DCtx* dctx) { return dctx->expected; }
1223
+
1224
+ /**
1225
+ * Similar to ZSTD_nextSrcSizeToDecompress(), but when a block input can be streamed, we
1226
+ * allow taking a partial block as the input. Currently only raw uncompressed blocks can
1227
+ * be streamed.
1228
+ *
1229
+ * For blocks that can be streamed, this allows us to reduce the latency until we produce
1230
+ * output, and avoid copying the input.
1231
+ *
1232
+ * @param inputSize - The total amount of input that the caller currently has.
1233
+ */
1234
+ static size_t ZSTD_nextSrcSizeToDecompressWithInputSize(ZSTD_DCtx* dctx, size_t inputSize) {
1235
+ if (!(dctx->stage == ZSTDds_decompressBlock || dctx->stage == ZSTDds_decompressLastBlock))
1236
+ return dctx->expected;
1237
+ if (dctx->bType != bt_raw)
1238
+ return dctx->expected;
1239
+ return BOUNDED(1, inputSize, dctx->expected);
1240
+ }
1241
+
1242
+ ZSTD_nextInputType_e ZSTD_nextInputType(ZSTD_DCtx* dctx) {
1243
+ switch(dctx->stage)
1244
+ {
1245
+ default: /* should not happen */
1246
+ assert(0);
1247
+ ZSTD_FALLTHROUGH;
1248
+ case ZSTDds_getFrameHeaderSize:
1249
+ ZSTD_FALLTHROUGH;
1250
+ case ZSTDds_decodeFrameHeader:
1251
+ return ZSTDnit_frameHeader;
1252
+ case ZSTDds_decodeBlockHeader:
1253
+ return ZSTDnit_blockHeader;
1254
+ case ZSTDds_decompressBlock:
1255
+ return ZSTDnit_block;
1256
+ case ZSTDds_decompressLastBlock:
1257
+ return ZSTDnit_lastBlock;
1258
+ case ZSTDds_checkChecksum:
1259
+ return ZSTDnit_checksum;
1260
+ case ZSTDds_decodeSkippableHeader:
1261
+ ZSTD_FALLTHROUGH;
1262
+ case ZSTDds_skipFrame:
1263
+ return ZSTDnit_skippableFrame;
1264
+ }
1265
+ }
1266
+
1267
+ static int ZSTD_isSkipFrame(ZSTD_DCtx* dctx) { return dctx->stage == ZSTDds_skipFrame; }
1268
+
1269
+ /** ZSTD_decompressContinue() :
1270
+ * srcSize : must be the exact nb of bytes expected (see ZSTD_nextSrcSizeToDecompress())
1271
+ * @return : nb of bytes generated into `dst` (necessarily <= `dstCapacity)
1272
+ * or an error code, which can be tested using ZSTD_isError() */
1273
+ size_t ZSTD_decompressContinue(ZSTD_DCtx* dctx, void* dst, size_t dstCapacity, const void* src, size_t srcSize)
1274
+ {
1275
+ DEBUGLOG(5, "ZSTD_decompressContinue (srcSize:%u)", (unsigned)srcSize);
1276
+ /* Sanity check */
1277
+ RETURN_ERROR_IF(srcSize != ZSTD_nextSrcSizeToDecompressWithInputSize(dctx, srcSize), srcSize_wrong, "not allowed");
1278
+ ZSTD_checkContinuity(dctx, dst, dstCapacity);
1279
+
1280
+ dctx->processedCSize += srcSize;
1281
+
1282
+ switch (dctx->stage)
1283
+ {
1284
+ case ZSTDds_getFrameHeaderSize :
1285
+ assert(src != NULL);
1286
+ if (dctx->format == ZSTD_f_zstd1) { /* allows header */
1287
+ assert(srcSize >= ZSTD_FRAMEIDSIZE); /* to read skippable magic number */
1288
+ if ((MEM_readLE32(src) & ZSTD_MAGIC_SKIPPABLE_MASK) == ZSTD_MAGIC_SKIPPABLE_START) { /* skippable frame */
1289
+ ZSTD_memcpy(dctx->headerBuffer, src, srcSize);
1290
+ dctx->expected = ZSTD_SKIPPABLEHEADERSIZE - srcSize; /* remaining to load to get full skippable frame header */
1291
+ dctx->stage = ZSTDds_decodeSkippableHeader;
1292
+ return 0;
1293
+ } }
1294
+ dctx->headerSize = ZSTD_frameHeaderSize_internal(src, srcSize, dctx->format);
1295
+ if (ZSTD_isError(dctx->headerSize)) return dctx->headerSize;
1296
+ ZSTD_memcpy(dctx->headerBuffer, src, srcSize);
1297
+ dctx->expected = dctx->headerSize - srcSize;
1298
+ dctx->stage = ZSTDds_decodeFrameHeader;
1299
+ return 0;
1300
+
1301
+ case ZSTDds_decodeFrameHeader:
1302
+ assert(src != NULL);
1303
+ ZSTD_memcpy(dctx->headerBuffer + (dctx->headerSize - srcSize), src, srcSize);
1304
+ FORWARD_IF_ERROR(ZSTD_decodeFrameHeader(dctx, dctx->headerBuffer, dctx->headerSize), "");
1305
+ dctx->expected = ZSTD_blockHeaderSize;
1306
+ dctx->stage = ZSTDds_decodeBlockHeader;
1307
+ return 0;
1308
+
1309
+ case ZSTDds_decodeBlockHeader:
1310
+ { blockProperties_t bp;
1311
+ size_t const cBlockSize = ZSTD_getcBlockSize(src, ZSTD_blockHeaderSize, &bp);
1312
+ if (ZSTD_isError(cBlockSize)) return cBlockSize;
1313
+ RETURN_ERROR_IF(cBlockSize > dctx->fParams.blockSizeMax, corruption_detected, "Block Size Exceeds Maximum");
1314
+ dctx->expected = cBlockSize;
1315
+ dctx->bType = bp.blockType;
1316
+ dctx->rleSize = bp.origSize;
1317
+ if (cBlockSize) {
1318
+ dctx->stage = bp.lastBlock ? ZSTDds_decompressLastBlock : ZSTDds_decompressBlock;
1319
+ return 0;
1320
+ }
1321
+ /* empty block */
1322
+ if (bp.lastBlock) {
1323
+ if (dctx->fParams.checksumFlag) {
1324
+ dctx->expected = 4;
1325
+ dctx->stage = ZSTDds_checkChecksum;
1326
+ } else {
1327
+ dctx->expected = 0; /* end of frame */
1328
+ dctx->stage = ZSTDds_getFrameHeaderSize;
1329
+ }
1330
+ } else {
1331
+ dctx->expected = ZSTD_blockHeaderSize; /* jump to next header */
1332
+ dctx->stage = ZSTDds_decodeBlockHeader;
1333
+ }
1334
+ return 0;
1335
+ }
1336
+
1337
+ case ZSTDds_decompressLastBlock:
1338
+ case ZSTDds_decompressBlock:
1339
+ DEBUGLOG(5, "ZSTD_decompressContinue: case ZSTDds_decompressBlock");
1340
+ { size_t rSize;
1341
+ switch(dctx->bType)
1342
+ {
1343
+ case bt_compressed:
1344
+ DEBUGLOG(5, "ZSTD_decompressContinue: case bt_compressed");
1345
+ assert(dctx->isFrameDecompression == 1);
1346
+ rSize = ZSTD_decompressBlock_internal(dctx, dst, dstCapacity, src, srcSize, is_streaming);
1347
+ dctx->expected = 0; /* Streaming not supported */
1348
+ break;
1349
+ case bt_raw :
1350
+ assert(srcSize <= dctx->expected);
1351
+ rSize = ZSTD_copyRawBlock(dst, dstCapacity, src, srcSize);
1352
+ FORWARD_IF_ERROR(rSize, "ZSTD_copyRawBlock failed");
1353
+ assert(rSize == srcSize);
1354
+ dctx->expected -= rSize;
1355
+ break;
1356
+ case bt_rle :
1357
+ rSize = ZSTD_setRleBlock(dst, dstCapacity, *(const BYTE*)src, dctx->rleSize);
1358
+ dctx->expected = 0; /* Streaming not supported */
1359
+ break;
1360
+ case bt_reserved : /* should never happen */
1361
+ default:
1362
+ RETURN_ERROR(corruption_detected, "invalid block type");
1363
+ }
1364
+ FORWARD_IF_ERROR(rSize, "");
1365
+ RETURN_ERROR_IF(rSize > dctx->fParams.blockSizeMax, corruption_detected, "Decompressed Block Size Exceeds Maximum");
1366
+ DEBUGLOG(5, "ZSTD_decompressContinue: decoded size from block : %u", (unsigned)rSize);
1367
+ dctx->decodedSize += rSize;
1368
+ if (dctx->validateChecksum) XXH64_update(&dctx->xxhState, dst, rSize);
1369
+ dctx->previousDstEnd = (char*)dst + rSize;
1370
+
1371
+ /* Stay on the same stage until we are finished streaming the block. */
1372
+ if (dctx->expected > 0) {
1373
+ return rSize;
1374
+ }
1375
+
1376
+ if (dctx->stage == ZSTDds_decompressLastBlock) { /* end of frame */
1377
+ DEBUGLOG(4, "ZSTD_decompressContinue: decoded size from frame : %u", (unsigned)dctx->decodedSize);
1378
+ RETURN_ERROR_IF(
1379
+ dctx->fParams.frameContentSize != ZSTD_CONTENTSIZE_UNKNOWN
1380
+ && dctx->decodedSize != dctx->fParams.frameContentSize,
1381
+ corruption_detected, "");
1382
+ if (dctx->fParams.checksumFlag) { /* another round for frame checksum */
1383
+ dctx->expected = 4;
1384
+ dctx->stage = ZSTDds_checkChecksum;
1385
+ } else {
1386
+ ZSTD_DCtx_trace_end(dctx, dctx->decodedSize, dctx->processedCSize, /* streaming */ 1);
1387
+ dctx->expected = 0; /* ends here */
1388
+ dctx->stage = ZSTDds_getFrameHeaderSize;
1389
+ }
1390
+ } else {
1391
+ dctx->stage = ZSTDds_decodeBlockHeader;
1392
+ dctx->expected = ZSTD_blockHeaderSize;
1393
+ }
1394
+ return rSize;
1395
+ }
1396
+
1397
+ case ZSTDds_checkChecksum:
1398
+ assert(srcSize == 4); /* guaranteed by dctx->expected */
1399
+ {
1400
+ if (dctx->validateChecksum) {
1401
+ U32 const h32 = (U32)XXH64_digest(&dctx->xxhState);
1402
+ U32 const check32 = MEM_readLE32(src);
1403
+ DEBUGLOG(4, "ZSTD_decompressContinue: checksum : calculated %08X :: %08X read", (unsigned)h32, (unsigned)check32);
1404
+ RETURN_ERROR_IF(check32 != h32, checksum_wrong, "");
1405
+ }
1406
+ ZSTD_DCtx_trace_end(dctx, dctx->decodedSize, dctx->processedCSize, /* streaming */ 1);
1407
+ dctx->expected = 0;
1408
+ dctx->stage = ZSTDds_getFrameHeaderSize;
1409
+ return 0;
1410
+ }
1411
+
1412
+ case ZSTDds_decodeSkippableHeader:
1413
+ assert(src != NULL);
1414
+ assert(srcSize <= ZSTD_SKIPPABLEHEADERSIZE);
1415
+ assert(dctx->format != ZSTD_f_zstd1_magicless);
1416
+ ZSTD_memcpy(dctx->headerBuffer + (ZSTD_SKIPPABLEHEADERSIZE - srcSize), src, srcSize); /* complete skippable header */
1417
+ dctx->expected = MEM_readLE32(dctx->headerBuffer + ZSTD_FRAMEIDSIZE); /* note : dctx->expected can grow seriously large, beyond local buffer size */
1418
+ dctx->stage = ZSTDds_skipFrame;
1419
+ return 0;
1420
+
1421
+ case ZSTDds_skipFrame:
1422
+ dctx->expected = 0;
1423
+ dctx->stage = ZSTDds_getFrameHeaderSize;
1424
+ return 0;
1425
+
1426
+ default:
1427
+ assert(0); /* impossible */
1428
+ RETURN_ERROR(GENERIC, "impossible to reach"); /* some compilers require default to do something */
1429
+ }
1430
+ }
1431
+
1432
+
1433
+ static size_t ZSTD_refDictContent(ZSTD_DCtx* dctx, const void* dict, size_t dictSize)
1434
+ {
1435
+ dctx->dictEnd = dctx->previousDstEnd;
1436
+ dctx->virtualStart = (const char*)dict - ((const char*)(dctx->previousDstEnd) - (const char*)(dctx->prefixStart));
1437
+ dctx->prefixStart = dict;
1438
+ dctx->previousDstEnd = (const char*)dict + dictSize;
1439
+ #ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
1440
+ dctx->dictContentBeginForFuzzing = dctx->prefixStart;
1441
+ dctx->dictContentEndForFuzzing = dctx->previousDstEnd;
1442
+ #endif
1443
+ return 0;
1444
+ }
1445
+
1446
+ /*! ZSTD_loadDEntropy() :
1447
+ * dict : must point at beginning of a valid zstd dictionary.
1448
+ * @return : size of entropy tables read */
1449
+ size_t
1450
+ ZSTD_loadDEntropy(ZSTD_entropyDTables_t* entropy,
1451
+ const void* const dict, size_t const dictSize)
1452
+ {
1453
+ const BYTE* dictPtr = (const BYTE*)dict;
1454
+ const BYTE* const dictEnd = dictPtr + dictSize;
1455
+
1456
+ RETURN_ERROR_IF(dictSize <= 8, dictionary_corrupted, "dict is too small");
1457
+ assert(MEM_readLE32(dict) == ZSTD_MAGIC_DICTIONARY); /* dict must be valid */
1458
+ dictPtr += 8; /* skip header = magic + dictID */
1459
+
1460
+ ZSTD_STATIC_ASSERT(offsetof(ZSTD_entropyDTables_t, OFTable) == offsetof(ZSTD_entropyDTables_t, LLTable) + sizeof(entropy->LLTable));
1461
+ ZSTD_STATIC_ASSERT(offsetof(ZSTD_entropyDTables_t, MLTable) == offsetof(ZSTD_entropyDTables_t, OFTable) + sizeof(entropy->OFTable));
1462
+ ZSTD_STATIC_ASSERT(sizeof(entropy->LLTable) + sizeof(entropy->OFTable) + sizeof(entropy->MLTable) >= HUF_DECOMPRESS_WORKSPACE_SIZE);
1463
+ { void* const workspace = &entropy->LLTable; /* use fse tables as temporary workspace; implies fse tables are grouped together */
1464
+ size_t const workspaceSize = sizeof(entropy->LLTable) + sizeof(entropy->OFTable) + sizeof(entropy->MLTable);
1465
+ #ifdef HUF_FORCE_DECOMPRESS_X1
1466
+ /* in minimal huffman, we always use X1 variants */
1467
+ size_t const hSize = HUF_readDTableX1_wksp(entropy->hufTable,
1468
+ dictPtr, dictEnd - dictPtr,
1469
+ workspace, workspaceSize, /* flags */ 0);
1470
+ #else
1471
+ size_t const hSize = HUF_readDTableX2_wksp(entropy->hufTable,
1472
+ dictPtr, (size_t)(dictEnd - dictPtr),
1473
+ workspace, workspaceSize, /* flags */ 0);
1474
+ #endif
1475
+ RETURN_ERROR_IF(HUF_isError(hSize), dictionary_corrupted, "");
1476
+ dictPtr += hSize;
1477
+ }
1478
+
1479
+ { short offcodeNCount[MaxOff+1];
1480
+ unsigned offcodeMaxValue = MaxOff, offcodeLog;
1481
+ size_t const offcodeHeaderSize = FSE_readNCount(offcodeNCount, &offcodeMaxValue, &offcodeLog, dictPtr, (size_t)(dictEnd-dictPtr));
1482
+ RETURN_ERROR_IF(FSE_isError(offcodeHeaderSize), dictionary_corrupted, "");
1483
+ RETURN_ERROR_IF(offcodeMaxValue > MaxOff, dictionary_corrupted, "");
1484
+ RETURN_ERROR_IF(offcodeLog > OffFSELog, dictionary_corrupted, "");
1485
+ ZSTD_buildFSETable( entropy->OFTable,
1486
+ offcodeNCount, offcodeMaxValue,
1487
+ OF_base, OF_bits,
1488
+ offcodeLog,
1489
+ entropy->workspace, sizeof(entropy->workspace),
1490
+ /* bmi2 */0);
1491
+ dictPtr += offcodeHeaderSize;
1492
+ }
1493
+
1494
+ { short matchlengthNCount[MaxML+1];
1495
+ unsigned matchlengthMaxValue = MaxML, matchlengthLog;
1496
+ size_t const matchlengthHeaderSize = FSE_readNCount(matchlengthNCount, &matchlengthMaxValue, &matchlengthLog, dictPtr, (size_t)(dictEnd-dictPtr));
1497
+ RETURN_ERROR_IF(FSE_isError(matchlengthHeaderSize), dictionary_corrupted, "");
1498
+ RETURN_ERROR_IF(matchlengthMaxValue > MaxML, dictionary_corrupted, "");
1499
+ RETURN_ERROR_IF(matchlengthLog > MLFSELog, dictionary_corrupted, "");
1500
+ ZSTD_buildFSETable( entropy->MLTable,
1501
+ matchlengthNCount, matchlengthMaxValue,
1502
+ ML_base, ML_bits,
1503
+ matchlengthLog,
1504
+ entropy->workspace, sizeof(entropy->workspace),
1505
+ /* bmi2 */ 0);
1506
+ dictPtr += matchlengthHeaderSize;
1507
+ }
1508
+
1509
+ { short litlengthNCount[MaxLL+1];
1510
+ unsigned litlengthMaxValue = MaxLL, litlengthLog;
1511
+ size_t const litlengthHeaderSize = FSE_readNCount(litlengthNCount, &litlengthMaxValue, &litlengthLog, dictPtr, (size_t)(dictEnd-dictPtr));
1512
+ RETURN_ERROR_IF(FSE_isError(litlengthHeaderSize), dictionary_corrupted, "");
1513
+ RETURN_ERROR_IF(litlengthMaxValue > MaxLL, dictionary_corrupted, "");
1514
+ RETURN_ERROR_IF(litlengthLog > LLFSELog, dictionary_corrupted, "");
1515
+ ZSTD_buildFSETable( entropy->LLTable,
1516
+ litlengthNCount, litlengthMaxValue,
1517
+ LL_base, LL_bits,
1518
+ litlengthLog,
1519
+ entropy->workspace, sizeof(entropy->workspace),
1520
+ /* bmi2 */ 0);
1521
+ dictPtr += litlengthHeaderSize;
1522
+ }
1523
+
1524
+ RETURN_ERROR_IF(dictPtr+12 > dictEnd, dictionary_corrupted, "");
1525
+ { int i;
1526
+ size_t const dictContentSize = (size_t)(dictEnd - (dictPtr+12));
1527
+ for (i=0; i<3; i++) {
1528
+ U32 const rep = MEM_readLE32(dictPtr); dictPtr += 4;
1529
+ RETURN_ERROR_IF(rep==0 || rep > dictContentSize,
1530
+ dictionary_corrupted, "");
1531
+ entropy->rep[i] = rep;
1532
+ } }
1533
+
1534
+ return (size_t)(dictPtr - (const BYTE*)dict);
1535
+ }
1536
+
1537
+ static size_t ZSTD_decompress_insertDictionary(ZSTD_DCtx* dctx, const void* dict, size_t dictSize)
1538
+ {
1539
+ if (dictSize < 8) return ZSTD_refDictContent(dctx, dict, dictSize);
1540
+ { U32 const magic = MEM_readLE32(dict);
1541
+ if (magic != ZSTD_MAGIC_DICTIONARY) {
1542
+ return ZSTD_refDictContent(dctx, dict, dictSize); /* pure content mode */
1543
+ } }
1544
+ dctx->dictID = MEM_readLE32((const char*)dict + ZSTD_FRAMEIDSIZE);
1545
+
1546
+ /* load entropy tables */
1547
+ { size_t const eSize = ZSTD_loadDEntropy(&dctx->entropy, dict, dictSize);
1548
+ RETURN_ERROR_IF(ZSTD_isError(eSize), dictionary_corrupted, "");
1549
+ dict = (const char*)dict + eSize;
1550
+ dictSize -= eSize;
1551
+ }
1552
+ dctx->litEntropy = dctx->fseEntropy = 1;
1553
+
1554
+ /* reference dictionary content */
1555
+ return ZSTD_refDictContent(dctx, dict, dictSize);
1556
+ }
1557
+
1558
+ size_t ZSTD_decompressBegin(ZSTD_DCtx* dctx)
1559
+ {
1560
+ assert(dctx != NULL);
1561
+ #if ZSTD_TRACE
1562
+ dctx->traceCtx = (ZSTD_trace_decompress_begin != NULL) ? ZSTD_trace_decompress_begin(dctx) : 0;
1563
+ #endif
1564
+ dctx->expected = ZSTD_startingInputLength(dctx->format); /* dctx->format must be properly set */
1565
+ dctx->stage = ZSTDds_getFrameHeaderSize;
1566
+ dctx->processedCSize = 0;
1567
+ dctx->decodedSize = 0;
1568
+ dctx->previousDstEnd = NULL;
1569
+ dctx->prefixStart = NULL;
1570
+ dctx->virtualStart = NULL;
1571
+ dctx->dictEnd = NULL;
1572
+ dctx->entropy.hufTable[0] = (HUF_DTable)((ZSTD_HUFFDTABLE_CAPACITY_LOG)*0x1000001); /* cover both little and big endian */
1573
+ dctx->litEntropy = dctx->fseEntropy = 0;
1574
+ dctx->dictID = 0;
1575
+ dctx->bType = bt_reserved;
1576
+ dctx->isFrameDecompression = 1;
1577
+ ZSTD_STATIC_ASSERT(sizeof(dctx->entropy.rep) == sizeof(repStartValue));
1578
+ ZSTD_memcpy(dctx->entropy.rep, repStartValue, sizeof(repStartValue)); /* initial repcodes */
1579
+ dctx->LLTptr = dctx->entropy.LLTable;
1580
+ dctx->MLTptr = dctx->entropy.MLTable;
1581
+ dctx->OFTptr = dctx->entropy.OFTable;
1582
+ dctx->HUFptr = dctx->entropy.hufTable;
1583
+ return 0;
1584
+ }
1585
+
1586
+ size_t ZSTD_decompressBegin_usingDict(ZSTD_DCtx* dctx, const void* dict, size_t dictSize)
1587
+ {
1588
+ FORWARD_IF_ERROR( ZSTD_decompressBegin(dctx) , "");
1589
+ if (dict && dictSize)
1590
+ RETURN_ERROR_IF(
1591
+ ZSTD_isError(ZSTD_decompress_insertDictionary(dctx, dict, dictSize)),
1592
+ dictionary_corrupted, "");
1593
+ return 0;
1594
+ }
1595
+
1596
+
1597
+ /* ====== ZSTD_DDict ====== */
1598
+
1599
+ size_t ZSTD_decompressBegin_usingDDict(ZSTD_DCtx* dctx, const ZSTD_DDict* ddict)
1600
+ {
1601
+ DEBUGLOG(4, "ZSTD_decompressBegin_usingDDict");
1602
+ assert(dctx != NULL);
1603
+ if (ddict) {
1604
+ const char* const dictStart = (const char*)ZSTD_DDict_dictContent(ddict);
1605
+ size_t const dictSize = ZSTD_DDict_dictSize(ddict);
1606
+ const void* const dictEnd = dictStart + dictSize;
1607
+ dctx->ddictIsCold = (dctx->dictEnd != dictEnd);
1608
+ DEBUGLOG(4, "DDict is %s",
1609
+ dctx->ddictIsCold ? "~cold~" : "hot!");
1610
+ }
1611
+ FORWARD_IF_ERROR( ZSTD_decompressBegin(dctx) , "");
1612
+ if (ddict) { /* NULL ddict is equivalent to no dictionary */
1613
+ ZSTD_copyDDictParameters(dctx, ddict);
1614
+ }
1615
+ return 0;
1616
+ }
1617
+
1618
+ /*! ZSTD_getDictID_fromDict() :
1619
+ * Provides the dictID stored within dictionary.
1620
+ * if @return == 0, the dictionary is not conformant with Zstandard specification.
1621
+ * It can still be loaded, but as a content-only dictionary. */
1622
+ unsigned ZSTD_getDictID_fromDict(const void* dict, size_t dictSize)
1623
+ {
1624
+ if (dictSize < 8) return 0;
1625
+ if (MEM_readLE32(dict) != ZSTD_MAGIC_DICTIONARY) return 0;
1626
+ return MEM_readLE32((const char*)dict + ZSTD_FRAMEIDSIZE);
1627
+ }
1628
+
1629
+ /*! ZSTD_getDictID_fromFrame() :
1630
+ * Provides the dictID required to decompress frame stored within `src`.
1631
+ * If @return == 0, the dictID could not be decoded.
1632
+ * This could for one of the following reasons :
1633
+ * - The frame does not require a dictionary (most common case).
1634
+ * - The frame was built with dictID intentionally removed.
1635
+ * Needed dictionary is a hidden piece of information.
1636
+ * Note : this use case also happens when using a non-conformant dictionary.
1637
+ * - `srcSize` is too small, and as a result, frame header could not be decoded.
1638
+ * Note : possible if `srcSize < ZSTD_FRAMEHEADERSIZE_MAX`.
1639
+ * - This is not a Zstandard frame.
1640
+ * When identifying the exact failure cause, it's possible to use
1641
+ * ZSTD_getFrameHeader(), which will provide a more precise error code. */
1642
+ unsigned ZSTD_getDictID_fromFrame(const void* src, size_t srcSize)
1643
+ {
1644
+ ZSTD_frameHeader zfp = { 0, 0, 0, ZSTD_frame, 0, 0, 0, 0, 0 };
1645
+ size_t const hError = ZSTD_getFrameHeader(&zfp, src, srcSize);
1646
+ if (ZSTD_isError(hError)) return 0;
1647
+ return zfp.dictID;
1648
+ }
1649
+
1650
+
1651
+ /*! ZSTD_decompress_usingDDict() :
1652
+ * Decompression using a pre-digested Dictionary
1653
+ * Use dictionary without significant overhead. */
1654
+ size_t ZSTD_decompress_usingDDict(ZSTD_DCtx* dctx,
1655
+ void* dst, size_t dstCapacity,
1656
+ const void* src, size_t srcSize,
1657
+ const ZSTD_DDict* ddict)
1658
+ {
1659
+ /* pass content and size in case legacy frames are encountered */
1660
+ return ZSTD_decompressMultiFrame(dctx, dst, dstCapacity, src, srcSize,
1661
+ NULL, 0,
1662
+ ddict);
1663
+ }
1664
+
1665
+
1666
+ /*=====================================
1667
+ * Streaming decompression
1668
+ *====================================*/
1669
+
1670
+ ZSTD_DStream* ZSTD_createDStream(void)
1671
+ {
1672
+ DEBUGLOG(3, "ZSTD_createDStream");
1673
+ return ZSTD_createDCtx_internal(ZSTD_defaultCMem);
1674
+ }
1675
+
1676
+ ZSTD_DStream* ZSTD_initStaticDStream(void *workspace, size_t workspaceSize)
1677
+ {
1678
+ return ZSTD_initStaticDCtx(workspace, workspaceSize);
1679
+ }
1680
+
1681
+ ZSTD_DStream* ZSTD_createDStream_advanced(ZSTD_customMem customMem)
1682
+ {
1683
+ return ZSTD_createDCtx_internal(customMem);
1684
+ }
1685
+
1686
+ size_t ZSTD_freeDStream(ZSTD_DStream* zds)
1687
+ {
1688
+ return ZSTD_freeDCtx(zds);
1689
+ }
1690
+
1691
+
1692
+ /* *** Initialization *** */
1693
+
1694
+ size_t ZSTD_DStreamInSize(void) { return ZSTD_BLOCKSIZE_MAX + ZSTD_blockHeaderSize; }
1695
+ size_t ZSTD_DStreamOutSize(void) { return ZSTD_BLOCKSIZE_MAX; }
1696
+
1697
+ size_t ZSTD_DCtx_loadDictionary_advanced(ZSTD_DCtx* dctx,
1698
+ const void* dict, size_t dictSize,
1699
+ ZSTD_dictLoadMethod_e dictLoadMethod,
1700
+ ZSTD_dictContentType_e dictContentType)
1701
+ {
1702
+ RETURN_ERROR_IF(dctx->streamStage != zdss_init, stage_wrong, "");
1703
+ ZSTD_clearDict(dctx);
1704
+ if (dict && dictSize != 0) {
1705
+ dctx->ddictLocal = ZSTD_createDDict_advanced(dict, dictSize, dictLoadMethod, dictContentType, dctx->customMem);
1706
+ RETURN_ERROR_IF(dctx->ddictLocal == NULL, memory_allocation, "NULL pointer!");
1707
+ dctx->ddict = dctx->ddictLocal;
1708
+ dctx->dictUses = ZSTD_use_indefinitely;
1709
+ }
1710
+ return 0;
1711
+ }
1712
+
1713
+ size_t ZSTD_DCtx_loadDictionary_byReference(ZSTD_DCtx* dctx, const void* dict, size_t dictSize)
1714
+ {
1715
+ return ZSTD_DCtx_loadDictionary_advanced(dctx, dict, dictSize, ZSTD_dlm_byRef, ZSTD_dct_auto);
1716
+ }
1717
+
1718
+ size_t ZSTD_DCtx_loadDictionary(ZSTD_DCtx* dctx, const void* dict, size_t dictSize)
1719
+ {
1720
+ return ZSTD_DCtx_loadDictionary_advanced(dctx, dict, dictSize, ZSTD_dlm_byCopy, ZSTD_dct_auto);
1721
+ }
1722
+
1723
+ size_t ZSTD_DCtx_refPrefix_advanced(ZSTD_DCtx* dctx, const void* prefix, size_t prefixSize, ZSTD_dictContentType_e dictContentType)
1724
+ {
1725
+ FORWARD_IF_ERROR(ZSTD_DCtx_loadDictionary_advanced(dctx, prefix, prefixSize, ZSTD_dlm_byRef, dictContentType), "");
1726
+ dctx->dictUses = ZSTD_use_once;
1727
+ return 0;
1728
+ }
1729
+
1730
+ size_t ZSTD_DCtx_refPrefix(ZSTD_DCtx* dctx, const void* prefix, size_t prefixSize)
1731
+ {
1732
+ return ZSTD_DCtx_refPrefix_advanced(dctx, prefix, prefixSize, ZSTD_dct_rawContent);
1733
+ }
1734
+
1735
+
1736
+ /* ZSTD_initDStream_usingDict() :
1737
+ * return : expected size, aka ZSTD_startingInputLength().
1738
+ * this function cannot fail */
1739
+ size_t ZSTD_initDStream_usingDict(ZSTD_DStream* zds, const void* dict, size_t dictSize)
1740
+ {
1741
+ DEBUGLOG(4, "ZSTD_initDStream_usingDict");
1742
+ FORWARD_IF_ERROR( ZSTD_DCtx_reset(zds, ZSTD_reset_session_only) , "");
1743
+ FORWARD_IF_ERROR( ZSTD_DCtx_loadDictionary(zds, dict, dictSize) , "");
1744
+ return ZSTD_startingInputLength(zds->format);
1745
+ }
1746
+
1747
+ /* note : this variant can't fail */
1748
+ size_t ZSTD_initDStream(ZSTD_DStream* zds)
1749
+ {
1750
+ DEBUGLOG(4, "ZSTD_initDStream");
1751
+ FORWARD_IF_ERROR(ZSTD_DCtx_reset(zds, ZSTD_reset_session_only), "");
1752
+ FORWARD_IF_ERROR(ZSTD_DCtx_refDDict(zds, NULL), "");
1753
+ return ZSTD_startingInputLength(zds->format);
1754
+ }
1755
+
1756
+ /* ZSTD_initDStream_usingDDict() :
1757
+ * ddict will just be referenced, and must outlive decompression session
1758
+ * this function cannot fail */
1759
+ size_t ZSTD_initDStream_usingDDict(ZSTD_DStream* dctx, const ZSTD_DDict* ddict)
1760
+ {
1761
+ DEBUGLOG(4, "ZSTD_initDStream_usingDDict");
1762
+ FORWARD_IF_ERROR( ZSTD_DCtx_reset(dctx, ZSTD_reset_session_only) , "");
1763
+ FORWARD_IF_ERROR( ZSTD_DCtx_refDDict(dctx, ddict) , "");
1764
+ return ZSTD_startingInputLength(dctx->format);
1765
+ }
1766
+
1767
+ /* ZSTD_resetDStream() :
1768
+ * return : expected size, aka ZSTD_startingInputLength().
1769
+ * this function cannot fail */
1770
+ size_t ZSTD_resetDStream(ZSTD_DStream* dctx)
1771
+ {
1772
+ DEBUGLOG(4, "ZSTD_resetDStream");
1773
+ FORWARD_IF_ERROR(ZSTD_DCtx_reset(dctx, ZSTD_reset_session_only), "");
1774
+ return ZSTD_startingInputLength(dctx->format);
1775
+ }
1776
+
1777
+
1778
+ size_t ZSTD_DCtx_refDDict(ZSTD_DCtx* dctx, const ZSTD_DDict* ddict)
1779
+ {
1780
+ RETURN_ERROR_IF(dctx->streamStage != zdss_init, stage_wrong, "");
1781
+ ZSTD_clearDict(dctx);
1782
+ if (ddict) {
1783
+ dctx->ddict = ddict;
1784
+ dctx->dictUses = ZSTD_use_indefinitely;
1785
+ if (dctx->refMultipleDDicts == ZSTD_rmd_refMultipleDDicts) {
1786
+ if (dctx->ddictSet == NULL) {
1787
+ dctx->ddictSet = ZSTD_createDDictHashSet(dctx->customMem);
1788
+ if (!dctx->ddictSet) {
1789
+ RETURN_ERROR(memory_allocation, "Failed to allocate memory for hash set!");
1790
+ }
1791
+ }
1792
+ assert(!dctx->staticSize); /* Impossible: ddictSet cannot have been allocated if static dctx */
1793
+ FORWARD_IF_ERROR(ZSTD_DDictHashSet_addDDict(dctx->ddictSet, ddict, dctx->customMem), "");
1794
+ }
1795
+ }
1796
+ return 0;
1797
+ }
1798
+
1799
+ /* ZSTD_DCtx_setMaxWindowSize() :
1800
+ * note : no direct equivalence in ZSTD_DCtx_setParameter,
1801
+ * since this version sets windowSize, and the other sets windowLog */
1802
+ size_t ZSTD_DCtx_setMaxWindowSize(ZSTD_DCtx* dctx, size_t maxWindowSize)
1803
+ {
1804
+ ZSTD_bounds const bounds = ZSTD_dParam_getBounds(ZSTD_d_windowLogMax);
1805
+ size_t const min = (size_t)1 << bounds.lowerBound;
1806
+ size_t const max = (size_t)1 << bounds.upperBound;
1807
+ RETURN_ERROR_IF(dctx->streamStage != zdss_init, stage_wrong, "");
1808
+ RETURN_ERROR_IF(maxWindowSize < min, parameter_outOfBound, "");
1809
+ RETURN_ERROR_IF(maxWindowSize > max, parameter_outOfBound, "");
1810
+ dctx->maxWindowSize = maxWindowSize;
1811
+ return 0;
1812
+ }
1813
+
1814
+ size_t ZSTD_DCtx_setFormat(ZSTD_DCtx* dctx, ZSTD_format_e format)
1815
+ {
1816
+ return ZSTD_DCtx_setParameter(dctx, ZSTD_d_format, (int)format);
1817
+ }
1818
+
1819
+ ZSTD_bounds ZSTD_dParam_getBounds(ZSTD_dParameter dParam)
1820
+ {
1821
+ ZSTD_bounds bounds = { 0, 0, 0 };
1822
+ switch(dParam) {
1823
+ case ZSTD_d_windowLogMax:
1824
+ bounds.lowerBound = ZSTD_WINDOWLOG_ABSOLUTEMIN;
1825
+ bounds.upperBound = ZSTD_WINDOWLOG_MAX;
1826
+ return bounds;
1827
+ case ZSTD_d_format:
1828
+ bounds.lowerBound = (int)ZSTD_f_zstd1;
1829
+ bounds.upperBound = (int)ZSTD_f_zstd1_magicless;
1830
+ ZSTD_STATIC_ASSERT(ZSTD_f_zstd1 < ZSTD_f_zstd1_magicless);
1831
+ return bounds;
1832
+ case ZSTD_d_stableOutBuffer:
1833
+ bounds.lowerBound = (int)ZSTD_bm_buffered;
1834
+ bounds.upperBound = (int)ZSTD_bm_stable;
1835
+ return bounds;
1836
+ case ZSTD_d_forceIgnoreChecksum:
1837
+ bounds.lowerBound = (int)ZSTD_d_validateChecksum;
1838
+ bounds.upperBound = (int)ZSTD_d_ignoreChecksum;
1839
+ return bounds;
1840
+ case ZSTD_d_refMultipleDDicts:
1841
+ bounds.lowerBound = (int)ZSTD_rmd_refSingleDDict;
1842
+ bounds.upperBound = (int)ZSTD_rmd_refMultipleDDicts;
1843
+ return bounds;
1844
+ case ZSTD_d_disableHuffmanAssembly:
1845
+ bounds.lowerBound = 0;
1846
+ bounds.upperBound = 1;
1847
+ return bounds;
1848
+ case ZSTD_d_maxBlockSize:
1849
+ bounds.lowerBound = ZSTD_BLOCKSIZE_MAX_MIN;
1850
+ bounds.upperBound = ZSTD_BLOCKSIZE_MAX;
1851
+ return bounds;
1852
+
1853
+ default:;
1854
+ }
1855
+ bounds.error = ERROR(parameter_unsupported);
1856
+ return bounds;
1857
+ }
1858
+
1859
+ /* ZSTD_dParam_withinBounds:
1860
+ * @return 1 if value is within dParam bounds,
1861
+ * 0 otherwise */
1862
+ static int ZSTD_dParam_withinBounds(ZSTD_dParameter dParam, int value)
1863
+ {
1864
+ ZSTD_bounds const bounds = ZSTD_dParam_getBounds(dParam);
1865
+ if (ZSTD_isError(bounds.error)) return 0;
1866
+ if (value < bounds.lowerBound) return 0;
1867
+ if (value > bounds.upperBound) return 0;
1868
+ return 1;
1869
+ }
1870
+
1871
+ #define CHECK_DBOUNDS(p,v) { \
1872
+ RETURN_ERROR_IF(!ZSTD_dParam_withinBounds(p, v), parameter_outOfBound, ""); \
1873
+ }
1874
+
1875
+ size_t ZSTD_DCtx_getParameter(ZSTD_DCtx* dctx, ZSTD_dParameter param, int* value)
1876
+ {
1877
+ switch (param) {
1878
+ case ZSTD_d_windowLogMax:
1879
+ *value = (int)ZSTD_highbit32((U32)dctx->maxWindowSize);
1880
+ return 0;
1881
+ case ZSTD_d_format:
1882
+ *value = (int)dctx->format;
1883
+ return 0;
1884
+ case ZSTD_d_stableOutBuffer:
1885
+ *value = (int)dctx->outBufferMode;
1886
+ return 0;
1887
+ case ZSTD_d_forceIgnoreChecksum:
1888
+ *value = (int)dctx->forceIgnoreChecksum;
1889
+ return 0;
1890
+ case ZSTD_d_refMultipleDDicts:
1891
+ *value = (int)dctx->refMultipleDDicts;
1892
+ return 0;
1893
+ case ZSTD_d_disableHuffmanAssembly:
1894
+ *value = (int)dctx->disableHufAsm;
1895
+ return 0;
1896
+ case ZSTD_d_maxBlockSize:
1897
+ *value = dctx->maxBlockSizeParam;
1898
+ return 0;
1899
+ default:;
1900
+ }
1901
+ RETURN_ERROR(parameter_unsupported, "");
1902
+ }
1903
+
1904
+ size_t ZSTD_DCtx_setParameter(ZSTD_DCtx* dctx, ZSTD_dParameter dParam, int value)
1905
+ {
1906
+ RETURN_ERROR_IF(dctx->streamStage != zdss_init, stage_wrong, "");
1907
+ switch(dParam) {
1908
+ case ZSTD_d_windowLogMax:
1909
+ if (value == 0) value = ZSTD_WINDOWLOG_LIMIT_DEFAULT;
1910
+ CHECK_DBOUNDS(ZSTD_d_windowLogMax, value);
1911
+ dctx->maxWindowSize = ((size_t)1) << value;
1912
+ return 0;
1913
+ case ZSTD_d_format:
1914
+ CHECK_DBOUNDS(ZSTD_d_format, value);
1915
+ dctx->format = (ZSTD_format_e)value;
1916
+ return 0;
1917
+ case ZSTD_d_stableOutBuffer:
1918
+ CHECK_DBOUNDS(ZSTD_d_stableOutBuffer, value);
1919
+ dctx->outBufferMode = (ZSTD_bufferMode_e)value;
1920
+ return 0;
1921
+ case ZSTD_d_forceIgnoreChecksum:
1922
+ CHECK_DBOUNDS(ZSTD_d_forceIgnoreChecksum, value);
1923
+ dctx->forceIgnoreChecksum = (ZSTD_forceIgnoreChecksum_e)value;
1924
+ return 0;
1925
+ case ZSTD_d_refMultipleDDicts:
1926
+ CHECK_DBOUNDS(ZSTD_d_refMultipleDDicts, value);
1927
+ if (dctx->staticSize != 0) {
1928
+ RETURN_ERROR(parameter_unsupported, "Static dctx does not support multiple DDicts!");
1929
+ }
1930
+ dctx->refMultipleDDicts = (ZSTD_refMultipleDDicts_e)value;
1931
+ return 0;
1932
+ case ZSTD_d_disableHuffmanAssembly:
1933
+ CHECK_DBOUNDS(ZSTD_d_disableHuffmanAssembly, value);
1934
+ dctx->disableHufAsm = value != 0;
1935
+ return 0;
1936
+ case ZSTD_d_maxBlockSize:
1937
+ if (value != 0) CHECK_DBOUNDS(ZSTD_d_maxBlockSize, value);
1938
+ dctx->maxBlockSizeParam = value;
1939
+ return 0;
1940
+ default:;
1941
+ }
1942
+ RETURN_ERROR(parameter_unsupported, "");
1943
+ }
1944
+
1945
+ size_t ZSTD_DCtx_reset(ZSTD_DCtx* dctx, ZSTD_ResetDirective reset)
1946
+ {
1947
+ if ( (reset == ZSTD_reset_session_only)
1948
+ || (reset == ZSTD_reset_session_and_parameters) ) {
1949
+ dctx->streamStage = zdss_init;
1950
+ dctx->noForwardProgress = 0;
1951
+ dctx->isFrameDecompression = 1;
1952
+ }
1953
+ if ( (reset == ZSTD_reset_parameters)
1954
+ || (reset == ZSTD_reset_session_and_parameters) ) {
1955
+ RETURN_ERROR_IF(dctx->streamStage != zdss_init, stage_wrong, "");
1956
+ ZSTD_clearDict(dctx);
1957
+ ZSTD_DCtx_resetParameters(dctx);
1958
+ }
1959
+ return 0;
1960
+ }
1961
+
1962
+
1963
+ size_t ZSTD_sizeof_DStream(const ZSTD_DStream* dctx)
1964
+ {
1965
+ return ZSTD_sizeof_DCtx(dctx);
1966
+ }
1967
+
1968
+ static size_t ZSTD_decodingBufferSize_internal(unsigned long long windowSize, unsigned long long frameContentSize, size_t blockSizeMax)
1969
+ {
1970
+ size_t const blockSize = MIN((size_t)MIN(windowSize, ZSTD_BLOCKSIZE_MAX), blockSizeMax);
1971
+ /* We need blockSize + WILDCOPY_OVERLENGTH worth of buffer so that if a block
1972
+ * ends at windowSize + WILDCOPY_OVERLENGTH + 1 bytes, we can start writing
1973
+ * the block at the beginning of the output buffer, and maintain a full window.
1974
+ *
1975
+ * We need another blockSize worth of buffer so that we can store split
1976
+ * literals at the end of the block without overwriting the extDict window.
1977
+ */
1978
+ unsigned long long const neededRBSize = windowSize + (blockSize * 2) + (WILDCOPY_OVERLENGTH * 2);
1979
+ unsigned long long const neededSize = MIN(frameContentSize, neededRBSize);
1980
+ size_t const minRBSize = (size_t) neededSize;
1981
+ RETURN_ERROR_IF((unsigned long long)minRBSize != neededSize,
1982
+ frameParameter_windowTooLarge, "");
1983
+ return minRBSize;
1984
+ }
1985
+
1986
+ size_t ZSTD_decodingBufferSize_min(unsigned long long windowSize, unsigned long long frameContentSize)
1987
+ {
1988
+ return ZSTD_decodingBufferSize_internal(windowSize, frameContentSize, ZSTD_BLOCKSIZE_MAX);
1989
+ }
1990
+
1991
+ size_t ZSTD_estimateDStreamSize(size_t windowSize)
1992
+ {
1993
+ size_t const blockSize = MIN(windowSize, ZSTD_BLOCKSIZE_MAX);
1994
+ size_t const inBuffSize = blockSize; /* no block can be larger */
1995
+ size_t const outBuffSize = ZSTD_decodingBufferSize_min(windowSize, ZSTD_CONTENTSIZE_UNKNOWN);
1996
+ return ZSTD_estimateDCtxSize() + inBuffSize + outBuffSize;
1997
+ }
1998
+
1999
+ size_t ZSTD_estimateDStreamSize_fromFrame(const void* src, size_t srcSize)
2000
+ {
2001
+ U32 const windowSizeMax = 1U << ZSTD_WINDOWLOG_MAX; /* note : should be user-selectable, but requires an additional parameter (or a dctx) */
2002
+ ZSTD_frameHeader zfh;
2003
+ size_t const err = ZSTD_getFrameHeader(&zfh, src, srcSize);
2004
+ if (ZSTD_isError(err)) return err;
2005
+ RETURN_ERROR_IF(err>0, srcSize_wrong, "");
2006
+ RETURN_ERROR_IF(zfh.windowSize > windowSizeMax,
2007
+ frameParameter_windowTooLarge, "");
2008
+ return ZSTD_estimateDStreamSize((size_t)zfh.windowSize);
2009
+ }
2010
+
2011
+
2012
+ /* ***** Decompression ***** */
2013
+
2014
+ static int ZSTD_DCtx_isOverflow(ZSTD_DStream* zds, size_t const neededInBuffSize, size_t const neededOutBuffSize)
2015
+ {
2016
+ return (zds->inBuffSize + zds->outBuffSize) >= (neededInBuffSize + neededOutBuffSize) * ZSTD_WORKSPACETOOLARGE_FACTOR;
2017
+ }
2018
+
2019
+ static void ZSTD_DCtx_updateOversizedDuration(ZSTD_DStream* zds, size_t const neededInBuffSize, size_t const neededOutBuffSize)
2020
+ {
2021
+ if (ZSTD_DCtx_isOverflow(zds, neededInBuffSize, neededOutBuffSize))
2022
+ zds->oversizedDuration++;
2023
+ else
2024
+ zds->oversizedDuration = 0;
2025
+ }
2026
+
2027
+ static int ZSTD_DCtx_isOversizedTooLong(ZSTD_DStream* zds)
2028
+ {
2029
+ return zds->oversizedDuration >= ZSTD_WORKSPACETOOLARGE_MAXDURATION;
2030
+ }
2031
+
2032
+ /* Checks that the output buffer hasn't changed if ZSTD_obm_stable is used. */
2033
+ static size_t ZSTD_checkOutBuffer(ZSTD_DStream const* zds, ZSTD_outBuffer const* output)
2034
+ {
2035
+ ZSTD_outBuffer const expect = zds->expectedOutBuffer;
2036
+ /* No requirement when ZSTD_obm_stable is not enabled. */
2037
+ if (zds->outBufferMode != ZSTD_bm_stable)
2038
+ return 0;
2039
+ /* Any buffer is allowed in zdss_init, this must be the same for every other call until
2040
+ * the context is reset.
2041
+ */
2042
+ if (zds->streamStage == zdss_init)
2043
+ return 0;
2044
+ /* The buffer must match our expectation exactly. */
2045
+ if (expect.dst == output->dst && expect.pos == output->pos && expect.size == output->size)
2046
+ return 0;
2047
+ RETURN_ERROR(dstBuffer_wrong, "ZSTD_d_stableOutBuffer enabled but output differs!");
2048
+ }
2049
+
2050
+ /* Calls ZSTD_decompressContinue() with the right parameters for ZSTD_decompressStream()
2051
+ * and updates the stage and the output buffer state. This call is extracted so it can be
2052
+ * used both when reading directly from the ZSTD_inBuffer, and in buffered input mode.
2053
+ * NOTE: You must break after calling this function since the streamStage is modified.
2054
+ */
2055
+ static size_t ZSTD_decompressContinueStream(
2056
+ ZSTD_DStream* zds, char** op, char* oend,
2057
+ void const* src, size_t srcSize) {
2058
+ int const isSkipFrame = ZSTD_isSkipFrame(zds);
2059
+ if (zds->outBufferMode == ZSTD_bm_buffered) {
2060
+ size_t const dstSize = isSkipFrame ? 0 : zds->outBuffSize - zds->outStart;
2061
+ size_t const decodedSize = ZSTD_decompressContinue(zds,
2062
+ zds->outBuff + zds->outStart, dstSize, src, srcSize);
2063
+ FORWARD_IF_ERROR(decodedSize, "");
2064
+ if (!decodedSize && !isSkipFrame) {
2065
+ zds->streamStage = zdss_read;
2066
+ } else {
2067
+ zds->outEnd = zds->outStart + decodedSize;
2068
+ zds->streamStage = zdss_flush;
2069
+ }
2070
+ } else {
2071
+ /* Write directly into the output buffer */
2072
+ size_t const dstSize = isSkipFrame ? 0 : (size_t)(oend - *op);
2073
+ size_t const decodedSize = ZSTD_decompressContinue(zds, *op, dstSize, src, srcSize);
2074
+ FORWARD_IF_ERROR(decodedSize, "");
2075
+ *op += decodedSize;
2076
+ /* Flushing is not needed. */
2077
+ zds->streamStage = zdss_read;
2078
+ assert(*op <= oend);
2079
+ assert(zds->outBufferMode == ZSTD_bm_stable);
2080
+ }
2081
+ return 0;
2082
+ }
2083
+
2084
+ size_t ZSTD_decompressStream(ZSTD_DStream* zds, ZSTD_outBuffer* output, ZSTD_inBuffer* input)
2085
+ {
2086
+ const char* const src = (const char*)input->src;
2087
+ const char* const istart = input->pos != 0 ? src + input->pos : src;
2088
+ const char* const iend = input->size != 0 ? src + input->size : src;
2089
+ const char* ip = istart;
2090
+ char* const dst = (char*)output->dst;
2091
+ char* const ostart = output->pos != 0 ? dst + output->pos : dst;
2092
+ char* const oend = output->size != 0 ? dst + output->size : dst;
2093
+ char* op = ostart;
2094
+ U32 someMoreWork = 1;
2095
+
2096
+ DEBUGLOG(5, "ZSTD_decompressStream");
2097
+ RETURN_ERROR_IF(
2098
+ input->pos > input->size,
2099
+ srcSize_wrong,
2100
+ "forbidden. in: pos: %u vs size: %u",
2101
+ (U32)input->pos, (U32)input->size);
2102
+ RETURN_ERROR_IF(
2103
+ output->pos > output->size,
2104
+ dstSize_tooSmall,
2105
+ "forbidden. out: pos: %u vs size: %u",
2106
+ (U32)output->pos, (U32)output->size);
2107
+ DEBUGLOG(5, "input size : %u", (U32)(input->size - input->pos));
2108
+ FORWARD_IF_ERROR(ZSTD_checkOutBuffer(zds, output), "");
2109
+
2110
+ while (someMoreWork) {
2111
+ switch(zds->streamStage)
2112
+ {
2113
+ case zdss_init :
2114
+ DEBUGLOG(5, "stage zdss_init => transparent reset ");
2115
+ zds->streamStage = zdss_loadHeader;
2116
+ zds->lhSize = zds->inPos = zds->outStart = zds->outEnd = 0;
2117
+ #if defined(ZSTD_LEGACY_SUPPORT) && (ZSTD_LEGACY_SUPPORT>=1)
2118
+ zds->legacyVersion = 0;
2119
+ #endif
2120
+ zds->hostageByte = 0;
2121
+ zds->expectedOutBuffer = *output;
2122
+ ZSTD_FALLTHROUGH;
2123
+
2124
+ case zdss_loadHeader :
2125
+ DEBUGLOG(5, "stage zdss_loadHeader (srcSize : %u)", (U32)(iend - ip));
2126
+ #if defined(ZSTD_LEGACY_SUPPORT) && (ZSTD_LEGACY_SUPPORT>=1)
2127
+ if (zds->legacyVersion) {
2128
+ RETURN_ERROR_IF(zds->staticSize, memory_allocation,
2129
+ "legacy support is incompatible with static dctx");
2130
+ { size_t const hint = ZSTD_decompressLegacyStream(zds->legacyContext, zds->legacyVersion, output, input);
2131
+ if (hint==0) zds->streamStage = zdss_init;
2132
+ return hint;
2133
+ } }
2134
+ #endif
2135
+ { size_t const hSize = ZSTD_getFrameHeader_advanced(&zds->fParams, zds->headerBuffer, zds->lhSize, zds->format);
2136
+ if (zds->refMultipleDDicts && zds->ddictSet) {
2137
+ ZSTD_DCtx_selectFrameDDict(zds);
2138
+ }
2139
+ if (ZSTD_isError(hSize)) {
2140
+ #if defined(ZSTD_LEGACY_SUPPORT) && (ZSTD_LEGACY_SUPPORT>=1)
2141
+ U32 const legacyVersion = ZSTD_isLegacy(istart, iend-istart);
2142
+ if (legacyVersion) {
2143
+ ZSTD_DDict const* const ddict = ZSTD_getDDict(zds);
2144
+ const void* const dict = ddict ? ZSTD_DDict_dictContent(ddict) : NULL;
2145
+ size_t const dictSize = ddict ? ZSTD_DDict_dictSize(ddict) : 0;
2146
+ DEBUGLOG(5, "ZSTD_decompressStream: detected legacy version v0.%u", legacyVersion);
2147
+ RETURN_ERROR_IF(zds->staticSize, memory_allocation,
2148
+ "legacy support is incompatible with static dctx");
2149
+ FORWARD_IF_ERROR(ZSTD_initLegacyStream(&zds->legacyContext,
2150
+ zds->previousLegacyVersion, legacyVersion,
2151
+ dict, dictSize), "");
2152
+ zds->legacyVersion = zds->previousLegacyVersion = legacyVersion;
2153
+ { size_t const hint = ZSTD_decompressLegacyStream(zds->legacyContext, legacyVersion, output, input);
2154
+ if (hint==0) zds->streamStage = zdss_init; /* or stay in stage zdss_loadHeader */
2155
+ return hint;
2156
+ } }
2157
+ #endif
2158
+ return hSize; /* error */
2159
+ }
2160
+ if (hSize != 0) { /* need more input */
2161
+ size_t const toLoad = hSize - zds->lhSize; /* if hSize!=0, hSize > zds->lhSize */
2162
+ size_t const remainingInput = (size_t)(iend-ip);
2163
+ assert(iend >= ip);
2164
+ if (toLoad > remainingInput) { /* not enough input to load full header */
2165
+ if (remainingInput > 0) {
2166
+ ZSTD_memcpy(zds->headerBuffer + zds->lhSize, ip, remainingInput);
2167
+ zds->lhSize += remainingInput;
2168
+ }
2169
+ input->pos = input->size;
2170
+ /* check first few bytes */
2171
+ FORWARD_IF_ERROR(
2172
+ ZSTD_getFrameHeader_advanced(&zds->fParams, zds->headerBuffer, zds->lhSize, zds->format),
2173
+ "First few bytes detected incorrect" );
2174
+ /* return hint input size */
2175
+ return (MAX((size_t)ZSTD_FRAMEHEADERSIZE_MIN(zds->format), hSize) - zds->lhSize) + ZSTD_blockHeaderSize; /* remaining header bytes + next block header */
2176
+ }
2177
+ assert(ip != NULL);
2178
+ ZSTD_memcpy(zds->headerBuffer + zds->lhSize, ip, toLoad); zds->lhSize = hSize; ip += toLoad;
2179
+ break;
2180
+ } }
2181
+
2182
+ /* check for single-pass mode opportunity */
2183
+ if (zds->fParams.frameContentSize != ZSTD_CONTENTSIZE_UNKNOWN
2184
+ && zds->fParams.frameType != ZSTD_skippableFrame
2185
+ && (U64)(size_t)(oend-op) >= zds->fParams.frameContentSize) {
2186
+ size_t const cSize = ZSTD_findFrameCompressedSize_advanced(istart, (size_t)(iend-istart), zds->format);
2187
+ if (cSize <= (size_t)(iend-istart)) {
2188
+ /* shortcut : using single-pass mode */
2189
+ size_t const decompressedSize = ZSTD_decompress_usingDDict(zds, op, (size_t)(oend-op), istart, cSize, ZSTD_getDDict(zds));
2190
+ if (ZSTD_isError(decompressedSize)) return decompressedSize;
2191
+ DEBUGLOG(4, "shortcut to single-pass ZSTD_decompress_usingDDict()");
2192
+ assert(istart != NULL);
2193
+ ip = istart + cSize;
2194
+ op = op ? op + decompressedSize : op; /* can occur if frameContentSize = 0 (empty frame) */
2195
+ zds->expected = 0;
2196
+ zds->streamStage = zdss_init;
2197
+ someMoreWork = 0;
2198
+ break;
2199
+ } }
2200
+
2201
+ /* Check output buffer is large enough for ZSTD_odm_stable. */
2202
+ if (zds->outBufferMode == ZSTD_bm_stable
2203
+ && zds->fParams.frameType != ZSTD_skippableFrame
2204
+ && zds->fParams.frameContentSize != ZSTD_CONTENTSIZE_UNKNOWN
2205
+ && (U64)(size_t)(oend-op) < zds->fParams.frameContentSize) {
2206
+ RETURN_ERROR(dstSize_tooSmall, "ZSTD_obm_stable passed but ZSTD_outBuffer is too small");
2207
+ }
2208
+
2209
+ /* Consume header (see ZSTDds_decodeFrameHeader) */
2210
+ DEBUGLOG(4, "Consume header");
2211
+ FORWARD_IF_ERROR(ZSTD_decompressBegin_usingDDict(zds, ZSTD_getDDict(zds)), "");
2212
+
2213
+ if (zds->format == ZSTD_f_zstd1
2214
+ && (MEM_readLE32(zds->headerBuffer) & ZSTD_MAGIC_SKIPPABLE_MASK) == ZSTD_MAGIC_SKIPPABLE_START) { /* skippable frame */
2215
+ zds->expected = MEM_readLE32(zds->headerBuffer + ZSTD_FRAMEIDSIZE);
2216
+ zds->stage = ZSTDds_skipFrame;
2217
+ } else {
2218
+ FORWARD_IF_ERROR(ZSTD_decodeFrameHeader(zds, zds->headerBuffer, zds->lhSize), "");
2219
+ zds->expected = ZSTD_blockHeaderSize;
2220
+ zds->stage = ZSTDds_decodeBlockHeader;
2221
+ }
2222
+
2223
+ /* control buffer memory usage */
2224
+ DEBUGLOG(4, "Control max memory usage (%u KB <= max %u KB)",
2225
+ (U32)(zds->fParams.windowSize >>10),
2226
+ (U32)(zds->maxWindowSize >> 10) );
2227
+ zds->fParams.windowSize = MAX(zds->fParams.windowSize, 1U << ZSTD_WINDOWLOG_ABSOLUTEMIN);
2228
+ RETURN_ERROR_IF(zds->fParams.windowSize > zds->maxWindowSize,
2229
+ frameParameter_windowTooLarge, "");
2230
+ if (zds->maxBlockSizeParam != 0)
2231
+ zds->fParams.blockSizeMax = MIN(zds->fParams.blockSizeMax, (unsigned)zds->maxBlockSizeParam);
2232
+
2233
+ /* Adapt buffer sizes to frame header instructions */
2234
+ { size_t const neededInBuffSize = MAX(zds->fParams.blockSizeMax, 4 /* frame checksum */);
2235
+ size_t const neededOutBuffSize = zds->outBufferMode == ZSTD_bm_buffered
2236
+ ? ZSTD_decodingBufferSize_internal(zds->fParams.windowSize, zds->fParams.frameContentSize, zds->fParams.blockSizeMax)
2237
+ : 0;
2238
+
2239
+ ZSTD_DCtx_updateOversizedDuration(zds, neededInBuffSize, neededOutBuffSize);
2240
+
2241
+ { int const tooSmall = (zds->inBuffSize < neededInBuffSize) || (zds->outBuffSize < neededOutBuffSize);
2242
+ int const tooLarge = ZSTD_DCtx_isOversizedTooLong(zds);
2243
+
2244
+ if (tooSmall || tooLarge) {
2245
+ size_t const bufferSize = neededInBuffSize + neededOutBuffSize;
2246
+ DEBUGLOG(4, "inBuff : from %u to %u",
2247
+ (U32)zds->inBuffSize, (U32)neededInBuffSize);
2248
+ DEBUGLOG(4, "outBuff : from %u to %u",
2249
+ (U32)zds->outBuffSize, (U32)neededOutBuffSize);
2250
+ if (zds->staticSize) { /* static DCtx */
2251
+ DEBUGLOG(4, "staticSize : %u", (U32)zds->staticSize);
2252
+ assert(zds->staticSize >= sizeof(ZSTD_DCtx)); /* controlled at init */
2253
+ RETURN_ERROR_IF(
2254
+ bufferSize > zds->staticSize - sizeof(ZSTD_DCtx),
2255
+ memory_allocation, "");
2256
+ } else {
2257
+ ZSTD_customFree(zds->inBuff, zds->customMem);
2258
+ zds->inBuffSize = 0;
2259
+ zds->outBuffSize = 0;
2260
+ zds->inBuff = (char*)ZSTD_customMalloc(bufferSize, zds->customMem);
2261
+ RETURN_ERROR_IF(zds->inBuff == NULL, memory_allocation, "");
2262
+ }
2263
+ zds->inBuffSize = neededInBuffSize;
2264
+ zds->outBuff = zds->inBuff + zds->inBuffSize;
2265
+ zds->outBuffSize = neededOutBuffSize;
2266
+ } } }
2267
+ zds->streamStage = zdss_read;
2268
+ ZSTD_FALLTHROUGH;
2269
+
2270
+ case zdss_read:
2271
+ DEBUGLOG(5, "stage zdss_read");
2272
+ { size_t const neededInSize = ZSTD_nextSrcSizeToDecompressWithInputSize(zds, (size_t)(iend - ip));
2273
+ DEBUGLOG(5, "neededInSize = %u", (U32)neededInSize);
2274
+ if (neededInSize==0) { /* end of frame */
2275
+ zds->streamStage = zdss_init;
2276
+ someMoreWork = 0;
2277
+ break;
2278
+ }
2279
+ if ((size_t)(iend-ip) >= neededInSize) { /* decode directly from src */
2280
+ FORWARD_IF_ERROR(ZSTD_decompressContinueStream(zds, &op, oend, ip, neededInSize), "");
2281
+ assert(ip != NULL);
2282
+ ip += neededInSize;
2283
+ /* Function modifies the stage so we must break */
2284
+ break;
2285
+ } }
2286
+ if (ip==iend) { someMoreWork = 0; break; } /* no more input */
2287
+ zds->streamStage = zdss_load;
2288
+ ZSTD_FALLTHROUGH;
2289
+
2290
+ case zdss_load:
2291
+ { size_t const neededInSize = ZSTD_nextSrcSizeToDecompress(zds);
2292
+ size_t const toLoad = neededInSize - zds->inPos;
2293
+ int const isSkipFrame = ZSTD_isSkipFrame(zds);
2294
+ size_t loadedSize;
2295
+ /* At this point we shouldn't be decompressing a block that we can stream. */
2296
+ assert(neededInSize == ZSTD_nextSrcSizeToDecompressWithInputSize(zds, (size_t)(iend - ip)));
2297
+ if (isSkipFrame) {
2298
+ loadedSize = MIN(toLoad, (size_t)(iend-ip));
2299
+ } else {
2300
+ RETURN_ERROR_IF(toLoad > zds->inBuffSize - zds->inPos,
2301
+ corruption_detected,
2302
+ "should never happen");
2303
+ loadedSize = ZSTD_limitCopy(zds->inBuff + zds->inPos, toLoad, ip, (size_t)(iend-ip));
2304
+ }
2305
+ if (loadedSize != 0) {
2306
+ /* ip may be NULL */
2307
+ ip += loadedSize;
2308
+ zds->inPos += loadedSize;
2309
+ }
2310
+ if (loadedSize < toLoad) { someMoreWork = 0; break; } /* not enough input, wait for more */
2311
+
2312
+ /* decode loaded input */
2313
+ zds->inPos = 0; /* input is consumed */
2314
+ FORWARD_IF_ERROR(ZSTD_decompressContinueStream(zds, &op, oend, zds->inBuff, neededInSize), "");
2315
+ /* Function modifies the stage so we must break */
2316
+ break;
2317
+ }
2318
+ case zdss_flush:
2319
+ {
2320
+ size_t const toFlushSize = zds->outEnd - zds->outStart;
2321
+ size_t const flushedSize = ZSTD_limitCopy(op, (size_t)(oend-op), zds->outBuff + zds->outStart, toFlushSize);
2322
+
2323
+ op = op ? op + flushedSize : op;
2324
+
2325
+ zds->outStart += flushedSize;
2326
+ if (flushedSize == toFlushSize) { /* flush completed */
2327
+ zds->streamStage = zdss_read;
2328
+ if ( (zds->outBuffSize < zds->fParams.frameContentSize)
2329
+ && (zds->outStart + zds->fParams.blockSizeMax > zds->outBuffSize) ) {
2330
+ DEBUGLOG(5, "restart filling outBuff from beginning (left:%i, needed:%u)",
2331
+ (int)(zds->outBuffSize - zds->outStart),
2332
+ (U32)zds->fParams.blockSizeMax);
2333
+ zds->outStart = zds->outEnd = 0;
2334
+ }
2335
+ break;
2336
+ } }
2337
+ /* cannot complete flush */
2338
+ someMoreWork = 0;
2339
+ break;
2340
+
2341
+ default:
2342
+ assert(0); /* impossible */
2343
+ RETURN_ERROR(GENERIC, "impossible to reach"); /* some compilers require default to do something */
2344
+ } }
2345
+
2346
+ /* result */
2347
+ input->pos = (size_t)(ip - (const char*)(input->src));
2348
+ output->pos = (size_t)(op - (char*)(output->dst));
2349
+
2350
+ /* Update the expected output buffer for ZSTD_obm_stable. */
2351
+ zds->expectedOutBuffer = *output;
2352
+
2353
+ if ((ip==istart) && (op==ostart)) { /* no forward progress */
2354
+ zds->noForwardProgress ++;
2355
+ if (zds->noForwardProgress >= ZSTD_NO_FORWARD_PROGRESS_MAX) {
2356
+ RETURN_ERROR_IF(op==oend, noForwardProgress_destFull, "");
2357
+ RETURN_ERROR_IF(ip==iend, noForwardProgress_inputEmpty, "");
2358
+ assert(0);
2359
+ }
2360
+ } else {
2361
+ zds->noForwardProgress = 0;
2362
+ }
2363
+ { size_t nextSrcSizeHint = ZSTD_nextSrcSizeToDecompress(zds);
2364
+ if (!nextSrcSizeHint) { /* frame fully decoded */
2365
+ if (zds->outEnd == zds->outStart) { /* output fully flushed */
2366
+ if (zds->hostageByte) {
2367
+ if (input->pos >= input->size) {
2368
+ /* can't release hostage (not present) */
2369
+ zds->streamStage = zdss_read;
2370
+ return 1;
2371
+ }
2372
+ input->pos++; /* release hostage */
2373
+ } /* zds->hostageByte */
2374
+ return 0;
2375
+ } /* zds->outEnd == zds->outStart */
2376
+ if (!zds->hostageByte) { /* output not fully flushed; keep last byte as hostage; will be released when all output is flushed */
2377
+ input->pos--; /* note : pos > 0, otherwise, impossible to finish reading last block */
2378
+ zds->hostageByte=1;
2379
+ }
2380
+ return 1;
2381
+ } /* nextSrcSizeHint==0 */
2382
+ nextSrcSizeHint += ZSTD_blockHeaderSize * (ZSTD_nextInputType(zds) == ZSTDnit_block); /* preload header of next block */
2383
+ assert(zds->inPos <= nextSrcSizeHint);
2384
+ nextSrcSizeHint -= zds->inPos; /* part already loaded*/
2385
+ return nextSrcSizeHint;
2386
+ }
2387
+ }
2388
+
2389
+ size_t ZSTD_decompressStream_simpleArgs (
2390
+ ZSTD_DCtx* dctx,
2391
+ void* dst, size_t dstCapacity, size_t* dstPos,
2392
+ const void* src, size_t srcSize, size_t* srcPos)
2393
+ {
2394
+ ZSTD_outBuffer output;
2395
+ ZSTD_inBuffer input;
2396
+ output.dst = dst;
2397
+ output.size = dstCapacity;
2398
+ output.pos = *dstPos;
2399
+ input.src = src;
2400
+ input.size = srcSize;
2401
+ input.pos = *srcPos;
2402
+ { size_t const cErr = ZSTD_decompressStream(dctx, &output, &input);
2403
+ *dstPos = output.pos;
2404
+ *srcPos = input.pos;
2405
+ return cErr;
2406
+ }
2407
+ }