0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024
0025
0026
0027
0028
0029
0030
0031
0032
0033
0034
0035
0036 #include <linux/lz4.h>
0037 #include "lz4defs.h"
0038 #include <linux/init.h>
0039 #include <linux/module.h>
0040 #include <linux/kernel.h>
0041 #include <asm/unaligned.h>
0042
0043
0044
0045
0046
0047 #define DEBUGLOG(l, ...) {}
0048
0049 #ifndef assert
0050 #define assert(condition) ((void)0)
0051 #endif
0052
0053
0054
0055
0056
0057
0058
0059
0060 static FORCE_INLINE int LZ4_decompress_generic(
0061 const char * const src,
0062 char * const dst,
0063 int srcSize,
0064
0065
0066
0067
0068 int outputSize,
0069
0070 endCondition_directive endOnInput,
0071
0072 earlyEnd_directive partialDecoding,
0073
0074 dict_directive dict,
0075
0076 const BYTE * const lowPrefix,
0077
0078 const BYTE * const dictStart,
0079
0080 const size_t dictSize
0081 )
0082 {
0083 const BYTE *ip = (const BYTE *) src;
0084 const BYTE * const iend = ip + srcSize;
0085
0086 BYTE *op = (BYTE *) dst;
0087 BYTE * const oend = op + outputSize;
0088 BYTE *cpy;
0089
0090 const BYTE * const dictEnd = (const BYTE *)dictStart + dictSize;
0091 static const unsigned int inc32table[8] = {0, 1, 2, 1, 0, 4, 4, 4};
0092 static const int dec64table[8] = {0, 0, 0, -1, -4, 1, 2, 3};
0093
0094 const int safeDecode = (endOnInput == endOnInputSize);
0095 const int checkOffset = ((safeDecode) && (dictSize < (int)(64 * KB)));
0096
0097
0098 const BYTE *const shortiend = iend -
0099 (endOnInput ? 14 : 8) - 2 ;
0100 const BYTE *const shortoend = oend -
0101 (endOnInput ? 14 : 8) - 18 ;
0102
0103 DEBUGLOG(5, "%s (srcSize:%i, dstSize:%i)", __func__,
0104 srcSize, outputSize);
0105
0106
0107 assert(lowPrefix <= op);
0108 assert(src != NULL);
0109
0110
0111 if ((endOnInput) && (unlikely(outputSize == 0)))
0112 return ((srcSize == 1) && (*ip == 0)) ? 0 : -1;
0113
0114 if ((!endOnInput) && (unlikely(outputSize == 0)))
0115 return (*ip == 0 ? 1 : -1);
0116
0117 if ((endOnInput) && unlikely(srcSize == 0))
0118 return -1;
0119
0120
0121 while (1) {
0122 size_t length;
0123 const BYTE *match;
0124 size_t offset;
0125
0126
0127 unsigned int const token = *ip++;
0128 length = token>>ML_BITS;
0129
0130
0131 assert(!endOnInput || ip <= iend);
0132
0133
0134
0135
0136
0137
0138
0139
0140
0141
0142
0143
0144
0145
0146
0147
0148 if ((endOnInput ? length != RUN_MASK : length <= 8)
0149
0150
0151
0152
0153 && likely((endOnInput ? ip < shortiend : 1) &
0154 (op <= shortoend))) {
0155
0156 LZ4_memcpy(op, ip, endOnInput ? 16 : 8);
0157 op += length; ip += length;
0158
0159
0160
0161
0162
0163
0164 length = token & ML_MASK;
0165 offset = LZ4_readLE16(ip);
0166 ip += 2;
0167 match = op - offset;
0168 assert(match <= op);
0169
0170
0171 if ((length != ML_MASK) &&
0172 (offset >= 8) &&
0173 (dict == withPrefix64k || match >= lowPrefix)) {
0174
0175 LZ4_memcpy(op + 0, match + 0, 8);
0176 LZ4_memcpy(op + 8, match + 8, 8);
0177 LZ4_memcpy(op + 16, match + 16, 2);
0178 op += length + MINMATCH;
0179
0180 continue;
0181 }
0182
0183
0184
0185
0186
0187
0188 goto _copy_match;
0189 }
0190
0191
0192 if (length == RUN_MASK) {
0193 unsigned int s;
0194
0195 if (unlikely(endOnInput ? ip >= iend - RUN_MASK : 0)) {
0196
0197 goto _output_error;
0198 }
0199 do {
0200 s = *ip++;
0201 length += s;
0202 } while (likely(endOnInput
0203 ? ip < iend - RUN_MASK
0204 : 1) & (s == 255));
0205
0206 if ((safeDecode)
0207 && unlikely((uptrval)(op) +
0208 length < (uptrval)(op))) {
0209
0210 goto _output_error;
0211 }
0212 if ((safeDecode)
0213 && unlikely((uptrval)(ip) +
0214 length < (uptrval)(ip))) {
0215
0216 goto _output_error;
0217 }
0218 }
0219
0220
0221 cpy = op + length;
0222 LZ4_STATIC_ASSERT(MFLIMIT >= WILDCOPYLENGTH);
0223
0224 if (((endOnInput) && ((cpy > oend - MFLIMIT)
0225 || (ip + length > iend - (2 + 1 + LASTLITERALS))))
0226 || ((!endOnInput) && (cpy > oend - WILDCOPYLENGTH))) {
0227 if (partialDecoding) {
0228 if (cpy > oend) {
0229
0230
0231
0232
0233 cpy = oend;
0234 length = oend - op;
0235 }
0236 if ((endOnInput)
0237 && (ip + length > iend)) {
0238
0239
0240
0241
0242
0243 goto _output_error;
0244 }
0245 } else {
0246 if ((!endOnInput)
0247 && (cpy != oend)) {
0248
0249
0250
0251
0252
0253 goto _output_error;
0254 }
0255 if ((endOnInput)
0256 && ((ip + length != iend)
0257 || (cpy > oend))) {
0258
0259
0260
0261
0262 goto _output_error;
0263 }
0264 }
0265
0266
0267
0268
0269
0270 LZ4_memmove(op, ip, length);
0271 ip += length;
0272 op += length;
0273
0274
0275
0276
0277
0278
0279 if (!partialDecoding || (cpy == oend) || (ip >= (iend - 2)))
0280 break;
0281 } else {
0282
0283 LZ4_wildCopy(op, ip, cpy);
0284 ip += length;
0285 op = cpy;
0286 }
0287
0288
0289 offset = LZ4_readLE16(ip);
0290 ip += 2;
0291 match = op - offset;
0292
0293
0294 length = token & ML_MASK;
0295
0296 _copy_match:
0297 if ((checkOffset) && (unlikely(match + dictSize < lowPrefix))) {
0298
0299 goto _output_error;
0300 }
0301
0302
0303
0304
0305
0306
0307 if (!partialDecoding) {
0308 assert(oend > op);
0309 assert(oend - op >= 4);
0310
0311 LZ4_write32(op, (U32)offset);
0312 }
0313
0314 if (length == ML_MASK) {
0315 unsigned int s;
0316
0317 do {
0318 s = *ip++;
0319
0320 if ((endOnInput) && (ip > iend - LASTLITERALS))
0321 goto _output_error;
0322
0323 length += s;
0324 } while (s == 255);
0325
0326 if ((safeDecode)
0327 && unlikely(
0328 (uptrval)(op) + length < (uptrval)op)) {
0329
0330 goto _output_error;
0331 }
0332 }
0333
0334 length += MINMATCH;
0335
0336
0337 if ((dict == usingExtDict) && (match < lowPrefix)) {
0338 if (unlikely(op + length > oend - LASTLITERALS)) {
0339
0340 if (!partialDecoding)
0341 goto _output_error;
0342 length = min(length, (size_t)(oend - op));
0343 }
0344
0345 if (length <= (size_t)(lowPrefix - match)) {
0346
0347
0348
0349
0350 memmove(op, dictEnd - (lowPrefix - match),
0351 length);
0352 op += length;
0353 } else {
0354
0355
0356
0357
0358 size_t const copySize = (size_t)(lowPrefix - match);
0359 size_t const restSize = length - copySize;
0360
0361 LZ4_memcpy(op, dictEnd - copySize, copySize);
0362 op += copySize;
0363 if (restSize > (size_t)(op - lowPrefix)) {
0364
0365 BYTE * const endOfMatch = op + restSize;
0366 const BYTE *copyFrom = lowPrefix;
0367
0368 while (op < endOfMatch)
0369 *op++ = *copyFrom++;
0370 } else {
0371 LZ4_memcpy(op, lowPrefix, restSize);
0372 op += restSize;
0373 }
0374 }
0375 continue;
0376 }
0377
0378
0379 cpy = op + length;
0380
0381
0382
0383
0384
0385 assert(op <= oend);
0386 if (partialDecoding &&
0387 (cpy > oend - MATCH_SAFEGUARD_DISTANCE)) {
0388 size_t const mlen = min(length, (size_t)(oend - op));
0389 const BYTE * const matchEnd = match + mlen;
0390 BYTE * const copyEnd = op + mlen;
0391
0392 if (matchEnd > op) {
0393
0394 while (op < copyEnd)
0395 *op++ = *match++;
0396 } else {
0397 LZ4_memcpy(op, match, mlen);
0398 }
0399 op = copyEnd;
0400 if (op == oend)
0401 break;
0402 continue;
0403 }
0404
0405 if (unlikely(offset < 8)) {
0406 op[0] = match[0];
0407 op[1] = match[1];
0408 op[2] = match[2];
0409 op[3] = match[3];
0410 match += inc32table[offset];
0411 LZ4_memcpy(op + 4, match, 4);
0412 match -= dec64table[offset];
0413 } else {
0414 LZ4_copy8(op, match);
0415 match += 8;
0416 }
0417
0418 op += 8;
0419
0420 if (unlikely(cpy > oend - MATCH_SAFEGUARD_DISTANCE)) {
0421 BYTE * const oCopyLimit = oend - (WILDCOPYLENGTH - 1);
0422
0423 if (cpy > oend - LASTLITERALS) {
0424
0425
0426
0427
0428 goto _output_error;
0429 }
0430
0431 if (op < oCopyLimit) {
0432 LZ4_wildCopy(op, match, oCopyLimit);
0433 match += oCopyLimit - op;
0434 op = oCopyLimit;
0435 }
0436 while (op < cpy)
0437 *op++ = *match++;
0438 } else {
0439 LZ4_copy8(op, match);
0440 if (length > 16)
0441 LZ4_wildCopy(op + 8, match + 8, cpy);
0442 }
0443 op = cpy;
0444 }
0445
0446
0447 if (endOnInput) {
0448
0449 return (int) (((char *)op) - dst);
0450 } else {
0451
0452 return (int) (((const char *)ip) - src);
0453 }
0454
0455
0456 _output_error:
0457 return (int) (-(((const char *)ip) - src)) - 1;
0458 }
0459
0460 int LZ4_decompress_safe(const char *source, char *dest,
0461 int compressedSize, int maxDecompressedSize)
0462 {
0463 return LZ4_decompress_generic(source, dest,
0464 compressedSize, maxDecompressedSize,
0465 endOnInputSize, decode_full_block,
0466 noDict, (BYTE *)dest, NULL, 0);
0467 }
0468
0469 int LZ4_decompress_safe_partial(const char *src, char *dst,
0470 int compressedSize, int targetOutputSize, int dstCapacity)
0471 {
0472 dstCapacity = min(targetOutputSize, dstCapacity);
0473 return LZ4_decompress_generic(src, dst, compressedSize, dstCapacity,
0474 endOnInputSize, partial_decode,
0475 noDict, (BYTE *)dst, NULL, 0);
0476 }
0477
0478 int LZ4_decompress_fast(const char *source, char *dest, int originalSize)
0479 {
0480 return LZ4_decompress_generic(source, dest, 0, originalSize,
0481 endOnOutputSize, decode_full_block,
0482 withPrefix64k,
0483 (BYTE *)dest - 64 * KB, NULL, 0);
0484 }
0485
0486
0487
0488 static int LZ4_decompress_safe_withPrefix64k(const char *source, char *dest,
0489 int compressedSize, int maxOutputSize)
0490 {
0491 return LZ4_decompress_generic(source, dest,
0492 compressedSize, maxOutputSize,
0493 endOnInputSize, decode_full_block,
0494 withPrefix64k,
0495 (BYTE *)dest - 64 * KB, NULL, 0);
0496 }
0497
0498 static int LZ4_decompress_safe_withSmallPrefix(const char *source, char *dest,
0499 int compressedSize,
0500 int maxOutputSize,
0501 size_t prefixSize)
0502 {
0503 return LZ4_decompress_generic(source, dest,
0504 compressedSize, maxOutputSize,
0505 endOnInputSize, decode_full_block,
0506 noDict,
0507 (BYTE *)dest - prefixSize, NULL, 0);
0508 }
0509
0510 static int LZ4_decompress_safe_forceExtDict(const char *source, char *dest,
0511 int compressedSize, int maxOutputSize,
0512 const void *dictStart, size_t dictSize)
0513 {
0514 return LZ4_decompress_generic(source, dest,
0515 compressedSize, maxOutputSize,
0516 endOnInputSize, decode_full_block,
0517 usingExtDict, (BYTE *)dest,
0518 (const BYTE *)dictStart, dictSize);
0519 }
0520
0521 static int LZ4_decompress_fast_extDict(const char *source, char *dest,
0522 int originalSize,
0523 const void *dictStart, size_t dictSize)
0524 {
0525 return LZ4_decompress_generic(source, dest,
0526 0, originalSize,
0527 endOnOutputSize, decode_full_block,
0528 usingExtDict, (BYTE *)dest,
0529 (const BYTE *)dictStart, dictSize);
0530 }
0531
0532
0533
0534
0535
0536
0537 static FORCE_INLINE
0538 int LZ4_decompress_safe_doubleDict(const char *source, char *dest,
0539 int compressedSize, int maxOutputSize,
0540 size_t prefixSize,
0541 const void *dictStart, size_t dictSize)
0542 {
0543 return LZ4_decompress_generic(source, dest,
0544 compressedSize, maxOutputSize,
0545 endOnInputSize, decode_full_block,
0546 usingExtDict, (BYTE *)dest - prefixSize,
0547 (const BYTE *)dictStart, dictSize);
0548 }
0549
0550 static FORCE_INLINE
0551 int LZ4_decompress_fast_doubleDict(const char *source, char *dest,
0552 int originalSize, size_t prefixSize,
0553 const void *dictStart, size_t dictSize)
0554 {
0555 return LZ4_decompress_generic(source, dest,
0556 0, originalSize,
0557 endOnOutputSize, decode_full_block,
0558 usingExtDict, (BYTE *)dest - prefixSize,
0559 (const BYTE *)dictStart, dictSize);
0560 }
0561
0562
0563
0564 int LZ4_setStreamDecode(LZ4_streamDecode_t *LZ4_streamDecode,
0565 const char *dictionary, int dictSize)
0566 {
0567 LZ4_streamDecode_t_internal *lz4sd =
0568 &LZ4_streamDecode->internal_donotuse;
0569
0570 lz4sd->prefixSize = (size_t) dictSize;
0571 lz4sd->prefixEnd = (const BYTE *) dictionary + dictSize;
0572 lz4sd->externalDict = NULL;
0573 lz4sd->extDictSize = 0;
0574 return 1;
0575 }
0576
0577
0578
0579
0580
0581
0582
0583
0584
0585
0586
0587 int LZ4_decompress_safe_continue(LZ4_streamDecode_t *LZ4_streamDecode,
0588 const char *source, char *dest, int compressedSize, int maxOutputSize)
0589 {
0590 LZ4_streamDecode_t_internal *lz4sd =
0591 &LZ4_streamDecode->internal_donotuse;
0592 int result;
0593
0594 if (lz4sd->prefixSize == 0) {
0595
0596 assert(lz4sd->extDictSize == 0);
0597 result = LZ4_decompress_safe(source, dest,
0598 compressedSize, maxOutputSize);
0599 if (result <= 0)
0600 return result;
0601 lz4sd->prefixSize = result;
0602 lz4sd->prefixEnd = (BYTE *)dest + result;
0603 } else if (lz4sd->prefixEnd == (BYTE *)dest) {
0604
0605 if (lz4sd->prefixSize >= 64 * KB - 1)
0606 result = LZ4_decompress_safe_withPrefix64k(source, dest,
0607 compressedSize, maxOutputSize);
0608 else if (lz4sd->extDictSize == 0)
0609 result = LZ4_decompress_safe_withSmallPrefix(source,
0610 dest, compressedSize, maxOutputSize,
0611 lz4sd->prefixSize);
0612 else
0613 result = LZ4_decompress_safe_doubleDict(source, dest,
0614 compressedSize, maxOutputSize,
0615 lz4sd->prefixSize,
0616 lz4sd->externalDict, lz4sd->extDictSize);
0617 if (result <= 0)
0618 return result;
0619 lz4sd->prefixSize += result;
0620 lz4sd->prefixEnd += result;
0621 } else {
0622
0623
0624
0625
0626 lz4sd->extDictSize = lz4sd->prefixSize;
0627 lz4sd->externalDict = lz4sd->prefixEnd - lz4sd->extDictSize;
0628 result = LZ4_decompress_safe_forceExtDict(source, dest,
0629 compressedSize, maxOutputSize,
0630 lz4sd->externalDict, lz4sd->extDictSize);
0631 if (result <= 0)
0632 return result;
0633 lz4sd->prefixSize = result;
0634 lz4sd->prefixEnd = (BYTE *)dest + result;
0635 }
0636
0637 return result;
0638 }
0639
0640 int LZ4_decompress_fast_continue(LZ4_streamDecode_t *LZ4_streamDecode,
0641 const char *source, char *dest, int originalSize)
0642 {
0643 LZ4_streamDecode_t_internal *lz4sd = &LZ4_streamDecode->internal_donotuse;
0644 int result;
0645
0646 if (lz4sd->prefixSize == 0) {
0647 assert(lz4sd->extDictSize == 0);
0648 result = LZ4_decompress_fast(source, dest, originalSize);
0649 if (result <= 0)
0650 return result;
0651 lz4sd->prefixSize = originalSize;
0652 lz4sd->prefixEnd = (BYTE *)dest + originalSize;
0653 } else if (lz4sd->prefixEnd == (BYTE *)dest) {
0654 if (lz4sd->prefixSize >= 64 * KB - 1 ||
0655 lz4sd->extDictSize == 0)
0656 result = LZ4_decompress_fast(source, dest,
0657 originalSize);
0658 else
0659 result = LZ4_decompress_fast_doubleDict(source, dest,
0660 originalSize, lz4sd->prefixSize,
0661 lz4sd->externalDict, lz4sd->extDictSize);
0662 if (result <= 0)
0663 return result;
0664 lz4sd->prefixSize += originalSize;
0665 lz4sd->prefixEnd += originalSize;
0666 } else {
0667 lz4sd->extDictSize = lz4sd->prefixSize;
0668 lz4sd->externalDict = lz4sd->prefixEnd - lz4sd->extDictSize;
0669 result = LZ4_decompress_fast_extDict(source, dest,
0670 originalSize, lz4sd->externalDict, lz4sd->extDictSize);
0671 if (result <= 0)
0672 return result;
0673 lz4sd->prefixSize = originalSize;
0674 lz4sd->prefixEnd = (BYTE *)dest + originalSize;
0675 }
0676 return result;
0677 }
0678
0679 int LZ4_decompress_safe_usingDict(const char *source, char *dest,
0680 int compressedSize, int maxOutputSize,
0681 const char *dictStart, int dictSize)
0682 {
0683 if (dictSize == 0)
0684 return LZ4_decompress_safe(source, dest,
0685 compressedSize, maxOutputSize);
0686 if (dictStart+dictSize == dest) {
0687 if (dictSize >= 64 * KB - 1)
0688 return LZ4_decompress_safe_withPrefix64k(source, dest,
0689 compressedSize, maxOutputSize);
0690 return LZ4_decompress_safe_withSmallPrefix(source, dest,
0691 compressedSize, maxOutputSize, dictSize);
0692 }
0693 return LZ4_decompress_safe_forceExtDict(source, dest,
0694 compressedSize, maxOutputSize, dictStart, dictSize);
0695 }
0696
0697 int LZ4_decompress_fast_usingDict(const char *source, char *dest,
0698 int originalSize,
0699 const char *dictStart, int dictSize)
0700 {
0701 if (dictSize == 0 || dictStart + dictSize == dest)
0702 return LZ4_decompress_fast(source, dest, originalSize);
0703
0704 return LZ4_decompress_fast_extDict(source, dest, originalSize,
0705 dictStart, dictSize);
0706 }
0707
0708 #ifndef STATIC
0709 EXPORT_SYMBOL(LZ4_decompress_safe);
0710 EXPORT_SYMBOL(LZ4_decompress_safe_partial);
0711 EXPORT_SYMBOL(LZ4_decompress_fast);
0712 EXPORT_SYMBOL(LZ4_setStreamDecode);
0713 EXPORT_SYMBOL(LZ4_decompress_safe_continue);
0714 EXPORT_SYMBOL(LZ4_decompress_fast_continue);
0715 EXPORT_SYMBOL(LZ4_decompress_safe_usingDict);
0716 EXPORT_SYMBOL(LZ4_decompress_fast_usingDict);
0717
0718 MODULE_LICENSE("Dual BSD/GPL");
0719 MODULE_DESCRIPTION("LZ4 decompressor");
0720 #endif