summaryrefslogtreecommitdiffstats
path: root/lib/lz4.c
diff options
context:
space:
mode:
authorJulius Werner <jwerner@chromium.org>2016-02-12 23:35:41 (GMT)
committerJulius Werner <jwerner@chromium.org>2016-02-13 06:52:51 (GMT)
commitdc868cd5b1bc2c68405732fe080b7b0e5dff0cca (patch)
tree4f81fe61be4cb253455dd4190b07daa03840bd7c /lib/lz4.c
parent4fcb2e17fb065f1d061a9c72066dd4dc1eb94a3f (diff)
downloadlz4-dc868cd5b1bc2c68405732fe080b7b0e5dff0cca.zip
lz4-dc868cd5b1bc2c68405732fe080b7b0e5dff0cca.tar.gz
lz4-dc868cd5b1bc2c68405732fe080b7b0e5dff0cca.tar.bz2
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 <jwerner@chromium.org>
Diffstat (limited to 'lib/lz4.c')
-rw-r--r--lib/lz4.c5
1 files changed, 4 insertions, 1 deletions
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 */