From 1ed69691a1d1226a6d6e7c465eb1e8c2706833cb Mon Sep 17 00:00:00 2001 From: Yann Collet Date: Wed, 17 Apr 2019 13:31:24 -0700 Subject: [PATCH 1/6] fuzzer: added tests to detect LZ4_decompress_fast() out of bound read --- tests/fuzzer.c | 48 ++++++++++++++++++++++++++++-------------------- 1 file changed, 28 insertions(+), 20 deletions(-) diff --git a/tests/fuzzer.c b/tests/fuzzer.c index 68e2232..0eece15 100644 --- a/tests/fuzzer.c +++ b/tests/fuzzer.c @@ -481,32 +481,40 @@ static int FUZ_test(U32 seed, U32 nbCycles, const U32 startCycle, const double c /* Test compression */ FUZ_DISPLAYTEST("test LZ4_compress_default()"); ret = LZ4_compress_default(block, compressedBuffer, blockSize, (int)compressedBufferSize); - FUZ_CHECKTEST(ret==0, "LZ4_compress_default() failed"); + FUZ_CHECKTEST(ret<=0, "LZ4_compress_default() failed"); compressedSize = ret; /* Decompression tests */ - /* Test decoding with output size exactly correct => must work */ - FUZ_DISPLAYTEST("LZ4_decompress_fast() with exact output buffer"); - ret = LZ4_decompress_fast(compressedBuffer, decodedBuffer, blockSize); - FUZ_CHECKTEST(ret<0, "LZ4_decompress_fast failed despite correct space"); - FUZ_CHECKTEST(ret!=compressedSize, "LZ4_decompress_fast failed : did not fully read compressed data"); - { U32 const crcCheck = XXH32(decodedBuffer, blockSize, 0); - FUZ_CHECKTEST(crcCheck!=crcOrig, "LZ4_decompress_fast corrupted decoded data"); + /* Test decompress_fast() with input buffer size exactly correct => must not read out of bound */ + { char* const cBuffer_exact = malloc((size_t)compressedSize); + assert(cBuffer_exact != NULL); + memcpy(cBuffer_exact, compressedBuffer, compressedSize); + + /* Test decoding with output size exactly correct => must work */ + FUZ_DISPLAYTEST("LZ4_decompress_fast() with exact output buffer"); + ret = LZ4_decompress_fast(cBuffer_exact, decodedBuffer, blockSize); + FUZ_CHECKTEST(ret<0, "LZ4_decompress_fast failed despite correct space"); + FUZ_CHECKTEST(ret!=compressedSize, "LZ4_decompress_fast failed : did not fully read compressed data"); + { U32 const crcCheck = XXH32(decodedBuffer, (size_t)blockSize, 0); + FUZ_CHECKTEST(crcCheck!=crcOrig, "LZ4_decompress_fast corrupted decoded data"); + } + + /* Test decoding with one byte missing => must fail */ + FUZ_DISPLAYTEST("LZ4_decompress_fast() with output buffer 1-byte too short"); + decodedBuffer[blockSize-1] = 0; + ret = LZ4_decompress_fast(cBuffer_exact, decodedBuffer, blockSize-1); + FUZ_CHECKTEST(ret>=0, "LZ4_decompress_fast should have failed, due to Output Size being too small"); + FUZ_CHECKTEST(decodedBuffer[blockSize-1], "LZ4_decompress_fast overrun specified output buffer"); + + /* Test decoding with one byte too much => must fail */ + FUZ_DISPLAYTEST(); + ret = LZ4_decompress_fast(cBuffer_exact, decodedBuffer, blockSize+1); + FUZ_CHECKTEST(ret>=0, "LZ4_decompress_fast should have failed, due to Output Size being too large"); + + free(cBuffer_exact); } - /* Test decoding with one byte missing => must fail */ - FUZ_DISPLAYTEST("LZ4_decompress_fast() with output buffer 1-byte too short"); - decodedBuffer[blockSize-1] = 0; - ret = LZ4_decompress_fast(compressedBuffer, decodedBuffer, blockSize-1); - FUZ_CHECKTEST(ret>=0, "LZ4_decompress_fast should have failed, due to Output Size being too small"); - FUZ_CHECKTEST(decodedBuffer[blockSize-1], "LZ4_decompress_fast overrun specified output buffer"); - - /* Test decoding with one byte too much => must fail */ - FUZ_DISPLAYTEST(); - ret = LZ4_decompress_fast(compressedBuffer, decodedBuffer, blockSize+1); - FUZ_CHECKTEST(ret>=0, "LZ4_decompress_fast should have failed, due to Output Size being too large"); - /* Test decoding with empty input */ FUZ_DISPLAYTEST("LZ4_decompress_safe() with empty input"); LZ4_decompress_safe(compressedBuffer, decodedBuffer, 0, blockSize); From 25d96f1e4d84b9fca8f754cd91b822fc32758e5c Mon Sep 17 00:00:00 2001 From: Yann Collet Date: Wed, 17 Apr 2019 15:01:53 -0700 Subject: [PATCH 2/6] fix out-of-bound read within LZ4_decompress_fast() and deprecate LZ4_decompress_fast(), with deprecation warnings enabled by default. Note that, as a consequence of the fix, LZ4_decompress_fast is now __slower__ than LZ4_decompress_safe(). That's because, since it doesn't know the input buffer size, it must progress more cautiously into the input buffer to ensure to out-of-bound read. --- lib/lz4.c | 15 +++++++++++++-- lib/lz4.h | 19 ++++++++++--------- 2 files changed, 23 insertions(+), 11 deletions(-) diff --git a/lib/lz4.c b/lib/lz4.c index bd8fa11..2f8aa04 100644 --- a/lib/lz4.c +++ b/lib/lz4.c @@ -135,6 +135,9 @@ # endif /* _MSC_VER */ #endif /* LZ4_FORCE_INLINE */ +#undef LZ4_FORCE_INLINE +#define LZ4_FORCE_INLINE static /* disable */ + /* LZ4_FORCE_O2_GCC_PPC64LE and LZ4_FORCE_O2_INLINE_GCC_PPC64LE * Gcc on ppc64le generates an unrolled SIMDized loop for LZ4_wildCopy, * together with a simple 8-byte copy loop as a fall-back path. @@ -1671,7 +1674,10 @@ LZ4_decompress_generic( { goto safe_literal_copy; } - LZ4_wildCopy32(op, ip, cpy); + if (endOnInput) + LZ4_wildCopy32(op, ip, cpy); + else + LZ4_wildCopy(op, ip, cpy); /* LZ4_decompress_fast() cannot copy more than 8 bytes at a time : it doesn't know input length, and only relies on end-of-block properties */ ip += length; op = cpy; } else { cpy = op+length; @@ -1681,7 +1687,12 @@ LZ4_decompress_generic( goto safe_literal_copy; } /* Literals can only be 14, but hope compilers optimize if we copy by a register size */ - memcpy(op, ip, 16); + if (endOnInput) + memcpy(op, ip, 16); + else { /* LZ4_decompress_fast() cannot copy more than 8 bytes at a time : it doesn't know input length, and only relies on end-of-block properties */ + memcpy(op, ip, 8); + if (length > 8) memcpy(op+8, ip+8, 8); + } ip += length; op = cpy; } diff --git a/lib/lz4.h b/lib/lz4.h index 1589be9..962f5e6 100644 --- a/lib/lz4.h +++ b/lib/lz4.h @@ -631,14 +631,15 @@ LZ4_DEPRECATED("use LZ4_decompress_safe_usingDict() instead") LZ4LIB_API int LZ4 LZ4_DEPRECATED("use LZ4_decompress_fast_usingDict() instead") LZ4LIB_API int LZ4_decompress_fast_withPrefix64k (const char* src, char* dst, int originalSize); /*! LZ4_decompress_fast() : **unsafe!** - * These functions are generally slightly faster than LZ4_decompress_safe(), - * though the difference is small (generally ~5%). - * However, the real cost is a risk : LZ4_decompress_safe() is protected vs malformed input, while `LZ4_decompress_fast()` is not, making it a security liability. + * These functions used to be faster than LZ4_decompress_safe(), + * but it has changed, and they are now slower than LZ4_decompress_safe(). + * This is because LZ4_decompress_fast() doesn't know the input size, + * and therefore must progress more cautiously in the input buffer to not read beyond the end of block. + * On top of that `LZ4_decompress_fast()` is not protected vs malformed or malicious inputs, making it a security liability. * As a consequence, LZ4_decompress_fast() is strongly discouraged, and deprecated. - * These functions will generate a deprecation warning in the future. * - * Last LZ4_decompress_fast() specificity is that it can decompress a block without knowing its compressed size. - * Note that even that functionality could be achieved in a more secure manner if need be, + * Only LZ4_decompress_fast() specificity is that it can decompress a block without knowing its compressed size. + * Even that functionality could be achieved in a more secure manner if need be, * though it would require new prototypes, and adaptation of the implementation to this new use case. * * Parameters: @@ -655,11 +656,11 @@ LZ4_DEPRECATED("use LZ4_decompress_fast_usingDict() instead") LZ4LIB_API int LZ4 * As a consequence, use these functions in trusted environments with trusted data **only**. */ -/* LZ4_DEPRECATED("This function is deprecated and unsafe. Consider using LZ4_decompress_safe() instead") */ +LZ4_DEPRECATED("This function is deprecated and unsafe. Consider using LZ4_decompress_safe() instead") LZ4LIB_API int LZ4_decompress_fast (const char* src, char* dst, int originalSize); -/* LZ4_DEPRECATED("This function is deprecated and unsafe. Consider using LZ4_decompress_safe_continue() instead") */ +LZ4_DEPRECATED("This function is deprecated and unsafe. Consider using LZ4_decompress_safe_continue() instead") LZ4LIB_API int LZ4_decompress_fast_continue (LZ4_streamDecode_t* LZ4_streamDecode, const char* src, char* dst, int originalSize); -/* LZ4_DEPRECATED("This function is deprecated and unsafe. Consider using LZ4_decompress_safe_usingDict() instead") */ +LZ4_DEPRECATED("This function is deprecated and unsafe. Consider using LZ4_decompress_safe_usingDict() instead") LZ4LIB_API int LZ4_decompress_fast_usingDict (const char* src, char* dst, int originalSize, const char* dictStart, int dictSize); /*! LZ4_resetStream() : From 5acfb15df066ab77301c32064b28ec9b3e571d67 Mon Sep 17 00:00:00 2001 From: Yann Collet Date: Wed, 17 Apr 2019 15:33:37 -0700 Subject: [PATCH 3/6] re-enable FORCE_INLINE was disabled for tests --- lib/lz4.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/lib/lz4.c b/lib/lz4.c index 2f8aa04..c38932e 100644 --- a/lib/lz4.c +++ b/lib/lz4.c @@ -135,9 +135,6 @@ # endif /* _MSC_VER */ #endif /* LZ4_FORCE_INLINE */ -#undef LZ4_FORCE_INLINE -#define LZ4_FORCE_INLINE static /* disable */ - /* LZ4_FORCE_O2_GCC_PPC64LE and LZ4_FORCE_O2_INLINE_GCC_PPC64LE * Gcc on ppc64le generates an unrolled SIMDized loop for LZ4_wildCopy, * together with a simple 8-byte copy loop as a fall-back path. From 8f0e7440633b956484626a432af3eae70c436419 Mon Sep 17 00:00:00 2001 From: Yann Collet Date: Wed, 17 Apr 2019 15:44:14 -0700 Subject: [PATCH 4/6] fuzzer: fix explicit cast for C++ --- tests/fuzzer.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/fuzzer.c b/tests/fuzzer.c index 0eece15..234be7c 100644 --- a/tests/fuzzer.c +++ b/tests/fuzzer.c @@ -487,7 +487,7 @@ static int FUZ_test(U32 seed, U32 nbCycles, const U32 startCycle, const double c /* Decompression tests */ /* Test decompress_fast() with input buffer size exactly correct => must not read out of bound */ - { char* const cBuffer_exact = malloc((size_t)compressedSize); + { char* const cBuffer_exact = (char*)malloc((size_t)compressedSize); assert(cBuffer_exact != NULL); memcpy(cBuffer_exact, compressedBuffer, compressedSize); From 3f558163ad74ee9553839aedb211c08a835f23a3 Mon Sep 17 00:00:00 2001 From: Yann Collet Date: Thu, 18 Apr 2019 10:38:51 -0700 Subject: [PATCH 5/6] fuzzer: fixed scan-build leak warning the program exit(), so there is no need to track and dealloc every buffer. --- tests/fuzzer.c | 29 ++++++++++------------------- 1 file changed, 10 insertions(+), 19 deletions(-) diff --git a/tests/fuzzer.c b/tests/fuzzer.c index 234be7c..14cd8a0 100644 --- a/tests/fuzzer.c +++ b/tests/fuzzer.c @@ -331,7 +331,7 @@ static int FUZ_test(U32 seed, U32 nbCycles, const U32 startCycle, const double c if (cond) { \ printf("Test %u : ", testNb); printf(__VA_ARGS__); \ printf(" (seed %u, cycle %u) \n", seed, cycleNb); \ - goto _output_error; \ + exit(1); \ } # define FUZ_DISPLAYTEST(...) { \ @@ -347,7 +347,7 @@ static int FUZ_test(U32 seed, U32 nbCycles, const U32 startCycle, const double c /* init */ if(!CNBuffer || !compressedBuffer || !decodedBuffer) { DISPLAY("Not enough memory to start fuzzer tests"); - goto _output_error; + exit(1); } if ( LZ4_initStream(&LZ4dict, sizeof(LZ4dict)) == NULL) abort(); if ( LZ4_initStreamHC(&LZ4dictHC, sizeof(LZ4dictHC)) == NULL) abort(); @@ -505,7 +505,7 @@ static int FUZ_test(U32 seed, U32 nbCycles, const U32 startCycle, const double c decodedBuffer[blockSize-1] = 0; ret = LZ4_decompress_fast(cBuffer_exact, decodedBuffer, blockSize-1); FUZ_CHECKTEST(ret>=0, "LZ4_decompress_fast should have failed, due to Output Size being too small"); - FUZ_CHECKTEST(decodedBuffer[blockSize-1], "LZ4_decompress_fast overrun specified output buffer"); + FUZ_CHECKTEST(decodedBuffer[blockSize-1]!=0, "LZ4_decompress_fast overrun specified output buffer"); /* Test decoding with one byte too much => must fail */ FUZ_DISPLAYTEST(); @@ -960,20 +960,13 @@ static int FUZ_test(U32 seed, U32 nbCycles, const U32 startCycle, const double c printf("ratio with dict: %0.3f%%\n", (double)ccbytes/bytes*100); /* release memory */ - { -_exit: - free(CNBuffer); - free(compressedBuffer); - free(decodedBuffer); - FUZ_freeLowAddr(lowAddrBuffer, labSize); - free(stateLZ4); - free(stateLZ4HC); - return result; - -_output_error: - result = 1; - goto _exit; - } + free(CNBuffer); + free(compressedBuffer); + free(decodedBuffer); + FUZ_freeLowAddr(lowAddrBuffer, labSize); + free(stateLZ4); + free(stateLZ4HC); + return result; } @@ -1388,8 +1381,6 @@ static void FUZ_unitTests(int compressionLevel) printf("All unit tests completed successfully compressionLevel=%d \n", compressionLevel); return; -_output_error: - exit(1); } From 4f6de46f60fc7b158e7fc5ce24eb06c39d8b6ce2 Mon Sep 17 00:00:00 2001 From: Yann Collet Date: Thu, 18 Apr 2019 12:05:50 -0700 Subject: [PATCH 6/6] fix several minor static analyzer warnings --- programs/bench.c | 12 ++++----- tests/checkFrame.c | 2 +- tests/frametest.c | 14 +++++----- tests/fuzzer.c | 64 +++++++++++++++++++++++++++------------------- 4 files changed, 52 insertions(+), 40 deletions(-) diff --git a/programs/bench.c b/programs/bench.c index 11bf044..5934935 100644 --- a/programs/bench.c +++ b/programs/bench.c @@ -209,7 +209,7 @@ static int BMK_benchMem(const void* srcBuffer, size_t srcSize, blockTable[nbBlocks].cPtr = cPtr; blockTable[nbBlocks].resPtr = resPtr; blockTable[nbBlocks].srcSize = thisBlockSize; - blockTable[nbBlocks].cRoom = LZ4_compressBound((int)thisBlockSize); + blockTable[nbBlocks].cRoom = (size_t)LZ4_compressBound((int)thisBlockSize); srcPtr += thisBlockSize; cPtr += blockTable[nbBlocks].cRoom; resPtr += thisBlockSize; @@ -257,8 +257,8 @@ static int BMK_benchMem(const void* srcBuffer, size_t srcSize, for (nbLoops=0; nbLoops < nbCompressionLoops; nbLoops++) { U32 blockNb; for (blockNb=0; blockNb 0) { diff --git a/tests/checkFrame.c b/tests/checkFrame.c index 50c0405..139a599 100644 --- a/tests/checkFrame.c +++ b/tests/checkFrame.c @@ -105,7 +105,7 @@ typedef struct { LZ4F_decompressionContext_t ctx; } cRess_t; -static int createCResources(cRess_t *ress) +static int createCResources(cRess_t* ress) { ress->srcBufferSize = 4 MB; ress->srcBuffer = malloc(ress->srcBufferSize); diff --git a/tests/frametest.c b/tests/frametest.c index a5197ff..9f7cb8d 100644 --- a/tests/frametest.c +++ b/tests/frametest.c @@ -167,7 +167,7 @@ static unsigned FUZ_highbit(U32 v32) /*-******************************************************* * Tests *********************************************************/ -#define CHECK_V(v,f) v = f; if (LZ4F_isError(v)) { fprintf(stderr, "%s\n", LZ4F_getErrorName(v)); goto _output_error; } +#define CHECK_V(v,f) v = f; if (LZ4F_isError(v)) { fprintf(stderr, "%s \n", LZ4F_getErrorName(v)); goto _output_error; } #define CHECK(f) { LZ4F_errorCode_t const CHECK_V(err_ , f); } int basicTests(U32 seed, double compressibility) @@ -795,8 +795,9 @@ int fuzzerTests(U32 seed, unsigned nbTests, unsigned startTest, double compressi clock_t const startClock = clock(); clock_t const clockDuration = duration_s * CLOCKS_PER_SEC; # undef CHECK -# define CHECK(cond, ...) if (cond) { DISPLAY("Error => "); DISPLAY(__VA_ARGS__); \ - DISPLAY(" (seed %u, test nb %u) \n", seed, testNb); goto _output_error; } +# define EXIT_MSG(...) { DISPLAY("Error => "); DISPLAY(__VA_ARGS__); \ + DISPLAY(" (seed %u, test nb %u) \n", seed, testNb); goto _output_error; } +# define CHECK(cond, ...) { if (cond) { EXIT_MSG(__VA_ARGS__); } } /* Create buffers */ { size_t const creationStatus = LZ4F_createDecompressionContext(&dCtx, LZ4F_VERSION); @@ -950,9 +951,10 @@ int fuzzerTests(U32 seed, unsigned nbTests, unsigned startTest, double compressi CHECK(decSize != 0, "Frame decompression failed (error %i)", (int)decSize); if (totalOut) { /* otherwise, it's a skippable frame */ U64 const crcDecoded = XXH64_digest(&xxh64); - if (crcDecoded != crcOrig) locateBuffDiff(srcStart, decodedBuffer, srcSize, nonContiguousDst); - CHECK(crcDecoded != crcOrig, "Decompression corruption"); - } + if (crcDecoded != crcOrig) { + locateBuffDiff(srcStart, decodedBuffer, srcSize, nonContiguousDst); + EXIT_MSG("Decompression corruption"); + } } } } diff --git a/tests/fuzzer.c b/tests/fuzzer.c index 14cd8a0..78f90a1 100644 --- a/tests/fuzzer.c +++ b/tests/fuzzer.c @@ -327,12 +327,13 @@ static int FUZ_test(U32 seed, U32 nbCycles, const U32 startCycle, const double c int result = 0; unsigned cycleNb; -# define FUZ_CHECKTEST(cond, ...) \ - if (cond) { \ - printf("Test %u : ", testNb); printf(__VA_ARGS__); \ - printf(" (seed %u, cycle %u) \n", seed, cycleNb); \ - exit(1); \ - } +# define EXIT_MSG(...) { \ + printf("Test %u : ", testNb); printf(__VA_ARGS__); \ + printf(" (seed %u, cycle %u) \n", seed, cycleNb); \ + exit(1); \ +} + +# define FUZ_CHECKTEST(cond, ...) { if (cond) { EXIT_MSG(__VA_ARGS__) } } # define FUZ_DISPLAYTEST(...) { \ testNb++; \ @@ -666,8 +667,10 @@ static int FUZ_test(U32 seed, U32 nbCycles, const U32 startCycle, const double c ret = LZ4_decompress_fast_usingDict(compressedBuffer, decodedBuffer+dictSize, blockSize, decodedBuffer, dictSize); FUZ_CHECKTEST(ret!=blockContinueCompressedSize, "LZ4_decompress_fast_usingDict did not read all compressed block input"); { U32 const crcCheck = XXH32(decodedBuffer+dictSize, (size_t)blockSize, 0); - if (crcCheck!=crcOrig) FUZ_findDiff(block, decodedBuffer); - FUZ_CHECKTEST(crcCheck!=crcOrig, "LZ4_decompress_fast_usingDict corrupted decoded data (dict %i)", dictSize); + if (crcCheck!=crcOrig) { + FUZ_findDiff(block, decodedBuffer); + EXIT_MSG("LZ4_decompress_fast_usingDict corrupted decoded data (dict %i)", dictSize); + } } FUZ_DISPLAYTEST("test LZ4_decompress_safe_usingDict()"); @@ -706,9 +709,11 @@ static int FUZ_test(U32 seed, U32 nbCycles, const U32 startCycle, const double c ret = LZ4_decompress_fast_usingDict(compressedBuffer, decodedBuffer, blockSize, dict, dictSize); FUZ_CHECKTEST(ret!=blockContinueCompressedSize, "LZ4_decompress_fast_usingDict did not read all compressed block input"); FUZ_CHECKTEST(decodedBuffer[blockSize], "LZ4_decompress_fast_usingDict overrun specified output buffer size"); - { U32 const crcCheck = XXH32(decodedBuffer, blockSize, 0); - if (crcCheck!=crcOrig) FUZ_findDiff(block, decodedBuffer); - FUZ_CHECKTEST(crcCheck!=crcOrig, "LZ4_decompress_fast_usingDict corrupted decoded data (dict %i)", dictSize); + { U32 const crcCheck = XXH32(decodedBuffer, (size_t)blockSize, 0); + if (crcCheck!=crcOrig) { + FUZ_findDiff(block, decodedBuffer); + EXIT_MSG("LZ4_decompress_fast_usingDict corrupted decoded data (dict %i)", dictSize); + } } FUZ_DISPLAYTEST(); @@ -804,8 +809,10 @@ static int FUZ_test(U32 seed, U32 nbCycles, const U32 startCycle, const double c FUZ_CHECKTEST(ret!=blockContinueCompressedSize, "LZ4_decompress_fast_usingDict did not read all compressed block input"); FUZ_CHECKTEST(decodedBuffer[blockSize], "LZ4_decompress_fast_usingDict overrun specified output buffer size"); { U32 const crcCheck = XXH32(decodedBuffer, blockSize, 0); - if (crcCheck!=crcOrig) FUZ_findDiff(block, decodedBuffer); - FUZ_CHECKTEST(crcCheck!=crcOrig, "LZ4_decompress_fast_usingDict corrupted decoded data (dict %i)", dictSize); + if (crcCheck!=crcOrig) { + FUZ_findDiff(block, decodedBuffer); + EXIT_MSG("LZ4_decompress_fast_usingDict corrupted decoded data (dict %i)", dictSize); + } } FUZ_DISPLAYTEST(); @@ -867,9 +874,10 @@ static int FUZ_test(U32 seed, U32 nbCycles, const U32 startCycle, const double c FUZ_CHECKTEST(ret!=blockSize, "LZ4_decompress_safe_usingDict did not regenerate original data"); FUZ_CHECKTEST(decodedBuffer[blockSize], "LZ4_decompress_safe_usingDict overrun specified output buffer size"); { U32 const crcCheck = XXH32(decodedBuffer, (size_t)blockSize, 0); - if (crcCheck!=crcOrig) FUZ_findDiff(block, decodedBuffer); - FUZ_CHECKTEST(crcCheck!=crcOrig, "LZ4_decompress_safe_usingDict corrupted decoded data"); - } + if (crcCheck!=crcOrig) { + FUZ_findDiff(block, decodedBuffer); + EXIT_MSG("LZ4_decompress_safe_usingDict corrupted decoded data"); + } } /* Compress HC using external dictionary stream */ FUZ_DISPLAYTEST(); @@ -914,9 +922,10 @@ static int FUZ_test(U32 seed, U32 nbCycles, const U32 startCycle, const double c FUZ_CHECKTEST(ret!=blockSize, "LZ4_decompress_safe_usingDict did not regenerate original data"); FUZ_CHECKTEST(decodedBuffer[blockSize], "LZ4_decompress_safe_usingDict overrun specified output buffer size"); { U32 const crcCheck = XXH32(decodedBuffer, (size_t)blockSize, 0); - if (crcCheck!=crcOrig) FUZ_findDiff(block, decodedBuffer); - FUZ_CHECKTEST(crcCheck!=crcOrig, "LZ4_decompress_safe_usingDict corrupted decoded data"); - } + if (crcCheck!=crcOrig) { + FUZ_findDiff(block, decodedBuffer); + EXIT_MSG("LZ4_decompress_safe_usingDict corrupted decoded data"); + } } /* Compress HC continue destSize */ FUZ_DISPLAYTEST(); @@ -938,9 +947,10 @@ static int FUZ_test(U32 seed, U32 nbCycles, const U32 startCycle, const double c FUZ_CHECKTEST(decodedBuffer[consumedSize], "LZ4_decompress_safe_usingDict overrun specified output buffer size") { U32 const crcSrc = XXH32(block, (size_t)consumedSize, 0); U32 const crcDst = XXH32(decodedBuffer, (size_t)consumedSize, 0); - if (crcSrc!=crcDst) FUZ_findDiff(block, decodedBuffer); - FUZ_CHECKTEST(crcSrc!=crcDst, "LZ4_decompress_safe_usingDict corrupted decoded data"); - } + if (crcSrc!=crcDst) { + FUZ_findDiff(block, decodedBuffer); + EXIT_MSG("LZ4_decompress_safe_usingDict corrupted decoded data"); + } } } /* ***** End of tests *** */ @@ -981,9 +991,8 @@ static void FUZ_unitTests(int compressionLevel) const unsigned cycleNb= 0; char testInput[testInputSize]; char testCompressed[testCompressedSize]; - size_t const testVerifySize = testInputSize; char testVerify[testInputSize]; - char ringBuffer[ringBufferSize]; + char ringBuffer[ringBufferSize] = {0}; U32 randState = 1; /* Init */ @@ -1026,7 +1035,6 @@ static void FUZ_unitTests(int compressionLevel) U32 rNext = 0; U32 dNext = 0; const U32 dBufferSize = ringBufferSize + maxMessageSizeMask; - int compressedSize; XXH64_reset(&xxhOrig, 0); XXH64_reset(&xxhNewSafe, 0); @@ -1036,6 +1044,7 @@ static void FUZ_unitTests(int compressionLevel) LZ4_setStreamDecode(&decodeStateFast, NULL, 0); while (iNext + messageSize < testCompressedSize) { + int compressedSize; XXH64_update(&xxhOrig, testInput + iNext, messageSize); crcOrig = XXH64_digest(&xxhOrig); @@ -1231,7 +1240,6 @@ static void FUZ_unitTests(int compressionLevel) U32 rNext = 0; U32 dNext = 0; const U32 dBufferSize = ringBufferSize + maxMessageSizeMask; - int compressedSize; XXH64_reset(&xxhOrig, 0); XXH64_reset(&xxhNewSafe, 0); @@ -1241,6 +1249,7 @@ static void FUZ_unitTests(int compressionLevel) LZ4_setStreamDecode(&decodeStateFast, NULL, 0); while (iNext + messageSize < testCompressedSize) { + int compressedSize; XXH64_update(&xxhOrig, testInput + iNext, messageSize); crcOrig = XXH64_digest(&xxhOrig); @@ -1293,6 +1302,7 @@ static void FUZ_unitTests(int compressionLevel) int iNext = 0; int dNext = 0; int compressedSize; + size_t const testVerifySize = testInputSize; assert((size_t)dBufferSize * 2 + 1 < testVerifySize); /* space used by ringBufferSafe and ringBufferFast */ XXH64_reset(&xxhOrig, 0); @@ -1306,7 +1316,7 @@ static void FUZ_unitTests(int compressionLevel) /* first block */ messageSize = BSIZE1; /* note : we cheat a bit here, in theory no message should be > maxMessageSize. We just want to fill the decoding ring buffer once. */ - XXH64_update(&xxhOrig, testInput + iNext, messageSize); + XXH64_update(&xxhOrig, testInput + iNext, (size_t)messageSize); crcOrig = XXH64_digest(&xxhOrig); compressedSize = LZ4_compress_HC_continue(&sHC, testInput + iNext, testCompressed, messageSize, testCompressedSize-ringBufferSize);