From 535636ff5cca702e4b5eb8e602c0ce70bfcde2c1 Mon Sep 17 00:00:00 2001 From: "W. Felix Handte" Date: Tue, 4 Dec 2018 14:05:11 -0800 Subject: [PATCH 1/2] Don't Attach Very Small Dictionaries Fixes a mismatch in behavior between loading into the context (via `LZ4_loadDict()`) a very small (<= 4 bytes) non-contiguous dictionary, versus attaching it with `LZ4_attach_dictionary()`. Before this patch, this divergence could be reproduced by running ``` make -C tests fuzzer MOREFLAGS="-m32" tests/fuzzer -v -s1239 -t3146 ``` Making sure these two paths behave exactly identically is an easy way to test the correctness of the attach path, so it's desirable that this remain an unpolluted, high signal test. --- lib/lz4.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/lib/lz4.c b/lib/lz4.c index dd9edcc..87cbb99 100644 --- a/lib/lz4.c +++ b/lib/lz4.c @@ -1271,7 +1271,9 @@ void LZ4_attach_dictionary(LZ4_stream_t *working_stream, const LZ4_stream_t *dic */ LZ4_resetStream_fast(working_stream); - if (dictionary_stream != NULL) { + if (dictionary_stream != NULL + && dictionary_stream->internal_donotuse.dictSize - 1 >= 4 + /* intentional underflow */) { /* If the current offset is zero, we will never look in the * external dictionary context, since there is no value a table * entry can take that indicate a miss. In that case, we need From 4e3accccb221c2e5dac90efec823a4b13fed70ae Mon Sep 17 00:00:00 2001 From: "W. Felix Handte" Date: Wed, 5 Dec 2018 11:24:33 -0800 Subject: [PATCH 2/2] Fix Dict Size Test in `LZ4_compress_fast_continue()` Dictionaries don't need to be > 4 bytes, they need to be >= 4 bytes. This test was overly conservative. Also removes the test in `LZ4_attach_dictionary()`. --- lib/lz4.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/lib/lz4.c b/lib/lz4.c index 87cbb99..53eff2e 100644 --- a/lib/lz4.c +++ b/lib/lz4.c @@ -1271,9 +1271,7 @@ void LZ4_attach_dictionary(LZ4_stream_t *working_stream, const LZ4_stream_t *dic */ LZ4_resetStream_fast(working_stream); - if (dictionary_stream != NULL - && dictionary_stream->internal_donotuse.dictSize - 1 >= 4 - /* intentional underflow */) { + if (dictionary_stream != NULL) { /* If the current offset is zero, we will never look in the * external dictionary context, since there is no value a table * entry can take that indicate a miss. In that case, we need @@ -1321,7 +1319,7 @@ int LZ4_compress_fast_continue (LZ4_stream_t* LZ4_stream, const char* source, ch if (acceleration < 1) acceleration = ACCELERATION_DEFAULT; /* invalidate tiny dictionaries */ - if ( (streamPtr->dictSize-1 < 4) /* intentional underflow */ + if ( (streamPtr->dictSize-1 < 4-1) /* intentional underflow */ && (dictEnd != (const BYTE*)source) ) { DEBUGLOG(5, "LZ4_compress_fast_continue: dictSize(%u) at addr:%p is too small", streamPtr->dictSize, streamPtr->dictionary); streamPtr->dictSize = 0;