diff options
author | Yann Collet <cyan@fb.com> | 2019-04-17 22:01:53 (GMT) |
---|---|---|
committer | Yann Collet <cyan@fb.com> | 2019-04-17 22:01:53 (GMT) |
commit | 25d96f1e4d84b9fca8f754cd91b822fc32758e5c (patch) | |
tree | 7c2818389ade8b2eed6b1900e659427c6dbdafc6 /lib/lz4.c | |
parent | 1ed69691a1d1226a6d6e7c465eb1e8c2706833cb (diff) | |
download | lz4-25d96f1e4d84b9fca8f754cd91b822fc32758e5c.zip lz4-25d96f1e4d84b9fca8f754cd91b822fc32758e5c.tar.gz lz4-25d96f1e4d84b9fca8f754cd91b822fc32758e5c.tar.bz2 |
fix out-of-bound read within LZ4_decompress_fast()
and deprecate LZ4_decompress_fast(),
with deprecation warnings enabled by default.
Note that, as a consequence of the fix,
LZ4_decompress_fast is now __slower__ than LZ4_decompress_safe().
That's because, since it doesn't know the input buffer size,
it must progress more cautiously into the input buffer
to ensure to out-of-bound read.
Diffstat (limited to 'lib/lz4.c')
-rw-r--r-- | lib/lz4.c | 15 |
1 files changed, 13 insertions, 2 deletions
@@ -135,6 +135,9 @@ # endif /* _MSC_VER */ #endif /* LZ4_FORCE_INLINE */ +#undef LZ4_FORCE_INLINE +#define LZ4_FORCE_INLINE static /* disable */ + /* LZ4_FORCE_O2_GCC_PPC64LE and LZ4_FORCE_O2_INLINE_GCC_PPC64LE * Gcc on ppc64le generates an unrolled SIMDized loop for LZ4_wildCopy, * together with a simple 8-byte copy loop as a fall-back path. @@ -1671,7 +1674,10 @@ LZ4_decompress_generic( { goto safe_literal_copy; } - LZ4_wildCopy32(op, ip, cpy); + if (endOnInput) + LZ4_wildCopy32(op, ip, cpy); + else + LZ4_wildCopy(op, ip, cpy); /* LZ4_decompress_fast() cannot copy more than 8 bytes at a time : it doesn't know input length, and only relies on end-of-block properties */ ip += length; op = cpy; } else { cpy = op+length; @@ -1681,7 +1687,12 @@ LZ4_decompress_generic( goto safe_literal_copy; } /* Literals can only be 14, but hope compilers optimize if we copy by a register size */ - memcpy(op, ip, 16); + if (endOnInput) + memcpy(op, ip, 16); + else { /* LZ4_decompress_fast() cannot copy more than 8 bytes at a time : it doesn't know input length, and only relies on end-of-block properties */ + memcpy(op, ip, 8); + if (length > 8) memcpy(op+8, ip+8, 8); + } ip += length; op = cpy; } |