diff options
author | Yann Collet <Cyan4973@users.noreply.github.com> | 2020-11-08 05:05:27 (GMT) |
---|---|---|
committer | GitHub <noreply@github.com> | 2020-11-08 05:05:27 (GMT) |
commit | c41be7e92060cfc2e5f52bcdd7f7426edd4935a4 (patch) | |
tree | 4c1cf21414f1feff4f309a2e9fad74fe8b0dff28 | |
parent | 1d02141bf8149c1f0091a4c2548cc4f28092f73a (diff) | |
parent | e251a840253c5564364bf5c8c662a6fe623dc3e9 (diff) | |
download | lz4-c41be7e92060cfc2e5f52bcdd7f7426edd4935a4.zip lz4-c41be7e92060cfc2e5f52bcdd7f7426edd4935a4.tar.gz lz4-c41be7e92060cfc2e5f52bcdd7f7426edd4935a4.tar.bz2 |
Merge pull request #942 from lz4/fix926
fix #926
-rw-r--r-- | lib/lz4.c | 4 | ||||
-rw-r--r-- | lib/lz4hc.c | 38 | ||||
-rw-r--r-- | tests/fuzzer.c | 36 |
3 files changed, 57 insertions, 21 deletions
@@ -1661,7 +1661,9 @@ int LZ4_saveDict (LZ4_stream_t* LZ4_dict, char* safeBuffer, int dictSize) if ((U32)dictSize > 64 KB) { dictSize = 64 KB; } /* useless to define a dictionary > 64 KB */ if ((U32)dictSize > dict->dictSize) { dictSize = (int)dict->dictSize; } - memmove(safeBuffer, previousDictEnd - dictSize, dictSize); + if (safeBuffer == NULL) assert(dictSize == 0); + if (safeBuffer != NULL) + memmove(safeBuffer, previousDictEnd - dictSize, dictSize); dict->dictionary = (const BYTE*)safeBuffer; dict->dictSize = (U32)dictSize; diff --git a/lib/lz4hc.c b/lib/lz4hc.c index ef7ded3..8875f1a 100644 --- a/lib/lz4hc.c +++ b/lib/lz4hc.c @@ -1003,18 +1003,16 @@ int LZ4_freeStreamHC (LZ4_streamHC_t* LZ4_streamHCPtr) LZ4_streamHC_t* LZ4_initStreamHC (void* buffer, size_t size) { LZ4_streamHC_t* const LZ4_streamHCPtr = (LZ4_streamHC_t*)buffer; + /* if compilation fails here, LZ4_STREAMHCSIZE must be increased */ + LZ4_STATIC_ASSERT(sizeof(LZ4HC_CCtx_internal) <= LZ4_STREAMHCSIZE); + DEBUGLOG(4, "LZ4_initStreamHC(%p, %u)", buffer, (unsigned)size); + /* check conditions */ if (buffer == NULL) return NULL; if (size < sizeof(LZ4_streamHC_t)) return NULL; if (!LZ4_isAligned(buffer, LZ4_streamHC_t_alignment())) return NULL; - /* if compilation fails here, LZ4_STREAMHCSIZE must be increased */ - LZ4_STATIC_ASSERT(sizeof(LZ4HC_CCtx_internal) <= LZ4_STREAMHCSIZE); - DEBUGLOG(4, "LZ4_initStreamHC(%p, %u)", LZ4_streamHCPtr, (unsigned)size); - /* end-base will trigger a clearTable on starting compression */ - LZ4_streamHCPtr->internal_donotuse.end = (const BYTE *)(ptrdiff_t)-1; - LZ4_streamHCPtr->internal_donotuse.base = NULL; - LZ4_streamHCPtr->internal_donotuse.dictCtx = NULL; - LZ4_streamHCPtr->internal_donotuse.favorDecSpeed = 0; - LZ4_streamHCPtr->internal_donotuse.dirty = 0; + /* init */ + { LZ4HC_CCtx_internal* const hcstate = &(LZ4_streamHCPtr->internal_donotuse); + MEM_INIT(hcstate, 0, sizeof(*hcstate)); } LZ4_setCompressionLevel(LZ4_streamHCPtr, LZ4HC_CLEVEL_DEFAULT); return LZ4_streamHCPtr; } @@ -1100,10 +1098,11 @@ static void LZ4HC_setExternalDict(LZ4HC_CCtx_internal* ctxPtr, const BYTE* newBl ctxPtr->dictCtx = NULL; } -static int LZ4_compressHC_continue_generic (LZ4_streamHC_t* LZ4_streamHCPtr, - const char* src, char* dst, - int* srcSizePtr, int dstCapacity, - limitedOutput_directive limit) +static int +LZ4_compressHC_continue_generic (LZ4_streamHC_t* LZ4_streamHCPtr, + const char* src, char* dst, + int* srcSizePtr, int dstCapacity, + limitedOutput_directive limit) { LZ4HC_CCtx_internal* const ctxPtr = &LZ4_streamHCPtr->internal_donotuse; DEBUGLOG(5, "LZ4_compressHC_continue_generic(ctx=%p, src=%p, srcSize=%d, limit=%d)", @@ -1131,8 +1130,7 @@ static int LZ4_compressHC_continue_generic (LZ4_streamHC_t* LZ4_streamHCPtr, if (sourceEnd > dictEnd) sourceEnd = dictEnd; ctxPtr->lowLimit = (U32)(sourceEnd - ctxPtr->dictBase); if (ctxPtr->dictLimit - ctxPtr->lowLimit < 4) ctxPtr->lowLimit = ctxPtr->dictLimit; - } - } + } } return LZ4HC_compress_generic (ctxPtr, src, dst, srcSizePtr, dstCapacity, ctxPtr->compressionLevel, limit); } @@ -1152,13 +1150,17 @@ int LZ4_compress_HC_continue_destSize (LZ4_streamHC_t* LZ4_streamHCPtr, const ch -/* dictionary saving */ - +/* LZ4_saveDictHC : + * save history content + * into a user-provided buffer + * which is then used to continue compression + */ int LZ4_saveDictHC (LZ4_streamHC_t* LZ4_streamHCPtr, char* safeBuffer, int dictSize) { LZ4HC_CCtx_internal* const streamPtr = &LZ4_streamHCPtr->internal_donotuse; int const prefixSize = (int)(streamPtr->end - (streamPtr->base + streamPtr->dictLimit)); - DEBUGLOG(4, "LZ4_saveDictHC(%p, %p, %d)", LZ4_streamHCPtr, safeBuffer, dictSize); + DEBUGLOG(5, "LZ4_saveDictHC(%p, %p, %d)", LZ4_streamHCPtr, safeBuffer, dictSize); + assert(prefixSize >= 0); if (dictSize > 64 KB) dictSize = 64 KB; if (dictSize < 4) dictSize = 0; if (dictSize > prefixSize) dictSize = prefixSize; diff --git a/tests/fuzzer.c b/tests/fuzzer.c index 29c6a8a..99361dd 100644 --- a/tests/fuzzer.c +++ b/tests/fuzzer.c @@ -1135,13 +1135,13 @@ static void FUZ_unitTests(int compressionLevel) shct* const shc = (shct*)malloc(sizeof(*shc)); assert(shc != NULL); memset(shc, 0, sizeof(*shc)); - DISPLAYLEVEL(3, "state1(%p) state2(%p) state3(%p) size(0x%x): ", + DISPLAYLEVEL(3, "state1(%p) state2(%p) state3(%p) LZ4_stream_t size(0x%x): ", &(shc->state1), &(shc->state2), &(shc->state3), (unsigned)sizeof(LZ4_stream_t)); FUZ_CHECKTEST( LZ4_initStream(&(shc->state1), sizeof(shc->state1)) == NULL, "state1 (%p) failed init", &(shc->state1) ); FUZ_CHECKTEST( LZ4_initStream(&(shc->state2), sizeof(shc->state2)) == NULL, "state2 (%p) failed init", &(shc->state2) ); FUZ_CHECKTEST( LZ4_initStream(&(shc->state3), sizeof(shc->state3)) == NULL, "state3 (%p) failed init", &(shc->state3) ); FUZ_CHECKTEST( LZ4_initStream((char*)&(shc->state1) + 1, sizeof(shc->state1)) != NULL, - "hc1+1 (%p) init must fail, due to bad alignment", (char*)&(shc->state1) + 1 ); + "hc1+1 (%p) init must fail, due to bad alignment", (char*)&(shc->state1) + 1 ); free(shc); } DISPLAYLEVEL(3, "all inits OK \n"); @@ -1167,6 +1167,22 @@ static void FUZ_unitTests(int compressionLevel) FUZ_CHECKTEST(crcOrig!=crcNew, "LZ4_decompress_safe() decompression corruption"); } } + /* early saveDict */ + DISPLAYLEVEL(3, "saveDict (right after init) : "); + { LZ4_stream_t* const ctx = LZ4_initStream(&streamingState, sizeof(streamingState)); + assert(ctx != NULL); /* ensure init is successful */ + + /* Check access violation with asan */ + FUZ_CHECKTEST( LZ4_saveDict(&streamingState, NULL, 0) != 0, + "LZ4_saveDict() can't save anything into (NULL,0)"); + + /* Check access violation with asan */ + { char tmp_buffer[240] = { 0 }; + FUZ_CHECKTEST( LZ4_saveDict(&streamingState, tmp_buffer, sizeof(tmp_buffer)) != 0, + "LZ4_saveDict() can't save anything since compression hasn't started"); + } } + DISPLAYLEVEL(3, "OK \n"); + /* ring buffer test */ { XXH64_state_t xxhOrig; XXH64_state_t xxhNewSafe, xxhNewFast; @@ -1268,6 +1284,22 @@ static void FUZ_unitTests(int compressionLevel) } } DISPLAYLEVEL(3, "OK \n"); + /* saveDictHC test #926 */ + DISPLAYLEVEL(3, "saveDictHC test #926 : "); + { LZ4_streamHC_t* const ctx = LZ4_initStreamHC(&sHC, sizeof(sHC)); + assert(ctx != NULL); /* ensure init is successful */ + + /* Check access violation with asan */ + FUZ_CHECKTEST( LZ4_saveDictHC(&sHC, NULL, 0) != 0, + "LZ4_saveDictHC() can't save anything into (NULL,0)"); + + /* Check access violation with asan */ + { char tmp_buffer[240] = { 0 }; + FUZ_CHECKTEST( LZ4_saveDictHC(&sHC, tmp_buffer, sizeof(tmp_buffer)) != 0, + "LZ4_saveDictHC() can't save anything since compression hasn't started"); + } } + DISPLAYLEVEL(3, "OK \n"); + /* long sequence test */ DISPLAYLEVEL(3, "Long sequence HC_destSize test : "); { size_t const blockSize = 1 MB; |