summaryrefslogtreecommitdiff
path: root/tests/fuzzer.c
diff options
context:
space:
mode:
Diffstat (limited to 'tests/fuzzer.c')
-rw-r--r--tests/fuzzer.c303
1 files changed, 243 insertions, 60 deletions
diff --git a/tests/fuzzer.c b/tests/fuzzer.c
index 8a095c4..a824813 100644
--- a/tests/fuzzer.c
+++ b/tests/fuzzer.c
@@ -341,7 +341,7 @@ static int FUZ_test(U32 seed, U32 nbCycles, const U32 startCycle, const double c
exit(1); \
}
-# define FUZ_CHECKTEST(cond, ...) { if (cond) { EXIT_MSG(__VA_ARGS__) } }
+# define FUZ_CHECKTEST(cond, ...) if (cond) { EXIT_MSG(__VA_ARGS__) }
# define FUZ_DISPLAYTEST(...) { \
testNb++; \
@@ -446,10 +446,10 @@ static int FUZ_test(U32 seed, U32 nbCycles, const U32 startCycle, const double c
FUZ_DISPLAYTEST();
decodedBuffer[srcSize] = canary;
{ int const dSize = LZ4_decompress_safe(compressedBuffer, decodedBuffer, cSize, srcSize);
- FUZ_CHECKTEST(dSize<0, "LZ4_decompress_safe() failed on data compressed by LZ4_compressHC_destSize");
- FUZ_CHECKTEST(dSize!=srcSize, "LZ4_decompress_safe() failed : did not fully decompressed data");
+ FUZ_CHECKTEST(dSize<0, "LZ4_decompress_safe failed (%i) on data compressed by LZ4_compressHC_destSize", dSize);
+ FUZ_CHECKTEST(dSize!=srcSize, "LZ4_decompress_safe failed : decompressed %i bytes, was supposed to decompress %i bytes", dSize, srcSize);
}
- FUZ_CHECKTEST(decodedBuffer[srcSize] != canary, "LZ4_decompress_safe() overwrite dst buffer !");
+ FUZ_CHECKTEST(decodedBuffer[srcSize] != canary, "LZ4_decompress_safe overwrite dst buffer !");
{ U32 const crcDec = XXH32(decodedBuffer, (size_t)srcSize, 0);
FUZ_CHECKTEST(crcDec!=crcBase, "LZ4_decompress_safe() corrupted decoded data");
} }
@@ -618,13 +618,16 @@ static int FUZ_test(U32 seed, U32 nbCycles, const U32 startCycle, const double c
/* Test partial decoding => must work */
FUZ_DISPLAYTEST("test LZ4_decompress_safe_partial");
- { size_t const missingBytes = FUZ_rand(&randState) % (unsigned)blockSize;
- int const targetSize = (int)((size_t)blockSize - missingBytes);
+ { size_t const missingOutBytes = FUZ_rand(&randState) % (unsigned)blockSize;
+ int const targetSize = (int)((size_t)blockSize - missingOutBytes);
+ size_t const extraneousInBytes = FUZ_rand(&randState) % 2;
+ int const inCSize = (int)((size_t)compressedSize + extraneousInBytes);
char const sentinel = decodedBuffer[targetSize] = block[targetSize] ^ 0x5A;
- int const decResult = LZ4_decompress_safe_partial(compressedBuffer, decodedBuffer, compressedSize, targetSize, blockSize);
+ int const decResult = LZ4_decompress_safe_partial(compressedBuffer, decodedBuffer, inCSize, targetSize, blockSize);
FUZ_CHECKTEST(decResult<0, "LZ4_decompress_safe_partial failed despite valid input data (error:%i)", decResult);
FUZ_CHECKTEST(decResult != targetSize, "LZ4_decompress_safe_partial did not regenerated required amount of data (%i < %i <= %i)", decResult, targetSize, blockSize);
FUZ_CHECKTEST(decodedBuffer[targetSize] != sentinel, "LZ4_decompress_safe_partial overwrite beyond requested size (though %i <= %i <= %i)", decResult, targetSize, blockSize);
+ FUZ_CHECKTEST(memcmp(block, decodedBuffer, (size_t)targetSize), "LZ4_decompress_safe_partial: corruption detected in regenerated data");
}
/* Test Compression with limited output size */
@@ -787,7 +790,6 @@ static int FUZ_test(U32 seed, U32 nbCycles, const U32 startCycle, const double c
LZ4_attach_dictionary(&LZ4_stream, &LZ4dictBody);
blockContinueCompressedSize = LZ4_compress_fast_continue(&LZ4_stream, block, compressedBuffer, blockSize, (int)compressedBufferSize, 1);
FUZ_CHECKTEST(blockContinueCompressedSize==0, "LZ4_compress_fast_continue using extDictCtx failed");
- FUZ_CHECKTEST(LZ4_stream.internal_donotuse.dirty, "context should be good");
/* In the future, it might be desirable to let extDictCtx mode's
* output diverge from the output generated by regular extDict mode.
@@ -812,7 +814,6 @@ static int FUZ_test(U32 seed, U32 nbCycles, const U32 startCycle, const double c
FUZ_CHECKTEST(ret<=0, "LZ4_compress_fast_continue using extDictCtx should work : enough size available within output buffer");
FUZ_CHECKTEST(ret != expectedSize, "LZ4_compress_fast_continue using extDictCtx produced different-sized output");
FUZ_CHECKTEST(XXH32(compressedBuffer, (size_t)ret, 0) != expectedCrc, "LZ4_compress_fast_continue using extDictCtx produced different output");
- FUZ_CHECKTEST(LZ4_stream.internal_donotuse.dirty, "context should be good");
FUZ_DISPLAYTEST();
LZ4_resetStream_fast(&LZ4_stream);
@@ -822,7 +823,6 @@ static int FUZ_test(U32 seed, U32 nbCycles, const U32 startCycle, const double c
FUZ_CHECKTEST(ret<=0, "LZ4_compress_fast_continue using extDictCtx with re-used context should work : enough size available within output buffer");
FUZ_CHECKTEST(ret != expectedSize, "LZ4_compress_fast_continue using extDictCtx produced different-sized output");
FUZ_CHECKTEST(XXH32(compressedBuffer, (size_t)ret, 0) != expectedCrc, "LZ4_compress_fast_continue using extDictCtx produced different output");
- FUZ_CHECKTEST(LZ4_stream.internal_donotuse.dirty, "context should be good");
}
/* Decompress with dictionary as external */
@@ -859,12 +859,12 @@ static int FUZ_test(U32 seed, U32 nbCycles, const U32 startCycle, const double c
FUZ_CHECKTEST(decodedBuffer[blockSize-1], "LZ4_decompress_safe_usingDict overrun specified output buffer size");
FUZ_DISPLAYTEST("LZ4_decompress_safe_usingDict with a too small output buffer");
- { U32 const missingBytes = (FUZ_rand(&randState) & 0xF) + 2;
- if ((U32)blockSize > missingBytes) {
- decodedBuffer[(U32)blockSize-missingBytes] = 0;
+ { int const missingBytes = (FUZ_rand(&randState) & 0xF) + 2;
+ if (blockSize > missingBytes) {
+ decodedBuffer[blockSize-missingBytes] = 0;
ret = LZ4_decompress_safe_usingDict(compressedBuffer, decodedBuffer, blockContinueCompressedSize, blockSize-missingBytes, dict, dictSize);
- FUZ_CHECKTEST(ret>=0, "LZ4_decompress_safe_usingDict should have failed : output buffer too small (-%u byte)", missingBytes);
- FUZ_CHECKTEST(decodedBuffer[blockSize-missingBytes], "LZ4_decompress_safe_usingDict overrun specified output buffer size (-%u byte) (blockSize=%i)", missingBytes, blockSize);
+ FUZ_CHECKTEST(ret>=0, "LZ4_decompress_safe_usingDict should have failed : output buffer too small (-%i byte)", missingBytes);
+ FUZ_CHECKTEST(decodedBuffer[blockSize-missingBytes], "LZ4_decompress_safe_usingDict overrun specified output buffer size (-%i byte) (blockSize=%i)", missingBytes, blockSize);
} }
/* Compress HC using External dictionary */
@@ -931,7 +931,8 @@ static int FUZ_test(U32 seed, U32 nbCycles, const U32 startCycle, const double c
LZ4_resetStreamHC_fast (LZ4_streamHC, compressionLevel);
LZ4_attach_HC_dictionary(LZ4_streamHC, LZ4dictHC);
ret = LZ4_compress_HC_continue(LZ4_streamHC, block, compressedBuffer, blockSize, blockContinueCompressedSize);
- FUZ_CHECKTEST(ret!=blockContinueCompressedSize, "LZ4_compress_HC_continue using ExtDictCtx and fast reset size is different (%i != %i)", ret, blockContinueCompressedSize);
+ FUZ_CHECKTEST(ret!=blockContinueCompressedSize, "LZ4_compress_HC_continue using ExtDictCtx and fast reset size is different (%i != %i)",
+ ret, blockContinueCompressedSize);
FUZ_CHECKTEST(ret<=0, "LZ4_compress_HC_continue using ExtDictCtx and fast reset should work : enough size available within output buffer");
FUZ_CHECKTEST(LZ4_streamHC->internal_donotuse.dirty, "Context should be clean");
@@ -951,13 +952,14 @@ static int FUZ_test(U32 seed, U32 nbCycles, const U32 startCycle, const double c
/* Compress HC continue destSize */
FUZ_DISPLAYTEST();
- { int const availableSpace = (int)(FUZ_rand(&randState) % blockSize) + 5;
+ { int const availableSpace = (int)(FUZ_rand(&randState) % (U32)blockSize) + 5;
int consumedSize = blockSize;
FUZ_DISPLAYTEST();
LZ4_loadDictHC(LZ4dictHC, dict, dictSize);
LZ4_setCompressionLevel(LZ4dictHC, compressionLevel);
blockContinueCompressedSize = LZ4_compress_HC_continue_destSize(LZ4dictHC, block, compressedBuffer, &consumedSize, availableSpace);
- DISPLAYLEVEL(5, " LZ4_compress_HC_continue_destSize : compressed %6i/%6i into %6i/%6i at cLevel=%i\n", consumedSize, blockSize, blockContinueCompressedSize, availableSpace, compressionLevel);
+ DISPLAYLEVEL(5, " LZ4_compress_HC_continue_destSize : compressed %6i/%6i into %6i/%6i at cLevel=%i \n",
+ consumedSize, blockSize, blockContinueCompressedSize, availableSpace, compressionLevel);
FUZ_CHECKTEST(blockContinueCompressedSize==0, "LZ4_compress_HC_continue_destSize failed");
FUZ_CHECKTEST(blockContinueCompressedSize > availableSpace, "LZ4_compress_HC_continue_destSize write overflow");
FUZ_CHECKTEST(consumedSize > blockSize, "LZ4_compress_HC_continue_destSize read overflow");
@@ -965,7 +967,7 @@ static int FUZ_test(U32 seed, U32 nbCycles, const U32 startCycle, const double c
FUZ_DISPLAYTEST();
decodedBuffer[consumedSize] = 0;
ret = LZ4_decompress_safe_usingDict(compressedBuffer, decodedBuffer, blockContinueCompressedSize, consumedSize, dict, dictSize);
- FUZ_CHECKTEST(ret!=consumedSize, "LZ4_decompress_safe_usingDict did not regenerate original data");
+ FUZ_CHECKTEST(ret != consumedSize, "LZ4_decompress_safe_usingDict regenerated %i bytes (%i expected)", ret, consumedSize);
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);
@@ -977,10 +979,14 @@ static int FUZ_test(U32 seed, U32 nbCycles, const U32 startCycle, const double c
/* ***** End of tests *** */
/* Fill stats */
- bytes += blockSize;
- cbytes += compressedSize;
- hcbytes += HCcompressedSize;
- ccbytes += blockContinueCompressedSize;
+ assert(blockSize >= 0);
+ bytes += (unsigned)blockSize;
+ assert(compressedSize >= 0);
+ cbytes += (unsigned)compressedSize;
+ assert(HCcompressedSize >= 0);
+ hcbytes += (unsigned)HCcompressedSize;
+ assert(blockContinueCompressedSize >= 0);
+ ccbytes += (unsigned)blockContinueCompressedSize;
}
if (nbCycles<=1) nbCycles = cycleNb; /* end by time */
@@ -1051,6 +1057,26 @@ static void FUZ_unitTests(int compressionLevel)
FUZ_CHECKTEST(r >= 0, "LZ4_decompress_safe() should fail");
} }
+
+ /* to be tested with undefined sanitizer */
+ DISPLAYLEVEL(3, "LZ4_compress_default() with NULL input:");
+ { int const maxCSize = LZ4_compressBound(0);
+ int const cSize = LZ4_compress_default(NULL, testCompressed, 0, maxCSize);
+ FUZ_CHECKTEST(!(cSize==1 && testCompressed[0]==0),
+ "compressing empty should give byte 0"
+ " (maxCSize == %i) (cSize == %i) (byte == 0x%02X)",
+ maxCSize, cSize, testCompressed[0]);
+ }
+ DISPLAYLEVEL(3, " OK \n");
+
+ DISPLAYLEVEL(3, "LZ4_compress_default() with both NULL input and output:");
+ { int const cSize = LZ4_compress_default(NULL, NULL, 0, 0);
+ FUZ_CHECKTEST(cSize != 0,
+ "compressing into NULL must fail"
+ " (cSize == %i != 0)", cSize);
+ }
+ DISPLAYLEVEL(3, " OK \n");
+
/* in-place compression test */
DISPLAYLEVEL(3, "in-place compression using LZ4_compress_default() :");
{ int const sampleSize = 65 KB;
@@ -1071,7 +1097,7 @@ static void FUZ_unitTests(int compressionLevel)
{ int const dSize = LZ4_decompress_safe(testCompressed, testVerify, cSize, testInputSize);
assert(dSize == sampleSize); /* correct size */
{ XXH32_hash_t const crcCheck = XXH32(testVerify, (size_t)dSize, 0);
- assert(crcCheck == crcOrig);
+ FUZ_CHECKTEST(crcCheck != crcOrig, "LZ4_decompress_safe decompression corruption");
} } }
DISPLAYLEVEL(3, " OK \n");
@@ -1095,32 +1121,67 @@ static void FUZ_unitTests(int compressionLevel)
{ int const dSize = LZ4_decompress_safe(startInput, testVerify, cSize, sampleSize);
assert(dSize == sampleSize); /* correct size */
{ XXH64_hash_t const crcCheck = XXH64(testVerify, (size_t)dSize, 0);
- assert(crcCheck == crcOrig);
+ FUZ_CHECKTEST(crcCheck != crcOrig, "LZ4_decompress_safe decompression corruption");
} } } } }
DISPLAYLEVEL(3, " OK \n");
- /* LZ4 streaming tests */
- { LZ4_stream_t streamingState;
- U64 crcOrig;
- int result;
+ DISPLAYLEVEL(3, "LZ4_initStream with multiple valid alignments : ");
+ { typedef struct {
+ LZ4_stream_t state1;
+ LZ4_stream_t state2;
+ char c;
+ LZ4_stream_t state3;
+ } shct;
+ shct* const shc = (shct*)malloc(sizeof(*shc));
+ assert(shc != NULL);
+ memset(shc, 0, sizeof(*shc));
+ DISPLAYLEVEL(4, "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 );
+ free(shc);
+ }
+ DISPLAYLEVEL(3, "all inits OK \n");
- /* Allocation test */
- { LZ4_stream_t* const statePtr = LZ4_createStream();
- FUZ_CHECKTEST(statePtr==NULL, "LZ4_createStream() allocation failed");
- LZ4_freeStream(statePtr);
- }
+ /* Allocation test */
+ { LZ4_stream_t* const statePtr = LZ4_createStream();
+ FUZ_CHECKTEST(statePtr==NULL, "LZ4_createStream() allocation failed");
+ LZ4_freeStream(statePtr);
+ }
+
+ /* LZ4 streaming tests */
+ { LZ4_stream_t streamingState;
/* simple compression test */
- crcOrig = XXH64(testInput, testCompressedSize, 0);
LZ4_initStream(&streamingState, sizeof(streamingState));
- result = LZ4_compress_fast_continue(&streamingState, testInput, testCompressed, testCompressedSize, testCompressedSize-1, 1);
- FUZ_CHECKTEST(result==0, "LZ4_compress_fast_continue() compression failed!");
- FUZ_CHECKTEST(streamingState.internal_donotuse.dirty, "context should be clean")
+ { int const cs = LZ4_compress_fast_continue(&streamingState, testInput, testCompressed, testCompressedSize, testCompressedSize-1, 1);
+ FUZ_CHECKTEST(cs==0, "LZ4_compress_fast_continue() compression failed!");
+ { int const r = LZ4_decompress_safe(testCompressed, testVerify, cs, testCompressedSize);
+ FUZ_CHECKTEST(r!=(int)testCompressedSize, "LZ4_decompress_safe() decompression failed");
+ } }
+ { U64 const crcOrig = XXH64(testInput, testCompressedSize, 0);
+ U64 const crcNew = XXH64(testVerify, testCompressedSize, 0);
+ 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 */
- result = LZ4_decompress_safe(testCompressed, testVerify, result, testCompressedSize);
- FUZ_CHECKTEST(result!=(int)testCompressedSize, "LZ4_decompress_safe() decompression failed");
- { U64 const crcNew = XXH64(testVerify, testCompressedSize, 0);
- FUZ_CHECKTEST(crcOrig!=crcNew, "LZ4_decompress_safe() decompression corruption"); }
+ /* Check access violation with asan */
+ FUZ_CHECKTEST( LZ4_saveDict(ctx, 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(ctx, 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;
@@ -1142,7 +1203,7 @@ static void FUZ_unitTests(int compressionLevel)
LZ4_setStreamDecode(&decodeStateFast, NULL, 0);
while (iNext + messageSize < testCompressedSize) {
- int compressedSize;
+ int compressedSize; U64 crcOrig;
XXH64_update(&xxhOrig, testInput + iNext, messageSize);
crcOrig = XXH64_digest(&xxhOrig);
@@ -1150,15 +1211,15 @@ static void FUZ_unitTests(int compressionLevel)
compressedSize = LZ4_compress_fast_continue(&streamingState, ringBuffer + rNext, testCompressed, (int)messageSize, testCompressedSize-ringBufferSize, 1);
FUZ_CHECKTEST(compressedSize==0, "LZ4_compress_fast_continue() compression failed");
- result = LZ4_decompress_safe_continue(&decodeStateSafe, testCompressed, testVerify + dNext, compressedSize, (int)messageSize);
- FUZ_CHECKTEST(result!=(int)messageSize, "ringBuffer : LZ4_decompress_safe_continue() test failed");
+ { int const r = LZ4_decompress_safe_continue(&decodeStateSafe, testCompressed, testVerify + dNext, compressedSize, (int)messageSize);
+ FUZ_CHECKTEST(r!=(int)messageSize, "ringBuffer : LZ4_decompress_safe_continue() test failed"); }
XXH64_update(&xxhNewSafe, testVerify + dNext, messageSize);
{ U64 const crcNew = XXH64_digest(&xxhNewSafe);
FUZ_CHECKTEST(crcOrig!=crcNew, "LZ4_decompress_safe_continue() decompression corruption"); }
- result = LZ4_decompress_fast_continue(&decodeStateFast, testCompressed, testVerify + dNext, (int)messageSize);
- FUZ_CHECKTEST(result!=compressedSize, "ringBuffer : LZ4_decompress_fast_continue() test failed");
+ { int const r = LZ4_decompress_fast_continue(&decodeStateFast, testCompressed, testVerify + dNext, (int)messageSize);
+ FUZ_CHECKTEST(r!=compressedSize, "ringBuffer : LZ4_decompress_fast_continue() test failed"); }
XXH64_update(&xxhNewFast, testVerify + dNext, messageSize);
{ U64 const crcNew = XXH64_digest(&xxhNewFast);
@@ -1171,26 +1232,45 @@ static void FUZ_unitTests(int compressionLevel)
messageSize = (FUZ_rand(&randState) & maxMessageSizeMask) + 1;
if (rNext + messageSize > ringBufferSize) rNext = 0;
if (dNext + messageSize > dBufferSize) dNext = 0;
- }
- }
+ } }
+ }
+
+ DISPLAYLEVEL(3, "LZ4_initStreamHC with multiple valid alignments : ");
+ { typedef struct {
+ LZ4_streamHC_t hc1;
+ LZ4_streamHC_t hc2;
+ char c;
+ LZ4_streamHC_t hc3;
+ } shct;
+ shct* const shc = (shct*)malloc(sizeof(*shc));
+ assert(shc != NULL);
+ memset(shc, 0, sizeof(*shc));
+ DISPLAYLEVEL(4, "hc1(%p) hc2(%p) hc3(%p) size(0x%x): ",
+ &(shc->hc1), &(shc->hc2), &(shc->hc3), (unsigned)sizeof(LZ4_streamHC_t));
+ FUZ_CHECKTEST( LZ4_initStreamHC(&(shc->hc1), sizeof(shc->hc1)) == NULL, "hc1 (%p) failed init", &(shc->hc1) );
+ FUZ_CHECKTEST( LZ4_initStreamHC(&(shc->hc2), sizeof(shc->hc2)) == NULL, "hc2 (%p) failed init", &(shc->hc2) );
+ FUZ_CHECKTEST( LZ4_initStreamHC(&(shc->hc3), sizeof(shc->hc3)) == NULL, "hc3 (%p) failed init", &(shc->hc3) );
+ FUZ_CHECKTEST( LZ4_initStreamHC((char*)&(shc->hc1) + 1, sizeof(shc->hc1)) != NULL,
+ "hc1+1 (%p) init must fail, due to bad alignment", (char*)&(shc->hc1) + 1 );
+ free(shc);
}
+ DISPLAYLEVEL(3, "all inits OK \n");
/* LZ4 HC streaming tests */
{ LZ4_streamHC_t sHC; /* statically allocated */
- U64 crcOrig;
int result;
LZ4_initStreamHC(&sHC, sizeof(sHC));
/* Allocation test */
- DISPLAYLEVEL(3, " Basic HC allocation : ");
+ DISPLAYLEVEL(3, "Basic HC allocation : ");
{ LZ4_streamHC_t* const sp = LZ4_createStreamHC();
FUZ_CHECKTEST(sp==NULL, "LZ4_createStreamHC() allocation failed");
LZ4_freeStreamHC(sp);
}
- DISPLAYLEVEL(3, " OK \n");
+ DISPLAYLEVEL(3, "OK \n");
/* simple HC compression test */
- DISPLAYLEVEL(3, " Simple HC round-trip : ");
+ DISPLAYLEVEL(3, "Simple HC round-trip : ");
{ U64 const crc64 = XXH64(testInput, testCompressedSize, 0);
LZ4_setCompressionLevel(&sHC, compressionLevel);
result = LZ4_compress_HC_continue(&sHC, testInput, testCompressed, testCompressedSize, testCompressedSize-1);
@@ -1202,10 +1282,26 @@ static void FUZ_unitTests(int compressionLevel)
{ U64 const crcNew = XXH64(testVerify, testCompressedSize, 0);
FUZ_CHECKTEST(crc64!=crcNew, "LZ4_decompress_safe() decompression corruption");
} }
- DISPLAYLEVEL(3, " OK \n");
+ 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(ctx, 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(ctx, 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 test : ");
+ DISPLAYLEVEL(3, "Long sequence HC_destSize test : ");
{ size_t const blockSize = 1 MB;
size_t const targetSize = 4116; /* size carefully selected to trigger an overflow */
void* const block = malloc(blockSize);
@@ -1223,8 +1319,13 @@ static void FUZ_unitTests(int compressionLevel)
assert(targetSize < INT_MAX);
result = LZ4_compress_HC_destSize(&sHC, (const char*)block, (char*)dstBlock, &srcSize, (int)targetSize, 3);
DISPLAYLEVEL(4, "cSize=%i; readSize=%i; ", result, srcSize);
- FUZ_CHECKTEST(result!=4116, "LZ4_compress_HC_destSize() : compression must fill dstBuffer completely, but no more !");
- FUZ_CHECKTEST(((char*)dstBlock)[targetSize] != sentinel, "LZ4_compress_HC_destSize()")
+ FUZ_CHECKTEST(result != 4116, "LZ4_compress_HC_destSize() : "
+ "compression (%i->%i) must fill dstBuffer (%i) exactly",
+ srcSize, result, (int)targetSize);
+ FUZ_CHECKTEST(((char*)dstBlock)[targetSize] != sentinel,
+ "LZ4_compress_HC_destSize() overwrites dst buffer");
+ FUZ_CHECKTEST(srcSize < 1045000, "LZ4_compress_HC_destSize() doesn't compress enough"
+ " (%i -> %i , expected > %i)", srcSize, result, 1045000);
LZ4_resetStreamHC_fast(&sHC, 3); /* make sure the context is clean after the test */
free(block);
@@ -1233,7 +1334,7 @@ static void FUZ_unitTests(int compressionLevel)
DISPLAYLEVEL(3, " OK \n");
/* simple dictionary HC compression test */
- DISPLAYLEVEL(3, " HC dictionary compression test : ");
+ DISPLAYLEVEL(3, "HC dictionary compression test : ");
{ U64 const crc64 = XXH64(testInput + 64 KB, testCompressedSize, 0);
LZ4_resetStreamHC_fast(&sHC, compressionLevel);
LZ4_loadDictHC(&sHC, testInput, 64 KB);
@@ -1302,6 +1403,7 @@ static void FUZ_unitTests(int compressionLevel)
XXH64_reset(&crcNewState, 0);
while (segStart + segSize < testInputSize) {
+ XXH64_hash_t crcOrig;
XXH64_update(&crcOrigState, testInput + segStart, segSize);
crcOrig = XXH64_digest(&crcOrigState);
assert(segSize <= INT_MAX);
@@ -1348,6 +1450,7 @@ static void FUZ_unitTests(int compressionLevel)
while (iNext + messageSize < testCompressedSize) {
int compressedSize;
+ XXH64_hash_t crcOrig;
XXH64_update(&xxhOrig, testInput + iNext, messageSize);
crcOrig = XXH64_digest(&xxhOrig);
@@ -1362,7 +1465,7 @@ static void FUZ_unitTests(int compressionLevel)
FUZ_CHECKTEST(result!=(int)messageSize, "ringBuffer : LZ4_decompress_safe_continue() test failed");
XXH64_update(&xxhNewSafe, testVerify + dNext, messageSize);
- { U64 const crcNew = XXH64_digest(&xxhNewSafe);
+ { XXH64_hash_t const crcNew = XXH64_digest(&xxhNewSafe);
FUZ_CHECKTEST(crcOrig!=crcNew, "LZ4_decompress_safe_continue() decompression corruption"); }
assert(messageSize < INT_MAX);
@@ -1370,7 +1473,7 @@ static void FUZ_unitTests(int compressionLevel)
FUZ_CHECKTEST(result!=compressedSize, "ringBuffer : LZ4_decompress_fast_continue() test failed");
XXH64_update(&xxhNewFast, testVerify + dNext, messageSize);
- { U64 const crcNew = XXH64_digest(&xxhNewFast);
+ { XXH64_hash_t const crcNew = XXH64_digest(&xxhNewFast);
FUZ_CHECKTEST(crcOrig!=crcNew, "LZ4_decompress_fast_continue() decompression corruption"); }
/* prepare next message */
@@ -1391,6 +1494,7 @@ static void FUZ_unitTests(int compressionLevel)
*/
{ XXH64_state_t xxhOrig;
XXH64_state_t xxhNewSafe, xxhNewFast;
+ XXH64_hash_t crcOrig;
LZ4_streamDecode_t decodeStateSafe, decodeStateFast;
const int maxMessageSizeLog = 12;
const int maxMessageSize = 1 << maxMessageSizeLog;
@@ -1487,8 +1591,87 @@ static void FUZ_unitTests(int compressionLevel)
iNext = (FUZ_rand(&randState) & 65535);
if (dNext + maxMessageSize > dBufferSize) dNext = 0;
}
+ } /* Ring buffer test : Non synchronized decoder */
+ }
+
+ DISPLAYLEVEL(3, "LZ4_compress_HC_destSize : ");
+ /* encode congenerical sequence test for HC compressors */
+ { LZ4_streamHC_t* const sHC = LZ4_createStreamHC();
+ int const src_buf_size = 3 MB;
+ int const dst_buf_size = 6 KB;
+ int const payload = 0;
+ int const dst_step = 43;
+ int const dst_min_len = 33 + (FUZ_rand(&randState) % dst_step);
+ int const dst_max_len = 5000;
+ int slen, dlen;
+ char* sbuf1 = (char*)malloc(src_buf_size + 1);
+ char* sbuf2 = (char*)malloc(src_buf_size + 1);
+ char* dbuf1 = (char*)malloc(dst_buf_size + 1);
+ char* dbuf2 = (char*)malloc(dst_buf_size + 1);
+
+ assert(sHC != NULL);
+ assert(dst_buf_size > dst_max_len);
+ if (!sbuf1 || !sbuf2 || !dbuf1 || !dbuf2) {
+ EXIT_MSG("not enough memory for FUZ_unitTests (destSize)");
+ }
+ for (dlen = dst_min_len; dlen <= dst_max_len; dlen += dst_step) {
+ int src_len = (dlen - 10)*255 + 24;
+ if (src_len + 10 >= src_buf_size) break; /* END of check */
+ for (slen = src_len - 3; slen <= src_len + 3; slen++) {
+ int srcsz1, srcsz2;
+ int dsz1, dsz2;
+ int res1, res2;
+ char const endchk = (char)0x88;
+ DISPLAYLEVEL(5, "slen = %i, ", slen);
+
+ srcsz1 = slen;
+ memset(sbuf1, payload, slen);
+ memset(dbuf1, 0, dlen);
+ dbuf1[dlen] = endchk;
+ dsz1 = LZ4_compress_destSize(sbuf1, dbuf1, &srcsz1, dlen);
+ DISPLAYLEVEL(5, "LZ4_compress_destSize: %i bytes compressed into %i bytes, ", srcsz1, dsz1);
+ DISPLAYLEVEL(5, "last token : 0x%0X, ", dbuf1[dsz1 - 6]);
+ DISPLAYLEVEL(5, "last ML extra lenbyte : 0x%0X, \n", dbuf1[dsz1 - 7]);
+ FUZ_CHECKTEST(dbuf1[dlen] != endchk, "LZ4_compress_destSize() overwrite dst buffer !");
+ FUZ_CHECKTEST(dsz1 <= 0, "LZ4_compress_destSize() compression failed");
+ FUZ_CHECKTEST(dsz1 > dlen, "LZ4_compress_destSize() result larger than dst buffer !");
+ FUZ_CHECKTEST(srcsz1 > slen, "LZ4_compress_destSize() read more than src buffer !");
+
+ res1 = LZ4_decompress_safe(dbuf1, sbuf1, dsz1, src_buf_size);
+ FUZ_CHECKTEST(res1 != srcsz1, "LZ4_compress_destSize() decompression failed!");
+
+ srcsz2 = slen;
+ memset(sbuf2, payload, slen);
+ memset(dbuf2, 0, dlen);
+ dbuf2[dlen] = endchk;
+ LZ4_resetStreamHC(sHC, compressionLevel);
+ dsz2 = LZ4_compress_HC_destSize(sHC, sbuf2, dbuf2, &srcsz2, dlen, compressionLevel);
+ DISPLAYLEVEL(5, "LZ4_compress_HC_destSize: %i bytes compressed into %i bytes, ", srcsz2, dsz2);
+ DISPLAYLEVEL(5, "last token : 0x%0X, ", dbuf2[dsz2 - 6]);
+ DISPLAYLEVEL(5, "last ML extra lenbyte : 0x%0X, \n", dbuf2[dsz2 - 7]);
+ FUZ_CHECKTEST(dbuf2[dlen] != endchk, "LZ4_compress_HC_destSize() overwrite dst buffer !");
+ FUZ_CHECKTEST(dsz2 <= 0, "LZ4_compress_HC_destSize() compression failed");
+ FUZ_CHECKTEST(dsz2 > dlen, "LZ4_compress_HC_destSize() result larger than dst buffer !");
+ FUZ_CHECKTEST(srcsz2 > slen, "LZ4_compress_HC_destSize() read more than src buffer !");
+ FUZ_CHECKTEST(dsz2 != dsz1, "LZ4_compress_HC_destSize() return incorrect result !");
+ FUZ_CHECKTEST(srcsz2 != srcsz1, "LZ4_compress_HC_destSize() return incorrect src buffer size "
+ ": srcsz2(%i) != srcsz1(%i)", srcsz2, srcsz1);
+ FUZ_CHECKTEST(memcmp(dbuf2, dbuf1, (size_t)dsz2), "LZ4_compress_HC_destSize() return incorrect data into dst buffer !");
+
+ res2 = LZ4_decompress_safe(dbuf2, sbuf1, dsz2, src_buf_size);
+ FUZ_CHECKTEST(res2 != srcsz1, "LZ4_compress_HC_destSize() decompression failed!");
+
+ FUZ_CHECKTEST(memcmp(sbuf1, sbuf2, (size_t)res2), "LZ4_compress_HC_destSize() decompression corruption!");
+ }
}
+ LZ4_freeStreamHC(sHC);
+ free(sbuf1);
+ free(sbuf2);
+ free(dbuf1);
+ free(dbuf2);
}
+ DISPLAYLEVEL(3, " OK \n");
+
/* clean up */
free(testInput);