aboutsummaryrefslogtreecommitdiff
path: root/lib/lz4.c
diff options
context:
space:
mode:
authorAlexey Tourbin <alexey.tourbin@gmail.com>2018-04-27 15:00:11 +0300
committerAlexey Tourbin <alexey.tourbin@gmail.com>2018-04-27 15:10:12 +0300
commitd81a434c3dc032779dba6f22a58b127922ef332f (patch)
treefdd21976d95440b8b3facf4453f7bebb14a8edc9 /lib/lz4.c
parentce4e1389cc38c3c26f40ecef9c4fa6438411fa90 (diff)
downloadlz4-d81a434c3dc032779dba6f22a58b127922ef332f.tar.gz
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/lz4.c')
-rw-r--r--lib/lz4.c24
1 files changed, 22 insertions, 2 deletions
diff --git a/lib/lz4.c b/lib/lz4.c
index eb3da213..916acf09 100644
--- a/lib/lz4.c
+++ b/lib/lz4.c
@@ -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;