Print this page
Integrated r91 LZ4.
*** 28,44 ****
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* You can contact the author at :
* - LZ4 homepage : http://fastcompression.blogspot.com/p/lz4.html
* - LZ4 source repository : http://code.google.com/p/lz4/
*/
#include <sys/zfs_context.h>
static int real_LZ4_compress(const char *source, char *dest, int isize,
int osize);
- static int real_LZ4_uncompress(const char *source, char *dest, int osize);
static int LZ4_compressBound(int isize);
static int LZ4_uncompress_unknownOutputSize(const char *source, char *dest,
int isize, int maxOutputSize);
static int LZ4_compressCtx(void *ctx, const char *source, char *dest,
int isize, int osize);
--- 28,44 ----
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* You can contact the author at :
* - LZ4 homepage : http://fastcompression.blogspot.com/p/lz4.html
* - LZ4 source repository : http://code.google.com/p/lz4/
+ * Upstream release : r91
*/
#include <sys/zfs_context.h>
static int real_LZ4_compress(const char *source, char *dest, int isize,
int osize);
static int LZ4_compressBound(int isize);
static int LZ4_uncompress_unknownOutputSize(const char *source, char *dest,
int isize, int maxOutputSize);
static int LZ4_compressCtx(void *ctx, const char *source, char *dest,
int isize, int osize);
*** 102,121 ****
* note : destination buffer must be already allocated.
* destination buffer must be sized to handle worst cases
* situations (input data not compressible) worst case size
* evaluation is provided by function LZ4_compressBound().
*
- * real_LZ4_uncompress() :
- * osize : is the output size, therefore the original size
- * return : the number of bytes read in the source buffer.
- * If the source stream is malformed, the function will stop
- * decoding and return a negative result, indicating the byte
- * position of the faulty instruction. This function never
- * writes beyond dest + osize, and is therefore protected
- * against malicious data packets.
- * note : destination buffer must be already allocated
- *
* Advanced Functions
*
* LZ4_compressBound() :
* Provides the maximum size that LZ4 may output in a "worst case"
* scenario (input data not compressible) primarily useful for memory
--- 102,111 ----
*** 135,145 ****
* negative result, indicating the byte position of the faulty
* instruction. This function never writes beyond dest +
* maxOutputSize, and is therefore protected against malicious
* data packets.
* note : Destination buffer must be already allocated.
- * This version is slightly slower than real_LZ4_uncompress()
*
* LZ4_compressCtx() :
* This function explicitly handles the CTX memory structure.
*
* ILLUMOS CHANGES: the CTX memory structure must be explicitly allocated
--- 125,134 ----
*** 530,540 ****
const BYTE *const mflimit = iend - MFLIMIT;
#define matchlimit (iend - LASTLITERALS)
BYTE *op = (BYTE *) dest;
! int len, length;
const int skipStrength = SKIPSTRENGTH;
U32 forwardH;
/* Init */
--- 519,529 ----
const BYTE *const mflimit = iend - MFLIMIT;
#define matchlimit (iend - LASTLITERALS)
BYTE *op = (BYTE *) dest;
! int length;
const int skipStrength = SKIPSTRENGTH;
U32 forwardH;
/* Init */
*** 585,594 ****
--- 574,584 ----
if unlikely(op + length + (2 + 1 + LASTLITERALS) +
(length >> 8) > oend)
return (0);
if (length >= (int)RUN_MASK) {
+ int len;
*token = (RUN_MASK << ML_BITS);
len = length - RUN_MASK;
for (; len > 254; len -= 255)
*op++ = 255;
*op++ = (BYTE)len;
*** 602,612 ****
/* Encode Offset */
LZ4_WRITE_LITTLEENDIAN_16(op, ip - ref);
/* Start Counting */
ip += MINMATCH;
! ref += MINMATCH; /* MinMatch verified */
anchor = ip;
while likely(ip < matchlimit - (STEPSIZE - 1)) {
UARCH diff = AARCH(ref) ^ AARCH(ip);
if (!diff) {
ip += STEPSIZE;
--- 592,602 ----
/* Encode Offset */
LZ4_WRITE_LITTLEENDIAN_16(op, ip - ref);
/* Start Counting */
ip += MINMATCH;
! ref += MINMATCH; /* MinMatch already verified */
anchor = ip;
while likely(ip < matchlimit - (STEPSIZE - 1)) {
UARCH diff = AARCH(ref) ^ AARCH(ip);
if (!diff) {
ip += STEPSIZE;
*** 629,656 ****
if ((ip < matchlimit) && (*ref == *ip))
ip++;
_endCount:
/* Encode MatchLength */
! len = (ip - anchor);
/* Check output limit */
! if unlikely(op + (1 + LASTLITERALS) + (len >> 8) > oend)
return (0);
! if (len >= (int)ML_MASK) {
*token += ML_MASK;
! len -= ML_MASK;
! for (; len > 509; len -= 510) {
*op++ = 255;
*op++ = 255;
}
! if (len > 254) {
! len -= 255;
*op++ = 255;
}
! *op++ = (BYTE)len;
} else
! *token += len;
/* Test end of chunk */
if (ip > mflimit) {
anchor = ip;
break;
--- 619,646 ----
if ((ip < matchlimit) && (*ref == *ip))
ip++;
_endCount:
/* Encode MatchLength */
! length = (int)(ip - anchor);
/* Check output limit */
! if unlikely(op + (1 + LASTLITERALS) + (length >> 8) > oend)
return (0);
! if (length >= (int)ML_MASK) {
*token += ML_MASK;
! length -= ML_MASK;
! for (; length > 509; length -= 510) {
*op++ = 255;
*op++ = 255;
}
! if (length > 254) {
! length -= 255;
*op++ = 255;
}
! *op++ = (BYTE)length;
} else
! *token += length;
/* Test end of chunk */
if (ip > mflimit) {
anchor = ip;
break;
*** 915,1047 ****
#endif
}
/* Decompression functions */
- /*
- * Note: The decoding functions real_LZ4_uncompress() and
- * LZ4_uncompress_unknownOutputSize() are safe against "buffer overflow"
- * attack type. They will never write nor read outside of the provided
- * output buffers. LZ4_uncompress_unknownOutputSize() also insures that
- * it will never read outside of the input buffer. A corrupted input
- * will produce an error result, a negative int, indicating the position
- * of the error within input stream.
- */
-
static int
- real_LZ4_uncompress(const char *source, char *dest, int osize)
- {
- /* Local Variables */
- const BYTE *restrict ip = (const BYTE *) source;
- const BYTE *ref;
-
- BYTE *op = (BYTE *) dest;
- BYTE *const oend = op + osize;
- BYTE *cpy;
-
- unsigned token;
-
- size_t length;
- size_t dec32table[] = {0, 3, 2, 3, 0, 0, 0, 0};
- #if LZ4_ARCH64
- size_t dec64table[] = {0, 0, 0, (size_t)-1, 0, 1, 2, 3};
- #endif
-
- /* Main Loop */
- for (;;) {
- /* get runlength */
- token = *ip++;
- if ((length = (token >> ML_BITS)) == RUN_MASK) {
- size_t len;
- for (; (len = *ip++) == 255; length += 255) {
- }
- length += len;
- }
- /* copy literals */
- cpy = op + length;
- if unlikely(cpy > oend - COPYLENGTH) {
- if (cpy != oend)
- /* Error: we must necessarily stand at EOF */
- goto _output_error;
- (void) memcpy(op, ip, length);
- ip += length;
- break; /* EOF */
- }
- LZ4_WILDCOPY(ip, op, cpy);
- ip -= (op - cpy);
- op = cpy;
-
- /* get offset */
- LZ4_READ_LITTLEENDIAN_16(ref, cpy, ip);
- ip += 2;
- if unlikely(ref < (BYTE * const) dest)
- /*
- * Error: offset create reference outside destination
- * buffer
- */
- goto _output_error;
-
- /* get matchlength */
- if ((length = (token & ML_MASK)) == ML_MASK) {
- for (; *ip == 255; length += 255) {
- ip++;
- }
- length += *ip++;
- }
- /* copy repeated sequence */
- if unlikely(op - ref < STEPSIZE) {
- #if LZ4_ARCH64
- size_t dec64 = dec64table[op-ref];
- #else
- const int dec64 = 0;
- #endif
- op[0] = ref[0];
- op[1] = ref[1];
- op[2] = ref[2];
- op[3] = ref[3];
- op += 4;
- ref += 4;
- ref -= dec32table[op-ref];
- A32(op) = A32(ref);
- op += STEPSIZE - 4;
- ref -= dec64;
- } else {
- LZ4_COPYSTEP(ref, op);
- }
- cpy = op + length - (STEPSIZE - 4);
- if (cpy > oend - COPYLENGTH) {
- if (cpy > oend)
- /*
- * Error: request to write beyond destination
- * buffer
- */
- goto _output_error;
- LZ4_SECURECOPY(ref, op, (oend - COPYLENGTH));
- while (op < cpy)
- *op++ = *ref++;
- op = cpy;
- if (op == oend)
- /*
- * Check EOF (should never happen, since last
- * 5 bytes are supposed to be literals)
- */
- goto _output_error;
- continue;
- }
- LZ4_SECURECOPY(ref, op, cpy);
- op = cpy; /* correction */
- }
-
- /* end of decoding */
- return (int)(((char *)ip) - source);
-
- /* write overflow error detected */
- _output_error:
- return (int)(-(((char *)ip) - source));
- }
-
- static int
LZ4_uncompress_unknownOutputSize(const char *source, char *dest, int isize,
int maxOutputSize)
{
/* Local Variables */
const BYTE *restrict ip = (const BYTE *) source;
--- 905,915 ----
*** 1055,1066 ****
size_t dec32table[] = {0, 3, 2, 3, 0, 0, 0, 0};
#if LZ4_ARCH64
size_t dec64table[] = {0, 0, 0, (size_t)-1, 0, 1, 2, 3};
#endif
/* Main Loop */
! while (ip < iend) {
unsigned token;
size_t length;
/* get runlength */
token = *ip++;
--- 923,943 ----
size_t dec32table[] = {0, 3, 2, 3, 0, 0, 0, 0};
#if LZ4_ARCH64
size_t dec64table[] = {0, 0, 0, (size_t)-1, 0, 1, 2, 3};
#endif
+ /*
+ * Special case
+ * A correctly formed null-compressed LZ4 must have at least
+ * one byte (token=0)
+ */
+ if (unlikely(ip == iend))
+ goto _output_error;
+
/* Main Loop */
! /*LINTED E_CONSTANT_CONDITION*/
! while (1) {
unsigned token;
size_t length;
/* get runlength */
token = *ip++;
*** 1071,1089 ****
length += s;
}
}
/* copy literals */
cpy = op + length;
! if ((cpy > oend - COPYLENGTH) ||
! (ip + length > iend - COPYLENGTH)) {
if (cpy > oend)
/* Error: writes beyond output buffer */
goto _output_error;
if (ip + length != iend)
/*
* Error: LZ4 format requires to consume all
! * input at this stage
*/
goto _output_error;
(void) memcpy(op, ip, length);
op += length;
/* Necessarily EOF, due to parsing restrictions */
--- 948,968 ----
length += s;
}
}
/* copy literals */
cpy = op + length;
! if ((cpy > oend - MFLIMIT) ||
! (ip + length > iend - (2 + 1 + LASTLITERALS))) {
if (cpy > oend)
/* Error: writes beyond output buffer */
goto _output_error;
if (ip + length != iend)
/*
* Error: LZ4 format requires to consume all
! * input at this stage (no match within the
! * last 11 bytes, and at least 8 remaining
! * input bytes for another match + literals
*/
goto _output_error;
(void) memcpy(op, ip, length);
op += length;
/* Necessarily EOF, due to parsing restrictions */
*** 1094,1113 ****
op = cpy;
/* get offset */
LZ4_READ_LITTLEENDIAN_16(ref, cpy, ip);
ip += 2;
! if (ref < (BYTE * const) dest)
/*
* Error: offset creates reference outside of
* destination buffer
*/
goto _output_error;
/* get matchlength */
if ((length = (token & ML_MASK)) == ML_MASK) {
! while (ip < iend) {
int s = *ip++;
length += s;
if (s == 255)
continue;
break;
--- 973,992 ----
op = cpy;
/* get offset */
LZ4_READ_LITTLEENDIAN_16(ref, cpy, ip);
ip += 2;
! if (unlikely(ref < (BYTE * const) dest))
/*
* Error: offset creates reference outside of
* destination buffer
*/
goto _output_error;
/* get matchlength */
if ((length = (token & ML_MASK)) == ML_MASK) {
! while (likely(ip < iend - (LASTLITERALS + 1))) {
int s = *ip++;
length += s;
if (s == 255)
continue;
break;
*** 1132,1146 ****
ref -= dec64;
} else {
LZ4_COPYSTEP(ref, op);
}
cpy = op + length - (STEPSIZE - 4);
! if (cpy > oend - COPYLENGTH) {
! if (cpy > oend)
/*
! * Error: request to write outside of
! * destination buffer
*/
goto _output_error;
LZ4_SECURECOPY(ref, op, (oend - COPYLENGTH));
while (op < cpy)
*op++ = *ref++;
--- 1011,1024 ----
ref -= dec64;
} else {
LZ4_COPYSTEP(ref, op);
}
cpy = op + length - (STEPSIZE - 4);
! if (unlikely(cpy > oend - (COPYLENGTH + (STEPSIZE - 4)))) {
! if (cpy > oend - LASTLITERALS)
/*
! * Error: last 5 bytes must be literals
*/
goto _output_error;
LZ4_SECURECOPY(ref, op, (oend - COPYLENGTH));
while (op < cpy)
*op++ = *ref++;
*** 1151,1161 ****
* last 5 bytes are supposed to be literals)
*/
goto _output_error;
continue;
}
! LZ4_SECURECOPY(ref, op, cpy);
op = cpy; /* correction */
}
/* end of decoding */
return (int)(((char *)op) - dest);
--- 1029,1039 ----
* last 5 bytes are supposed to be literals)
*/
goto _output_error;
continue;
}
! LZ4_WILDCOPY(ref, op, cpy);
op = cpy; /* correction */
}
/* end of decoding */
return (int)(((char *)op) - dest);