diff options
author | Alexey Tourbin <alexey.tourbin@gmail.com> | 2018-04-27 12:00:11 (GMT) |
---|---|---|
committer | Alexey Tourbin <alexey.tourbin@gmail.com> | 2018-04-27 12:10:12 (GMT) |
commit | d81a434c3dc032779dba6f22a58b127922ef332f (patch) | |
tree | fdd21976d95440b8b3facf4453f7bebb14a8edc9 /lib | |
parent | ce4e1389cc38c3c26f40ecef9c4fa6438411fa90 (diff) | |
download | lz4-d81a434c3dc032779dba6f22a58b127922ef332f.zip lz4-d81a434c3dc032779dba6f22a58b127922ef332f.tar.gz lz4-d81a434c3dc032779dba6f22a58b127922ef332f.tar.bz2 |
lz4.c: fixed the LZ4_decompress_fast_continue case
The change is very similar to that of the LZ4_decompress_safe_continue
case. The only reason a make this a separate change is to ensure that
the fuzzer, after it's been enhanced, can detect the flaw in
LZ4_decompress_fast_continue, and that the change indeed fixes the flaw.
Diffstat (limited to 'lib')
-rw-r--r-- | lib/lz4.c | 24 |
1 files changed, 22 insertions, 2 deletions
@@ -1752,6 +1752,15 @@ int LZ4_decompress_safe_doubleDict(const char* source, char* dest, int compresse (BYTE*)dest-prefixSize, (const BYTE*)dictStart, dictSize); } +LZ4_FORCE_INLINE +int LZ4_decompress_fast_doubleDict(const char* source, char* dest, int originalSize, + size_t prefixSize, const void* dictStart, size_t dictSize) +{ + return LZ4_decompress_generic(source, dest, 0, originalSize, + endOnOutputSize, full, 0, usingExtDict, + (BYTE*)dest-prefixSize, (const BYTE*)dictStart, dictSize); +} + /*===== streaming decompression functions =====*/ LZ4_streamDecode_t* LZ4_createStreamDecode(void) @@ -1831,21 +1840,32 @@ int LZ4_decompress_safe_continue (LZ4_streamDecode_t* LZ4_streamDecode, const ch return result; } +LZ4_FORCE_O2_GCC_PPC64LE int LZ4_decompress_fast_continue (LZ4_streamDecode_t* LZ4_streamDecode, const char* source, char* dest, int originalSize) { LZ4_streamDecode_t_internal* lz4sd = &LZ4_streamDecode->internal_donotuse; int result; - if (lz4sd->prefixSize == 0 || lz4sd->prefixEnd == (BYTE*)dest) { + if (lz4sd->prefixSize == 0) { + assert(lz4sd->extDictSize == 0); result = LZ4_decompress_fast(source, dest, originalSize); if (result <= 0) return result; + lz4sd->prefixSize = originalSize; + lz4sd->prefixEnd = (BYTE*)dest + originalSize; + } else if (lz4sd->prefixEnd == (BYTE*)dest) { + if (lz4sd->prefixSize >= 64 KB - 1 || lz4sd->extDictSize == 0) + result = LZ4_decompress_fast(source, dest, originalSize); + else + result = LZ4_decompress_fast_doubleDict(source, dest, originalSize, + lz4sd->prefixSize, lz4sd->externalDict, lz4sd->extDictSize); + if (result <= 0) return result; lz4sd->prefixSize += originalSize; lz4sd->prefixEnd += originalSize; } else { lz4sd->extDictSize = lz4sd->prefixSize; lz4sd->externalDict = lz4sd->prefixEnd - lz4sd->extDictSize; result = LZ4_decompress_fast_extDict(source, dest, originalSize, - (const char*)lz4sd->externalDict, lz4sd->extDictSize); + lz4sd->externalDict, lz4sd->extDictSize); if (result <= 0) return result; lz4sd->prefixSize = originalSize; lz4sd->prefixEnd = (BYTE*)dest + originalSize; |