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); |
f535537f |
127 | char x; |
128 | /* Avoid passing NULL to legacy decoding. */ |
129 | if (dst == NULL) { |
130 | assert(dstCapacity == 0); |
131 | dst = &x; |
132 | } |
133 | if (src == NULL) { |
134 | assert(compressedSize == 0); |
135 | src = &x; |
136 | } |
137 | if (dict == NULL) { |
138 | assert(dictSize == 0); |
139 | dict = &x; |
140 | } |
648db22b |
141 | (void)dst; (void)dstCapacity; (void)dict; (void)dictSize; /* unused when ZSTD_LEGACY_SUPPORT >= 8 */ |
142 | switch(version) |
143 | { |
144 | #if (ZSTD_LEGACY_SUPPORT <= 1) |
145 | case 1 : |
146 | return ZSTDv01_decompress(dst, dstCapacity, src, compressedSize); |
147 | #endif |
148 | #if (ZSTD_LEGACY_SUPPORT <= 2) |
149 | case 2 : |
150 | return ZSTDv02_decompress(dst, dstCapacity, src, compressedSize); |
151 | #endif |
152 | #if (ZSTD_LEGACY_SUPPORT <= 3) |
153 | case 3 : |
154 | return ZSTDv03_decompress(dst, dstCapacity, src, compressedSize); |
155 | #endif |
156 | #if (ZSTD_LEGACY_SUPPORT <= 4) |
157 | case 4 : |
158 | return ZSTDv04_decompress(dst, dstCapacity, src, compressedSize); |
159 | #endif |
160 | #if (ZSTD_LEGACY_SUPPORT <= 5) |
161 | case 5 : |
162 | { size_t result; |
163 | ZSTDv05_DCtx* const zd = ZSTDv05_createDCtx(); |
164 | if (zd==NULL) return ERROR(memory_allocation); |
165 | result = ZSTDv05_decompress_usingDict(zd, dst, dstCapacity, src, compressedSize, dict, dictSize); |
166 | ZSTDv05_freeDCtx(zd); |
167 | return result; |
168 | } |
169 | #endif |
170 | #if (ZSTD_LEGACY_SUPPORT <= 6) |
171 | case 6 : |
172 | { size_t result; |
173 | ZSTDv06_DCtx* const zd = ZSTDv06_createDCtx(); |
174 | if (zd==NULL) return ERROR(memory_allocation); |
175 | result = ZSTDv06_decompress_usingDict(zd, dst, dstCapacity, src, compressedSize, dict, dictSize); |
176 | ZSTDv06_freeDCtx(zd); |
177 | return result; |
178 | } |
179 | #endif |
180 | #if (ZSTD_LEGACY_SUPPORT <= 7) |
181 | case 7 : |
182 | { size_t result; |
183 | ZSTDv07_DCtx* const zd = ZSTDv07_createDCtx(); |
184 | if (zd==NULL) return ERROR(memory_allocation); |
185 | result = ZSTDv07_decompress_usingDict(zd, dst, dstCapacity, src, compressedSize, dict, dictSize); |
186 | ZSTDv07_freeDCtx(zd); |
187 | return result; |
188 | } |
189 | #endif |
190 | default : |
191 | return ERROR(prefix_unknown); |
192 | } |
193 | } |
194 | |
195 | MEM_STATIC ZSTD_frameSizeInfo ZSTD_findFrameSizeInfoLegacy(const void *src, size_t srcSize) |
196 | { |
197 | ZSTD_frameSizeInfo frameSizeInfo; |
198 | U32 const version = ZSTD_isLegacy(src, srcSize); |
199 | switch(version) |
200 | { |
201 | #if (ZSTD_LEGACY_SUPPORT <= 1) |
202 | case 1 : |
203 | ZSTDv01_findFrameSizeInfoLegacy(src, srcSize, |
204 | &frameSizeInfo.compressedSize, |
205 | &frameSizeInfo.decompressedBound); |
206 | break; |
207 | #endif |
208 | #if (ZSTD_LEGACY_SUPPORT <= 2) |
209 | case 2 : |
210 | ZSTDv02_findFrameSizeInfoLegacy(src, srcSize, |
211 | &frameSizeInfo.compressedSize, |
212 | &frameSizeInfo.decompressedBound); |
213 | break; |
214 | #endif |
215 | #if (ZSTD_LEGACY_SUPPORT <= 3) |
216 | case 3 : |
217 | ZSTDv03_findFrameSizeInfoLegacy(src, srcSize, |
218 | &frameSizeInfo.compressedSize, |
219 | &frameSizeInfo.decompressedBound); |
220 | break; |
221 | #endif |
222 | #if (ZSTD_LEGACY_SUPPORT <= 4) |
223 | case 4 : |
224 | ZSTDv04_findFrameSizeInfoLegacy(src, srcSize, |
225 | &frameSizeInfo.compressedSize, |
226 | &frameSizeInfo.decompressedBound); |
227 | break; |
228 | #endif |
229 | #if (ZSTD_LEGACY_SUPPORT <= 5) |
230 | case 5 : |
231 | ZSTDv05_findFrameSizeInfoLegacy(src, srcSize, |
232 | &frameSizeInfo.compressedSize, |
233 | &frameSizeInfo.decompressedBound); |
234 | break; |
235 | #endif |
236 | #if (ZSTD_LEGACY_SUPPORT <= 6) |
237 | case 6 : |
238 | ZSTDv06_findFrameSizeInfoLegacy(src, srcSize, |
239 | &frameSizeInfo.compressedSize, |
240 | &frameSizeInfo.decompressedBound); |
241 | break; |
242 | #endif |
243 | #if (ZSTD_LEGACY_SUPPORT <= 7) |
244 | case 7 : |
245 | ZSTDv07_findFrameSizeInfoLegacy(src, srcSize, |
246 | &frameSizeInfo.compressedSize, |
247 | &frameSizeInfo.decompressedBound); |
248 | break; |
249 | #endif |
250 | default : |
251 | frameSizeInfo.compressedSize = ERROR(prefix_unknown); |
252 | frameSizeInfo.decompressedBound = ZSTD_CONTENTSIZE_ERROR; |
253 | break; |
254 | } |
255 | if (!ZSTD_isError(frameSizeInfo.compressedSize) && frameSizeInfo.compressedSize > srcSize) { |
256 | frameSizeInfo.compressedSize = ERROR(srcSize_wrong); |
257 | frameSizeInfo.decompressedBound = ZSTD_CONTENTSIZE_ERROR; |
258 | } |
259 | /* In all cases, decompressedBound == nbBlocks * ZSTD_BLOCKSIZE_MAX. |
260 | * So we can compute nbBlocks without having to change every function. |
261 | */ |
262 | if (frameSizeInfo.decompressedBound != ZSTD_CONTENTSIZE_ERROR) { |
263 | assert((frameSizeInfo.decompressedBound & (ZSTD_BLOCKSIZE_MAX - 1)) == 0); |
264 | frameSizeInfo.nbBlocks = (size_t)(frameSizeInfo.decompressedBound / ZSTD_BLOCKSIZE_MAX); |
265 | } |
266 | return frameSizeInfo; |
267 | } |
268 | |
269 | MEM_STATIC size_t ZSTD_findFrameCompressedSizeLegacy(const void *src, size_t srcSize) |
270 | { |
271 | ZSTD_frameSizeInfo frameSizeInfo = ZSTD_findFrameSizeInfoLegacy(src, srcSize); |
272 | return frameSizeInfo.compressedSize; |
273 | } |
274 | |
275 | MEM_STATIC size_t ZSTD_freeLegacyStreamContext(void* legacyContext, U32 version) |
276 | { |
277 | switch(version) |
278 | { |
279 | default : |
280 | case 1 : |
281 | case 2 : |
282 | case 3 : |
283 | (void)legacyContext; |
284 | return ERROR(version_unsupported); |
285 | #if (ZSTD_LEGACY_SUPPORT <= 4) |
286 | case 4 : return ZBUFFv04_freeDCtx((ZBUFFv04_DCtx*)legacyContext); |
287 | #endif |
288 | #if (ZSTD_LEGACY_SUPPORT <= 5) |
289 | case 5 : return ZBUFFv05_freeDCtx((ZBUFFv05_DCtx*)legacyContext); |
290 | #endif |
291 | #if (ZSTD_LEGACY_SUPPORT <= 6) |
292 | case 6 : return ZBUFFv06_freeDCtx((ZBUFFv06_DCtx*)legacyContext); |
293 | #endif |
294 | #if (ZSTD_LEGACY_SUPPORT <= 7) |
295 | case 7 : return ZBUFFv07_freeDCtx((ZBUFFv07_DCtx*)legacyContext); |
296 | #endif |
297 | } |
298 | } |
299 | |
300 | |
301 | MEM_STATIC size_t ZSTD_initLegacyStream(void** legacyContext, U32 prevVersion, U32 newVersion, |
302 | const void* dict, size_t dictSize) |
303 | { |
f535537f |
304 | char x; |
305 | /* Avoid passing NULL to legacy decoding. */ |
306 | if (dict == NULL) { |
307 | assert(dictSize == 0); |
308 | dict = &x; |
309 | } |
648db22b |
310 | DEBUGLOG(5, "ZSTD_initLegacyStream for v0.%u", newVersion); |
311 | if (prevVersion != newVersion) ZSTD_freeLegacyStreamContext(*legacyContext, prevVersion); |
312 | switch(newVersion) |
313 | { |
314 | default : |
315 | case 1 : |
316 | case 2 : |
317 | case 3 : |
318 | (void)dict; (void)dictSize; |
319 | return 0; |
320 | #if (ZSTD_LEGACY_SUPPORT <= 4) |
321 | case 4 : |
322 | { |
323 | ZBUFFv04_DCtx* dctx = (prevVersion != newVersion) ? ZBUFFv04_createDCtx() : (ZBUFFv04_DCtx*)*legacyContext; |
324 | if (dctx==NULL) return ERROR(memory_allocation); |
325 | ZBUFFv04_decompressInit(dctx); |
326 | ZBUFFv04_decompressWithDictionary(dctx, dict, dictSize); |
327 | *legacyContext = dctx; |
328 | return 0; |
329 | } |
330 | #endif |
331 | #if (ZSTD_LEGACY_SUPPORT <= 5) |
332 | case 5 : |
333 | { |
334 | ZBUFFv05_DCtx* dctx = (prevVersion != newVersion) ? ZBUFFv05_createDCtx() : (ZBUFFv05_DCtx*)*legacyContext; |
335 | if (dctx==NULL) return ERROR(memory_allocation); |
336 | ZBUFFv05_decompressInitDictionary(dctx, dict, dictSize); |
337 | *legacyContext = dctx; |
338 | return 0; |
339 | } |
340 | #endif |
341 | #if (ZSTD_LEGACY_SUPPORT <= 6) |
342 | case 6 : |
343 | { |
344 | ZBUFFv06_DCtx* dctx = (prevVersion != newVersion) ? ZBUFFv06_createDCtx() : (ZBUFFv06_DCtx*)*legacyContext; |
345 | if (dctx==NULL) return ERROR(memory_allocation); |
346 | ZBUFFv06_decompressInitDictionary(dctx, dict, dictSize); |
347 | *legacyContext = dctx; |
348 | return 0; |
349 | } |
350 | #endif |
351 | #if (ZSTD_LEGACY_SUPPORT <= 7) |
352 | case 7 : |
353 | { |
354 | ZBUFFv07_DCtx* dctx = (prevVersion != newVersion) ? ZBUFFv07_createDCtx() : (ZBUFFv07_DCtx*)*legacyContext; |
355 | if (dctx==NULL) return ERROR(memory_allocation); |
356 | ZBUFFv07_decompressInitDictionary(dctx, dict, dictSize); |
357 | *legacyContext = dctx; |
358 | return 0; |
359 | } |
360 | #endif |
361 | } |
362 | } |
363 | |
364 | |
365 | |
366 | MEM_STATIC size_t ZSTD_decompressLegacyStream(void* legacyContext, U32 version, |
367 | ZSTD_outBuffer* output, ZSTD_inBuffer* input) |
368 | { |
f535537f |
369 | static char x; |
370 | /* Avoid passing NULL to legacy decoding. */ |
371 | if (output->dst == NULL) { |
372 | assert(output->size == 0); |
373 | output->dst = &x; |
374 | } |
375 | if (input->src == NULL) { |
376 | assert(input->size == 0); |
377 | input->src = &x; |
378 | } |
648db22b |
379 | DEBUGLOG(5, "ZSTD_decompressLegacyStream for v0.%u", version); |
380 | switch(version) |
381 | { |
382 | default : |
383 | case 1 : |
384 | case 2 : |
385 | case 3 : |
386 | (void)legacyContext; (void)output; (void)input; |
387 | return ERROR(version_unsupported); |
388 | #if (ZSTD_LEGACY_SUPPORT <= 4) |
389 | case 4 : |
390 | { |
391 | ZBUFFv04_DCtx* dctx = (ZBUFFv04_DCtx*) legacyContext; |
392 | const void* src = (const char*)input->src + input->pos; |
393 | size_t readSize = input->size - input->pos; |
394 | void* dst = (char*)output->dst + output->pos; |
395 | size_t decodedSize = output->size - output->pos; |
396 | size_t const hintSize = ZBUFFv04_decompressContinue(dctx, dst, &decodedSize, src, &readSize); |
397 | output->pos += decodedSize; |
398 | input->pos += readSize; |
399 | return hintSize; |
400 | } |
401 | #endif |
402 | #if (ZSTD_LEGACY_SUPPORT <= 5) |
403 | case 5 : |
404 | { |
405 | ZBUFFv05_DCtx* dctx = (ZBUFFv05_DCtx*) legacyContext; |
406 | const void* src = (const char*)input->src + input->pos; |
407 | size_t readSize = input->size - input->pos; |
408 | void* dst = (char*)output->dst + output->pos; |
409 | size_t decodedSize = output->size - output->pos; |
410 | size_t const hintSize = ZBUFFv05_decompressContinue(dctx, dst, &decodedSize, src, &readSize); |
411 | output->pos += decodedSize; |
412 | input->pos += readSize; |
413 | return hintSize; |
414 | } |
415 | #endif |
416 | #if (ZSTD_LEGACY_SUPPORT <= 6) |
417 | case 6 : |
418 | { |
419 | ZBUFFv06_DCtx* dctx = (ZBUFFv06_DCtx*) legacyContext; |
420 | const void* src = (const char*)input->src + input->pos; |
421 | size_t readSize = input->size - input->pos; |
422 | void* dst = (char*)output->dst + output->pos; |
423 | size_t decodedSize = output->size - output->pos; |
424 | size_t const hintSize = ZBUFFv06_decompressContinue(dctx, dst, &decodedSize, src, &readSize); |
425 | output->pos += decodedSize; |
426 | input->pos += readSize; |
427 | return hintSize; |
428 | } |
429 | #endif |
430 | #if (ZSTD_LEGACY_SUPPORT <= 7) |
431 | case 7 : |
432 | { |
433 | ZBUFFv07_DCtx* dctx = (ZBUFFv07_DCtx*) legacyContext; |
434 | const void* src = (const char*)input->src + input->pos; |
435 | size_t readSize = input->size - input->pos; |
436 | void* dst = (char*)output->dst + output->pos; |
437 | size_t decodedSize = output->size - output->pos; |
438 | size_t const hintSize = ZBUFFv07_decompressContinue(dctx, dst, &decodedSize, src, &readSize); |
439 | output->pos += decodedSize; |
440 | input->pos += readSize; |
441 | return hintSize; |
442 | } |
443 | #endif |
444 | } |
445 | } |
446 | |
447 | |
448 | #if defined (__cplusplus) |
449 | } |
450 | #endif |
451 | |
452 | #endif /* ZSTD_LEGACY_H */ |