All tests should give some portion of data to the producer and use the rest.

This commit is contained in:
Dario Pavlovic 2019-09-10 16:52:38 -07:00
parent 4dfc1bbf48
commit 23cc2d8510
8 changed files with 50 additions and 32 deletions

View File

@ -52,9 +52,13 @@ static size_t roundTripTest(void *result, size_t resultCapacity,
int LLVMFuzzerTestOneInput(const uint8_t *src, size_t size) int LLVMFuzzerTestOneInput(const uint8_t *src, size_t size)
{ {
/* Give a random portion of src data to the producer, to use for
parameter generation. The rest will be used for (de)compression */
FUZZ_dataProducer_t *producer = FUZZ_dataProducer_create(src, size); FUZZ_dataProducer_t *producer = FUZZ_dataProducer_create(src, size);
size_t producerSliceSize = FUZZ_dataProducer_uint32Range(producer, 0, size);
size = FUZZ_dataProducer_contract(producer, producerSliceSize);
int cLevel = FUZZ_dataProducer_uint32(producer) % kMaxClevel; int cLevel = FUZZ_dataProducer_uint32(producer) % kMaxClevel;
size = FUZZ_dataProducer_remainingBytes(producer);
size_t neededBufSize = size; size_t neededBufSize = size;
if (size > ZSTD_BLOCKSIZE_MAX) if (size > ZSTD_BLOCKSIZE_MAX)

View File

@ -24,7 +24,12 @@ static ZSTD_DCtx *dctx = NULL;
int LLVMFuzzerTestOneInput(const uint8_t *src, size_t size) int LLVMFuzzerTestOneInput(const uint8_t *src, size_t size)
{ {
/* Give a random portion of src data to the producer, to use for
parameter generation. The rest will be used for (de)compression */
FUZZ_dataProducer_t *producer = FUZZ_dataProducer_create(src, size); FUZZ_dataProducer_t *producer = FUZZ_dataProducer_create(src, size);
size_t producerSliceSize = FUZZ_dataProducer_uint32Range(producer, 0, size);
size = FUZZ_dataProducer_contract(producer, producerSliceSize);
FUZZ_dict_t dict; FUZZ_dict_t dict;
ZSTD_DDict* ddict = NULL; ZSTD_DDict* ddict = NULL;
int i; int i;
@ -43,8 +48,8 @@ int LLVMFuzzerTestOneInput(const uint8_t *src, size_t size)
(ZSTD_dictLoadMethod_e)FUZZ_dataProducer_uint32Range(producer, 0, 1), (ZSTD_dictLoadMethod_e)FUZZ_dataProducer_uint32Range(producer, 0, 1),
(ZSTD_dictContentType_e)FUZZ_dataProducer_uint32Range(producer, 0, 2))); (ZSTD_dictContentType_e)FUZZ_dataProducer_uint32Range(producer, 0, 2)));
} }
/* Run it 10 times over 10 output sizes. Reuse the context and dict. */
for (i = 0; i < 10; ++i) { {
size_t const bufSize = FUZZ_dataProducer_uint32Range(producer, 0, 2 * size); size_t const bufSize = FUZZ_dataProducer_uint32Range(producer, 0, 2 * size);
void* rBuf = malloc(bufSize); void* rBuf = malloc(bufSize);
FUZZ_ASSERT(rBuf); FUZZ_ASSERT(rBuf);

View File

@ -68,13 +68,16 @@ static size_t roundTripTest(void *result, size_t resultCapacity,
int LLVMFuzzerTestOneInput(const uint8_t *src, size_t size) int LLVMFuzzerTestOneInput(const uint8_t *src, size_t size)
{ {
/* Give a random portion of src data to the producer, to use for
parameter generation. The rest will be used for (de)compression */
FUZZ_dataProducer_t *producer = FUZZ_dataProducer_create(src, size);
size_t producerSliceSize = FUZZ_dataProducer_uint32Range(producer, 0, size);
size = FUZZ_dataProducer_contract(producer, producerSliceSize);
size_t const rBufSize = size; size_t const rBufSize = size;
void* rBuf = malloc(rBufSize); void* rBuf = malloc(rBufSize);
size_t cBufSize = ZSTD_compressBound(size); size_t cBufSize = ZSTD_compressBound(size);
void* cBuf; void *cBuf;
FUZZ_dataProducer_t *producer = FUZZ_dataProducer_create(src, size);
/* Half of the time fuzz with a 1 byte smaller output size. /* Half of the time fuzz with a 1 byte smaller output size.
* This will still succeed because we force the checksum to be disabled, * This will still succeed because we force the checksum to be disabled,
* giving us 4 bytes of overhead. * giving us 4 bytes of overhead.

View File

@ -24,14 +24,17 @@ static ZSTD_CCtx *cctx = NULL;
int LLVMFuzzerTestOneInput(const uint8_t *src, size_t size) int LLVMFuzzerTestOneInput(const uint8_t *src, size_t size)
{ {
/* Give a random portion of src data to the producer, to use for
parameter generation. The rest will be used for (de)compression */
FUZZ_dataProducer_t *producer = FUZZ_dataProducer_create(src, size); FUZZ_dataProducer_t *producer = FUZZ_dataProducer_create(src, size);
size_t producerSliceSize = FUZZ_dataProducer_uint32Range(producer, 0, size);
size = FUZZ_dataProducer_contract(producer, producerSliceSize);
int const level = (int)FUZZ_dataProducer_uint32Range(
producer, 0, 19 + 3) - 3; /* [-3, 19] */
size_t const maxSize = ZSTD_compressBound(size); size_t const maxSize = ZSTD_compressBound(size);
size_t const bufSize = FUZZ_dataProducer_uint32Range(producer, 0, maxSize); size_t const bufSize = FUZZ_dataProducer_uint32Range(producer, 0, maxSize);
size = FUZZ_dataProducer_remainingBytes(producer); int const level = (int)FUZZ_dataProducer_uint32Range(
producer, 0, 19 + 3) - 3; /* [-3, 19] */
if (!cctx) { if (!cctx) {
cctx = ZSTD_createCCtx(); cctx = ZSTD_createCCtx();

View File

@ -23,25 +23,25 @@ static ZSTD_DCtx *dctx = NULL;
int LLVMFuzzerTestOneInput(const uint8_t *src, size_t size) int LLVMFuzzerTestOneInput(const uint8_t *src, size_t size)
{ {
FUZZ_dataProducer_t *producer = FUZZ_dataProducer_create(src, size); /* Give a random portion of src data to the producer, to use for
parameter generation. The rest will be used for (de)compression */
FUZZ_dataProducer_t *producer = FUZZ_dataProducer_create(src, size);
size_t producerSliceSize = FUZZ_dataProducer_uint32Range(producer, 0, size);
size = FUZZ_dataProducer_contract(producer, producerSliceSize);
if (!dctx) { if (!dctx) {
dctx = ZSTD_createDCtx(); dctx = ZSTD_createDCtx();
FUZZ_ASSERT(dctx); FUZZ_ASSERT(dctx);
} }
size_t const bufSize = FUZZ_dataProducer_uint32Range(producer, 0, 10 * size); size_t const bufSize = FUZZ_dataProducer_uint32Range(producer, 0, 10 * size);
void *rBuf = malloc(bufSize); void *rBuf = malloc(bufSize);
FUZZ_ASSERT(rBuf); FUZZ_ASSERT(rBuf);
/* Restrict to remaining data. If we run out of data while generating params, ZSTD_decompressDCtx(dctx, rBuf, bufSize, src, size);
we should still continue and let decompression happen on empty data. */ free(rBuf);
size = FUZZ_dataProducer_remainingBytes(producer);
ZSTD_decompressDCtx(dctx, rBuf, bufSize, src, size); FUZZ_dataProducer_free(producer);
free(rBuf);
FUZZ_dataProducer_free(producer);
#ifndef STATEFUL_FUZZING #ifndef STATEFUL_FUZZING
ZSTD_freeDCtx(dctx); dctx = NULL; ZSTD_freeDCtx(dctx); dctx = NULL;

View File

@ -52,12 +52,19 @@ int LLVMFuzzerTestOneInput(const uint8_t *src, size_t size)
size_t cBufSize = ZSTD_compressBound(size); size_t cBufSize = ZSTD_compressBound(size);
void* cBuf; void* cBuf;
/* Give a random portion of src data to the producer, to use for
parameter generation. The rest will be used for (de)compression */
FUZZ_dataProducer_t *producer = FUZZ_dataProducer_create(src, size); FUZZ_dataProducer_t *producer = FUZZ_dataProducer_create(src, size);
size_t producerSliceSize = FUZZ_dataProducer_uint32Range(producer, 0, size);
size = FUZZ_dataProducer_contract(producer, producerSliceSize);
/* Half of the time fuzz with a 1 byte smaller output size. /* Half of the time fuzz with a 1 byte smaller output size.
* This will still succeed because we don't use a dictionary, so the dictID * This will still succeed because we don't use a dictionary, so the dictID
* field is empty, giving us 4 bytes of overhead. * field is empty, giving us 4 bytes of overhead.
*/ */
cBufSize -= FUZZ_dataProducer_uint32Range(producer, 0, 1); cBufSize -= FUZZ_dataProducer_uint32Range(producer, 0, 1);
size = FUZZ_dataProducer_remainingBytes(producer);
cBuf = malloc(cBufSize); cBuf = malloc(cBufSize);
FUZZ_ASSERT(cBuf && rBuf); FUZZ_ASSERT(cBuf && rBuf);

View File

@ -125,15 +125,15 @@ static size_t compress(uint8_t *dst, size_t capacity,
int LLVMFuzzerTestOneInput(const uint8_t *src, size_t size) int LLVMFuzzerTestOneInput(const uint8_t *src, size_t size)
{ {
size_t neededBufSize;
neededBufSize = ZSTD_compressBound(size) * 5;
/* Give a random portion of src data to the producer, to use for /* Give a random portion of src data to the producer, to use for
parameter generation. The rest will be used for (de)compression */ parameter generation. The rest will be used for (de)compression */
FUZZ_dataProducer_t *producer = FUZZ_dataProducer_create(src, size); FUZZ_dataProducer_t *producer = FUZZ_dataProducer_create(src, size);
size_t producerSliceSize = FUZZ_dataProducer_uint32Range(producer, 0, size); size_t producerSliceSize = FUZZ_dataProducer_uint32Range(producer, 0, size);
size = FUZZ_dataProducer_contract(producer, producerSliceSize); size = FUZZ_dataProducer_contract(producer, producerSliceSize);
size_t neededBufSize;
neededBufSize = ZSTD_compressBound(size) * 5;
/* Allocate all buffers and contexts if not already allocated */ /* Allocate all buffers and contexts if not already allocated */
if (neededBufSize > bufSize) { if (neededBufSize > bufSize) {
free(cBuf); free(cBuf);

View File

@ -21,10 +21,6 @@
int LLVMFuzzerTestOneInput(const uint8_t *src, size_t size) int LLVMFuzzerTestOneInput(const uint8_t *src, size_t size)
{ {
ZSTD_frameHeader zfh; ZSTD_frameHeader zfh;
/* Consume the seed to be compatible with the corpora of other decompression
* fuzzers.
*/
FUZZ_seed(&src, &size);
/* You can fuzz any helper functions here that are fast, and take zstd /* You can fuzz any helper functions here that are fast, and take zstd
* compressed data as input. E.g. don't expect the input to be a dictionary, * compressed data as input. E.g. don't expect the input to be a dictionary,
* so don't fuzz ZSTD_getDictID_fromDict(). * so don't fuzz ZSTD_getDictID_fromDict().