Skip to content

Commit

Permalink
Merge pull request #3373 from facebook/decompressBound
Browse files Browse the repository at this point in the history
decompressBound tests and fix
  • Loading branch information
Cyan4973 committed Dec 17, 2022
2 parents 51355e1 + 2f4238e commit 3a484ef
Show file tree
Hide file tree
Showing 3 changed files with 57 additions and 2 deletions.
2 changes: 1 addition & 1 deletion lib/decompress/zstd_decompress.c
Original file line number Diff line number Diff line change
Expand Up @@ -785,7 +785,7 @@ static ZSTD_frameSizeInfo ZSTD_findFrameSizeInfo(const void* src, size_t srcSize
frameSizeInfo.compressedSize = (size_t)(ip - ipstart);
frameSizeInfo.decompressedBound = (zfh.frameContentSize != ZSTD_CONTENTSIZE_UNKNOWN)
? zfh.frameContentSize
: nbBlocks * zfh.blockSizeMax;
: (unsigned long long)nbBlocks * zfh.blockSizeMax;
return frameSizeInfo;
}
}
Expand Down
2 changes: 1 addition & 1 deletion lib/zstd.h
Original file line number Diff line number Diff line change
Expand Up @@ -228,7 +228,7 @@ ZSTDLIB_API size_t ZSTD_findFrameCompressedSize(const void* src, size_t srcSize)
* Will produce constant value 0 if srcSize too large.
*/
#define ZSTD_MAX_INPUT_SIZE ((sizeof(size_t)==8) ? 0xFF00FF00FF00FF00LLU : 0xFF00FF00U)
#define ZSTD_COMPRESSBOUND(srcSize) (((size_t)(srcSize) > ZSTD_MAX_INPUT_SIZE) ? 0 : (srcSize) + ((srcSize)>>8) + (((srcSize) < (128<<10)) ? (((128<<10) - (srcSize)) >> 11) /* margin, from 64 to 0 */ : 0)) /* this formula ensures that bound(A) + bound(B) <= bound(A+B) as long as A and B >= 128 KB */
#define ZSTD_COMPRESSBOUND(srcSize) (((size_t)(srcSize) >= ZSTD_MAX_INPUT_SIZE) ? 0 : (srcSize) + ((srcSize)>>8) + (((srcSize) < (128<<10)) ? (((128<<10) - (srcSize)) >> 11) /* margin, from 64 to 0 */ : 0)) /* this formula ensures that bound(A) + bound(B) <= bound(A+B) as long as A and B >= 128 KB */
ZSTDLIB_API size_t ZSTD_compressBound(size_t srcSize); /*!< maximum compressed size in worst case single-pass scenario */
/* ZSTD_isError() :
* Most ZSTD_* functions returning a size_t value can be tested for error,
Expand Down
55 changes: 55 additions & 0 deletions tests/fuzzer.c
Original file line number Diff line number Diff line change
Expand Up @@ -485,6 +485,59 @@ static void test_compressBound(int tnb)
DISPLAYLEVEL(3, "OK \n");
}

static void test_decompressBound(int tnb)
{
DISPLAYLEVEL(3, "test%3i : decompressBound : ", tnb);

// Simple compression, with size : should provide size;
{ const char example[] = "abcd";
char cBuffer[ZSTD_COMPRESSBOUND(sizeof(example))];
size_t const cSize = ZSTD_compress(cBuffer, sizeof(cBuffer), example, sizeof(example), 0);
CHECK_Z(cSize);
CHECK_EQ(ZSTD_decompressBound(cBuffer, cSize), (unsigned long long)sizeof(example));
}

// Simple small compression without size : should provide 1 block size
{ char cBuffer[ZSTD_COMPRESSBOUND(0)];
ZSTD_outBuffer out = { cBuffer, sizeof(cBuffer), 0 };
ZSTD_inBuffer in = { NULL, 0, 0 };
ZSTD_CCtx* const cctx = ZSTD_createCCtx();
assert(cctx);
CHECK_Z( ZSTD_initCStream(cctx, 0) );
CHECK_Z( ZSTD_compressStream(cctx, &out, &in) );
CHECK_EQ( ZSTD_endStream(cctx, &out), 0 );
CHECK_EQ( ZSTD_decompressBound(cBuffer, out.pos), ZSTD_BLOCKSIZE_MAX );
ZSTD_freeCCtx(cctx);
}

// Attempt to overflow 32-bit intermediate multiplication result
// This requires dBound >= 4 GB, aka 2^32.
// This requires 2^32 / 2^17 = 2^15 blocks
// => create 2^15 blocks (can be empty, or just 1 byte).
{ const char input[] = "a";
size_t const nbBlocks = (1 << 15) + 1;
size_t blockNb;
size_t const outCapacity = 1 << 18; // large margin
char* const outBuffer = malloc (outCapacity);
ZSTD_outBuffer out = { outBuffer, outCapacity, 0 };
ZSTD_CCtx* const cctx = ZSTD_createCCtx();
assert(cctx);
assert(outBuffer);
CHECK_Z( ZSTD_initCStream(cctx, 0) );
for (blockNb=0; blockNb<nbBlocks; blockNb++) {
ZSTD_inBuffer in = { input, sizeof(input), 0 };
CHECK_Z( ZSTD_compressStream(cctx, &out, &in) );
CHECK_EQ( ZSTD_flushStream(cctx, &out), 0 );
}
CHECK_EQ( ZSTD_endStream(cctx, &out), 0 );
CHECK( ZSTD_decompressBound(outBuffer, out.pos) > 0x100000000LLU /* 4 GB */ );
ZSTD_freeCCtx(cctx);
free(outBuffer);
}

DISPLAYLEVEL(3, "OK \n");
}

static int basicUnitTests(U32 const seed, double compressibility)
{
size_t const CNBuffSize = 5 MB;
Expand Down Expand Up @@ -533,6 +586,8 @@ static int basicUnitTests(U32 const seed, double compressibility)

test_compressBound(testNb++);

test_decompressBound(testNb++);

DISPLAYLEVEL(3, "test%3u : ZSTD_adjustCParams : ", testNb++);
{
ZSTD_compressionParameters params;
Expand Down

0 comments on commit 3a484ef

Please sign in to comment.