diff --git a/tests/fuzz/Makefile b/tests/fuzz/Makefile index 1333675d0..a64d2d252 100644 --- a/tests/fuzz/Makefile +++ b/tests/fuzz/Makefile @@ -28,6 +28,9 @@ LIBZSTD_MK_DIR = ../../lib DEBUGLEVEL ?= 2 ZSTD_LEGACY_SUPPORT ?= 1 +.PHONY: default +default: all + include $(LIBZSTD_MK_DIR)/libzstd.mk 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_ROUND_TRIP_OBJ := $(FUZZ_RT_OBJ10:.S=.o) -.PHONY: default all clean cleanall - -default: all - FUZZ_TARGETS := \ simple_round_trip \ stream_round_trip \ @@ -128,6 +127,7 @@ FUZZ_TARGETS := \ decompress_cross_format \ generate_sequences +.PHONY: all clean cleanall all: libregression.a $(FUZZ_TARGETS) rt_lib_common_%.o: $(LIB_SRCDIR)/common/%.c diff --git a/tests/fuzz/sequence_compression_api.c b/tests/fuzz/sequence_compression_api.c index 5e5e1e604..32710afb9 100644 --- a/tests/fuzz/sequence_compression_api.c +++ b/tests/fuzz/sequence_compression_api.c @@ -155,7 +155,7 @@ static size_t generateRandomSequences(FUZZ_dataProducer_t* producer, if (mode == ZSTD_sf_explicitBlockDelimiters) { /* ensure that no sequence can be larger than one block */ 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 */ @@ -171,7 +171,7 @@ static size_t generateRandomSequences(FUZZ_dataProducer_t* producer, if (bytesGenerated > ZSTD_FUZZ_GENERATED_SRC_MAXSIZE) { 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); if (dictSize > 0 && bytesGenerated <= windowSize) { /* 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; 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); } else { 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 */ const ZSTD_Sequence endBlock = {0, 0, 0, 0}; generatedSequences[nbSeqGenerated++] = endBlock; - blockSize = seqSize; + blockSize = (uint32_t)seqSize; } if (split) { const ZSTD_Sequence endBlock = {0, lastLits, 0, 0}; generatedSequences[nbSeqGenerated++] = endBlock; assert(lastLits <= seq.litLength); seq.litLength -= lastLits; - blockSize = seqSize - lastLits; + blockSize = (uint32_t)(seqSize - lastLits); } else { blockSize += seqSize; } @@ -227,10 +227,67 @@ static size_t generateRandomSequences(FUZZ_dataProducer_t* producer, 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= 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, void* compressed, size_t compressedCapacity, const void* src, size_t srcSize, - const ZSTD_Sequence* seqs, size_t seqSize, + const ZSTD_Sequence* seqs, size_t nbSeqs, unsigned hasDict, ZSTD_SequenceFormat_e mode) { @@ -242,8 +299,16 @@ static size_t roundTripTest(void* result, size_t resultCapacity, 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, - seqs, seqSize, + seqs, nbSeqs, src, srcSize); if ( (ZSTD_getErrorCode(cSize) == ZSTD_error_dstSize_tooSmall) && (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_setParameter(cctx, ZSTD_c_nbWorkers, 0); 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_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); if (!literalsBuffer) {