From 04f5b17b7227bbc3ee788f869b55641f6c776b08 Mon Sep 17 00:00:00 2001 From: Yann Collet Date: Sat, 6 Sep 2014 22:48:03 +0100 Subject: Improved frame decompression test Fixed : frame decompression bug --- lz4frame.c | 7 ++++--- programs/frametest.c | 33 ++++++++++++++++++++++++++++----- 2 files changed, 32 insertions(+), 8 deletions(-) diff --git a/lz4frame.c b/lz4frame.c index 866c922..19b228c 100644 --- a/lz4frame.c +++ b/lz4frame.c @@ -866,7 +866,7 @@ goto_getCBlock: selectedIn = srcPtr; srcPtr += nextCBlockSize; dctxPtr->dStage = dstage_decodeCBlock; - break; + goto goto_decodeCBlock; /* break risks leaving the while loop */ } case dstage_storeCBlock: { @@ -881,6 +881,7 @@ goto_getCBlock: /* break; break unnecessary because it follows */ } case dstage_decodeCBlock: +goto_decodeCBlock: { int decodedSize; if ((size_t)(dstEnd-dstPtr) < dctxPtr->maxBlockSize) /* not enough room : decode into tmpOut */ @@ -937,14 +938,14 @@ goto_getSuffix: case dstage_storeSuffix: { size_t sizeToCopy = 4 - dctxPtr->tmpInSize; - if (sizeToCopy < (size_t)(srcEnd - srcPtr)) sizeToCopy = srcEnd - srcPtr; + if (sizeToCopy > (size_t)(srcEnd - srcPtr)) sizeToCopy = srcEnd - srcPtr; memcpy(dctxPtr->tmpIn + dctxPtr->tmpInSize, srcPtr, sizeToCopy); srcPtr += sizeToCopy; dctxPtr->tmpInSize += sizeToCopy; if (dctxPtr->tmpInSize < 4) break; /* not enough input to read suffix */ selectedIn = dctxPtr->tmpIn; dctxPtr->dStage = dstage_checkSuffix; - break; + /* break; useless, it follows; would need a goto anyway */ } case dstage_checkSuffix: goto_checkSuffix: diff --git a/programs/frametest.c b/programs/frametest.c index facff30..6462d14 100644 --- a/programs/frametest.c +++ b/programs/frametest.c @@ -362,7 +362,7 @@ _output_error: static const U32 srcDataLength = 4 MB; -int fuzzerTests(U32 seed, unsigned nbTests, int startCycle, double compressibility) +int fuzzerTests(U32 seed, unsigned nbTests, int startTest, double compressibility) { unsigned testResult = 0; unsigned testNb = 0; @@ -374,7 +374,7 @@ int fuzzerTests(U32 seed, unsigned nbTests, int startCycle, double compressibili # define CHECK(cond, ...) if (cond) { DISPLAY("Error => "); DISPLAY(__VA_ARGS__); \ DISPLAY(" (seed %u, test nb %i) \n", seed, testNb); goto _output_error; } - (void)startCycle; + (void)startTest; // Create compressible test buffer LZ4F_createDecompressionContext(&dCtx, LZ4F_VERSION); srcBuffer = malloc(srcDataLength); @@ -395,17 +395,40 @@ int fuzzerTests(U32 seed, unsigned nbTests, int startCycle, double compressibili U64 crcOrig, crcDecoded; size_t result; - DISPLAYUPDATE(2, "%5i \r", testNb); + DISPLAYUPDATE(2, "\r%5i ", testNb); result = LZ4F_compressFrame(compressedBuffer, LZ4F_compressFrameBound(srcSize, &(prefs.frameInfo)), srcBuffer+srcStart, srcSize, &prefs ); - CHECK(LZ4F_isError(result), "Compression failed"); + CHECK(LZ4F_isError(result), "Compression failed (error %i)", (int)result); crcOrig = XXH64(srcBuffer+srcStart, srcSize, 1); cSize = result; decodedSize = srcDataLength; result = LZ4F_decompress(dCtx, decodedBuffer, &decodedSize, compressedBuffer, &cSize, NULL); - CHECK(result!=OK_FrameEnd, "Decompression failed"); + CHECK(result!=OK_FrameEnd, "Decompression failed (error %i)", (int)result); crcDecoded = XXH64(decodedBuffer, decodedSize, 1); CHECK(crcDecoded != crcOrig, "Decompression corruption"); + + { + const BYTE* ip = compressedBuffer; + const BYTE* const iend = ip + cSize; + BYTE* op = decodedBuffer; + BYTE* const oend = op + srcDataLength; + unsigned segRand = randState ^ PRIME1; + unsigned maxBits = FUZ_highbit(decodedSize); + while (ip < iend) + { + unsigned nbBitsSeg = FUZ_rand(&segRand) % maxBits; + size_t iSize = (FUZ_rand(&segRand) & ((1< (size_t)(iend-ip)) iSize = iend-ip; + result = LZ4F_decompress(dCtx, op, &oSize, ip, &iSize, NULL); + CHECK(LZ4F_isError(result), "Decompression failed (error %i)", (int)result); + op += oSize; + ip += iSize; + } + CHECK(result != OK_FrameEnd, "Frame decompression failed (error %i)", (int)result); + crcDecoded = XXH64(decodedBuffer, decodedSize, 1); + CHECK(crcDecoded != crcOrig, "Decompression corruption"); + } } DISPLAYLEVEL(2, "All tests completed \n"); -- cgit v0.12