fix #369
The bug would make the bt search read one byte in an invalid memory region, and make a branch decision based on its value. Impact was small (missed compression opportunity). It only happens in -BD mode, with extDict-prefix overlapping matches. The bt match search is supposed to work also in extDict mode. In which case, the match ptr can point into Dict. When the match was overlapping Dict<->Prefix, match[matchLength] would end up outside of Dict, in an invalid memory area. The correction ensures that in such a case, match[matchLength] ends up at intended location, inside prefix.
This commit is contained in:
parent
2ef4afeebe
commit
6ad3a983db
14
lib/lz4.c
14
lib/lz4.c
@ -280,10 +280,22 @@ static const int LZ4_minLength = (MFLIMIT+1);
|
|||||||
|
|
||||||
|
|
||||||
/*-************************************
|
/*-************************************
|
||||||
* Common Utils
|
* Error detection
|
||||||
**************************************/
|
**************************************/
|
||||||
#define LZ4_STATIC_ASSERT(c) { enum { LZ4_static_assert = 1/(int)(!!(c)) }; } /* use only *after* variable declarations */
|
#define LZ4_STATIC_ASSERT(c) { enum { LZ4_static_assert = 1/(int)(!!(c)) }; } /* use only *after* variable declarations */
|
||||||
|
|
||||||
|
#if defined(LZ4_DEBUG) && (LZ4_DEBUG>=2)
|
||||||
|
# include <stdio.h>
|
||||||
|
# define DEBUGLOG(l, ...) { \
|
||||||
|
if (l<=LZ4_DEBUG) { \
|
||||||
|
fprintf(stderr, __FILE__ ": "); \
|
||||||
|
fprintf(stderr, __VA_ARGS__); \
|
||||||
|
fprintf(stderr, " \n"); \
|
||||||
|
} }
|
||||||
|
#else
|
||||||
|
# define DEBUGLOG(l, ...) {} /* disabled */
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
/*-************************************
|
/*-************************************
|
||||||
* Common functions
|
* Common functions
|
||||||
|
@ -122,6 +122,8 @@ FORCE_INLINE int LZ4HC_BinTree_InsertAndGetAllMatches (
|
|||||||
matchLength = LZ4_count(ip, match, vLimit);
|
matchLength = LZ4_count(ip, match, vLimit);
|
||||||
if ((ip+matchLength == vLimit) && (vLimit < iHighLimit))
|
if ((ip+matchLength == vLimit) && (vLimit < iHighLimit))
|
||||||
matchLength += LZ4_count(ip+matchLength, base+dictLimit, iHighLimit);
|
matchLength += LZ4_count(ip+matchLength, base+dictLimit, iHighLimit);
|
||||||
|
if (matchIndex+matchLength >= dictLimit)
|
||||||
|
match = base + matchIndex; /* to prepare for next usage of match[matchLength] */
|
||||||
}
|
}
|
||||||
|
|
||||||
if (matchLength > best_mlen) {
|
if (matchLength > best_mlen) {
|
||||||
@ -140,6 +142,8 @@ FORCE_INLINE int LZ4HC_BinTree_InsertAndGetAllMatches (
|
|||||||
if (ip+matchLength >= iHighLimit) /* equal : no way to know if inf or sup */
|
if (ip+matchLength >= iHighLimit) /* equal : no way to know if inf or sup */
|
||||||
break; /* drop , to guarantee consistency ; miss a bit of compression, but other solutions can corrupt the tree */
|
break; /* drop , to guarantee consistency ; miss a bit of compression, but other solutions can corrupt the tree */
|
||||||
|
|
||||||
|
DEBUGLOG(6, "ip :%016llX", (U64)ip);
|
||||||
|
DEBUGLOG(6, "match:%016llX", (U64)match);
|
||||||
if (*(ip+matchLength) < *(match+matchLength)) {
|
if (*(ip+matchLength) < *(match+matchLength)) {
|
||||||
*ptr0 = delta0;
|
*ptr0 = delta0;
|
||||||
ptr0 = &DELTANEXTMAXD(matchIndex*2);
|
ptr0 = &DELTANEXTMAXD(matchIndex*2);
|
||||||
@ -224,6 +228,7 @@ static int LZ4HC_compress_optimal (
|
|||||||
BYTE* const oend = op + maxOutputSize;
|
BYTE* const oend = op + maxOutputSize;
|
||||||
|
|
||||||
/* init */
|
/* init */
|
||||||
|
DEBUGLOG(5, "LZ4HC_compress_optimal");
|
||||||
if (sufficient_len >= LZ4_OPT_NUM) sufficient_len = LZ4_OPT_NUM-1;
|
if (sufficient_len >= LZ4_OPT_NUM) sufficient_len = LZ4_OPT_NUM-1;
|
||||||
ctx->end += inputSize;
|
ctx->end += inputSize;
|
||||||
ip++;
|
ip++;
|
||||||
|
Loading…
Reference in New Issue
Block a user