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 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 } 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 { 304 char x; 305 /* Avoid passing NULL to legacy decoding. */ 306 if (dict == NULL) { 307 assert(dictSize == 0); 308 dict = &x; 309 } 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 { 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 } 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 */ 453