"Das U-Boot" Source Tree
0
fork

Configure Feed

Select the types of activity you want to include in your feed.

lib/lz4: update LZ4 decompressor module

Update the LZ4 compression module based on LZ4 v1.8.3 in order to
use the newest LZ4_decompress_safe_partial() which can now decode
exactly the nb of bytes requested.

Signed-off-by: Huang Jianan <jnhuang95@gmail.com>

authored by

Huang Jianan and committed by
Tom Rini
26c7fdad 830613f8

+519 -198
+49
include/u-boot/lz4.h
··· 21 21 */ 22 22 int ulz4fn(const void *src, size_t srcn, void *dst, size_t *dstn); 23 23 24 + /** 25 + * LZ4_decompress_safe() - Decompression protected against buffer overflow 26 + * @source: source address of the compressed data 27 + * @dest: output buffer address of the uncompressed data 28 + * which must be already allocated 29 + * @compressedSize: is the precise full size of the compressed block 30 + * @maxDecompressedSize: is the size of 'dest' buffer 31 + * 32 + * Decompresses data from 'source' into 'dest'. 33 + * If the source stream is detected malformed, the function will 34 + * stop decoding and return a negative result. 35 + * This function is protected against buffer overflow exploits, 36 + * including malicious data packets. It never writes outside output buffer, 37 + * nor reads outside input buffer. 38 + * 39 + * Return: number of bytes decompressed into destination buffer 40 + * (necessarily <= maxDecompressedSize) 41 + * or a negative result in case of error 42 + */ 43 + int LZ4_decompress_safe(const char *source, char *dest, 44 + int compressedSize, int maxDecompressedSize); 45 + 46 + /** 47 + * LZ4_decompress_safe_partial() - Decompress a block of size 'compressedSize' 48 + * at position 'source' into buffer 'dest' 49 + * @source: source address of the compressed data 50 + * @dest: output buffer address of the decompressed data which must be 51 + * already allocated 52 + * @compressedSize: is the precise full size of the compressed block. 53 + * @targetOutputSize: the decompression operation will try 54 + * to stop as soon as 'targetOutputSize' has been reached 55 + * @maxDecompressedSize: is the size of destination buffer 56 + * 57 + * This function decompresses a compressed block of size 'compressedSize' 58 + * at position 'source' into destination buffer 'dest' 59 + * of size 'maxDecompressedSize'. 60 + * The function tries to stop decompressing operation as soon as 61 + * 'targetOutputSize' has been reached, reducing decompression time. 62 + * This function never writes outside of output buffer, 63 + * and never reads outside of input buffer. 64 + * It is therefore protected against malicious data packets. 65 + * 66 + * Return: the number of bytes decoded in the destination buffer 67 + * (necessarily <= maxDecompressedSize) 68 + * or a negative result in case of error 69 + * 70 + */ 71 + int LZ4_decompress_safe_partial(const char *src, char *dst, 72 + int compressedSize, int targetOutputSize, int dstCapacity); 24 73 #endif
+469 -176
lib/lz4.c
··· 1 - // SPDX-License-Identifier: BSD-2-Clause 1 + // SPDX-License-Identifier: GPL 2.0+ OR BSD-2-Clause 2 2 /* 3 - LZ4 - Fast LZ compression algorithm 4 - Copyright (C) 2011-2015, Yann Collet. 3 + * LZ4 - Fast LZ compression algorithm 4 + * Copyright (C) 2011 - 2016, Yann Collet. 5 + * BSD 2 - Clause License (http://www.opensource.org/licenses/bsd - license.php) 6 + * Redistribution and use in source and binary forms, with or without 7 + * modification, are permitted provided that the following conditions are 8 + * met: 9 + * * Redistributions of source code must retain the above copyright 10 + * notice, this list of conditions and the following disclaimer. 11 + * * Redistributions in binary form must reproduce the above 12 + * copyright notice, this list of conditions and the following disclaimer 13 + * in the documentation and/or other materials provided with the 14 + * distribution. 15 + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 16 + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 17 + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 18 + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 19 + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 20 + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 21 + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 22 + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 23 + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 24 + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 25 + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 + * You can contact the author at : 27 + * - LZ4 homepage : http://www.lz4.org 28 + * - LZ4 source repository : https://github.com/lz4/lz4 29 + */ 30 + #include <common.h> 31 + #include <compiler.h> 32 + #include <linux/kernel.h> 33 + #include <linux/types.h> 34 + #include <linux/bug.h> 35 + #include <asm/unaligned.h> 36 + #include <u-boot/lz4.h> 37 + 38 + #define FORCE_INLINE inline __attribute__((always_inline)) 39 + 40 + static FORCE_INLINE u16 LZ4_readLE16(const void *src) 41 + { 42 + return get_unaligned_le16(src); 43 + } 5 44 6 - You can contact the author at : 7 - - LZ4 source repository : https://github.com/Cyan4973/lz4 8 - - LZ4 public forum : https://groups.google.com/forum/#!forum/lz4c 9 - */ 45 + static FORCE_INLINE void LZ4_copy8(void *dst, const void *src) 46 + { 47 + put_unaligned(get_unaligned((const u64 *)src), (u64 *)dst); 48 + } 10 49 50 + typedef uint8_t BYTE; 51 + typedef uint16_t U16; 52 + typedef uint32_t U32; 53 + typedef int32_t S32; 54 + typedef uint64_t U64; 55 + typedef uintptr_t uptrval; 56 + 57 + static FORCE_INLINE void LZ4_write32(void *memPtr, U32 value) 58 + { 59 + put_unaligned(value, (U32 *)memPtr); 60 + } 11 61 12 62 /************************************** 13 63 * Reading and writing into memory ··· 28 78 **************************************/ 29 79 #define MINMATCH 4 30 80 31 - #define COPYLENGTH 8 81 + #define WILDCOPYLENGTH 8 32 82 #define LASTLITERALS 5 33 - #define MFLIMIT (COPYLENGTH+MINMATCH) 34 - static const int LZ4_minLength = (MFLIMIT+1); 83 + #define MFLIMIT (WILDCOPYLENGTH + MINMATCH) 35 84 36 - #define KB *(1 <<10) 37 - #define MB *(1 <<20) 38 - #define GB *(1U<<30) 85 + /* 86 + * ensure it's possible to write 2 x wildcopyLength 87 + * without overflowing output buffer 88 + */ 89 + #define MATCH_SAFEGUARD_DISTANCE ((2 * WILDCOPYLENGTH) - MINMATCH) 90 + 91 + #define KB (1 <<10) 39 92 40 93 #define MAXD_LOG 16 41 94 #define MAX_DISTANCE ((1 << MAXD_LOG) - 1) ··· 45 98 #define RUN_BITS (8-ML_BITS) 46 99 #define RUN_MASK ((1U<<RUN_BITS)-1) 47 100 101 + #define LZ4_STATIC_ASSERT(c) BUILD_BUG_ON(!(c)) 48 102 49 103 /************************************** 50 104 * Local Structures and types 51 105 **************************************/ 52 106 typedef enum { noDict = 0, withPrefix64k, usingExtDict } dict_directive; 53 107 typedef enum { endOnOutputSize = 0, endOnInputSize = 1 } endCondition_directive; 54 - typedef enum { full = 0, partial = 1 } earlyEnd_directive; 108 + typedef enum { decode_full_block = 0, partial_decode = 1 } earlyEnd_directive; 55 109 110 + #define DEBUGLOG(l, ...) {} /* disabled */ 56 111 112 + #ifndef assert 113 + #define assert(condition) ((void)0) 114 + #endif 57 115 58 - /******************************* 59 - * Decompression functions 60 - *******************************/ 61 116 /* 62 - * This generic decompression function cover all use cases. 63 - * It shall be instantiated several times, using different sets of directives 64 - * Note that it is essential this generic function is really inlined, 117 + * LZ4_decompress_generic() : 118 + * This generic decompression function covers all use cases. 119 + * It shall be instantiated several times, using different sets of directives. 120 + * Note that it is important for performance that this function really get inlined, 65 121 * in order to remove useless branches during compilation optimization. 66 122 */ 67 - FORCE_INLINE int LZ4_decompress_generic( 68 - const char* const source, 69 - char* const dest, 70 - int inputSize, 71 - int outputSize, /* If endOnInput==endOnInputSize, this value is the max size of Output Buffer. */ 123 + static FORCE_INLINE int LZ4_decompress_generic( 124 + const char * const src, 125 + char * const dst, 126 + int srcSize, 127 + /* 128 + * If endOnInput == endOnInputSize, 129 + * this value is `dstCapacity` 130 + */ 131 + int outputSize, 132 + /* endOnOutputSize, endOnInputSize */ 133 + endCondition_directive endOnInput, 134 + /* full, partial */ 135 + earlyEnd_directive partialDecoding, 136 + /* noDict, withPrefix64k, usingExtDict */ 137 + dict_directive dict, 138 + /* always <= dst, == dst when no prefix */ 139 + const BYTE * const lowPrefix, 140 + /* only if dict == usingExtDict */ 141 + const BYTE * const dictStart, 142 + /* note : = 0 if noDict */ 143 + const size_t dictSize 144 + ) 145 + { 146 + const BYTE *ip = (const BYTE *) src; 147 + const BYTE * const iend = ip + srcSize; 148 + 149 + BYTE *op = (BYTE *) dst; 150 + BYTE * const oend = op + outputSize; 151 + BYTE *cpy; 152 + 153 + const BYTE * const dictEnd = (const BYTE *)dictStart + dictSize; 154 + static const unsigned int inc32table[8] = {0, 1, 2, 1, 0, 4, 4, 4}; 155 + static const int dec64table[8] = {0, 0, 0, -1, -4, 1, 2, 3}; 156 + 157 + const int safeDecode = (endOnInput == endOnInputSize); 158 + const int checkOffset = ((safeDecode) && (dictSize < (int)(64 * KB))); 159 + 160 + /* Set up the "end" pointers for the shortcut. */ 161 + const BYTE *const shortiend = iend - 162 + (endOnInput ? 14 : 8) /*maxLL*/ - 2 /*offset*/; 163 + const BYTE *const shortoend = oend - 164 + (endOnInput ? 14 : 8) /*maxLL*/ - 18 /*maxML*/; 165 + 166 + DEBUGLOG(5, "%s (srcSize:%i, dstSize:%i)", __func__, 167 + srcSize, outputSize); 168 + 169 + /* Special cases */ 170 + assert(lowPrefix <= op); 171 + assert(src != NULL); 172 + 173 + /* Empty output buffer */ 174 + if ((endOnInput) && (unlikely(outputSize == 0))) 175 + return ((srcSize == 1) && (*ip == 0)) ? 0 : -1; 176 + 177 + if ((!endOnInput) && (unlikely(outputSize == 0))) 178 + return (*ip == 0 ? 1 : -1); 179 + 180 + if ((endOnInput) && unlikely(srcSize == 0)) 181 + return -1; 182 + 183 + /* Main Loop : decode sequences */ 184 + while (1) { 185 + size_t length; 186 + const BYTE *match; 187 + size_t offset; 188 + 189 + /* get literal length */ 190 + unsigned int const token = *ip++; 191 + length = token>>ML_BITS; 192 + 193 + /* ip < iend before the increment */ 194 + assert(!endOnInput || ip <= iend); 195 + 196 + /* 197 + * A two-stage shortcut for the most common case: 198 + * 1) If the literal length is 0..14, and there is enough 199 + * space, enter the shortcut and copy 16 bytes on behalf 200 + * of the literals (in the fast mode, only 8 bytes can be 201 + * safely copied this way). 202 + * 2) Further if the match length is 4..18, copy 18 bytes 203 + * in a similar manner; but we ensure that there's enough 204 + * space in the output for those 18 bytes earlier, upon 205 + * entering the shortcut (in other words, there is a 206 + * combined check for both stages). 207 + * 208 + * The & in the likely() below is intentionally not && so that 209 + * some compilers can produce better parallelized runtime code 210 + */ 211 + if ((endOnInput ? length != RUN_MASK : length <= 8) 212 + /* 213 + * strictly "less than" on input, to re-enter 214 + * the loop with at least one byte 215 + */ 216 + && likely((endOnInput ? ip < shortiend : 1) & 217 + (op <= shortoend))) { 218 + /* Copy the literals */ 219 + memcpy(op, ip, endOnInput ? 16 : 8); 220 + op += length; ip += length; 221 + 222 + /* 223 + * The second stage: 224 + * prepare for match copying, decode full info. 225 + * If it doesn't work out, the info won't be wasted. 226 + */ 227 + length = token & ML_MASK; /* match length */ 228 + offset = LZ4_readLE16(ip); 229 + ip += 2; 230 + match = op - offset; 231 + assert(match <= op); /* check overflow */ 232 + 233 + /* Do not deal with overlapping matches. */ 234 + if ((length != ML_MASK) && 235 + (offset >= 8) && 236 + (dict == withPrefix64k || match >= lowPrefix)) { 237 + /* Copy the match. */ 238 + memcpy(op + 0, match + 0, 8); 239 + memcpy(op + 8, match + 8, 8); 240 + memcpy(op + 16, match + 16, 2); 241 + op += length + MINMATCH; 242 + /* Both stages worked, load the next token. */ 243 + continue; 244 + } 245 + 246 + /* 247 + * The second stage didn't work out, but the info 248 + * is ready. Propel it right to the point of match 249 + * copying. 250 + */ 251 + goto _copy_match; 252 + } 253 + 254 + /* decode literal length */ 255 + if (length == RUN_MASK) { 256 + unsigned int s; 257 + 258 + if (unlikely(endOnInput ? ip >= iend - RUN_MASK : 0)) { 259 + /* overflow detection */ 260 + goto _output_error; 261 + } 262 + do { 263 + s = *ip++; 264 + length += s; 265 + } while (likely(endOnInput 266 + ? ip < iend - RUN_MASK 267 + : 1) & (s == 255)); 268 + 269 + if ((safeDecode) 270 + && unlikely((uptrval)(op) + 271 + length < (uptrval)(op))) { 272 + /* overflow detection */ 273 + goto _output_error; 274 + } 275 + if ((safeDecode) 276 + && unlikely((uptrval)(ip) + 277 + length < (uptrval)(ip))) { 278 + /* overflow detection */ 279 + goto _output_error; 280 + } 281 + } 282 + 283 + /* copy literals */ 284 + cpy = op + length; 285 + LZ4_STATIC_ASSERT(MFLIMIT >= WILDCOPYLENGTH); 286 + 287 + if (((endOnInput) && ((cpy > oend - MFLIMIT) 288 + || (ip + length > iend - (2 + 1 + LASTLITERALS)))) 289 + || ((!endOnInput) && (cpy > oend - WILDCOPYLENGTH))) { 290 + if (partialDecoding) { 291 + if (cpy > oend) { 292 + /* 293 + * Partial decoding : 294 + * stop in the middle of literal segment 295 + */ 296 + cpy = oend; 297 + length = oend - op; 298 + } 299 + if ((endOnInput) 300 + && (ip + length > iend)) { 301 + /* 302 + * Error : 303 + * read attempt beyond 304 + * end of input buffer 305 + */ 306 + goto _output_error; 307 + } 308 + } else { 309 + if ((!endOnInput) 310 + && (cpy != oend)) { 311 + /* 312 + * Error : 313 + * block decoding must 314 + * stop exactly there 315 + */ 316 + goto _output_error; 317 + } 318 + if ((endOnInput) 319 + && ((ip + length != iend) 320 + || (cpy > oend))) { 321 + /* 322 + * Error : 323 + * input must be consumed 324 + */ 325 + goto _output_error; 326 + } 327 + } 328 + 329 + /* 330 + * supports overlapping memory regions; only matters 331 + * for in-place decompression scenarios 332 + */ 333 + memmove(op, ip, length); 334 + ip += length; 335 + op += length; 336 + 337 + /* Necessarily EOF, due to parsing restrictions */ 338 + if (!partialDecoding || (cpy == oend)) 339 + break; 340 + } else { 341 + /* may overwrite up to WILDCOPYLENGTH beyond cpy */ 342 + LZ4_wildCopy(op, ip, cpy); 343 + ip += length; 344 + op = cpy; 345 + } 346 + 347 + /* get offset */ 348 + offset = LZ4_readLE16(ip); 349 + ip += 2; 350 + match = op - offset; 72 351 73 - int endOnInput, /* endOnOutputSize, endOnInputSize */ 74 - int partialDecoding, /* full, partial */ 75 - int targetOutputSize, /* only used if partialDecoding==partial */ 76 - int dict, /* noDict, withPrefix64k, usingExtDict */ 77 - const BYTE* const lowPrefix, /* == dest if dict == noDict */ 78 - const BYTE* const dictStart, /* only if dict==usingExtDict */ 79 - const size_t dictSize /* note : = 0 if noDict */ 80 - ) 81 - { 82 - /* Local Variables */ 83 - const BYTE* ip = (const BYTE*) source; 84 - const BYTE* const iend = ip + inputSize; 352 + /* get matchlength */ 353 + length = token & ML_MASK; 85 354 86 - BYTE* op = (BYTE*) dest; 87 - BYTE* const oend = op + outputSize; 88 - BYTE* cpy; 89 - BYTE* oexit = op + targetOutputSize; 90 - const BYTE* const lowLimit = lowPrefix - dictSize; 355 + _copy_match: 356 + if ((checkOffset) && (unlikely(match + dictSize < lowPrefix))) { 357 + /* Error : offset outside buffers */ 358 + goto _output_error; 359 + } 91 360 92 - const BYTE* const dictEnd = (const BYTE*)dictStart + dictSize; 93 - const size_t dec32table[] = {4, 1, 2, 1, 4, 4, 4, 4}; 94 - const size_t dec64table[] = {0, 0, 0, (size_t)-1, 0, 1, 2, 3}; 361 + /* costs ~1%; silence an msan warning when offset == 0 */ 362 + /* 363 + * note : when partialDecoding, there is no guarantee that 364 + * at least 4 bytes remain available in output buffer 365 + */ 366 + if (!partialDecoding) { 367 + assert(oend > op); 368 + assert(oend - op >= 4); 95 369 96 - const int safeDecode = (endOnInput==endOnInputSize); 97 - const int checkOffset = ((safeDecode) && (dictSize < (int)(64 KB))); 370 + LZ4_write32(op, (U32)offset); 371 + } 98 372 373 + if (length == ML_MASK) { 374 + unsigned int s; 99 375 100 - /* Special cases */ 101 - if ((partialDecoding) && (oexit> oend-MFLIMIT)) oexit = oend-MFLIMIT; /* targetOutputSize too high => decode everything */ 102 - if ((endOnInput) && (unlikely(outputSize==0))) return ((inputSize==1) && (*ip==0)) ? 0 : -1; /* Empty output buffer */ 103 - if ((!endOnInput) && (unlikely(outputSize==0))) return (*ip==0?1:-1); 376 + do { 377 + s = *ip++; 104 378 379 + if ((endOnInput) && (ip > iend - LASTLITERALS)) 380 + goto _output_error; 105 381 106 - /* Main Loop */ 107 - while (1) 108 - { 109 - unsigned token; 110 - size_t length; 111 - const BYTE* match; 382 + length += s; 383 + } while (s == 255); 112 384 113 - /* get literal length */ 114 - token = *ip++; 115 - if ((length=(token>>ML_BITS)) == RUN_MASK) 116 - { 117 - unsigned s; 118 - do 119 - { 120 - s = *ip++; 121 - length += s; 122 - } 123 - while (likely((endOnInput)?ip<iend-RUN_MASK:1) && (s==255)); 124 - if ((safeDecode) && unlikely((size_t)(op+length)<(size_t)(op))) goto _output_error; /* overflow detection */ 125 - if ((safeDecode) && unlikely((size_t)(ip+length)<(size_t)(ip))) goto _output_error; /* overflow detection */ 126 - } 385 + if ((safeDecode) 386 + && unlikely( 387 + (uptrval)(op) + length < (uptrval)op)) { 388 + /* overflow detection */ 389 + goto _output_error; 390 + } 391 + } 127 392 128 - /* copy literals */ 129 - cpy = op+length; 130 - if (((endOnInput) && ((cpy>(partialDecoding?oexit:oend-MFLIMIT)) || (ip+length>iend-(2+1+LASTLITERALS))) ) 131 - || ((!endOnInput) && (cpy>oend-COPYLENGTH))) 132 - { 133 - if (partialDecoding) 134 - { 135 - if (cpy > oend) goto _output_error; /* Error : write attempt beyond end of output buffer */ 136 - if ((endOnInput) && (ip+length > iend)) goto _output_error; /* Error : read attempt beyond end of input buffer */ 137 - } 138 - else 139 - { 140 - if ((!endOnInput) && (cpy != oend)) goto _output_error; /* Error : block decoding must stop exactly there */ 141 - if ((endOnInput) && ((ip+length != iend) || (cpy > oend))) goto _output_error; /* Error : input must be consumed */ 142 - } 143 - memcpy(op, ip, length); 144 - ip += length; 145 - op += length; 146 - break; /* Necessarily EOF, due to parsing restrictions */ 147 - } 148 - LZ4_wildCopy(op, ip, cpy); 149 - ip += length; op = cpy; 393 + length += MINMATCH; 150 394 151 - /* get offset */ 152 - match = cpy - LZ4_readLE16(ip); ip+=2; 153 - if ((checkOffset) && (unlikely(match < lowLimit))) goto _output_error; /* Error : offset outside destination buffer */ 395 + /* match starting within external dictionary */ 396 + if ((dict == usingExtDict) && (match < lowPrefix)) { 397 + if (unlikely(op + length > oend - LASTLITERALS)) { 398 + /* doesn't respect parsing restriction */ 399 + if (!partialDecoding) 400 + goto _output_error; 401 + length = min(length, (size_t)(oend - op)); 402 + } 154 403 155 - /* get matchlength */ 156 - length = token & ML_MASK; 157 - if (length == ML_MASK) 158 - { 159 - unsigned s; 160 - do 161 - { 162 - if ((endOnInput) && (ip > iend-LASTLITERALS)) goto _output_error; 163 - s = *ip++; 164 - length += s; 165 - } while (s==255); 166 - if ((safeDecode) && unlikely((size_t)(op+length)<(size_t)op)) goto _output_error; /* overflow detection */ 167 - } 168 - length += MINMATCH; 404 + if (length <= (size_t)(lowPrefix - match)) { 405 + /* 406 + * match fits entirely within external 407 + * dictionary : just copy 408 + */ 409 + memmove(op, dictEnd - (lowPrefix - match), 410 + length); 411 + op += length; 412 + } else { 413 + /* 414 + * match stretches into both external 415 + * dictionary and current block 416 + */ 417 + size_t const copySize = (size_t)(lowPrefix - match); 418 + size_t const restSize = length - copySize; 169 419 170 - /* check external dictionary */ 171 - if ((dict==usingExtDict) && (match < lowPrefix)) 172 - { 173 - if (unlikely(op+length > oend-LASTLITERALS)) goto _output_error; /* doesn't respect parsing restriction */ 420 + memcpy(op, dictEnd - copySize, copySize); 421 + op += copySize; 422 + if (restSize > (size_t)(op - lowPrefix)) { 423 + /* overlap copy */ 424 + BYTE * const endOfMatch = op + restSize; 425 + const BYTE *copyFrom = lowPrefix; 174 426 175 - if (length <= (size_t)(lowPrefix-match)) 176 - { 177 - /* match can be copied as a single segment from external dictionary */ 178 - match = dictEnd - (lowPrefix-match); 179 - memmove(op, match, length); op += length; 180 - } 181 - else 182 - { 183 - /* match encompass external dictionary and current segment */ 184 - size_t copySize = (size_t)(lowPrefix-match); 185 - memcpy(op, dictEnd - copySize, copySize); 186 - op += copySize; 187 - copySize = length - copySize; 188 - if (copySize > (size_t)(op-lowPrefix)) /* overlap within current segment */ 189 - { 190 - BYTE* const endOfMatch = op + copySize; 191 - const BYTE* copyFrom = lowPrefix; 192 - while (op < endOfMatch) *op++ = *copyFrom++; 193 - } 194 - else 195 - { 196 - memcpy(op, lowPrefix, copySize); 197 - op += copySize; 198 - } 199 - } 200 - continue; 201 - } 427 + while (op < endOfMatch) 428 + *op++ = *copyFrom++; 429 + } else { 430 + memcpy(op, lowPrefix, restSize); 431 + op += restSize; 432 + } 433 + } 434 + continue; 435 + } 436 + 437 + /* copy match within block */ 438 + cpy = op + length; 439 + 440 + /* 441 + * partialDecoding : 442 + * may not respect endBlock parsing restrictions 443 + */ 444 + assert(op <= oend); 445 + if (partialDecoding && 446 + (cpy > oend - MATCH_SAFEGUARD_DISTANCE)) { 447 + size_t const mlen = min(length, (size_t)(oend - op)); 448 + const BYTE * const matchEnd = match + mlen; 449 + BYTE * const copyEnd = op + mlen; 450 + 451 + if (matchEnd > op) { 452 + /* overlap copy */ 453 + while (op < copyEnd) 454 + *op++ = *match++; 455 + } else { 456 + memcpy(op, match, mlen); 457 + } 458 + op = copyEnd; 459 + if (op == oend) 460 + break; 461 + continue; 462 + } 463 + 464 + if (unlikely(offset < 8)) { 465 + op[0] = match[0]; 466 + op[1] = match[1]; 467 + op[2] = match[2]; 468 + op[3] = match[3]; 469 + match += inc32table[offset]; 470 + memcpy(op + 4, match, 4); 471 + match -= dec64table[offset]; 472 + } else { 473 + LZ4_copy8(op, match); 474 + match += 8; 475 + } 202 476 203 - /* copy repeated sequence */ 204 - cpy = op + length; 205 - if (unlikely((op-match)<8)) 206 - { 207 - const size_t dec64 = dec64table[op-match]; 208 - op[0] = match[0]; 209 - op[1] = match[1]; 210 - op[2] = match[2]; 211 - op[3] = match[3]; 212 - match += dec32table[op-match]; 213 - LZ4_copy4(op+4, match); 214 - op += 8; match -= dec64; 215 - } else { LZ4_copy8(op, match); op+=8; match+=8; } 477 + op += 8; 478 + 479 + if (unlikely(cpy > oend - MATCH_SAFEGUARD_DISTANCE)) { 480 + BYTE * const oCopyLimit = oend - (WILDCOPYLENGTH - 1); 481 + 482 + if (cpy > oend - LASTLITERALS) { 483 + /* 484 + * Error : last LASTLITERALS bytes 485 + * must be literals (uncompressed) 486 + */ 487 + goto _output_error; 488 + } 216 489 217 - if (unlikely(cpy>oend-12)) 218 - { 219 - if (cpy > oend-LASTLITERALS) goto _output_error; /* Error : last LASTLITERALS bytes must be literals */ 220 - if (op < oend-8) 221 - { 222 - LZ4_wildCopy(op, match, oend-8); 223 - match += (oend-8) - op; 224 - op = oend-8; 225 - } 226 - while (op<cpy) *op++ = *match++; 227 - } 228 - else 229 - LZ4_wildCopy(op, match, cpy); 230 - op=cpy; /* correction */ 231 - } 490 + if (op < oCopyLimit) { 491 + LZ4_wildCopy(op, match, oCopyLimit); 492 + match += oCopyLimit - op; 493 + op = oCopyLimit; 494 + } 495 + while (op < cpy) 496 + *op++ = *match++; 497 + } else { 498 + LZ4_copy8(op, match); 499 + if (length > 16) 500 + LZ4_wildCopy(op + 8, match + 8, cpy); 501 + } 502 + op = cpy; /* wildcopy correction */ 503 + } 232 504 233 - /* end of decoding */ 234 - if (endOnInput) 235 - return (int) (((char*)op)-dest); /* Nb of output bytes decoded */ 236 - else 237 - return (int) (((const char*)ip)-source); /* Nb of input bytes read */ 505 + /* end of decoding */ 506 + if (endOnInput) { 507 + /* Nb of output bytes decoded */ 508 + return (int) (((char *)op) - dst); 509 + } else { 510 + /* Nb of input bytes read */ 511 + return (int) (((const char *)ip) - src); 512 + } 238 513 239 - /* Overflow error detected */ 514 + /* Overflow error detected */ 240 515 _output_error: 241 - return (int) (-(((const char*)ip)-source))-1; 516 + return (int) (-(((const char *)ip) - src)) - 1; 517 + } 518 + 519 + int LZ4_decompress_safe(const char *source, char *dest, 520 + int compressedSize, int maxDecompressedSize) 521 + { 522 + return LZ4_decompress_generic(source, dest, 523 + compressedSize, maxDecompressedSize, 524 + endOnInputSize, decode_full_block, 525 + noDict, (BYTE *)dest, NULL, 0); 526 + } 527 + 528 + int LZ4_decompress_safe_partial(const char *src, char *dst, 529 + int compressedSize, int targetOutputSize, int dstCapacity) 530 + { 531 + dstCapacity = min(targetOutputSize, dstCapacity); 532 + return LZ4_decompress_generic(src, dst, compressedSize, dstCapacity, 533 + endOnInputSize, partial_decode, 534 + noDict, (BYTE *)dst, NULL, 0); 242 535 }
+1 -22
lib/lz4_wrapper.c
··· 11 11 #include <asm/unaligned.h> 12 12 #include <u-boot/lz4.h> 13 13 14 - static u16 LZ4_readLE16(const void *src) 15 - { 16 - return get_unaligned_le16(src); 17 - } 18 - static void LZ4_copy4(void *dst, const void *src) 19 - { 20 - put_unaligned(get_unaligned((const u32 *)src), (u32 *)dst); 21 - } 22 - static void LZ4_copy8(void *dst, const void *src) 23 - { 24 - put_unaligned(get_unaligned((const u64 *)src), (u64 *)dst); 25 - } 26 - 27 - typedef uint8_t BYTE; 28 - typedef uint16_t U16; 29 - typedef uint32_t U32; 30 - typedef int32_t S32; 31 - typedef uint64_t U64; 32 - 33 - #define FORCE_INLINE static inline __attribute__((always_inline)) 34 - 35 14 /* lz4.c is unaltered (except removing unrelated code) from github.com/Cyan4973/lz4. */ 36 15 #include "lz4.c" /* #include for inlining, do not link! */ 37 16 ··· 112 91 /* constant folding essential, do not touch params! */ 113 92 ret = LZ4_decompress_generic(in, out, block_size, 114 93 end - out, endOnInputSize, 115 - full, 0, noDict, out, NULL, 0); 94 + decode_full_block, noDict, out, NULL, 0); 116 95 if (ret < 0) { 117 96 ret = -EPROTO; /* decompression error */ 118 97 break;