648db22b |
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 | #ifndef ZSTD_LEGACY_H |
12 | #define ZSTD_LEGACY_H |
13 | |
14 | #if defined (__cplusplus) |
15 | extern "C" { |
16 | #endif |
17 | |
18 | /* ************************************* |
19 | * Includes |
20 | ***************************************/ |
21 | #include "../common/mem.h" /* MEM_STATIC */ |
22 | #include "../common/error_private.h" /* ERROR */ |
23 | #include "../common/zstd_internal.h" /* ZSTD_inBuffer, ZSTD_outBuffer, ZSTD_frameSizeInfo */ |
24 | |
25 | #if !defined (ZSTD_LEGACY_SUPPORT) || (ZSTD_LEGACY_SUPPORT == 0) |
26 | # undef ZSTD_LEGACY_SUPPORT |
27 | # define ZSTD_LEGACY_SUPPORT 8 |
28 | #endif |
29 | |
30 | #if (ZSTD_LEGACY_SUPPORT <= 1) |
31 | # include "zstd_v01.h" |
32 | #endif |
33 | #if (ZSTD_LEGACY_SUPPORT <= 2) |
34 | # include "zstd_v02.h" |
35 | #endif |
36 | #if (ZSTD_LEGACY_SUPPORT <= 3) |
37 | # include "zstd_v03.h" |
38 | #endif |
39 | #if (ZSTD_LEGACY_SUPPORT <= 4) |
40 | # include "zstd_v04.h" |
41 | #endif |
42 | #if (ZSTD_LEGACY_SUPPORT <= 5) |
43 | # include "zstd_v05.h" |
44 | #endif |
45 | #if (ZSTD_LEGACY_SUPPORT <= 6) |
46 | # include "zstd_v06.h" |
47 | #endif |
48 | #if (ZSTD_LEGACY_SUPPORT <= 7) |
49 | # include "zstd_v07.h" |
50 | #endif |
51 | |
52 | /** ZSTD_isLegacy() : |
53 | @return : > 0 if supported by legacy decoder. 0 otherwise. |
54 | return value is the version. |
55 | */ |
56 | MEM_STATIC unsigned ZSTD_isLegacy(const void* src, size_t srcSize) |
57 | { |
58 | U32 magicNumberLE; |
59 | if (srcSize<4) return 0; |
60 | magicNumberLE = MEM_readLE32(src); |
61 | switch(magicNumberLE) |
62 | { |
63 | #if (ZSTD_LEGACY_SUPPORT <= 1) |
64 | case ZSTDv01_magicNumberLE:return 1; |
65 | #endif |
66 | #if (ZSTD_LEGACY_SUPPORT <= 2) |
67 | case ZSTDv02_magicNumber : return 2; |
68 | #endif |
69 | #if (ZSTD_LEGACY_SUPPORT <= 3) |
70 | case ZSTDv03_magicNumber : return 3; |
71 | #endif |
72 | #if (ZSTD_LEGACY_SUPPORT <= 4) |
73 | case ZSTDv04_magicNumber : return 4; |
74 | #endif |
75 | #if (ZSTD_LEGACY_SUPPORT <= 5) |
76 | case ZSTDv05_MAGICNUMBER : return 5; |
77 | #endif |
78 | #if (ZSTD_LEGACY_SUPPORT <= 6) |
79 | case ZSTDv06_MAGICNUMBER : return 6; |
80 | #endif |
81 | #if (ZSTD_LEGACY_SUPPORT <= 7) |
82 | case ZSTDv07_MAGICNUMBER : return 7; |
83 | #endif |
84 | default : return 0; |
85 | } |
86 | } |
87 | |
88 | |
89 | MEM_STATIC unsigned long long ZSTD_getDecompressedSize_legacy(const void* src, size_t srcSize) |
90 | { |
91 | U32 const version = ZSTD_isLegacy(src, srcSize); |
92 | if (version < 5) return 0; /* no decompressed size in frame header, or not a legacy format */ |
93 | #if (ZSTD_LEGACY_SUPPORT <= 5) |
94 | if (version==5) { |
95 | ZSTDv05_parameters fParams; |
96 | size_t const frResult = ZSTDv05_getFrameParams(&fParams, src, srcSize); |
97 | if (frResult != 0) return 0; |
98 | return fParams.srcSize; |
99 | } |
100 | #endif |
101 | #if (ZSTD_LEGACY_SUPPORT <= 6) |
102 | if (version==6) { |
103 | ZSTDv06_frameParams fParams; |
104 | size_t const frResult = ZSTDv06_getFrameParams(&fParams, src, srcSize); |
105 | if (frResult != 0) return 0; |
106 | return fParams.frameContentSize; |
107 | } |
108 | #endif |
109 | #if (ZSTD_LEGACY_SUPPORT <= 7) |
110 | if (version==7) { |
111 | ZSTDv07_frameParams fParams; |
112 | size_t const frResult = ZSTDv07_getFrameParams(&fParams, src, srcSize); |
113 | if (frResult != 0) return 0; |
114 | return fParams.frameContentSize; |
115 | } |
116 | #endif |
117 | return 0; /* should not be possible */ |
118 | } |
119 | |
120 | |
121 | MEM_STATIC size_t ZSTD_decompressLegacy( |
122 | void* dst, size_t dstCapacity, |
123 | const void* src, size_t compressedSize, |
124 | const void* dict,size_t dictSize) |
125 | { |
126 | U32 const version = ZSTD_isLegacy(src, compressedSize); |
127 | (void)dst; (void)dstCapacity; (void)dict; (void)dictSize; /* unused when ZSTD_LEGACY_SUPPORT >= 8 */ |
128 | switch(version) |
129 | { |
130 | #if (ZSTD_LEGACY_SUPPORT <= 1) |
131 | case 1 : |
132 | return ZSTDv01_decompress(dst, dstCapacity, src, compressedSize); |
133 | #endif |
134 | #if (ZSTD_LEGACY_SUPPORT <= 2) |
135 | case 2 : |
136 | return ZSTDv02_decompress(dst, dstCapacity, src, compressedSize); |
137 | #endif |
138 | #if (ZSTD_LEGACY_SUPPORT <= 3) |
139 | case 3 : |
140 | return ZSTDv03_decompress(dst, dstCapacity, src, compressedSize); |
141 | #endif |
142 | #if (ZSTD_LEGACY_SUPPORT <= 4) |
143 | case 4 : |
144 | return ZSTDv04_decompress(dst, dstCapacity, src, compressedSize); |
145 | #endif |
146 | #if (ZSTD_LEGACY_SUPPORT <= 5) |
147 | case 5 : |
148 | { size_t result; |
149 | ZSTDv05_DCtx* const zd = ZSTDv05_createDCtx(); |
150 | if (zd==NULL) return ERROR(memory_allocation); |
151 | result = ZSTDv05_decompress_usingDict(zd, dst, dstCapacity, src, compressedSize, dict, dictSize); |
152 | ZSTDv05_freeDCtx(zd); |
153 | return result; |
154 | } |
155 | #endif |
156 | #if (ZSTD_LEGACY_SUPPORT <= 6) |
157 | case 6 : |
158 | { size_t result; |
159 | ZSTDv06_DCtx* const zd = ZSTDv06_createDCtx(); |
160 | if (zd==NULL) return ERROR(memory_allocation); |
161 | result = ZSTDv06_decompress_usingDict(zd, dst, dstCapacity, src, compressedSize, dict, dictSize); |
162 | ZSTDv06_freeDCtx(zd); |
163 | return result; |
164 | } |
165 | #endif |
166 | #if (ZSTD_LEGACY_SUPPORT <= 7) |
167 | case 7 : |
168 | { size_t result; |
169 | ZSTDv07_DCtx* const zd = ZSTDv07_createDCtx(); |
170 | if (zd==NULL) return ERROR(memory_allocation); |
171 | result = ZSTDv07_decompress_usingDict(zd, dst, dstCapacity, src, compressedSize, dict, dictSize); |
172 | ZSTDv07_freeDCtx(zd); |
173 | return result; |
174 | } |
175 | #endif |
176 | default : |
177 | return ERROR(prefix_unknown); |
178 | } |
179 | } |
180 | |
181 | MEM_STATIC ZSTD_frameSizeInfo ZSTD_findFrameSizeInfoLegacy(const void *src, size_t srcSize) |
182 | { |
183 | ZSTD_frameSizeInfo frameSizeInfo; |
184 | U32 const version = ZSTD_isLegacy(src, srcSize); |
185 | switch(version) |
186 | { |
187 | #if (ZSTD_LEGACY_SUPPORT <= 1) |
188 | case 1 : |
189 | ZSTDv01_findFrameSizeInfoLegacy(src, srcSize, |
190 | &frameSizeInfo.compressedSize, |
191 | &frameSizeInfo.decompressedBound); |
192 | break; |
193 | #endif |
194 | #if (ZSTD_LEGACY_SUPPORT <= 2) |
195 | case 2 : |
196 | ZSTDv02_findFrameSizeInfoLegacy(src, srcSize, |
197 | &frameSizeInfo.compressedSize, |
198 | &frameSizeInfo.decompressedBound); |
199 | break; |
200 | #endif |
201 | #if (ZSTD_LEGACY_SUPPORT <= 3) |
202 | case 3 : |
203 | ZSTDv03_findFrameSizeInfoLegacy(src, srcSize, |
204 | &frameSizeInfo.compressedSize, |
205 | &frameSizeInfo.decompressedBound); |
206 | break; |
207 | #endif |
208 | #if (ZSTD_LEGACY_SUPPORT <= 4) |
209 | case 4 : |
210 | ZSTDv04_findFrameSizeInfoLegacy(src, srcSize, |
211 | &frameSizeInfo.compressedSize, |
212 | &frameSizeInfo.decompressedBound); |
213 | break; |
214 | #endif |
215 | #if (ZSTD_LEGACY_SUPPORT <= 5) |
216 | case 5 : |
217 | ZSTDv05_findFrameSizeInfoLegacy(src, srcSize, |
218 | &frameSizeInfo.compressedSize, |
219 | &frameSizeInfo.decompressedBound); |
220 | break; |
221 | #endif |
222 | #if (ZSTD_LEGACY_SUPPORT <= 6) |
223 | case 6 : |
224 | ZSTDv06_findFrameSizeInfoLegacy(src, srcSize, |
225 | &frameSizeInfo.compressedSize, |
226 | &frameSizeInfo.decompressedBound); |
227 | break; |
228 | #endif |
229 | #if (ZSTD_LEGACY_SUPPORT <= 7) |
230 | case 7 : |
231 | ZSTDv07_findFrameSizeInfoLegacy(src, srcSize, |
232 | &frameSizeInfo.compressedSize, |
233 | &frameSizeInfo.decompressedBound); |
234 | break; |
235 | #endif |
236 | default : |
237 | frameSizeInfo.compressedSize = ERROR(prefix_unknown); |
238 | frameSizeInfo.decompressedBound = ZSTD_CONTENTSIZE_ERROR; |
239 | break; |
240 | } |
241 | if (!ZSTD_isError(frameSizeInfo.compressedSize) && frameSizeInfo.compressedSize > srcSize) { |
242 | frameSizeInfo.compressedSize = ERROR(srcSize_wrong); |
243 | frameSizeInfo.decompressedBound = ZSTD_CONTENTSIZE_ERROR; |
244 | } |
245 | /* In all cases, decompressedBound == nbBlocks * ZSTD_BLOCKSIZE_MAX. |
246 | * So we can compute nbBlocks without having to change every function. |
247 | */ |
248 | if (frameSizeInfo.decompressedBound != ZSTD_CONTENTSIZE_ERROR) { |
249 | assert((frameSizeInfo.decompressedBound & (ZSTD_BLOCKSIZE_MAX - 1)) == 0); |
250 | frameSizeInfo.nbBlocks = (size_t)(frameSizeInfo.decompressedBound / ZSTD_BLOCKSIZE_MAX); |
251 | } |
252 | return frameSizeInfo; |
253 | } |
254 | |
255 | MEM_STATIC size_t ZSTD_findFrameCompressedSizeLegacy(const void *src, size_t srcSize) |
256 | { |
257 | ZSTD_frameSizeInfo frameSizeInfo = ZSTD_findFrameSizeInfoLegacy(src, srcSize); |
258 | return frameSizeInfo.compressedSize; |
259 | } |
260 | |
261 | MEM_STATIC size_t ZSTD_freeLegacyStreamContext(void* legacyContext, U32 version) |
262 | { |
263 | switch(version) |
264 | { |
265 | default : |
266 | case 1 : |
267 | case 2 : |
268 | case 3 : |
269 | (void)legacyContext; |
270 | return ERROR(version_unsupported); |
271 | #if (ZSTD_LEGACY_SUPPORT <= 4) |
272 | case 4 : return ZBUFFv04_freeDCtx((ZBUFFv04_DCtx*)legacyContext); |
273 | #endif |
274 | #if (ZSTD_LEGACY_SUPPORT <= 5) |
275 | case 5 : return ZBUFFv05_freeDCtx((ZBUFFv05_DCtx*)legacyContext); |
276 | #endif |
277 | #if (ZSTD_LEGACY_SUPPORT <= 6) |
278 | case 6 : return ZBUFFv06_freeDCtx((ZBUFFv06_DCtx*)legacyContext); |
279 | #endif |
280 | #if (ZSTD_LEGACY_SUPPORT <= 7) |
281 | case 7 : return ZBUFFv07_freeDCtx((ZBUFFv07_DCtx*)legacyContext); |
282 | #endif |
283 | } |
284 | } |
285 | |
286 | |
287 | MEM_STATIC size_t ZSTD_initLegacyStream(void** legacyContext, U32 prevVersion, U32 newVersion, |
288 | const void* dict, size_t dictSize) |
289 | { |
290 | DEBUGLOG(5, "ZSTD_initLegacyStream for v0.%u", newVersion); |
291 | if (prevVersion != newVersion) ZSTD_freeLegacyStreamContext(*legacyContext, prevVersion); |
292 | switch(newVersion) |
293 | { |
294 | default : |
295 | case 1 : |
296 | case 2 : |
297 | case 3 : |
298 | (void)dict; (void)dictSize; |
299 | return 0; |
300 | #if (ZSTD_LEGACY_SUPPORT <= 4) |
301 | case 4 : |
302 | { |
303 | ZBUFFv04_DCtx* dctx = (prevVersion != newVersion) ? ZBUFFv04_createDCtx() : (ZBUFFv04_DCtx*)*legacyContext; |
304 | if (dctx==NULL) return ERROR(memory_allocation); |
305 | ZBUFFv04_decompressInit(dctx); |
306 | ZBUFFv04_decompressWithDictionary(dctx, dict, dictSize); |
307 | *legacyContext = dctx; |
308 | return 0; |
309 | } |
310 | #endif |
311 | #if (ZSTD_LEGACY_SUPPORT <= 5) |
312 | case 5 : |
313 | { |
314 | ZBUFFv05_DCtx* dctx = (prevVersion != newVersion) ? ZBUFFv05_createDCtx() : (ZBUFFv05_DCtx*)*legacyContext; |
315 | if (dctx==NULL) return ERROR(memory_allocation); |
316 | ZBUFFv05_decompressInitDictionary(dctx, dict, dictSize); |
317 | *legacyContext = dctx; |
318 | return 0; |
319 | } |
320 | #endif |
321 | #if (ZSTD_LEGACY_SUPPORT <= 6) |
322 | case 6 : |
323 | { |
324 | ZBUFFv06_DCtx* dctx = (prevVersion != newVersion) ? ZBUFFv06_createDCtx() : (ZBUFFv06_DCtx*)*legacyContext; |
325 | if (dctx==NULL) return ERROR(memory_allocation); |
326 | ZBUFFv06_decompressInitDictionary(dctx, dict, dictSize); |
327 | *legacyContext = dctx; |
328 | return 0; |
329 | } |
330 | #endif |
331 | #if (ZSTD_LEGACY_SUPPORT <= 7) |
332 | case 7 : |
333 | { |
334 | ZBUFFv07_DCtx* dctx = (prevVersion != newVersion) ? ZBUFFv07_createDCtx() : (ZBUFFv07_DCtx*)*legacyContext; |
335 | if (dctx==NULL) return ERROR(memory_allocation); |
336 | ZBUFFv07_decompressInitDictionary(dctx, dict, dictSize); |
337 | *legacyContext = dctx; |
338 | return 0; |
339 | } |
340 | #endif |
341 | } |
342 | } |
343 | |
344 | |
345 | |
346 | MEM_STATIC size_t ZSTD_decompressLegacyStream(void* legacyContext, U32 version, |
347 | ZSTD_outBuffer* output, ZSTD_inBuffer* input) |
348 | { |
349 | DEBUGLOG(5, "ZSTD_decompressLegacyStream for v0.%u", version); |
350 | switch(version) |
351 | { |
352 | default : |
353 | case 1 : |
354 | case 2 : |
355 | case 3 : |
356 | (void)legacyContext; (void)output; (void)input; |
357 | return ERROR(version_unsupported); |
358 | #if (ZSTD_LEGACY_SUPPORT <= 4) |
359 | case 4 : |
360 | { |
361 | ZBUFFv04_DCtx* dctx = (ZBUFFv04_DCtx*) legacyContext; |
362 | const void* src = (const char*)input->src + input->pos; |
363 | size_t readSize = input->size - input->pos; |
364 | void* dst = (char*)output->dst + output->pos; |
365 | size_t decodedSize = output->size - output->pos; |
366 | size_t const hintSize = ZBUFFv04_decompressContinue(dctx, dst, &decodedSize, src, &readSize); |
367 | output->pos += decodedSize; |
368 | input->pos += readSize; |
369 | return hintSize; |
370 | } |
371 | #endif |
372 | #if (ZSTD_LEGACY_SUPPORT <= 5) |
373 | case 5 : |
374 | { |
375 | ZBUFFv05_DCtx* dctx = (ZBUFFv05_DCtx*) legacyContext; |
376 | const void* src = (const char*)input->src + input->pos; |
377 | size_t readSize = input->size - input->pos; |
378 | void* dst = (char*)output->dst + output->pos; |
379 | size_t decodedSize = output->size - output->pos; |
380 | size_t const hintSize = ZBUFFv05_decompressContinue(dctx, dst, &decodedSize, src, &readSize); |
381 | output->pos += decodedSize; |
382 | input->pos += readSize; |
383 | return hintSize; |
384 | } |
385 | #endif |
386 | #if (ZSTD_LEGACY_SUPPORT <= 6) |
387 | case 6 : |
388 | { |
389 | ZBUFFv06_DCtx* dctx = (ZBUFFv06_DCtx*) legacyContext; |
390 | const void* src = (const char*)input->src + input->pos; |
391 | size_t readSize = input->size - input->pos; |
392 | void* dst = (char*)output->dst + output->pos; |
393 | size_t decodedSize = output->size - output->pos; |
394 | size_t const hintSize = ZBUFFv06_decompressContinue(dctx, dst, &decodedSize, src, &readSize); |
395 | output->pos += decodedSize; |
396 | input->pos += readSize; |
397 | return hintSize; |
398 | } |
399 | #endif |
400 | #if (ZSTD_LEGACY_SUPPORT <= 7) |
401 | case 7 : |
402 | { |
403 | ZBUFFv07_DCtx* dctx = (ZBUFFv07_DCtx*) legacyContext; |
404 | const void* src = (const char*)input->src + input->pos; |
405 | size_t readSize = input->size - input->pos; |
406 | void* dst = (char*)output->dst + output->pos; |
407 | size_t decodedSize = output->size - output->pos; |
408 | size_t const hintSize = ZBUFFv07_decompressContinue(dctx, dst, &decodedSize, src, &readSize); |
409 | output->pos += decodedSize; |
410 | input->pos += readSize; |
411 | return hintSize; |
412 | } |
413 | #endif |
414 | } |
415 | } |
416 | |
417 | |
418 | #if defined (__cplusplus) |
419 | } |
420 | #endif |
421 | |
422 | #endif /* ZSTD_LEGACY_H */ |