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);