From dc868cd5b1bc2c68405732fe080b7b0e5dff0cca Mon Sep 17 00:00:00 2001 From: Julius Werner Date: Fri, 12 Feb 2016 15:35:41 -0800 Subject: [PATCH] Allow for safe in-place decoding Add a check to allow safe "in-place" decoding (meaning that the beginning of the source buffer partially overlaps the end of the destination buffer). This is usually possible as long as the output stops at least 15 bytes before the end of the input buffer (7 to account for the extra spill from LZ4_wildCopy, 4 for a possible block checksum, and 4 for the terminating block header), but in some pathological edge cases it could be possible for the output stream to overwrite a byte in the input stream before it gets decoded. With this patch the decoder will reliably detect those cases and return a decoding error. Signed-off-by: Julius Werner --- lib/lz4.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/lib/lz4.c b/lib/lz4.c index ff48644..8512452 100644 --- a/lib/lz4.c +++ b/lib/lz4.c @@ -1182,6 +1182,7 @@ FORCE_INLINE int LZ4_decompress_generic( const int safeDecode = (endOnInput==endOnInputSize); const int checkOffset = ((safeDecode) && (dictSize < (int)(64 KB))); + const int inPlaceDecode = ((ip >= op) && (ip < oend)); /* Special cases */ @@ -1198,6 +1199,8 @@ FORCE_INLINE int LZ4_decompress_generic( const BYTE* match; size_t offset; + if (unlikely((inPlaceDecode) && (op + WILDCOPYLENGTH > ip))) goto _output_error; /* output stream ran over input stream */ + /* get literal length */ token = *ip++; if ((length=(token>>ML_BITS)) == RUN_MASK) @@ -1228,7 +1231,7 @@ FORCE_INLINE int LZ4_decompress_generic( if ((!endOnInput) && (cpy != oend)) goto _output_error; /* Error : block decoding must stop exactly there */ if ((endOnInput) && ((ip+length != iend) || (cpy > oend))) goto _output_error; /* Error : input must be consumed */ } - memcpy(op, ip, length); + memmove(op, ip, length); ip += length; op += length; break; /* Necessarily EOF, due to parsing restrictions */