1 /*
   2  * LZ4 - Fast LZ compression algorithm
   3  * Header File
   4  * Copyright (C) 2011-2013, Yann Collet.
   5  * BSD 2-Clause License (http://www.opensource.org/licenses/bsd-license.php)
   6  *
   7  * Redistribution and use in source and binary forms, with or without
   8  * modification, are permitted provided that the following conditions are
   9  * met:
  10  *
  11  *     * Redistributions of source code must retain the above copyright
  12  * notice, this list of conditions and the following disclaimer.
  13  *     * Redistributions in binary form must reproduce the above
  14  * copyright notice, this list of conditions and the following disclaimer
  15  * in the documentation and/or other materials provided with the
  16  * distribution.
  17  *
  18  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  19  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  20  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
  21  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
  22  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  23  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
  24  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
  25  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
  26  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  27  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
  28  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  29  *
  30  * You can contact the author at :
  31  * - LZ4 homepage : http://fastcompression.blogspot.com/p/lz4.html
  32  * - LZ4 source repository : http://code.google.com/p/lz4/
  33  */
  34 
  35 #include "fsys_zfs.h"
  36 #include <string.h>
  37 
  38 static int LZ4_uncompress_unknownOutputSize(const char *source, char *dest,
  39                                             int isize, int maxOutputSize);
  40 
  41 int
  42 lz4_decompress(void *s_start, void *d_start, size_t s_len, size_t d_len)
  43 {
  44         const uint8_t *src = s_start;
  45         uint32_t bufsiz = (src[0] << 24) | (src[1] << 16) | (src[2] << 8) |
  46             src[3];
  47 
  48         /* invalid compressed buffer size encoded at start */
  49         if (bufsiz + 4 > s_len)
  50                 return (1);
  51 
  52         /*
  53          * Returns 0 on success (decompression function returned non-negative)
  54          * and non-zero on failure (decompression function returned negative).
  55          */
  56         return (LZ4_uncompress_unknownOutputSize(s_start + 4, d_start, bufsiz,
  57             d_len) < 0);
  58 }
  59 
  60 /*
  61  * CPU Feature Detection
  62  */
  63 
  64 /* 32 or 64 bits ? */
  65 #if (defined(__x86_64__) || defined(__x86_64) || defined(__amd64__) || \
  66         defined(__amd64) || defined(__ppc64__) || defined(_WIN64) || \
  67         defined(__LP64__) || defined(_LP64))
  68 #define LZ4_ARCH64      1
  69 #else
  70 #define LZ4_ARCH64      0
  71 #endif
  72 
  73 /*
  74  * Little Endian or Big Endian?
  75  * Note: overwrite the below #define if you know your architecture endianess.
  76  */
  77 #if (defined(__BIG_ENDIAN__) || defined(__BIG_ENDIAN) || \
  78         defined(_BIG_ENDIAN) || defined(_ARCH_PPC) || defined(__PPC__) || \
  79         defined(__PPC) || defined(PPC) || defined(__powerpc__) || \
  80         defined(__powerpc) || defined(powerpc) || \
  81         ((defined(__BYTE_ORDER__)&&(__BYTE_ORDER__ == __ORDER_BIG_ENDIAN__))))
  82 #define LZ4_BIG_ENDIAN  1
  83 #else
  84         /*
  85          * Little Endian assumed. PDP Endian and other very rare endian format
  86          * are unsupported.
  87          */
  88 #endif
  89 
  90 /*
  91  * Compiler Options
  92  */
  93 #if __STDC_VERSION__ >= 199901L      /* C99 */
  94 /* "restrict" is a known keyword */
  95 #else
  96 /* Disable restrict */
  97 #define restrict
  98 #endif
  99 
 100 #define GCC_VERSION (__GNUC__ * 100 + __GNUC_MINOR__)
 101 
 102 #define lz4_bswap16(x) ((unsigned short int) ((((x) >> 8) & 0xffu) \
 103         | (((x) & 0xffu) << 8)))
 104 
 105 #if (GCC_VERSION >= 302) || (__INTEL_COMPILER >= 800) || defined(__clang__)
 106 #define expect(expr, value)    (__builtin_expect((expr), (value)))
 107 #else
 108 #define expect(expr, value)    (expr)
 109 #endif
 110 
 111 #define likely(expr)    expect((expr) != 0, 1)
 112 #define unlikely(expr)  expect((expr) != 0, 0)
 113 
 114 /* Basic types */
 115 #define BYTE    uint8_t
 116 #define U16     uint16_t
 117 #define U32     uint32_t
 118 #define S32     int32_t
 119 #define U64     uint64_t
 120 
 121 typedef struct _U16_S {
 122         U16 v;
 123 } U16_S;
 124 typedef struct _U32_S {
 125         U32 v;
 126 } U32_S;
 127 typedef struct _U64_S {
 128         U64 v;
 129 } U64_S;
 130 
 131 #define A64(x)  (((U64_S *)(x))->v)
 132 #define A32(x)  (((U32_S *)(x))->v)
 133 #define A16(x)  (((U16_S *)(x))->v)
 134 
 135 /*
 136  * Constants
 137  */
 138 #define MINMATCH 4
 139 
 140 #define COPYLENGTH 8
 141 #define LASTLITERALS 5
 142 
 143 #define ML_BITS 4
 144 #define ML_MASK ((1U<<ML_BITS)-1)
 145 #define RUN_BITS (8-ML_BITS)
 146 #define RUN_MASK ((1U<<RUN_BITS)-1)
 147 
 148 /*
 149  * Architecture-specific macros
 150  */
 151 #if LZ4_ARCH64
 152 #define STEPSIZE 8
 153 #define UARCH U64
 154 #define AARCH A64
 155 #define LZ4_COPYSTEP(s, d)      A64(d) = A64(s); d += 8; s += 8;
 156 #define LZ4_COPYPACKET(s, d)    LZ4_COPYSTEP(s, d)
 157 #define LZ4_SECURECOPY(s, d, e) if (d < e) LZ4_WILDCOPY(s, d, e)
 158 #define HTYPE U32
 159 #define INITBASE(base)          const BYTE* const base = ip
 160 #else
 161 #define STEPSIZE 4
 162 #define UARCH U32
 163 #define AARCH A32
 164 #define LZ4_COPYSTEP(s, d)      A32(d) = A32(s); d += 4; s += 4;
 165 #define LZ4_COPYPACKET(s, d)    LZ4_COPYSTEP(s, d); LZ4_COPYSTEP(s, d);
 166 #define LZ4_SECURECOPY          LZ4_WILDCOPY
 167 #define HTYPE const BYTE*
 168 #define INITBASE(base)          const int base = 0
 169 #endif
 170 
 171 #if (defined(LZ4_BIG_ENDIAN) && !defined(BIG_ENDIAN_NATIVE_BUT_INCOMPATIBLE))
 172 #define LZ4_READ_LITTLEENDIAN_16(d, s, p) \
 173         { U16 v = A16(p); v = lz4_bswap16(v); d = (s) - v; }
 174 #define LZ4_WRITE_LITTLEENDIAN_16(p, i) \
 175         { U16 v = (U16)(i); v = lz4_bswap16(v); A16(p) = v; p += 2; }
 176 #else
 177 #define LZ4_READ_LITTLEENDIAN_16(d, s, p) { d = (s) - A16(p); }
 178 #define LZ4_WRITE_LITTLEENDIAN_16(p, v)  { A16(p) = v; p += 2; }
 179 #endif
 180 
 181 /* Macros */
 182 #define LZ4_WILDCOPY(s, d, e) do { LZ4_COPYPACKET(s, d) } while (d < e);
 183 
 184 /* Decompression functions */
 185 
 186 static int
 187 LZ4_uncompress_unknownOutputSize(const char *source,
 188     char *dest, int isize, int maxOutputSize)
 189 {
 190         /* Local Variables */
 191         const BYTE *restrict ip = (const BYTE *) source;
 192         const BYTE *const iend = ip + isize;
 193         const BYTE *restrict ref;
 194 
 195         BYTE *restrict op = (BYTE *) dest;
 196         BYTE *const oend = op + maxOutputSize;
 197         BYTE *cpy;
 198 
 199         size_t dec[] = { 0, 3, 2, 3, 0, 0, 0, 0 };
 200 
 201         /* Main Loop */
 202         while (ip < iend) {
 203                 BYTE token;
 204                 int length;
 205 
 206                 /* get runlength */
 207                 token = *ip++;
 208                 if ((length = (token >> ML_BITS)) == RUN_MASK) {
 209                         int s = 255;
 210                         while ((ip < iend) && (s == 255)) {
 211                                 s = *ip++;
 212                                 length += s;
 213                         }
 214                 }
 215                 /* copy literals */
 216                 cpy = op + length;
 217                 if ((cpy > oend - COPYLENGTH) ||
 218                     (ip + length > iend - COPYLENGTH)) {
 219                         if (cpy > oend)
 220                                 /*
 221                                  * Error: request to write beyond destination
 222                                  * buffer.
 223                                  */
 224                                 goto _output_error;
 225                         if (ip + length > iend)
 226                                 /*
 227                                  * Error : request to read beyond source
 228                                  * buffer.
 229                                  */
 230                                 goto _output_error;
 231                         memcpy(op, ip, length);
 232                         op += length;
 233                         ip += length;
 234                         if (ip < iend)
 235                                 /* Error : LZ4 format violation */
 236                                 goto _output_error;
 237                         /* Necessarily EOF, due to parsing restrictions. */
 238                         break;
 239                 }
 240                 LZ4_WILDCOPY(ip, op, cpy);
 241                 ip -= (op - cpy);
 242                 op = cpy;
 243 
 244                 /* get offset */
 245                 LZ4_READ_LITTLEENDIAN_16(ref, cpy, ip);
 246                 ip += 2;
 247                 if (ref < (BYTE * const) dest)
 248                         /*
 249                          * Error: offset creates reference outside of
 250                          * destination buffer.
 251                          */
 252                         goto _output_error;
 253 
 254                 /* get matchlength */
 255                 if ((length = (token & ML_MASK)) == ML_MASK) {
 256                         while (ip < iend) {
 257                                 int s = *ip++;
 258                                 length += s;
 259                                 if (s == 255)
 260                                         continue;
 261                                 break;
 262                         }
 263                 }
 264                 /* copy repeated sequence */
 265                 if unlikely(op - ref < STEPSIZE) {
 266 #if LZ4_ARCH64
 267                         size_t dec2table[] = { 0, 0, 0, -1, 0, 1, 2, 3 };
 268                         size_t dec2 = dec2table[op - ref];
 269 #else
 270                         const int dec2 = 0;
 271 #endif
 272                         *op++ = *ref++;
 273                         *op++ = *ref++;
 274                         *op++ = *ref++;
 275                         *op++ = *ref++;
 276                         ref -= dec[op - ref];
 277                         A32(op) = A32(ref);
 278                         op += STEPSIZE - 4;
 279                         ref -= dec2;
 280                 } else {
 281                         LZ4_COPYSTEP(ref, op);
 282                 }
 283                 cpy = op + length - (STEPSIZE - 4);
 284                 if (cpy > oend - COPYLENGTH) {
 285                         if (cpy > oend)
 286                                 /*
 287                                  * Error: request to write outside of
 288                                  * destination buffer.
 289                                  */
 290                                 goto _output_error;
 291                         LZ4_SECURECOPY(ref, op, (oend - COPYLENGTH));
 292                         while (op < cpy)
 293                                 *op++ = *ref++;
 294                         op = cpy;
 295                         if (op == oend)
 296                                 /*
 297                                  * Check EOF (should never happen, since last
 298                                  * 5 bytes are supposed to be literals).
 299                                  */
 300                                 break;
 301                         continue;
 302                 }
 303                 LZ4_SECURECOPY(ref, op, cpy);
 304                 op = cpy;       /* correction */
 305         }
 306 
 307         /* end of decoding */
 308         return (int)(((char *)op) - dest);
 309 
 310         /* write overflow error detected */
 311         _output_error:
 312         return (int)(-(((char *)ip) - source));
 313 }