--- old/usr/src/uts/common/fs/zfs/lz4.c	Sat Apr 20 02:07:53 2013
+++ new/usr/src/uts/common/fs/zfs/lz4.c	Sat Apr 20 02:07:53 2013
@@ -30,6 +30,7 @@
  * 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>
@@ -36,7 +37,6 @@
 
 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);
@@ -104,16 +104,6 @@
  * 		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() :
@@ -137,7 +127,6 @@
  * 		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.
@@ -532,7 +521,7 @@
 
 	BYTE *op = (BYTE *) dest;
 
-	int len, length;
+	int length;
 	const int skipStrength = SKIPSTRENGTH;
 	U32 forwardH;
 
@@ -587,6 +576,7 @@
 			return (0);
 
 		if (length >= (int)RUN_MASK) {
+			int len;
 			*token = (RUN_MASK << ML_BITS);
 			len = length - RUN_MASK;
 			for (; len > 254; len -= 255)
@@ -604,7 +594,7 @@
 
 		/* Start Counting */
 		ip += MINMATCH;
-		ref += MINMATCH;	/* MinMatch verified */
+		ref += MINMATCH;	/* MinMatch already verified */
 		anchor = ip;
 		while likely(ip < matchlimit - (STEPSIZE - 1)) {
 			UARCH diff = AARCH(ref) ^ AARCH(ip);
@@ -631,24 +621,24 @@
 		_endCount:
 
 		/* Encode MatchLength */
-		len = (ip - anchor);
+		length = (int)(ip - anchor);
 		/* Check output limit */
-		if unlikely(op + (1 + LASTLITERALS) + (len >> 8) > oend)
+		if unlikely(op + (1 + LASTLITERALS) + (length >> 8) > oend)
 			return (0);
-		if (len >= (int)ML_MASK) {
+		if (length >= (int)ML_MASK) {
 			*token += ML_MASK;
-			len -= ML_MASK;
-			for (; len > 509; len -= 510) {
+			length -= ML_MASK;
+			for (; length > 509; length -= 510) {
 				*op++ = 255;
 				*op++ = 255;
 			}
-			if (len > 254) {
-				len -= 255;
+			if (length > 254) {
+				length -= 255;
 				*op++ = 255;
 			}
-			*op++ = (BYTE)len;
+			*op++ = (BYTE)length;
 		} else
-			*token += len;
+			*token += length;
 
 		/* Test end of chunk */
 		if (ip > mflimit) {
@@ -917,129 +907,7 @@
 
 /* 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)
 {
@@ -1057,8 +925,17 @@
 	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 */
-	while (ip < iend) {
+	/*LINTED E_CONSTANT_CONDITION*/
+	while (1) {
 		unsigned token;
 		size_t length;
 
@@ -1073,8 +950,8 @@
 		}
 		/* copy literals */
 		cpy = op + length;
-		if ((cpy > oend - COPYLENGTH) ||
-		    (ip + length > iend - COPYLENGTH)) {
+		if ((cpy > oend - MFLIMIT) ||
+		    (ip + length > iend - (2 + 1 + LASTLITERALS))) {
 			if (cpy > oend)
 				/* Error: writes beyond output buffer */
 				goto _output_error;
@@ -1081,7 +958,9 @@
 			if (ip + length != iend)
 				/*
 				 * Error: LZ4 format requires to consume all
-				 * input at this stage
+				 * 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);
@@ -1096,7 +975,7 @@
 		/* get offset */
 		LZ4_READ_LITTLEENDIAN_16(ref, cpy, ip);
 		ip += 2;
-		if (ref < (BYTE * const) dest)
+		if (unlikely(ref < (BYTE * const) dest))
 			/*
 			 * Error: offset creates reference outside of
 			 * destination buffer
@@ -1105,7 +984,7 @@
 
 		/* get matchlength */
 		if ((length = (token & ML_MASK)) == ML_MASK) {
-			while (ip < iend) {
+			while (likely(ip < iend - (LASTLITERALS + 1))) {
 				int s = *ip++;
 				length += s;
 				if (s == 255)
@@ -1134,11 +1013,10 @@
 			LZ4_COPYSTEP(ref, op);
 		}
 		cpy = op + length - (STEPSIZE - 4);
-		if (cpy > oend - COPYLENGTH) {
-			if (cpy > oend)
+		if (unlikely(cpy > oend - (COPYLENGTH + (STEPSIZE - 4)))) {
+			if (cpy > oend - LASTLITERALS)
 				/*
-				 * Error: request to write outside of
-				 * destination buffer
+				 * Error: last 5 bytes must be literals
 				 */
 				goto _output_error;
 			LZ4_SECURECOPY(ref, op, (oend - COPYLENGTH));
@@ -1153,7 +1031,7 @@
 				goto _output_error;
 			continue;
 		}
-		LZ4_SECURECOPY(ref, op, cpy);
+		LZ4_WILDCOPY(ref, op, cpy);
 		op = cpy;	/* correction */
 	}
 
