mirror of
https://github.com/facebook/zstd.git
synced 2025-07-30 22:23:13 +03:00
added fuzzer test for compressSequencesAndLiterals()
piggy-backing onto existing compressSequences() fuzzer test
This commit is contained in:
@ -28,6 +28,9 @@ LIBZSTD_MK_DIR = ../../lib
|
|||||||
DEBUGLEVEL ?= 2
|
DEBUGLEVEL ?= 2
|
||||||
ZSTD_LEGACY_SUPPORT ?= 1
|
ZSTD_LEGACY_SUPPORT ?= 1
|
||||||
|
|
||||||
|
.PHONY: default
|
||||||
|
default: all
|
||||||
|
|
||||||
include $(LIBZSTD_MK_DIR)/libzstd.mk
|
include $(LIBZSTD_MK_DIR)/libzstd.mk
|
||||||
|
|
||||||
PRGDIR = ../../programs
|
PRGDIR = ../../programs
|
||||||
@ -101,10 +104,6 @@ FUZZ_RT_OBJ9 := $(FUZZ_RT_OBJ8:.c=.o)
|
|||||||
FUZZ_RT_OBJ10 := $(THIRD_PARTY_SEQ_PROD_OBJ) $(FUZZ_RT_OBJ9)
|
FUZZ_RT_OBJ10 := $(THIRD_PARTY_SEQ_PROD_OBJ) $(FUZZ_RT_OBJ9)
|
||||||
FUZZ_ROUND_TRIP_OBJ := $(FUZZ_RT_OBJ10:.S=.o)
|
FUZZ_ROUND_TRIP_OBJ := $(FUZZ_RT_OBJ10:.S=.o)
|
||||||
|
|
||||||
.PHONY: default all clean cleanall
|
|
||||||
|
|
||||||
default: all
|
|
||||||
|
|
||||||
FUZZ_TARGETS := \
|
FUZZ_TARGETS := \
|
||||||
simple_round_trip \
|
simple_round_trip \
|
||||||
stream_round_trip \
|
stream_round_trip \
|
||||||
@ -128,6 +127,7 @@ FUZZ_TARGETS := \
|
|||||||
decompress_cross_format \
|
decompress_cross_format \
|
||||||
generate_sequences
|
generate_sequences
|
||||||
|
|
||||||
|
.PHONY: all clean cleanall
|
||||||
all: libregression.a $(FUZZ_TARGETS)
|
all: libregression.a $(FUZZ_TARGETS)
|
||||||
|
|
||||||
rt_lib_common_%.o: $(LIB_SRCDIR)/common/%.c
|
rt_lib_common_%.o: $(LIB_SRCDIR)/common/%.c
|
||||||
|
@ -155,7 +155,7 @@ static size_t generateRandomSequences(FUZZ_dataProducer_t* producer,
|
|||||||
if (mode == ZSTD_sf_explicitBlockDelimiters) {
|
if (mode == ZSTD_sf_explicitBlockDelimiters) {
|
||||||
/* ensure that no sequence can be larger than one block */
|
/* ensure that no sequence can be larger than one block */
|
||||||
literalsSizeLimit = MIN(literalsSizeLimit, blockSizeMax/2);
|
literalsSizeLimit = MIN(literalsSizeLimit, blockSizeMax/2);
|
||||||
matchLengthMax = MIN(matchLengthMax, blockSizeMax/2);
|
matchLengthMax = MIN(matchLengthMax, (uint32_t)blockSizeMax/2);
|
||||||
}
|
}
|
||||||
|
|
||||||
while ( nbSeqGenerated < ZSTD_FUZZ_MAX_NBSEQ - 3 /* extra room for explicit delimiters */
|
while ( nbSeqGenerated < ZSTD_FUZZ_MAX_NBSEQ - 3 /* extra room for explicit delimiters */
|
||||||
@ -171,7 +171,7 @@ static size_t generateRandomSequences(FUZZ_dataProducer_t* producer,
|
|||||||
if (bytesGenerated > ZSTD_FUZZ_GENERATED_SRC_MAXSIZE) {
|
if (bytesGenerated > ZSTD_FUZZ_GENERATED_SRC_MAXSIZE) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
offsetBound = (bytesGenerated > windowSize) ? windowSize : bytesGenerated + (uint32_t)dictSize;
|
offsetBound = (bytesGenerated > windowSize) ? (uint32_t)windowSize : bytesGenerated + (uint32_t)dictSize;
|
||||||
offset = FUZZ_dataProducer_uint32Range(producer, 1, offsetBound);
|
offset = FUZZ_dataProducer_uint32Range(producer, 1, offsetBound);
|
||||||
if (dictSize > 0 && bytesGenerated <= windowSize) {
|
if (dictSize > 0 && bytesGenerated <= windowSize) {
|
||||||
/* Prevent match length from being such that it would be associated with an offset too large
|
/* Prevent match length from being such that it would be associated with an offset too large
|
||||||
@ -180,7 +180,7 @@ static size_t generateRandomSequences(FUZZ_dataProducer_t* producer,
|
|||||||
*/
|
*/
|
||||||
const size_t bytesToReachWindowSize = windowSize - bytesGenerated;
|
const size_t bytesToReachWindowSize = windowSize - bytesGenerated;
|
||||||
if (bytesToReachWindowSize < ZSTD_MINMATCH_MIN) {
|
if (bytesToReachWindowSize < ZSTD_MINMATCH_MIN) {
|
||||||
const uint32_t newOffsetBound = offsetBound > windowSize ? windowSize : offsetBound;
|
const uint32_t newOffsetBound = offsetBound > windowSize ? (uint32_t)windowSize : offsetBound;
|
||||||
offset = FUZZ_dataProducer_uint32Range(producer, 1, newOffsetBound);
|
offset = FUZZ_dataProducer_uint32Range(producer, 1, newOffsetBound);
|
||||||
} else {
|
} else {
|
||||||
matchBound = MIN(matchLengthMax, (uint32_t)bytesToReachWindowSize);
|
matchBound = MIN(matchLengthMax, (uint32_t)bytesToReachWindowSize);
|
||||||
@ -201,14 +201,14 @@ static size_t generateRandomSequences(FUZZ_dataProducer_t* producer,
|
|||||||
if (blockSize + seqSize > blockSizeMax) { /* reaching limit : must end block now */
|
if (blockSize + seqSize > blockSizeMax) { /* reaching limit : must end block now */
|
||||||
const ZSTD_Sequence endBlock = {0, 0, 0, 0};
|
const ZSTD_Sequence endBlock = {0, 0, 0, 0};
|
||||||
generatedSequences[nbSeqGenerated++] = endBlock;
|
generatedSequences[nbSeqGenerated++] = endBlock;
|
||||||
blockSize = seqSize;
|
blockSize = (uint32_t)seqSize;
|
||||||
}
|
}
|
||||||
if (split) {
|
if (split) {
|
||||||
const ZSTD_Sequence endBlock = {0, lastLits, 0, 0};
|
const ZSTD_Sequence endBlock = {0, lastLits, 0, 0};
|
||||||
generatedSequences[nbSeqGenerated++] = endBlock;
|
generatedSequences[nbSeqGenerated++] = endBlock;
|
||||||
assert(lastLits <= seq.litLength);
|
assert(lastLits <= seq.litLength);
|
||||||
seq.litLength -= lastLits;
|
seq.litLength -= lastLits;
|
||||||
blockSize = seqSize - lastLits;
|
blockSize = (uint32_t)(seqSize - lastLits);
|
||||||
} else {
|
} else {
|
||||||
blockSize += seqSize;
|
blockSize += seqSize;
|
||||||
}
|
}
|
||||||
@ -227,10 +227,67 @@ static size_t generateRandomSequences(FUZZ_dataProducer_t* producer,
|
|||||||
return nbSeqGenerated;
|
return nbSeqGenerated;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static size_t
|
||||||
|
transferLiterals(void* dst, size_t dstCapacity, const ZSTD_Sequence* seqs, size_t nbSeqs, const void* src, size_t srcSize)
|
||||||
|
{
|
||||||
|
size_t n;
|
||||||
|
char* op = dst;
|
||||||
|
char* const oend = op + dstCapacity;
|
||||||
|
const char* ip = src;
|
||||||
|
const char* const iend = ip + srcSize;
|
||||||
|
for (n=0; n<nbSeqs; n++) {
|
||||||
|
size_t litLen = seqs[n].litLength;
|
||||||
|
size_t mlen = seqs[n].matchLength;
|
||||||
|
assert(op + litLen < oend);
|
||||||
|
assert(ip + litLen + mlen <= iend);
|
||||||
|
memcpy(op, ip, litLen);
|
||||||
|
op += litLen;
|
||||||
|
ip += litLen + mlen;
|
||||||
|
}
|
||||||
|
assert(oend - op >= 8);
|
||||||
|
return (size_t)(op - (char*)dst);
|
||||||
|
}
|
||||||
|
|
||||||
|
static size_t roundTripTest_compressSequencesAndLiterals(
|
||||||
|
void* result, size_t resultCapacity,
|
||||||
|
void* compressed, size_t compressedCapacity,
|
||||||
|
const void* src, size_t srcSize,
|
||||||
|
const ZSTD_Sequence* seqs, size_t nbSeqs,
|
||||||
|
ZSTD_SequenceFormat_e mode)
|
||||||
|
{
|
||||||
|
size_t const litCapacity = srcSize + 8;
|
||||||
|
void* literals = malloc(litCapacity);
|
||||||
|
size_t cSize, litSize;
|
||||||
|
|
||||||
|
assert(literals);
|
||||||
|
litSize = transferLiterals(literals, litCapacity, seqs, nbSeqs, src, srcSize);
|
||||||
|
|
||||||
|
cSize = ZSTD_compressSequencesAndLiterals(cctx,
|
||||||
|
compressed, compressedCapacity,
|
||||||
|
seqs, nbSeqs,
|
||||||
|
literals, litSize, litCapacity, srcSize);
|
||||||
|
if ( (ZSTD_getErrorCode(cSize) == ZSTD_error_dstSize_tooSmall)
|
||||||
|
&& (mode == ZSTD_sf_explicitBlockDelimiters) ) {
|
||||||
|
/* Valid scenario : in explicit delimiter mode,
|
||||||
|
* it might be possible for the compressed size to outgrow dstCapacity.
|
||||||
|
* In which case, it's still a valid fuzzer scenario,
|
||||||
|
* but no roundtrip shall be possible */
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
/* round-trip */
|
||||||
|
FUZZ_ZASSERT(cSize);
|
||||||
|
{ size_t const dSize = ZSTD_decompressDCtx(dctx, result, resultCapacity, compressed, cSize);
|
||||||
|
FUZZ_ZASSERT(dSize);
|
||||||
|
FUZZ_ASSERT_MSG(dSize == srcSize, "Incorrect regenerated size");
|
||||||
|
FUZZ_ASSERT_MSG(!FUZZ_memcmp(src, result, srcSize), "Corruption!");
|
||||||
|
return dSize;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static size_t roundTripTest(void* result, size_t resultCapacity,
|
static size_t roundTripTest(void* result, size_t resultCapacity,
|
||||||
void* compressed, size_t compressedCapacity,
|
void* compressed, size_t compressedCapacity,
|
||||||
const void* src, size_t srcSize,
|
const void* src, size_t srcSize,
|
||||||
const ZSTD_Sequence* seqs, size_t seqSize,
|
const ZSTD_Sequence* seqs, size_t nbSeqs,
|
||||||
unsigned hasDict,
|
unsigned hasDict,
|
||||||
ZSTD_SequenceFormat_e mode)
|
ZSTD_SequenceFormat_e mode)
|
||||||
{
|
{
|
||||||
@ -242,8 +299,16 @@ static size_t roundTripTest(void* result, size_t resultCapacity,
|
|||||||
FUZZ_ZASSERT(ZSTD_DCtx_refDDict(dctx, ddict));
|
FUZZ_ZASSERT(ZSTD_DCtx_refDDict(dctx, ddict));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
{ int blockMode;
|
||||||
|
/* compressSequencesAndLiterals() only supports explicitBlockDelimiters */
|
||||||
|
FUZZ_ZASSERT(ZSTD_CCtx_getParameter(cctx, ZSTD_c_blockDelimiters, &blockMode));
|
||||||
|
if (blockMode == ZSTD_sf_explicitBlockDelimiters) {
|
||||||
|
FUZZ_ZASSERT(roundTripTest_compressSequencesAndLiterals(result, resultCapacity, compressed, compressedCapacity, src, srcSize, seqs, nbSeqs, mode));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
cSize = ZSTD_compressSequences(cctx, compressed, compressedCapacity,
|
cSize = ZSTD_compressSequences(cctx, compressed, compressedCapacity,
|
||||||
seqs, seqSize,
|
seqs, nbSeqs,
|
||||||
src, srcSize);
|
src, srcSize);
|
||||||
if ( (ZSTD_getErrorCode(cSize) == ZSTD_error_dstSize_tooSmall)
|
if ( (ZSTD_getErrorCode(cSize) == ZSTD_error_dstSize_tooSmall)
|
||||||
&& (mode == ZSTD_sf_explicitBlockDelimiters) ) {
|
&& (mode == ZSTD_sf_explicitBlockDelimiters) ) {
|
||||||
@ -298,10 +363,10 @@ int LLVMFuzzerTestOneInput(const uint8_t* src, size_t size)
|
|||||||
ZSTD_CCtx_reset(cctx, ZSTD_reset_session_and_parameters);
|
ZSTD_CCtx_reset(cctx, ZSTD_reset_session_and_parameters);
|
||||||
ZSTD_CCtx_setParameter(cctx, ZSTD_c_nbWorkers, 0);
|
ZSTD_CCtx_setParameter(cctx, ZSTD_c_nbWorkers, 0);
|
||||||
ZSTD_CCtx_setParameter(cctx, ZSTD_c_compressionLevel, cLevel);
|
ZSTD_CCtx_setParameter(cctx, ZSTD_c_compressionLevel, cLevel);
|
||||||
ZSTD_CCtx_setParameter(cctx, ZSTD_c_windowLog, wLog);
|
ZSTD_CCtx_setParameter(cctx, ZSTD_c_windowLog, (int)wLog);
|
||||||
ZSTD_CCtx_setParameter(cctx, ZSTD_c_minMatch, ZSTD_MINMATCH_MIN);
|
ZSTD_CCtx_setParameter(cctx, ZSTD_c_minMatch, ZSTD_MINMATCH_MIN);
|
||||||
ZSTD_CCtx_setParameter(cctx, ZSTD_c_validateSequences, 1);
|
ZSTD_CCtx_setParameter(cctx, ZSTD_c_validateSequences, 1);
|
||||||
ZSTD_CCtx_setParameter(cctx, ZSTD_c_blockDelimiters, mode);
|
ZSTD_CCtx_setParameter(cctx, ZSTD_c_blockDelimiters, (int)mode);
|
||||||
ZSTD_CCtx_setParameter(cctx, ZSTD_c_forceAttachDict, ZSTD_dictForceAttach);
|
ZSTD_CCtx_setParameter(cctx, ZSTD_c_forceAttachDict, ZSTD_dictForceAttach);
|
||||||
|
|
||||||
if (!literalsBuffer) {
|
if (!literalsBuffer) {
|
||||||
|
Reference in New Issue
Block a user