1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36#include <linux/lz4.h>
37#include "lz4defs.h"
38#include <linux/init.h>
39#include <linux/module.h>
40#include <linux/kernel.h>
41#include <asm/unaligned.h>
42
43
44
45
46
47#define DEBUGLOG(l, ...) {}
48
49#ifndef assert
50#define assert(condition) ((void)0)
51#endif
52
53
54
55
56
57
58
59
60static FORCE_INLINE int LZ4_decompress_generic(
61 const char * const src,
62 char * const dst,
63 int srcSize,
64
65
66
67
68 int outputSize,
69
70 endCondition_directive endOnInput,
71
72 earlyEnd_directive partialDecoding,
73
74 dict_directive dict,
75
76 const BYTE * const lowPrefix,
77
78 const BYTE * const dictStart,
79
80 const size_t dictSize
81 )
82{
83 const BYTE *ip = (const BYTE *) src;
84 const BYTE * const iend = ip + srcSize;
85
86 BYTE *op = (BYTE *) dst;
87 BYTE * const oend = op + outputSize;
88 BYTE *cpy;
89
90 const BYTE * const dictEnd = (const BYTE *)dictStart + dictSize;
91 static const unsigned int inc32table[8] = {0, 1, 2, 1, 0, 4, 4, 4};
92 static const int dec64table[8] = {0, 0, 0, -1, -4, 1, 2, 3};
93
94 const int safeDecode = (endOnInput == endOnInputSize);
95 const int checkOffset = ((safeDecode) && (dictSize < (int)(64 * KB)));
96
97
98 const BYTE *const shortiend = iend -
99 (endOnInput ? 14 : 8) - 2 ;
100 const BYTE *const shortoend = oend -
101 (endOnInput ? 14 : 8) - 18 ;
102
103 DEBUGLOG(5, "%s (srcSize:%i, dstSize:%i)", __func__,
104 srcSize, outputSize);
105
106
107 assert(lowPrefix <= op);
108 assert(src != NULL);
109
110
111 if ((endOnInput) && (unlikely(outputSize == 0)))
112 return ((srcSize == 1) && (*ip == 0)) ? 0 : -1;
113
114 if ((!endOnInput) && (unlikely(outputSize == 0)))
115 return (*ip == 0 ? 1 : -1);
116
117 if ((endOnInput) && unlikely(srcSize == 0))
118 return -1;
119
120
121 while (1) {
122 size_t length;
123 const BYTE *match;
124 size_t offset;
125
126
127 unsigned int const token = *ip++;
128 length = token>>ML_BITS;
129
130
131 assert(!endOnInput || ip <= iend);
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148 if ((endOnInput ? length != RUN_MASK : length <= 8)
149
150
151
152
153 && likely((endOnInput ? ip < shortiend : 1) &
154 (op <= shortoend))) {
155
156 LZ4_memcpy(op, ip, endOnInput ? 16 : 8);
157 op += length; ip += length;
158
159
160
161
162
163
164 length = token & ML_MASK;
165 offset = LZ4_readLE16(ip);
166 ip += 2;
167 match = op - offset;
168 assert(match <= op);
169
170
171 if ((length != ML_MASK) &&
172 (offset >= 8) &&
173 (dict == withPrefix64k || match >= lowPrefix)) {
174
175 LZ4_memcpy(op + 0, match + 0, 8);
176 LZ4_memcpy(op + 8, match + 8, 8);
177 LZ4_memcpy(op + 16, match + 16, 2);
178 op += length + MINMATCH;
179
180 continue;
181 }
182
183
184
185
186
187
188 goto _copy_match;
189 }
190
191
192 if (length == RUN_MASK) {
193 unsigned int s;
194
195 if (unlikely(endOnInput ? ip >= iend - RUN_MASK : 0)) {
196
197 goto _output_error;
198 }
199 do {
200 s = *ip++;
201 length += s;
202 } while (likely(endOnInput
203 ? ip < iend - RUN_MASK
204 : 1) & (s == 255));
205
206 if ((safeDecode)
207 && unlikely((uptrval)(op) +
208 length < (uptrval)(op))) {
209
210 goto _output_error;
211 }
212 if ((safeDecode)
213 && unlikely((uptrval)(ip) +
214 length < (uptrval)(ip))) {
215
216 goto _output_error;
217 }
218 }
219
220
221 cpy = op + length;
222 LZ4_STATIC_ASSERT(MFLIMIT >= WILDCOPYLENGTH);
223
224 if (((endOnInput) && ((cpy > oend - MFLIMIT)
225 || (ip + length > iend - (2 + 1 + LASTLITERALS))))
226 || ((!endOnInput) && (cpy > oend - WILDCOPYLENGTH))) {
227 if (partialDecoding) {
228 if (cpy > oend) {
229
230
231
232
233 cpy = oend;
234 length = oend - op;
235 }
236 if ((endOnInput)
237 && (ip + length > iend)) {
238
239
240
241
242
243 goto _output_error;
244 }
245 } else {
246 if ((!endOnInput)
247 && (cpy != oend)) {
248
249
250
251
252
253 goto _output_error;
254 }
255 if ((endOnInput)
256 && ((ip + length != iend)
257 || (cpy > oend))) {
258
259
260
261
262 goto _output_error;
263 }
264 }
265
266
267
268
269
270 LZ4_memmove(op, ip, length);
271 ip += length;
272 op += length;
273
274
275 if (!partialDecoding || (cpy == oend))
276 break;
277 } else {
278
279 LZ4_wildCopy(op, ip, cpy);
280 ip += length;
281 op = cpy;
282 }
283
284
285 offset = LZ4_readLE16(ip);
286 ip += 2;
287 match = op - offset;
288
289
290 length = token & ML_MASK;
291
292_copy_match:
293 if ((checkOffset) && (unlikely(match + dictSize < lowPrefix))) {
294
295 goto _output_error;
296 }
297
298
299
300
301
302
303 if (!partialDecoding) {
304 assert(oend > op);
305 assert(oend - op >= 4);
306
307 LZ4_write32(op, (U32)offset);
308 }
309
310 if (length == ML_MASK) {
311 unsigned int s;
312
313 do {
314 s = *ip++;
315
316 if ((endOnInput) && (ip > iend - LASTLITERALS))
317 goto _output_error;
318
319 length += s;
320 } while (s == 255);
321
322 if ((safeDecode)
323 && unlikely(
324 (uptrval)(op) + length < (uptrval)op)) {
325
326 goto _output_error;
327 }
328 }
329
330 length += MINMATCH;
331
332
333 if ((dict == usingExtDict) && (match < lowPrefix)) {
334 if (unlikely(op + length > oend - LASTLITERALS)) {
335
336 if (!partialDecoding)
337 goto _output_error;
338 length = min(length, (size_t)(oend - op));
339 }
340
341 if (length <= (size_t)(lowPrefix - match)) {
342
343
344
345
346 memmove(op, dictEnd - (lowPrefix - match),
347 length);
348 op += length;
349 } else {
350
351
352
353
354 size_t const copySize = (size_t)(lowPrefix - match);
355 size_t const restSize = length - copySize;
356
357 LZ4_memcpy(op, dictEnd - copySize, copySize);
358 op += copySize;
359 if (restSize > (size_t)(op - lowPrefix)) {
360
361 BYTE * const endOfMatch = op + restSize;
362 const BYTE *copyFrom = lowPrefix;
363
364 while (op < endOfMatch)
365 *op++ = *copyFrom++;
366 } else {
367 LZ4_memcpy(op, lowPrefix, restSize);
368 op += restSize;
369 }
370 }
371 continue;
372 }
373
374
375 cpy = op + length;
376
377
378
379
380
381 assert(op <= oend);
382 if (partialDecoding &&
383 (cpy > oend - MATCH_SAFEGUARD_DISTANCE)) {
384 size_t const mlen = min(length, (size_t)(oend - op));
385 const BYTE * const matchEnd = match + mlen;
386 BYTE * const copyEnd = op + mlen;
387
388 if (matchEnd > op) {
389
390 while (op < copyEnd)
391 *op++ = *match++;
392 } else {
393 LZ4_memcpy(op, match, mlen);
394 }
395 op = copyEnd;
396 if (op == oend)
397 break;
398 continue;
399 }
400
401 if (unlikely(offset < 8)) {
402 op[0] = match[0];
403 op[1] = match[1];
404 op[2] = match[2];
405 op[3] = match[3];
406 match += inc32table[offset];
407 LZ4_memcpy(op + 4, match, 4);
408 match -= dec64table[offset];
409 } else {
410 LZ4_copy8(op, match);
411 match += 8;
412 }
413
414 op += 8;
415
416 if (unlikely(cpy > oend - MATCH_SAFEGUARD_DISTANCE)) {
417 BYTE * const oCopyLimit = oend - (WILDCOPYLENGTH - 1);
418
419 if (cpy > oend - LASTLITERALS) {
420
421
422
423
424 goto _output_error;
425 }
426
427 if (op < oCopyLimit) {
428 LZ4_wildCopy(op, match, oCopyLimit);
429 match += oCopyLimit - op;
430 op = oCopyLimit;
431 }
432 while (op < cpy)
433 *op++ = *match++;
434 } else {
435 LZ4_copy8(op, match);
436 if (length > 16)
437 LZ4_wildCopy(op + 8, match + 8, cpy);
438 }
439 op = cpy;
440 }
441
442
443 if (endOnInput) {
444
445 return (int) (((char *)op) - dst);
446 } else {
447
448 return (int) (((const char *)ip) - src);
449 }
450
451
452_output_error:
453 return (int) (-(((const char *)ip) - src)) - 1;
454}
455
456int LZ4_decompress_safe(const char *source, char *dest,
457 int compressedSize, int maxDecompressedSize)
458{
459 return LZ4_decompress_generic(source, dest,
460 compressedSize, maxDecompressedSize,
461 endOnInputSize, decode_full_block,
462 noDict, (BYTE *)dest, NULL, 0);
463}
464
465int LZ4_decompress_safe_partial(const char *src, char *dst,
466 int compressedSize, int targetOutputSize, int dstCapacity)
467{
468 dstCapacity = min(targetOutputSize, dstCapacity);
469 return LZ4_decompress_generic(src, dst, compressedSize, dstCapacity,
470 endOnInputSize, partial_decode,
471 noDict, (BYTE *)dst, NULL, 0);
472}
473
474int LZ4_decompress_fast(const char *source, char *dest, int originalSize)
475{
476 return LZ4_decompress_generic(source, dest, 0, originalSize,
477 endOnOutputSize, decode_full_block,
478 withPrefix64k,
479 (BYTE *)dest - 64 * KB, NULL, 0);
480}
481
482
483
484int LZ4_decompress_safe_withPrefix64k(const char *source, char *dest,
485 int compressedSize, int maxOutputSize)
486{
487 return LZ4_decompress_generic(source, dest,
488 compressedSize, maxOutputSize,
489 endOnInputSize, decode_full_block,
490 withPrefix64k,
491 (BYTE *)dest - 64 * KB, NULL, 0);
492}
493
494static int LZ4_decompress_safe_withSmallPrefix(const char *source, char *dest,
495 int compressedSize,
496 int maxOutputSize,
497 size_t prefixSize)
498{
499 return LZ4_decompress_generic(source, dest,
500 compressedSize, maxOutputSize,
501 endOnInputSize, decode_full_block,
502 noDict,
503 (BYTE *)dest - prefixSize, NULL, 0);
504}
505
506int LZ4_decompress_safe_forceExtDict(const char *source, char *dest,
507 int compressedSize, int maxOutputSize,
508 const void *dictStart, size_t dictSize)
509{
510 return LZ4_decompress_generic(source, dest,
511 compressedSize, maxOutputSize,
512 endOnInputSize, decode_full_block,
513 usingExtDict, (BYTE *)dest,
514 (const BYTE *)dictStart, dictSize);
515}
516
517static int LZ4_decompress_fast_extDict(const char *source, char *dest,
518 int originalSize,
519 const void *dictStart, size_t dictSize)
520{
521 return LZ4_decompress_generic(source, dest,
522 0, originalSize,
523 endOnOutputSize, decode_full_block,
524 usingExtDict, (BYTE *)dest,
525 (const BYTE *)dictStart, dictSize);
526}
527
528
529
530
531
532
533static FORCE_INLINE
534int LZ4_decompress_safe_doubleDict(const char *source, char *dest,
535 int compressedSize, int maxOutputSize,
536 size_t prefixSize,
537 const void *dictStart, size_t dictSize)
538{
539 return LZ4_decompress_generic(source, dest,
540 compressedSize, maxOutputSize,
541 endOnInputSize, decode_full_block,
542 usingExtDict, (BYTE *)dest - prefixSize,
543 (const BYTE *)dictStart, dictSize);
544}
545
546static FORCE_INLINE
547int LZ4_decompress_fast_doubleDict(const char *source, char *dest,
548 int originalSize, size_t prefixSize,
549 const void *dictStart, size_t dictSize)
550{
551 return LZ4_decompress_generic(source, dest,
552 0, originalSize,
553 endOnOutputSize, decode_full_block,
554 usingExtDict, (BYTE *)dest - prefixSize,
555 (const BYTE *)dictStart, dictSize);
556}
557
558
559
560int LZ4_setStreamDecode(LZ4_streamDecode_t *LZ4_streamDecode,
561 const char *dictionary, int dictSize)
562{
563 LZ4_streamDecode_t_internal *lz4sd =
564 &LZ4_streamDecode->internal_donotuse;
565
566 lz4sd->prefixSize = (size_t) dictSize;
567 lz4sd->prefixEnd = (const BYTE *) dictionary + dictSize;
568 lz4sd->externalDict = NULL;
569 lz4sd->extDictSize = 0;
570 return 1;
571}
572
573
574
575
576
577
578
579
580
581
582
583int LZ4_decompress_safe_continue(LZ4_streamDecode_t *LZ4_streamDecode,
584 const char *source, char *dest, int compressedSize, int maxOutputSize)
585{
586 LZ4_streamDecode_t_internal *lz4sd =
587 &LZ4_streamDecode->internal_donotuse;
588 int result;
589
590 if (lz4sd->prefixSize == 0) {
591
592 assert(lz4sd->extDictSize == 0);
593 result = LZ4_decompress_safe(source, dest,
594 compressedSize, maxOutputSize);
595 if (result <= 0)
596 return result;
597 lz4sd->prefixSize = result;
598 lz4sd->prefixEnd = (BYTE *)dest + result;
599 } else if (lz4sd->prefixEnd == (BYTE *)dest) {
600
601 if (lz4sd->prefixSize >= 64 * KB - 1)
602 result = LZ4_decompress_safe_withPrefix64k(source, dest,
603 compressedSize, maxOutputSize);
604 else if (lz4sd->extDictSize == 0)
605 result = LZ4_decompress_safe_withSmallPrefix(source,
606 dest, compressedSize, maxOutputSize,
607 lz4sd->prefixSize);
608 else
609 result = LZ4_decompress_safe_doubleDict(source, dest,
610 compressedSize, maxOutputSize,
611 lz4sd->prefixSize,
612 lz4sd->externalDict, lz4sd->extDictSize);
613 if (result <= 0)
614 return result;
615 lz4sd->prefixSize += result;
616 lz4sd->prefixEnd += result;
617 } else {
618
619
620
621
622 lz4sd->extDictSize = lz4sd->prefixSize;
623 lz4sd->externalDict = lz4sd->prefixEnd - lz4sd->extDictSize;
624 result = LZ4_decompress_safe_forceExtDict(source, dest,
625 compressedSize, maxOutputSize,
626 lz4sd->externalDict, lz4sd->extDictSize);
627 if (result <= 0)
628 return result;
629 lz4sd->prefixSize = result;
630 lz4sd->prefixEnd = (BYTE *)dest + result;
631 }
632
633 return result;
634}
635
636int LZ4_decompress_fast_continue(LZ4_streamDecode_t *LZ4_streamDecode,
637 const char *source, char *dest, int originalSize)
638{
639 LZ4_streamDecode_t_internal *lz4sd = &LZ4_streamDecode->internal_donotuse;
640 int result;
641
642 if (lz4sd->prefixSize == 0) {
643 assert(lz4sd->extDictSize == 0);
644 result = LZ4_decompress_fast(source, dest, originalSize);
645 if (result <= 0)
646 return result;
647 lz4sd->prefixSize = originalSize;
648 lz4sd->prefixEnd = (BYTE *)dest + originalSize;
649 } else if (lz4sd->prefixEnd == (BYTE *)dest) {
650 if (lz4sd->prefixSize >= 64 * KB - 1 ||
651 lz4sd->extDictSize == 0)
652 result = LZ4_decompress_fast(source, dest,
653 originalSize);
654 else
655 result = LZ4_decompress_fast_doubleDict(source, dest,
656 originalSize, lz4sd->prefixSize,
657 lz4sd->externalDict, lz4sd->extDictSize);
658 if (result <= 0)
659 return result;
660 lz4sd->prefixSize += originalSize;
661 lz4sd->prefixEnd += originalSize;
662 } else {
663 lz4sd->extDictSize = lz4sd->prefixSize;
664 lz4sd->externalDict = lz4sd->prefixEnd - lz4sd->extDictSize;
665 result = LZ4_decompress_fast_extDict(source, dest,
666 originalSize, lz4sd->externalDict, lz4sd->extDictSize);
667 if (result <= 0)
668 return result;
669 lz4sd->prefixSize = originalSize;
670 lz4sd->prefixEnd = (BYTE *)dest + originalSize;
671 }
672 return result;
673}
674
675int LZ4_decompress_safe_usingDict(const char *source, char *dest,
676 int compressedSize, int maxOutputSize,
677 const char *dictStart, int dictSize)
678{
679 if (dictSize == 0)
680 return LZ4_decompress_safe(source, dest,
681 compressedSize, maxOutputSize);
682 if (dictStart+dictSize == dest) {
683 if (dictSize >= 64 * KB - 1)
684 return LZ4_decompress_safe_withPrefix64k(source, dest,
685 compressedSize, maxOutputSize);
686 return LZ4_decompress_safe_withSmallPrefix(source, dest,
687 compressedSize, maxOutputSize, dictSize);
688 }
689 return LZ4_decompress_safe_forceExtDict(source, dest,
690 compressedSize, maxOutputSize, dictStart, dictSize);
691}
692
693int LZ4_decompress_fast_usingDict(const char *source, char *dest,
694 int originalSize,
695 const char *dictStart, int dictSize)
696{
697 if (dictSize == 0 || dictStart + dictSize == dest)
698 return LZ4_decompress_fast(source, dest, originalSize);
699
700 return LZ4_decompress_fast_extDict(source, dest, originalSize,
701 dictStart, dictSize);
702}
703
704#ifndef STATIC
705EXPORT_SYMBOL(LZ4_decompress_safe);
706EXPORT_SYMBOL(LZ4_decompress_safe_partial);
707EXPORT_SYMBOL(LZ4_decompress_fast);
708EXPORT_SYMBOL(LZ4_setStreamDecode);
709EXPORT_SYMBOL(LZ4_decompress_safe_continue);
710EXPORT_SYMBOL(LZ4_decompress_fast_continue);
711EXPORT_SYMBOL(LZ4_decompress_safe_usingDict);
712EXPORT_SYMBOL(LZ4_decompress_fast_usingDict);
713
714MODULE_LICENSE("Dual BSD/GPL");
715MODULE_DESCRIPTION("LZ4 decompressor");
716#endif
717