Path: blob/main/sys/cddl/contrib/opensolaris/common/lz4/lz4.c
48521 views
/*1* LZ4 - Fast LZ compression algorithm2* Header File3* Copyright (C) 2011-2013, Yann Collet.4* BSD 2-Clause License (http://www.opensource.org/licenses/bsd-license.php)5*6* Redistribution and use in source and binary forms, with or without7* modification, are permitted provided that the following conditions are8* met:9*10* * Redistributions of source code must retain the above copyright11* notice, this list of conditions and the following disclaimer.12* * Redistributions in binary form must reproduce the above13* copyright notice, this list of conditions and the following disclaimer14* in the documentation and/or other materials provided with the15* distribution.16*17* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS18* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT19* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR20* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT21* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,22* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT23* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,24* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY25* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT26* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE27* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.28*29* You can contact the author at :30* - LZ4 homepage : http://fastcompression.blogspot.com/p/lz4.html31* - LZ4 source repository : http://code.google.com/p/lz4/32*/33/*34* Copyright (c) 2016 by Delphix. All rights reserved.35*/3637#if defined(_KERNEL) || defined(_FAKE_KERNEL)38#include <sys/zfs_context.h>39#elif defined(_STANDALONE)40#include <sys/cdefs.h>41#include <stand.h>42#include <sys/types.h>43#include <sys/endian.h>44#include <assert.h>4546#undef ASSERT47#define ASSERT assert48#else49#include <string.h>50#include <stdlib.h>51#include <sys/types.h>52#include <netinet/in.h>53#include <assert.h>5455#undef ASSERT56#define ASSERT assert57#endif58#include "lz4.h"5960static int real_LZ4_compress(const char *source, char *dest, int isize,61int osize);62static int LZ4_uncompress_unknownOutputSize(const char *source, char *dest,63int isize, int maxOutputSize);64static int LZ4_compressCtx(void *ctx, const char *source, char *dest,65int isize, int osize);66static int LZ4_compress64kCtx(void *ctx, const char *source, char *dest,67int isize, int osize);6869#if defined(_KERNEL) || defined(_FAKE_KERNEL)70static kmem_cache_t *lz4_ctx_cache;71#endif7273size_t74lz4_compress(void *s_start, void *d_start, size_t s_len, size_t d_len,75int n __unused)76{77uint32_t bufsiz;78char *dest = d_start;7980ASSERT(d_len >= sizeof (bufsiz));8182bufsiz = real_LZ4_compress(s_start, &dest[sizeof (bufsiz)], s_len,83d_len - sizeof (bufsiz));8485/* Signal an error if the compression routine returned zero. */86if (bufsiz == 0)87return (s_len);8889/*90* Encode the compresed buffer size at the start. We'll need this in91* decompression to counter the effects of padding which might be92* added to the compressed buffer and which, if unhandled, would93* confuse the hell out of our decompression function.94*/95#if defined(_KERNEL) || defined(_FAKE_KERNEL)96*(uint32_t *)(void *)dest = BE_32(bufsiz);97#else98*(uint32_t *)(void *)dest = htonl(bufsiz);99#endif100101return (bufsiz + sizeof (bufsiz));102}103104int105lz4_decompress(void *s_start, void *d_start, size_t s_len, size_t d_len,106int n __unused)107{108const char *src = s_start;109#if defined(_KERNEL) || defined(_FAKE_KERNEL)110uint32_t bufsiz = BE_IN32(s_start);111#else112uint32_t bufsiz = htonl(*(uint32_t *)s_start);113#endif114115/* invalid compressed buffer size encoded at start */116if (bufsiz + sizeof (bufsiz) > s_len)117return (1);118119/*120* Returns 0 on success (decompression function returned non-negative)121* and non-zero on failure (decompression function returned negative).122*/123return (LZ4_uncompress_unknownOutputSize(&src[sizeof (bufsiz)],124d_start, bufsiz, d_len) < 0);125}126127/*128* LZ4 API Description:129*130* Simple Functions:131* real_LZ4_compress() :132* isize : is the input size. Max supported value is ~1.9GB133* return : the number of bytes written in buffer dest134* or 0 if the compression fails (if LZ4_COMPRESSMIN is set).135* note : destination buffer must be already allocated.136* destination buffer must be sized to handle worst cases137* situations (input data not compressible).138*139* Advanced Functions140*141* LZ4_uncompress_unknownOutputSize() :142* isize : is the input size, therefore the compressed size143* maxOutputSize : is the size of the destination buffer (which must be144* already allocated)145* return : the number of bytes decoded in the destination buffer146* (necessarily <= maxOutputSize). If the source stream is147* malformed, the function will stop decoding and return a148* negative result, indicating the byte position of the faulty149* instruction. This function never writes beyond dest +150* maxOutputSize, and is therefore protected against malicious151* data packets.152* note : Destination buffer must be already allocated.153*154* LZ4_compressCtx() :155* This function explicitly handles the CTX memory structure.156*157* ILLUMOS CHANGES: the CTX memory structure must be explicitly allocated158* by the caller (either on the stack or using kmem_zalloc). Passing NULL159* isn't valid.160*161* LZ4_compress64kCtx() :162* Same as LZ4_compressCtx(), but specific to small inputs (<64KB).163* isize *Must* be <64KB, otherwise the output will be corrupted.164*165* ILLUMOS CHANGES: the CTX memory structure must be explicitly allocated166* by the caller (either on the stack or using kmem_zalloc). Passing NULL167* isn't valid.168*/169170/*171* Tuning parameters172*/173174/*175* COMPRESSIONLEVEL: Increasing this value improves compression ratio176* Lowering this value reduces memory usage. Reduced memory usage177* typically improves speed, due to cache effect (ex: L1 32KB for Intel,178* L1 64KB for AMD). Memory usage formula : N->2^(N+2) Bytes179* (examples : 12 -> 16KB ; 17 -> 512KB)180*/181#define COMPRESSIONLEVEL 12182183/*184* NOTCOMPRESSIBLE_CONFIRMATION: Decreasing this value will make the185* algorithm skip faster data segments considered "incompressible".186* This may decrease compression ratio dramatically, but will be187* faster on incompressible data. Increasing this value will make188* the algorithm search more before declaring a segment "incompressible".189* This could improve compression a bit, but will be slower on190* incompressible data. The default value (6) is recommended.191*/192#define NOTCOMPRESSIBLE_CONFIRMATION 6193194/*195* BIG_ENDIAN_NATIVE_BUT_INCOMPATIBLE: This will provide a boost to196* performance for big endian cpu, but the resulting compressed stream197* will be incompatible with little-endian CPU. You can set this option198* to 1 in situations where data will stay within closed environment.199* This option is useless on Little_Endian CPU (such as x86).200*/201/* #define BIG_ENDIAN_NATIVE_BUT_INCOMPATIBLE 1 */202203/*204* CPU Feature Detection205*/206207/* 32 or 64 bits ? */208#if (defined(__x86_64__) || defined(__x86_64) || defined(__amd64__) || \209defined(__amd64) || defined(__ppc64__) || defined(_WIN64) || \210defined(__LP64__) || defined(_LP64))211#define LZ4_ARCH64 1212#else213#define LZ4_ARCH64 0214#endif215216/*217* Limits the amount of stack space that the algorithm may consume to hold218* the compression lookup table. The value `9' here means we'll never use219* more than 2k of stack (see above for a description of COMPRESSIONLEVEL).220* If more memory is needed, it is allocated from the heap.221*/222/* FreeBSD: Use heap for all platforms for now */223#define STACKLIMIT 0224225/*226* Little Endian or Big Endian?227* Note: overwrite the below #define if you know your architecture endianess.228*/229#if BYTE_ORDER == BIG_ENDIAN230#define LZ4_BIG_ENDIAN 1231#else232/*233* Little Endian assumed. PDP Endian and other very rare endian format234* are unsupported.235*/236#endif237238/*239* Unaligned memory access is automatically enabled for "common" CPU,240* such as x86. For others CPU, the compiler will be more cautious, and241* insert extra code to ensure aligned access is respected. If you know242* your target CPU supports unaligned memory access, you may want to243* force this option manually to improve performance244*/245#if defined(__ARM_FEATURE_UNALIGNED)246#define LZ4_FORCE_UNALIGNED_ACCESS 1247#endif248249/*250* Compiler Options251*/252#if __STDC_VERSION__ >= 199901L /* C99 */253/* "restrict" is a known keyword */254#else255/* Disable restrict */256#define restrict257#endif258259#define lz4_bswap16(x) ((unsigned short int) ((((x) >> 8) & 0xffu) | \260(((x) & 0xffu) << 8)))261262#define expect(expr, value) (__builtin_expect((expr), (value)))263264#if defined(likely)265#undef likely266#endif267#if defined(unlikely)268#undef unlikely269#endif270271#ifndef likely272#define likely(expr) expect((expr) != 0, 1)273#endif274275#ifndef unlikely276#define unlikely(expr) expect((expr) != 0, 0)277#endif278279/* Basic types */280#define BYTE uint8_t281#define U16 uint16_t282#define U32 uint32_t283#define S32 int32_t284#define U64 uint64_t285286#ifndef LZ4_FORCE_UNALIGNED_ACCESS287#pragma pack(1)288#endif289290typedef struct _U16_S {291U16 v;292} U16_S;293typedef struct _U32_S {294U32 v;295} U32_S;296typedef struct _U64_S {297U64 v;298} U64_S;299300#ifndef LZ4_FORCE_UNALIGNED_ACCESS301#pragma pack()302#endif303304#define A64(x) (((U64_S *)(__DECONST(void *, x)))->v)305#define A32(x) (((U32_S *)(__DECONST(void *, x)))->v)306#define A16(x) (((U16_S *)(__DECONST(void *, x)))->v)307308/*309* Constants310*/311#define MINMATCH 4312313#define HASH_LOG COMPRESSIONLEVEL314#define HASHTABLESIZE (1 << HASH_LOG)315#define HASH_MASK (HASHTABLESIZE - 1)316317#define SKIPSTRENGTH (NOTCOMPRESSIBLE_CONFIRMATION > 2 ? \318NOTCOMPRESSIBLE_CONFIRMATION : 2)319320/*321* Defines if memory is allocated into the stack (local variable),322* or into the heap (kmem_alloc()).323*/324#define HEAPMODE (HASH_LOG > STACKLIMIT)325#define COPYLENGTH 8326#define LASTLITERALS 5327#define MFLIMIT (COPYLENGTH + MINMATCH)328#define MINLENGTH (MFLIMIT + 1)329330#define MAXD_LOG 16331#define MAX_DISTANCE ((1 << MAXD_LOG) - 1)332333#define ML_BITS 4334#define ML_MASK ((1U<<ML_BITS)-1)335#define RUN_BITS (8-ML_BITS)336#define RUN_MASK ((1U<<RUN_BITS)-1)337338339/*340* Architecture-specific macros341*/342#if LZ4_ARCH64343#define STEPSIZE 8344#define UARCH U64345#define AARCH A64346#define LZ4_COPYSTEP(s, d) A64(d) = A64(s); d += 8; s += 8;347#define LZ4_COPYPACKET(s, d) LZ4_COPYSTEP(s, d)348#define LZ4_SECURECOPY(s, d, e) if (d < e) LZ4_WILDCOPY(s, d, e)349#define HTYPE U32350#define INITBASE(base) const BYTE* const base = ip351#else /* !LZ4_ARCH64 */352#define STEPSIZE 4353#define UARCH U32354#define AARCH A32355#define LZ4_COPYSTEP(s, d) A32(d) = A32(s); d += 4; s += 4;356#define LZ4_COPYPACKET(s, d) LZ4_COPYSTEP(s, d); LZ4_COPYSTEP(s, d);357#define LZ4_SECURECOPY LZ4_WILDCOPY358#define HTYPE const BYTE *359#define INITBASE(base) const int base = 0360#endif /* !LZ4_ARCH64 */361362#if (defined(LZ4_BIG_ENDIAN) && !defined(BIG_ENDIAN_NATIVE_BUT_INCOMPATIBLE))363#define LZ4_READ_LITTLEENDIAN_16(d, s, p) \364{ U16 v = A16(p); v = lz4_bswap16(v); d = (s) - v; }365#define LZ4_WRITE_LITTLEENDIAN_16(p, i) \366{ U16 v = (U16)(i); v = lz4_bswap16(v); A16(p) = v; p += 2; }367#else368#define LZ4_READ_LITTLEENDIAN_16(d, s, p) { d = (s) - A16(p); }369#define LZ4_WRITE_LITTLEENDIAN_16(p, v) { A16(p) = v; p += 2; }370#endif371372373/* Local structures */374struct refTables {375HTYPE hashTable[HASHTABLESIZE];376};377378379/* Macros */380#define LZ4_HASH_FUNCTION(i) (((i) * 2654435761U) >> ((MINMATCH * 8) - \381HASH_LOG))382#define LZ4_HASH_VALUE(p) LZ4_HASH_FUNCTION(A32(p))383#define LZ4_WILDCOPY(s, d, e) do { LZ4_COPYPACKET(s, d) } while (d < e);384#define LZ4_BLINDCOPY(s, d, l) { BYTE* e = (d) + l; LZ4_WILDCOPY(s, d, e); \385d = e; }386387388/* Private functions */389#if LZ4_ARCH64390391static inline int392LZ4_NbCommonBytes(register U64 val)393{394#if defined(LZ4_BIG_ENDIAN)395#if !defined(LZ4_FORCE_SW_BITCOUNT)396return (__builtin_clzll(val) >> 3);397#else398int r;399if (!(val >> 32)) {400r = 4;401} else {402r = 0;403val >>= 32;404}405if (!(val >> 16)) {406r += 2;407val >>= 8;408} else {409val >>= 24;410}411r += (!val);412return (r);413#endif414#else415#if !defined(LZ4_FORCE_SW_BITCOUNT)416return (__builtin_ctzll(val) >> 3);417#else418static const int DeBruijnBytePos[64] =419{ 0, 0, 0, 0, 0, 1, 1, 2, 0, 3, 1, 3, 1, 4, 2, 7, 0, 2, 3, 6, 1, 5,4203, 5, 1, 3, 4, 4, 2, 5, 6, 7, 7, 0, 1, 2, 3, 3, 4, 6, 2, 6, 5,4215, 3, 4, 5, 6, 7, 1, 2, 4, 6, 4,4224, 5, 7, 2, 6, 5, 7, 6, 7, 7423};424return DeBruijnBytePos[((U64) ((val & -val) * 0x0218A392CDABBD3F)) >>42558];426#endif427#endif428}429430#else431432static inline int433LZ4_NbCommonBytes(register U32 val)434{435#if defined(LZ4_BIG_ENDIAN)436#if !defined(LZ4_FORCE_SW_BITCOUNT)437return (__builtin_clz(val) >> 3);438#else439int r;440if (!(val >> 16)) {441r = 2;442val >>= 8;443} else {444r = 0;445val >>= 24;446}447r += (!val);448return (r);449#endif450#else451#if !defined(LZ4_FORCE_SW_BITCOUNT)452return (__builtin_ctz(val) >> 3);453#else454static const int DeBruijnBytePos[32] = {4550, 0, 3, 0, 3, 1, 3, 0,4563, 2, 2, 1, 3, 2, 0, 1,4573, 3, 1, 2, 2, 2, 2, 0,4583, 1, 2, 0, 1, 0, 1, 1459};460return DeBruijnBytePos[((U32) ((val & -(S32) val) * 0x077CB531U)) >>46127];462#endif463#endif464}465466#endif467468/* Compression functions */469470/*ARGSUSED*/471static int472LZ4_compressCtx(void *ctx, const char *source, char *dest, int isize,473int osize)474{475#if HEAPMODE476struct refTables *srt = (struct refTables *)ctx;477HTYPE *HashTable = (HTYPE *) (srt->hashTable);478#else479HTYPE HashTable[HASHTABLESIZE] = { 0 };480#endif481482const BYTE *ip = (const BYTE *) source;483INITBASE(base);484const BYTE *anchor = ip;485const BYTE *const iend = ip + isize;486const BYTE *const oend = (BYTE *) dest + osize;487const BYTE *const mflimit = iend - MFLIMIT;488#define matchlimit (iend - LASTLITERALS)489490BYTE *op = (BYTE *) dest;491492int len, length;493const int skipStrength = SKIPSTRENGTH;494U32 forwardH;495496497/* Init */498if (isize < MINLENGTH)499goto _last_literals;500501/* First Byte */502HashTable[LZ4_HASH_VALUE(ip)] = ip - base;503ip++;504forwardH = LZ4_HASH_VALUE(ip);505506/* Main Loop */507for (;;) {508int findMatchAttempts = (1U << skipStrength) + 3;509const BYTE *forwardIp = ip;510const BYTE *ref;511BYTE *token;512513/* Find a match */514do {515U32 h = forwardH;516int step = findMatchAttempts++ >> skipStrength;517ip = forwardIp;518forwardIp = ip + step;519520if unlikely(forwardIp > mflimit) {521goto _last_literals;522}523524forwardH = LZ4_HASH_VALUE(forwardIp);525ref = base + HashTable[h];526HashTable[h] = ip - base;527528} while ((ref < ip - MAX_DISTANCE) || (A32(ref) != A32(ip)));529530/* Catch up */531while ((ip > anchor) && (ref > (const BYTE *) source) &&532unlikely(ip[-1] == ref[-1])) {533ip--;534ref--;535}536537/* Encode Literal length */538length = ip - anchor;539token = op++;540541/* Check output limit */542if unlikely(op + length + (2 + 1 + LASTLITERALS) +543(length >> 8) > oend)544return (0);545546if (length >= (int)RUN_MASK) {547*token = (RUN_MASK << ML_BITS);548len = length - RUN_MASK;549for (; len > 254; len -= 255)550*op++ = 255;551*op++ = (BYTE)len;552} else553*token = (length << ML_BITS);554555/* Copy Literals */556LZ4_BLINDCOPY(anchor, op, length);557558_next_match:559/* Encode Offset */560LZ4_WRITE_LITTLEENDIAN_16(op, ip - ref);561562/* Start Counting */563ip += MINMATCH;564ref += MINMATCH; /* MinMatch verified */565anchor = ip;566while likely(ip < matchlimit - (STEPSIZE - 1)) {567UARCH diff = AARCH(ref) ^ AARCH(ip);568if (!diff) {569ip += STEPSIZE;570ref += STEPSIZE;571continue;572}573ip += LZ4_NbCommonBytes(diff);574goto _endCount;575}576#if LZ4_ARCH64577if ((ip < (matchlimit - 3)) && (A32(ref) == A32(ip))) {578ip += 4;579ref += 4;580}581#endif582if ((ip < (matchlimit - 1)) && (A16(ref) == A16(ip))) {583ip += 2;584ref += 2;585}586if ((ip < matchlimit) && (*ref == *ip))587ip++;588_endCount:589590/* Encode MatchLength */591len = (ip - anchor);592/* Check output limit */593if unlikely(op + (1 + LASTLITERALS) + (len >> 8) > oend)594return (0);595if (len >= (int)ML_MASK) {596*token += ML_MASK;597len -= ML_MASK;598for (; len > 509; len -= 510) {599*op++ = 255;600*op++ = 255;601}602if (len > 254) {603len -= 255;604*op++ = 255;605}606*op++ = (BYTE)len;607} else608*token += len;609610/* Test end of chunk */611if (ip > mflimit) {612anchor = ip;613break;614}615/* Fill table */616HashTable[LZ4_HASH_VALUE(ip - 2)] = ip - 2 - base;617618/* Test next position */619ref = base + HashTable[LZ4_HASH_VALUE(ip)];620HashTable[LZ4_HASH_VALUE(ip)] = ip - base;621if ((ref > ip - (MAX_DISTANCE + 1)) && (A32(ref) == A32(ip))) {622token = op++;623*token = 0;624goto _next_match;625}626/* Prepare next loop */627anchor = ip++;628forwardH = LZ4_HASH_VALUE(ip);629}630631_last_literals:632/* Encode Last Literals */633{634int lastRun = iend - anchor;635if (op + lastRun + 1 + ((lastRun + 255 - RUN_MASK) / 255) >636oend)637return (0);638if (lastRun >= (int)RUN_MASK) {639*op++ = (RUN_MASK << ML_BITS);640lastRun -= RUN_MASK;641for (; lastRun > 254; lastRun -= 255) {642*op++ = 255;643}644*op++ = (BYTE)lastRun;645} else646*op++ = (lastRun << ML_BITS);647(void) memcpy(op, anchor, iend - anchor);648op += iend - anchor;649}650651/* End */652return (int)(((char *)op) - dest);653}654655656657/* Note : this function is valid only if isize < LZ4_64KLIMIT */658#define LZ4_64KLIMIT ((1 << 16) + (MFLIMIT - 1))659#define HASHLOG64K (HASH_LOG + 1)660#define HASH64KTABLESIZE (1U << HASHLOG64K)661#define LZ4_HASH64K_FUNCTION(i) (((i) * 2654435761U) >> ((MINMATCH*8) - \662HASHLOG64K))663#define LZ4_HASH64K_VALUE(p) LZ4_HASH64K_FUNCTION(A32(p))664665/*ARGSUSED*/666static int667LZ4_compress64kCtx(void *ctx, const char *source, char *dest, int isize,668int osize)669{670#if HEAPMODE671struct refTables *srt = (struct refTables *)ctx;672U16 *HashTable = (U16 *) (srt->hashTable);673#else674U16 HashTable[HASH64KTABLESIZE] = { 0 };675#endif676677const BYTE *ip = (const BYTE *) source;678const BYTE *anchor = ip;679const BYTE *const base = ip;680const BYTE *const iend = ip + isize;681const BYTE *const oend = (BYTE *) dest + osize;682const BYTE *const mflimit = iend - MFLIMIT;683#define matchlimit (iend - LASTLITERALS)684685BYTE *op = (BYTE *) dest;686687int len, length;688const int skipStrength = SKIPSTRENGTH;689U32 forwardH;690691/* Init */692if (isize < MINLENGTH)693goto _last_literals;694695/* First Byte */696ip++;697forwardH = LZ4_HASH64K_VALUE(ip);698699/* Main Loop */700for (;;) {701int findMatchAttempts = (1U << skipStrength) + 3;702const BYTE *forwardIp = ip;703const BYTE *ref;704BYTE *token;705706/* Find a match */707do {708U32 h = forwardH;709int step = findMatchAttempts++ >> skipStrength;710ip = forwardIp;711forwardIp = ip + step;712713if (forwardIp > mflimit) {714goto _last_literals;715}716717forwardH = LZ4_HASH64K_VALUE(forwardIp);718ref = base + HashTable[h];719HashTable[h] = ip - base;720721} while (A32(ref) != A32(ip));722723/* Catch up */724while ((ip > anchor) && (ref > (const BYTE *) source) &&725(ip[-1] == ref[-1])) {726ip--;727ref--;728}729730/* Encode Literal length */731length = ip - anchor;732token = op++;733734/* Check output limit */735if unlikely(op + length + (2 + 1 + LASTLITERALS) +736(length >> 8) > oend)737return (0);738739if (length >= (int)RUN_MASK) {740*token = (RUN_MASK << ML_BITS);741len = length - RUN_MASK;742for (; len > 254; len -= 255)743*op++ = 255;744*op++ = (BYTE)len;745} else746*token = (length << ML_BITS);747748/* Copy Literals */749LZ4_BLINDCOPY(anchor, op, length);750751_next_match:752/* Encode Offset */753LZ4_WRITE_LITTLEENDIAN_16(op, ip - ref);754755/* Start Counting */756ip += MINMATCH;757ref += MINMATCH; /* MinMatch verified */758anchor = ip;759while (ip < matchlimit - (STEPSIZE - 1)) {760UARCH diff = AARCH(ref) ^ AARCH(ip);761if (!diff) {762ip += STEPSIZE;763ref += STEPSIZE;764continue;765}766ip += LZ4_NbCommonBytes(diff);767goto _endCount;768}769#if LZ4_ARCH64770if ((ip < (matchlimit - 3)) && (A32(ref) == A32(ip))) {771ip += 4;772ref += 4;773}774#endif775if ((ip < (matchlimit - 1)) && (A16(ref) == A16(ip))) {776ip += 2;777ref += 2;778}779if ((ip < matchlimit) && (*ref == *ip))780ip++;781_endCount:782783/* Encode MatchLength */784len = (ip - anchor);785/* Check output limit */786if unlikely(op + (1 + LASTLITERALS) + (len >> 8) > oend)787return (0);788if (len >= (int)ML_MASK) {789*token += ML_MASK;790len -= ML_MASK;791for (; len > 509; len -= 510) {792*op++ = 255;793*op++ = 255;794}795if (len > 254) {796len -= 255;797*op++ = 255;798}799*op++ = (BYTE)len;800} else801*token += len;802803/* Test end of chunk */804if (ip > mflimit) {805anchor = ip;806break;807}808/* Fill table */809HashTable[LZ4_HASH64K_VALUE(ip - 2)] = ip - 2 - base;810811/* Test next position */812ref = base + HashTable[LZ4_HASH64K_VALUE(ip)];813HashTable[LZ4_HASH64K_VALUE(ip)] = ip - base;814if (A32(ref) == A32(ip)) {815token = op++;816*token = 0;817goto _next_match;818}819/* Prepare next loop */820anchor = ip++;821forwardH = LZ4_HASH64K_VALUE(ip);822}823824_last_literals:825/* Encode Last Literals */826{827int lastRun = iend - anchor;828if (op + lastRun + 1 + ((lastRun + 255 - RUN_MASK) / 255) >829oend)830return (0);831if (lastRun >= (int)RUN_MASK) {832*op++ = (RUN_MASK << ML_BITS);833lastRun -= RUN_MASK;834for (; lastRun > 254; lastRun -= 255)835*op++ = 255;836*op++ = (BYTE)lastRun;837} else838*op++ = (lastRun << ML_BITS);839(void) memcpy(op, anchor, iend - anchor);840op += iend - anchor;841}842843/* End */844return (int)(((char *)op) - dest);845}846847static int848real_LZ4_compress(const char *source, char *dest, int isize, int osize)849{850#if HEAPMODE851#if defined(_KERNEL) || defined(_FAKE_KERNEL)852void *ctx = kmem_cache_alloc(lz4_ctx_cache, KM_NOSLEEP);853#else854void *ctx = calloc(1, sizeof(struct refTables));855#endif856int result;857858/*859* out of kernel memory, gently fall through - this will disable860* compression in zio_compress_data861*/862if (ctx == NULL)863return (0);864865bzero(ctx, sizeof(struct refTables));866if (isize < LZ4_64KLIMIT)867result = LZ4_compress64kCtx(ctx, source, dest, isize, osize);868else869result = LZ4_compressCtx(ctx, source, dest, isize, osize);870871#if defined(_KERNEL) || defined(_FAKE_KERNEL)872kmem_cache_free(lz4_ctx_cache, ctx);873#else874free(ctx);875#endif876return (result);877#else878if (isize < (int)LZ4_64KLIMIT)879return (LZ4_compress64kCtx(NULL, source, dest, isize, osize));880return (LZ4_compressCtx(NULL, source, dest, isize, osize));881#endif882}883884/* Decompression functions */885886/*887* Note: The decoding function LZ4_uncompress_unknownOutputSize() is safe888* against "buffer overflow" attack type. It will never write nor889* read outside of the provided output buffers.890* LZ4_uncompress_unknownOutputSize() also insures that it will never891* read outside of the input buffer. A corrupted input will produce892* an error result, a negative int, indicating the position of the893* error within input stream.894*/895896static int897LZ4_uncompress_unknownOutputSize(const char *source, char *dest, int isize,898int maxOutputSize)899{900/* Local Variables */901const BYTE *restrict ip = (const BYTE *) source;902const BYTE *const iend = ip + isize;903const BYTE *ref;904905BYTE *op = (BYTE *) dest;906BYTE *const oend = op + maxOutputSize;907BYTE *cpy;908909size_t dec32table[] = {0, 3, 2, 3, 0, 0, 0, 0};910#if LZ4_ARCH64911size_t dec64table[] = {0, 0, 0, (size_t)-1, 0, 1, 2, 3};912#endif913914/* Main Loop */915while (ip < iend) {916unsigned token;917size_t length;918919/* get runlength */920token = *ip++;921if ((length = (token >> ML_BITS)) == RUN_MASK) {922int s = 255;923while ((ip < iend) && (s == 255)) {924s = *ip++;925length += s;926}927}928/* copy literals */929cpy = op + length;930/* CORNER-CASE: cpy might overflow. */931if (cpy < op)932goto _output_error; /* cpy was overflowed, bail! */933if ((cpy > oend - COPYLENGTH) ||934(ip + length > iend - COPYLENGTH)) {935if (cpy > oend)936/* Error: writes beyond output buffer */937goto _output_error;938if (ip + length != iend)939/*940* Error: LZ4 format requires to consume all941* input at this stage942*/943goto _output_error;944(void) memcpy(op, ip, length);945op += length;946/* Necessarily EOF, due to parsing restrictions */947break;948}949LZ4_WILDCOPY(ip, op, cpy);950ip -= (op - cpy);951op = cpy;952953/* get offset */954LZ4_READ_LITTLEENDIAN_16(ref, cpy, ip);955ip += 2;956if (ref < (BYTE * const) dest)957/*958* Error: offset creates reference outside of959* destination buffer960*/961goto _output_error;962963/* get matchlength */964if ((length = (token & ML_MASK)) == ML_MASK) {965while (ip < iend) {966int s = *ip++;967length += s;968if (s == 255)969continue;970break;971}972}973/* copy repeated sequence */974if unlikely(op - ref < STEPSIZE) {975#if LZ4_ARCH64976size_t dec64 = dec64table[op-ref];977#else978const int dec64 = 0;979#endif980op[0] = ref[0];981op[1] = ref[1];982op[2] = ref[2];983op[3] = ref[3];984op += 4;985ref += 4;986ref -= dec32table[op-ref];987A32(op) = A32(ref);988op += STEPSIZE - 4;989ref -= dec64;990} else {991LZ4_COPYSTEP(ref, op);992}993cpy = op + length - (STEPSIZE - 4);994if (cpy > oend - COPYLENGTH) {995if (cpy > oend)996/*997* Error: request to write outside of998* destination buffer999*/1000goto _output_error;1001LZ4_SECURECOPY(ref, op, (oend - COPYLENGTH));1002while (op < cpy)1003*op++ = *ref++;1004op = cpy;1005if (op == oend)1006/*1007* Check EOF (should never happen, since1008* last 5 bytes are supposed to be literals)1009*/1010goto _output_error;1011continue;1012}1013LZ4_SECURECOPY(ref, op, cpy);1014op = cpy; /* correction */1015}10161017/* end of decoding */1018return (int)(((char *)op) - dest);10191020/* write overflow error detected */1021_output_error:1022return (int)(-(((const char *)ip) - source));1023}10241025#if defined(_KERNEL) || defined(_FAKE_KERNEL)1026void1027lz4_init(void)1028{10291030#if HEAPMODE1031lz4_ctx_cache = kmem_cache_create("lz4_ctx", sizeof(struct refTables),10320, NULL, NULL, NULL, NULL, NULL, 0);1033#endif1034}10351036void1037lz4_fini(void)1038{10391040#if HEAPMODE1041kmem_cache_destroy(lz4_ctx_cache);1042#endif1043}1044#endif /* _KERNEL || _FAKE_KERNEL */104510461047