diff --git a/tests/fuzz/fuzz.h b/tests/fuzz/fuzz.h index 3017db3aa..a64845473 100644 --- a/tests/fuzz/fuzz.h +++ b/tests/fuzz/fuzz.h @@ -12,15 +12,17 @@ * Fuzz targets have some common parameters passed as macros during compilation. * Check the documentation for each individual fuzzer for more parameters. * - * @param STATEFULL_FUZZING: + * @param STATEFUL_FUZZING: * Define this to reuse state between fuzzer runs. This can be useful to * test code paths which are only executed when contexts are reused. * WARNING: Makes reproducing crashes much harder. * Default: Not defined. * @param FUZZ_RNG_SEED_SIZE: * The number of bytes of the source to look at when constructing a seed - * for the deterministic RNG. - * Default: 128. + * for the deterministic RNG. These bytes are discarded before passing + * the data to zstd functions. Every fuzzer initializes the RNG exactly + * once before doing anything else, even if it is unused. + * Default: 4. * @param ZSTD_DEBUG: * This is a parameter for the zstd library. Defining `ZSTD_DEBUG=1` * enables assert() statements in the zstd library. Higher levels enable @@ -41,12 +43,20 @@ #define FUZZ_H #ifndef FUZZ_RNG_SEED_SIZE -# define FUZZ_RNG_SEED_SIZE 128 +# define FUZZ_RNG_SEED_SIZE 4 #endif #include #include +#ifdef __cplusplus +extern "C" { +#endif + int LLVMFuzzerTestOneInput(const uint8_t *src, size_t size); +#ifdef __cplusplus +} +#endif + #endif diff --git a/tests/fuzz/fuzz_helpers.h b/tests/fuzz/fuzz_helpers.h index f7cc3d5bb..d93881c80 100644 --- a/tests/fuzz/fuzz_helpers.h +++ b/tests/fuzz/fuzz_helpers.h @@ -19,6 +19,10 @@ #include #include +#ifdef __cplusplus +extern "C" { +#endif + #define MIN(a, b) ((a) < (b) ? (a) : (b)) #define MAX(a, b) ((a) > (b) ? (a) : (b)) @@ -48,11 +52,13 @@ /** * Determininistically constructs a seed based on the fuzz input. - * Only looks at the first FUZZ_RNG_SEED_SIZE bytes of the input. + * Consumes up to the first FUZZ_RNG_SEED_SIZE bytes of the input. */ -FUZZ_STATIC uint32_t FUZZ_seed(const uint8_t *src, size_t size) { - size_t const toHash = MIN(FUZZ_RNG_SEED_SIZE, size); - return XXH32(src, toHash, 0); +FUZZ_STATIC uint32_t FUZZ_seed(uint8_t const **src, size_t* size) { + size_t const toHash = MIN(FUZZ_RNG_SEED_SIZE, *size); + return XXH32(*src, toHash, 0); + *size -= toHash; + *src += toHash; } #define FUZZ_rotl32(x, r) (((x) << (r)) | ((x) >> (32 - (r)))) @@ -67,4 +73,8 @@ FUZZ_STATIC uint32_t FUZZ_rand(uint32_t *state) { return rand32 >> 5; } +#ifdef __cplusplus +} +#endif + #endif diff --git a/tests/fuzz/simple_decompress.c b/tests/fuzz/simple_decompress.c index a225b9dc7..bba272c62 100644 --- a/tests/fuzz/simple_decompress.c +++ b/tests/fuzz/simple_decompress.c @@ -24,7 +24,10 @@ static size_t bufSize = 0; int LLVMFuzzerTestOneInput(const uint8_t *src, size_t size) { - size_t const neededBufSize = MAX(20 * size, (size_t)256 << 10); + size_t neededBufSize; + + FUZZ_seed(&src, &size); + neededBufSize = MAX(20 * size, (size_t)256 << 10); /* Allocate all buffers and contexts if not already allocated */ if (neededBufSize > bufSize) { @@ -39,7 +42,7 @@ int LLVMFuzzerTestOneInput(const uint8_t *src, size_t size) } ZSTD_decompressDCtx(dctx, rBuf, neededBufSize, src, size); -#ifndef STATEFULL_FUZZING +#ifndef STATEFUL_FUZZING ZSTD_freeDCtx(dctx); dctx = NULL; #endif return 0; diff --git a/tests/fuzz/simple_round_trip.c b/tests/fuzz/simple_round_trip.c index 63472bb44..9df025283 100644 --- a/tests/fuzz/simple_round_trip.c +++ b/tests/fuzz/simple_round_trip.c @@ -44,9 +44,10 @@ static size_t roundTripTest(void *result, size_t resultCapacity, int LLVMFuzzerTestOneInput(const uint8_t *src, size_t size) { - size_t const neededBufSize = ZSTD_compressBound(size); + size_t neededBufSize; - seed = FUZZ_seed(src, size); + seed = FUZZ_seed(&src, &size); + neededBufSize = ZSTD_compressBound(size); /* Allocate all buffers and contexts if not already allocated */ if (neededBufSize > bufSize) { @@ -73,7 +74,7 @@ int LLVMFuzzerTestOneInput(const uint8_t *src, size_t size) FUZZ_ASSERT_MSG(result == size, "Incorrect regenerated size"); FUZZ_ASSERT_MSG(!memcmp(src, rBuf, size), "Corruption!"); } -#ifndef STATEFULL_FUZZING +#ifndef STATEFUL_FUZZING ZSTD_freeCCtx(cctx); cctx = NULL; ZSTD_freeDCtx(dctx); dctx = NULL; #endif diff --git a/tests/fuzz/stream_decompress.c b/tests/fuzz/stream_decompress.c index dfd746972..7ad571221 100644 --- a/tests/fuzz/stream_decompress.c +++ b/tests/fuzz/stream_decompress.c @@ -51,7 +51,7 @@ static ZSTD_inBuffer makeInBuffer(const uint8_t **src, size_t *size) int LLVMFuzzerTestOneInput(const uint8_t *src, size_t size) { - seed = FUZZ_seed(src, size); + seed = FUZZ_seed(&src, &size); /* Allocate all buffers and contexts if not already allocated */ if (!buf) { @@ -78,7 +78,7 @@ int LLVMFuzzerTestOneInput(const uint8_t *src, size_t size) } error: -#ifndef STATEFULL_FUZZING +#ifndef STATEFUL_FUZZING ZSTD_freeDStream(dstream); dstream = NULL; #endif return 0; diff --git a/tests/fuzz/stream_round_trip.c b/tests/fuzz/stream_round_trip.c index 74adbeaba..e796c1e7f 100644 --- a/tests/fuzz/stream_round_trip.c +++ b/tests/fuzz/stream_round_trip.c @@ -114,9 +114,10 @@ static size_t compress(uint8_t *dst, size_t capacity, int LLVMFuzzerTestOneInput(const uint8_t *src, size_t size) { - size_t const neededBufSize = ZSTD_compressBound(size) * 2; + size_t neededBufSize; - seed = FUZZ_seed(src, size); + seed = FUZZ_seed(&src, &size); + neededBufSize = ZSTD_compressBound(size) * 2; /* Allocate all buffers and contexts if not already allocated */ if (neededBufSize > bufSize) { @@ -145,7 +146,7 @@ int LLVMFuzzerTestOneInput(const uint8_t *src, size_t size) FUZZ_ASSERT_MSG(!memcmp(src, rBuf, size), "Corruption!"); } -#ifndef STATEFULL_FUZZING +#ifndef STATEFUL_FUZZING ZSTD_freeCStream(cstream); cstream = NULL; ZSTD_freeDCtx(dctx); dctx = NULL; #endif