aboutsummaryrefslogtreecommitdiffstats
path: root/lib/lz4/lz4_decompress.c
diff options
context:
space:
mode:
Diffstat (limited to 'lib/lz4/lz4_decompress.c')
-rw-r--r--lib/lz4/lz4_decompress.c665
1 files changed, 415 insertions, 250 deletions
diff --git a/lib/lz4/lz4_decompress.c b/lib/lz4/lz4_decompress.c
index 6d940c72b5fc..bd3574312b82 100644
--- a/lib/lz4/lz4_decompress.c
+++ b/lib/lz4/lz4_decompress.c
@@ -1,25 +1,16 @@
1/* 1/*
2 * LZ4 Decompressor for Linux kernel
3 *
4 * Copyright (C) 2013, LG Electronics, Kyungsik Lee <kyungsik.lee@lge.com>
5 *
6 * Based on LZ4 implementation by Yann Collet.
7 *
8 * LZ4 - Fast LZ compression algorithm 2 * LZ4 - Fast LZ compression algorithm
9 * Copyright (C) 2011-2012, Yann Collet. 3 * Copyright (C) 2011 - 2016, Yann Collet.
10 * BSD 2-Clause License (http://www.opensource.org/licenses/bsd-license.php) 4 * BSD 2 - Clause License (http://www.opensource.org/licenses/bsd - license.php)
11 *
12 * Redistribution and use in source and binary forms, with or without 5 * Redistribution and use in source and binary forms, with or without
13 * modification, are permitted provided that the following conditions are 6 * modification, are permitted provided that the following conditions are
14 * met: 7 * met:
15 * 8 * * Redistributions of source code must retain the above copyright
16 * * Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer.
17 * notice, this list of conditions and the following disclaimer. 10 * * Redistributions in binary form must reproduce the above
18 * * Redistributions in binary form must reproduce the above
19 * copyright notice, this list of conditions and the following disclaimer 11 * copyright notice, this list of conditions and the following disclaimer
20 * in the documentation and/or other materials provided with the 12 * in the documentation and/or other materials provided with the
21 * distribution. 13 * distribution.
22 *
23 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 14 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
24 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 15 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
25 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 16 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
@@ -31,313 +22,487 @@
31 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 22 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 23 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
33 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25 * You can contact the author at :
26 * - LZ4 homepage : http://www.lz4.org
27 * - LZ4 source repository : https://github.com/lz4/lz4
34 * 28 *
35 * You can contact the author at : 29 * Changed for kernel usage by:
36 * - LZ4 homepage : http://fastcompression.blogspot.com/p/lz4.html 30 * Sven Schmidt <4sschmid@informatik.uni-hamburg.de>
37 * - LZ4 source repository : http://code.google.com/p/lz4/
38 */ 31 */
39 32
40#ifndef STATIC 33/*-************************************
34 * Dependencies
35 **************************************/
36#include <linux/lz4.h>
37#include "lz4defs.h"
38#include <linux/init.h>
41#include <linux/module.h> 39#include <linux/module.h>
42#include <linux/kernel.h> 40#include <linux/kernel.h>
43#endif
44#include <linux/lz4.h>
45
46#include <asm/unaligned.h> 41#include <asm/unaligned.h>
47 42
48#include "lz4defs.h" 43/*-*****************************
49 44 * Decompression functions
50static const int dec32table[] = {0, 3, 2, 3, 0, 0, 0, 0}; 45 *******************************/
51#if LZ4_ARCH64 46/* LZ4_decompress_generic() :
52static const int dec64table[] = {0, 0, 0, -1, 0, 1, 2, 3}; 47 * This generic decompression function cover all use cases.
53#endif 48 * It shall be instantiated several times, using different sets of directives
54 49 * Note that it is important this generic function is really inlined,
55static int lz4_uncompress(const char *source, char *dest, int osize) 50 * in order to remove useless branches during compilation optimization.
51 */
52static FORCE_INLINE int LZ4_decompress_generic(
53 const char * const source,
54 char * const dest,
55 int inputSize,
56 /*
57 * If endOnInput == endOnInputSize,
58 * this value is the max size of Output Buffer.
59 */
60 int outputSize,
61 /* endOnOutputSize, endOnInputSize */
62 int endOnInput,
63 /* full, partial */
64 int partialDecoding,
65 /* only used if partialDecoding == partial */
66 int targetOutputSize,
67 /* noDict, withPrefix64k, usingExtDict */
68 int dict,
69 /* == dest when no prefix */
70 const BYTE * const lowPrefix,
71 /* only if dict == usingExtDict */
72 const BYTE * const dictStart,
73 /* note : = 0 if noDict */
74 const size_t dictSize
75 )
56{ 76{
77 /* Local Variables */
57 const BYTE *ip = (const BYTE *) source; 78 const BYTE *ip = (const BYTE *) source;
58 const BYTE *ref; 79 const BYTE * const iend = ip + inputSize;
80
59 BYTE *op = (BYTE *) dest; 81 BYTE *op = (BYTE *) dest;
60 BYTE * const oend = op + osize; 82 BYTE * const oend = op + outputSize;
61 BYTE *cpy; 83 BYTE *cpy;
62 unsigned token; 84 BYTE *oexit = op + targetOutputSize;
63 size_t length; 85 const BYTE * const lowLimit = lowPrefix - dictSize;
64 86
87 const BYTE * const dictEnd = (const BYTE *)dictStart + dictSize;
88 const unsigned int dec32table[] = { 0, 1, 2, 1, 4, 4, 4, 4 };
89 const int dec64table[] = { 0, 0, 0, -1, 0, 1, 2, 3 };
90
91 const int safeDecode = (endOnInput == endOnInputSize);
92 const int checkOffset = ((safeDecode) && (dictSize < (int)(64 * KB)));
93
94 /* Special cases */
95 /* targetOutputSize too high => decode everything */
96 if ((partialDecoding) && (oexit > oend - MFLIMIT))
97 oexit = oend - MFLIMIT;
98
99 /* Empty output buffer */
100 if ((endOnInput) && (unlikely(outputSize == 0)))
101 return ((inputSize == 1) && (*ip == 0)) ? 0 : -1;
102
103 if ((!endOnInput) && (unlikely(outputSize == 0)))
104 return (*ip == 0 ? 1 : -1);
105
106 /* Main Loop : decode sequences */
65 while (1) { 107 while (1) {
108 size_t length;
109 const BYTE *match;
110 size_t offset;
111
112 /* get literal length */
113 unsigned int const token = *ip++;
114
115 length = token>>ML_BITS;
66 116
67 /* get runlength */
68 token = *ip++;
69 length = (token >> ML_BITS);
70 if (length == RUN_MASK) { 117 if (length == RUN_MASK) {
71 size_t len; 118 unsigned int s;
72 119
73 len = *ip++; 120 do {
74 for (; len == 255; length += 255) 121 s = *ip++;
75 len = *ip++; 122 length += s;
76 if (unlikely(length > (size_t)(length + len))) 123 } while (likely(endOnInput
124 ? ip < iend - RUN_MASK
125 : 1) & (s == 255));
126
127 if ((safeDecode)
128 && unlikely(
129 (size_t)(op + length) < (size_t)(op))) {
130 /* overflow detection */
131 goto _output_error;
132 }
133 if ((safeDecode)
134 && unlikely(
135 (size_t)(ip + length) < (size_t)(ip))) {
136 /* overflow detection */
77 goto _output_error; 137 goto _output_error;
78 length += len; 138 }
79 } 139 }
80 140
81 /* copy literals */ 141 /* copy literals */
82 cpy = op + length; 142 cpy = op + length;
83 if (unlikely(cpy > oend - COPYLENGTH)) { 143 if (((endOnInput) && ((cpy > (partialDecoding ? oexit : oend - MFLIMIT))
84 /* 144 || (ip + length > iend - (2 + 1 + LASTLITERALS))))
85 * Error: not enough place for another match 145 || ((!endOnInput) && (cpy > oend - WILDCOPYLENGTH))) {
86 * (min 4) + 5 literals 146 if (partialDecoding) {
87 */ 147 if (cpy > oend) {
88 if (cpy != oend) 148 /*
89 goto _output_error; 149 * Error :
150 * write attempt beyond end of output buffer
151 */
152 goto _output_error;
153 }
154 if ((endOnInput)
155 && (ip + length > iend)) {
156 /*
157 * Error :
158 * read attempt beyond
159 * end of input buffer
160 */
161 goto _output_error;
162 }
163 } else {
164 if ((!endOnInput)
165 && (cpy != oend)) {
166 /*
167 * Error :
168 * block decoding must
169 * stop exactly there
170 */
171 goto _output_error;
172 }
173 if ((endOnInput)
174 && ((ip + length != iend)
175 || (cpy > oend))) {
176 /*
177 * Error :
178 * input must be consumed
179 */
180 goto _output_error;
181 }
182 }
90 183
91 memcpy(op, ip, length); 184 memcpy(op, ip, length);
92 ip += length; 185 ip += length;
93 break; /* EOF */ 186 op += length;
187 /* Necessarily EOF, due to parsing restrictions */
188 break;
94 } 189 }
95 LZ4_WILDCOPY(ip, op, cpy); 190
96 ip -= (op - cpy); 191 LZ4_wildCopy(op, ip, cpy);
192 ip += length;
97 op = cpy; 193 op = cpy;
98 194
99 /* get offset */ 195 /* get offset */
100 LZ4_READ_LITTLEENDIAN_16(ref, cpy, ip); 196 offset = LZ4_readLE16(ip);
101 ip += 2; 197 ip += 2;
198 match = op - offset;
102 199
103 /* Error: offset create reference outside destination buffer */ 200 if ((checkOffset) && (unlikely(match < lowLimit))) {
104 if (unlikely(ref < (BYTE *const) dest)) 201 /* Error : offset outside buffers */
105 goto _output_error; 202 goto _output_error;
203 }
204
205 /* costs ~1%; silence an msan warning when offset == 0 */
206 LZ4_write32(op, (U32)offset);
106 207
107 /* get matchlength */ 208 /* get matchlength */
108 length = token & ML_MASK; 209 length = token & ML_MASK;
109 if (length == ML_MASK) { 210 if (length == ML_MASK) {
110 for (; *ip == 255; length += 255) 211 unsigned int s;
111 ip++; 212
112 if (unlikely(length > (size_t)(length + *ip))) 213 do {
214 s = *ip++;
215
216 if ((endOnInput) && (ip > iend - LASTLITERALS))
217 goto _output_error;
218
219 length += s;
220 } while (s == 255);
221
222 if ((safeDecode)
223 && unlikely(
224 (size_t)(op + length) < (size_t)op)) {
225 /* overflow detection */
113 goto _output_error; 226 goto _output_error;
114 length += *ip++; 227 }
115 } 228 }
116 229
117 /* copy repeated sequence */ 230 length += MINMATCH;
118 if (unlikely((op - ref) < STEPSIZE)) { 231
119#if LZ4_ARCH64 232 /* check external dictionary */
120 int dec64 = dec64table[op - ref]; 233 if ((dict == usingExtDict) && (match < lowPrefix)) {
121#else 234 if (unlikely(op + length > oend - LASTLITERALS)) {
122 const int dec64 = 0; 235 /* doesn't respect parsing restriction */
123#endif 236 goto _output_error;
124 op[0] = ref[0]; 237 }
125 op[1] = ref[1]; 238
126 op[2] = ref[2]; 239 if (length <= (size_t)(lowPrefix - match)) {
127 op[3] = ref[3]; 240 /*
128 op += 4; 241 * match can be copied as a single segment
129 ref += 4; 242 * from external dictionary
130 ref -= dec32table[op-ref]; 243 */
131 PUT4(ref, op); 244 memmove(op, dictEnd - (lowPrefix - match),
132 op += STEPSIZE - 4; 245 length);
133 ref -= dec64; 246 op += length;
247 } else {
248 /*
249 * match encompass external
250 * dictionary and current block
251 */
252 size_t const copySize = (size_t)(lowPrefix - match);
253 size_t const restSize = length - copySize;
254
255 memcpy(op, dictEnd - copySize, copySize);
256 op += copySize;
257
258 if (restSize > (size_t)(op - lowPrefix)) {
259 /* overlap copy */
260 BYTE * const endOfMatch = op + restSize;
261 const BYTE *copyFrom = lowPrefix;
262
263 while (op < endOfMatch)
264 *op++ = *copyFrom++;
265 } else {
266 memcpy(op, lowPrefix, restSize);
267 op += restSize;
268 }
269 }
270
271 continue;
272 }
273
274 /* copy match within block */
275 cpy = op + length;
276
277 if (unlikely(offset < 8)) {
278 const int dec64 = dec64table[offset];
279
280 op[0] = match[0];
281 op[1] = match[1];
282 op[2] = match[2];
283 op[3] = match[3];
284 match += dec32table[offset];
285 memcpy(op + 4, match, 4);
286 match -= dec64;
134 } else { 287 } else {
135 LZ4_COPYSTEP(ref, op); 288 LZ4_copy8(op, match);
289 match += 8;
136 } 290 }
137 cpy = op + length - (STEPSIZE - 4);
138 if (cpy > (oend - COPYLENGTH)) {
139 291
140 /* Error: request to write beyond destination buffer */ 292 op += 8;
141 if (cpy > oend) 293
142 goto _output_error; 294 if (unlikely(cpy > oend - 12)) {
143#if LZ4_ARCH64 295 BYTE * const oCopyLimit = oend - (WILDCOPYLENGTH - 1);
144 if ((ref + COPYLENGTH) > oend) 296
145#else 297 if (cpy > oend - LASTLITERALS) {
146 if ((ref + COPYLENGTH) > oend || 298 /*
147 (op + COPYLENGTH) > oend) 299 * Error : last LASTLITERALS bytes
148#endif 300 * must be literals (uncompressed)
301 */
149 goto _output_error; 302 goto _output_error;
150 LZ4_SECURECOPY(ref, op, (oend - COPYLENGTH)); 303 }
304
305 if (op < oCopyLimit) {
306 LZ4_wildCopy(op, match, oCopyLimit);
307 match += oCopyLimit - op;
308 op = oCopyLimit;
309 }
310
151 while (op < cpy) 311 while (op < cpy)
152 *op++ = *ref++; 312 *op++ = *match++;
153 op = cpy; 313 } else {
154 /* 314 LZ4_copy8(op, match);
155 * Check EOF (should never happen, since last 5 bytes 315
156 * are supposed to be literals) 316 if (length > 16)
157 */ 317 LZ4_wildCopy(op + 8, match + 8, cpy);
158 if (op == oend)
159 goto _output_error;
160 continue;
161 } 318 }
162 LZ4_SECURECOPY(ref, op, cpy); 319
163 op = cpy; /* correction */ 320 op = cpy; /* correction */
164 } 321 }
322
165 /* end of decoding */ 323 /* end of decoding */
166 return (int) (((char *)ip) - source); 324 if (endOnInput) {
325 /* Nb of output bytes decoded */
326 return (int) (((char *)op) - dest);
327 } else {
328 /* Nb of input bytes read */
329 return (int) (((const char *)ip) - source);
330 }
167 331
168 /* write overflow error detected */ 332 /* Overflow error detected */
169_output_error: 333_output_error:
170 return -1; 334 return -1;
171} 335}
172 336
173static int lz4_uncompress_unknownoutputsize(const char *source, char *dest, 337int LZ4_decompress_safe(const char *source, char *dest,
174 int isize, size_t maxoutputsize) 338 int compressedSize, int maxDecompressedSize)
175{ 339{
176 const BYTE *ip = (const BYTE *) source; 340 return LZ4_decompress_generic(source, dest, compressedSize,
177 const BYTE *const iend = ip + isize; 341 maxDecompressedSize, endOnInputSize, full, 0,
178 const BYTE *ref; 342 noDict, (BYTE *)dest, NULL, 0);
179 343}
180 344
181 BYTE *op = (BYTE *) dest; 345int LZ4_decompress_safe_partial(const char *source, char *dest,
182 BYTE * const oend = op + maxoutputsize; 346 int compressedSize, int targetOutputSize, int maxDecompressedSize)
183 BYTE *cpy; 347{
348 return LZ4_decompress_generic(source, dest, compressedSize,
349 maxDecompressedSize, endOnInputSize, partial,
350 targetOutputSize, noDict, (BYTE *)dest, NULL, 0);
351}
184 352
185 /* Main Loop */ 353int LZ4_decompress_fast(const char *source, char *dest, int originalSize)
186 while (ip < iend) { 354{
355 return LZ4_decompress_generic(source, dest, 0, originalSize,
356 endOnOutputSize, full, 0, withPrefix64k,
357 (BYTE *)(dest - 64 * KB), NULL, 64 * KB);
358}
187 359
188 unsigned token; 360int LZ4_setStreamDecode(LZ4_streamDecode_t *LZ4_streamDecode,
189 size_t length; 361 const char *dictionary, int dictSize)
362{
363 LZ4_streamDecode_t_internal *lz4sd = (LZ4_streamDecode_t_internal *) LZ4_streamDecode;
190 364
191 /* get runlength */ 365 lz4sd->prefixSize = (size_t) dictSize;
192 token = *ip++; 366 lz4sd->prefixEnd = (const BYTE *) dictionary + dictSize;
193 length = (token >> ML_BITS); 367 lz4sd->externalDict = NULL;
194 if (length == RUN_MASK) { 368 lz4sd->extDictSize = 0;
195 int s = 255; 369 return 1;
196 while ((ip < iend) && (s == 255)) { 370}
197 s = *ip++;
198 if (unlikely(length > (size_t)(length + s)))
199 goto _output_error;
200 length += s;
201 }
202 }
203 /* copy literals */
204 cpy = op + length;
205 if ((cpy > oend - COPYLENGTH) ||
206 (ip + length > iend - COPYLENGTH)) {
207
208 if (cpy > oend)
209 goto _output_error;/* writes beyond buffer */
210
211 if (ip + length != iend)
212 goto _output_error;/*
213 * Error: LZ4 format requires
214 * to consume all input
215 * at this stage
216 */
217 memcpy(op, ip, length);
218 op += length;
219 break;/* Necessarily EOF, due to parsing restrictions */
220 }
221 LZ4_WILDCOPY(ip, op, cpy);
222 ip -= (op - cpy);
223 op = cpy;
224 371
225 /* get offset */ 372/*
226 LZ4_READ_LITTLEENDIAN_16(ref, cpy, ip); 373 * *_continue() :
227 ip += 2; 374 * These decoding functions allow decompression of multiple blocks
228 if (ref < (BYTE * const) dest) 375 * in "streaming" mode.
229 goto _output_error; 376 * Previously decoded blocks must still be available at the memory
230 /* 377 * position where they were decoded.
231 * Error : offset creates reference 378 * If it's not possible, save the relevant part of
232 * outside of destination buffer 379 * decoded data into a safe buffer,
233 */ 380 * and indicate where it stands using LZ4_setStreamDecode()
381 */
382int LZ4_decompress_safe_continue(LZ4_streamDecode_t *LZ4_streamDecode,
383 const char *source, char *dest, int compressedSize, int maxOutputSize)
384{
385 LZ4_streamDecode_t_internal *lz4sd = &LZ4_streamDecode->internal_donotuse;
386 int result;
387
388 if (lz4sd->prefixEnd == (BYTE *)dest) {
389 result = LZ4_decompress_generic(source, dest,
390 compressedSize,
391 maxOutputSize,
392 endOnInputSize, full, 0,
393 usingExtDict, lz4sd->prefixEnd - lz4sd->prefixSize,
394 lz4sd->externalDict,
395 lz4sd->extDictSize);
396
397 if (result <= 0)
398 return result;
399
400 lz4sd->prefixSize += result;
401 lz4sd->prefixEnd += result;
402 } else {
403 lz4sd->extDictSize = lz4sd->prefixSize;
404 lz4sd->externalDict = lz4sd->prefixEnd - lz4sd->extDictSize;
405 result = LZ4_decompress_generic(source, dest,
406 compressedSize, maxOutputSize,
407 endOnInputSize, full, 0,
408 usingExtDict, (BYTE *)dest,
409 lz4sd->externalDict, lz4sd->extDictSize);
410 if (result <= 0)
411 return result;
412 lz4sd->prefixSize = result;
413 lz4sd->prefixEnd = (BYTE *)dest + result;
414 }
234 415
235 /* get matchlength */ 416 return result;
236 length = (token & ML_MASK); 417}
237 if (length == ML_MASK) {
238 while (ip < iend) {
239 int s = *ip++;
240 if (unlikely(length > (size_t)(length + s)))
241 goto _output_error;
242 length += s;
243 if (s == 255)
244 continue;
245 break;
246 }
247 }
248 418
249 /* copy repeated sequence */ 419int LZ4_decompress_fast_continue(LZ4_streamDecode_t *LZ4_streamDecode,
250 if (unlikely((op - ref) < STEPSIZE)) { 420 const char *source, char *dest, int originalSize)
251#if LZ4_ARCH64 421{
252 int dec64 = dec64table[op - ref]; 422 LZ4_streamDecode_t_internal *lz4sd = &LZ4_streamDecode->internal_donotuse;
253#else 423 int result;
254 const int dec64 = 0; 424
255#endif 425 if (lz4sd->prefixEnd == (BYTE *)dest) {
256 op[0] = ref[0]; 426 result = LZ4_decompress_generic(source, dest, 0, originalSize,
257 op[1] = ref[1]; 427 endOnOutputSize, full, 0,
258 op[2] = ref[2]; 428 usingExtDict,
259 op[3] = ref[3]; 429 lz4sd->prefixEnd - lz4sd->prefixSize,
260 op += 4; 430 lz4sd->externalDict, lz4sd->extDictSize);
261 ref += 4; 431
262 ref -= dec32table[op - ref]; 432 if (result <= 0)
263 PUT4(ref, op); 433 return result;
264 op += STEPSIZE - 4; 434
265 ref -= dec64; 435 lz4sd->prefixSize += originalSize;
266 } else { 436 lz4sd->prefixEnd += originalSize;
267 LZ4_COPYSTEP(ref, op); 437 } else {
268 } 438 lz4sd->extDictSize = lz4sd->prefixSize;
269 cpy = op + length - (STEPSIZE-4); 439 lz4sd->externalDict = lz4sd->prefixEnd - lz4sd->extDictSize;
270 if (cpy > oend - COPYLENGTH) { 440 result = LZ4_decompress_generic(source, dest, 0, originalSize,
271 if (cpy > oend) 441 endOnOutputSize, full, 0,
272 goto _output_error; /* write outside of buf */ 442 usingExtDict, (BYTE *)dest,
273#if LZ4_ARCH64 443 lz4sd->externalDict, lz4sd->extDictSize);
274 if ((ref + COPYLENGTH) > oend) 444 if (result <= 0)
275#else 445 return result;
276 if ((ref + COPYLENGTH) > oend || 446 lz4sd->prefixSize = originalSize;
277 (op + COPYLENGTH) > oend) 447 lz4sd->prefixEnd = (BYTE *)dest + originalSize;
278#endif
279 goto _output_error;
280 LZ4_SECURECOPY(ref, op, (oend - COPYLENGTH));
281 while (op < cpy)
282 *op++ = *ref++;
283 op = cpy;
284 /*
285 * Check EOF (should never happen, since last 5 bytes
286 * are supposed to be literals)
287 */
288 if (op == oend)
289 goto _output_error;
290 continue;
291 }
292 LZ4_SECURECOPY(ref, op, cpy);
293 op = cpy; /* correction */
294 } 448 }
295 /* end of decoding */
296 return (int) (((char *) op) - dest);
297 449
298 /* write overflow error detected */ 450 return result;
299_output_error:
300 return -1;
301} 451}
302 452
303int lz4_decompress(const unsigned char *src, size_t *src_len, 453/*
304 unsigned char *dest, size_t actual_dest_len) 454 * Advanced decoding functions :
455 * *_usingDict() :
456 * These decoding functions work the same as "_continue" ones,
457 * the dictionary must be explicitly provided within parameters
458 */
459static FORCE_INLINE int LZ4_decompress_usingDict_generic(const char *source,
460 char *dest, int compressedSize, int maxOutputSize, int safe,
461 const char *dictStart, int dictSize)
305{ 462{
306 int ret = -1; 463 if (dictSize == 0)
307 int input_len = 0; 464 return LZ4_decompress_generic(source, dest,
308 465 compressedSize, maxOutputSize, safe, full, 0,
309 input_len = lz4_uncompress(src, dest, actual_dest_len); 466 noDict, (BYTE *)dest, NULL, 0);
310 if (input_len < 0) 467 if (dictStart + dictSize == dest) {
311 goto exit_0; 468 if (dictSize >= (int)(64 * KB - 1))
312 *src_len = input_len; 469 return LZ4_decompress_generic(source, dest,
470 compressedSize, maxOutputSize, safe, full, 0,
471 withPrefix64k, (BYTE *)dest - 64 * KB, NULL, 0);
472 return LZ4_decompress_generic(source, dest, compressedSize,
473 maxOutputSize, safe, full, 0, noDict,
474 (BYTE *)dest - dictSize, NULL, 0);
475 }
476 return LZ4_decompress_generic(source, dest, compressedSize,
477 maxOutputSize, safe, full, 0, usingExtDict,
478 (BYTE *)dest, (const BYTE *)dictStart, dictSize);
479}
313 480
314 return 0; 481int LZ4_decompress_safe_usingDict(const char *source, char *dest,
315exit_0: 482 int compressedSize, int maxOutputSize,
316 return ret; 483 const char *dictStart, int dictSize)
484{
485 return LZ4_decompress_usingDict_generic(source, dest,
486 compressedSize, maxOutputSize, 1, dictStart, dictSize);
317} 487}
318#ifndef STATIC
319EXPORT_SYMBOL(lz4_decompress);
320#endif
321 488
322int lz4_decompress_unknownoutputsize(const unsigned char *src, size_t src_len, 489int LZ4_decompress_fast_usingDict(const char *source, char *dest,
323 unsigned char *dest, size_t *dest_len) 490 int originalSize, const char *dictStart, int dictSize)
324{ 491{
325 int ret = -1; 492 return LZ4_decompress_usingDict_generic(source, dest, 0,
326 int out_len = 0; 493 originalSize, 0, dictStart, dictSize);
327
328 out_len = lz4_uncompress_unknownoutputsize(src, dest, src_len,
329 *dest_len);
330 if (out_len < 0)
331 goto exit_0;
332 *dest_len = out_len;
333
334 return 0;
335exit_0:
336 return ret;
337} 494}
495
338#ifndef STATIC 496#ifndef STATIC
339EXPORT_SYMBOL(lz4_decompress_unknownoutputsize); 497EXPORT_SYMBOL(LZ4_decompress_safe);
498EXPORT_SYMBOL(LZ4_decompress_safe_partial);
499EXPORT_SYMBOL(LZ4_decompress_fast);
500EXPORT_SYMBOL(LZ4_setStreamDecode);
501EXPORT_SYMBOL(LZ4_decompress_safe_continue);
502EXPORT_SYMBOL(LZ4_decompress_fast_continue);
503EXPORT_SYMBOL(LZ4_decompress_safe_usingDict);
504EXPORT_SYMBOL(LZ4_decompress_fast_usingDict);
340 505
341MODULE_LICENSE("Dual BSD/GPL"); 506MODULE_LICENSE("Dual BSD/GPL");
342MODULE_DESCRIPTION("LZ4 Decompressor"); 507MODULE_DESCRIPTION("LZ4 decompressor");
343#endif 508#endif