Merge branch 'dev' into extract_sequences_api

This commit is contained in:
Bimba Shrestha
2019-09-16 13:29:59 -07:00
committed by GitHub
91 changed files with 5728 additions and 2472 deletions
+2 -11
View File
@@ -40,8 +40,8 @@ FUZZ_LDFLAGS := -pthread $(LDFLAGS)
FUZZ_ARFLAGS := $(ARFLAGS)
FUZZ_TARGET_FLAGS = $(FUZZ_CPPFLAGS) $(FUZZ_CXXFLAGS) $(FUZZ_LDFLAGS)
FUZZ_HEADERS := fuzz_helpers.h fuzz.h zstd_helpers.h
FUZZ_SRC := $(PRGDIR)/util.c zstd_helpers.c
FUZZ_HEADERS := fuzz_helpers.h fuzz.h zstd_helpers.h fuzz_data_producer.h
FUZZ_SRC := $(PRGDIR)/util.c zstd_helpers.c fuzz_data_producer.c
ZSTDCOMMON_SRC := $(ZSTDDIR)/common/*.c
ZSTDCOMP_SRC := $(ZSTDDIR)/compress/*.c
@@ -113,15 +113,6 @@ zstd_frame_info: $(FUZZ_HEADERS) $(FUZZ_OBJ) zstd_frame_info.o
libregression.a: $(FUZZ_HEADERS) $(PRGDIR)/util.h $(PRGDIR)/util.c regression_driver.o
$(AR) $(FUZZ_ARFLAGS) $@ regression_driver.o
# Install libfuzzer (not usable for MSAN testing)
# Provided for convenience. To use this library run make libFuzzer and
# set LDFLAGS=-L.
.PHONY: libFuzzer
libFuzzer:
@$(RM) -rf Fuzzer
@git clone https://chromium.googlesource.com/chromium/llvm-project/compiler-rt/lib/fuzzer Fuzzer
@cd Fuzzer && ./build.sh
corpora/%_seed_corpus.zip:
@mkdir -p corpora
$(DOWNLOAD) $@ $(CORPORA_URL_PREFIX)$*_seed_corpus.zip
+13 -8
View File
@@ -35,6 +35,8 @@ The environment variables can be overridden with the corresponding flags
`--cc`, `--cflags`, etc.
The specific fuzzing engine is selected with `LIB_FUZZING_ENGINE` or
`--lib-fuzzing-engine`, the default is `libregression.a`.
Alternatively, you can use Clang's built in fuzzing engine with
`--enable-fuzzer`.
It has flags that can easily set up sanitizers `--enable-{a,ub,m}san`, and
coverage instrumentation `--enable-coverage`.
It sets sane defaults which can be overridden with flags `--debug`,
@@ -51,22 +53,25 @@ The command used to run the fuzzer is printed for debugging.
## LibFuzzer
```
# Build libfuzzer if necessary
make libFuzzer
# Build the fuzz targets
./fuzz.py build all --enable-coverage --enable-asan --enable-ubsan --lib-fuzzing-engine Fuzzer/libFuzzer.a --cc clang --cxx clang++
./fuzz.py build all --enable-fuzzer --enable-asan --enable-ubsan --cc clang --cxx clang++
# OR equivalently
CC=clang CXX=clang++ LIB_FUZZING_ENGINE=Fuzzer/libFuzzer.a ./fuzz.py build all --enable-coverage --enable-asan --enable-ubsan
CC=clang CXX=clang++ ./fuzz.py build all --enable-fuzzer --enable-asan --enable-ubsan
# Run the fuzzer
./fuzz.py libfuzzer TARGET -max_len=8192 -jobs=4
./fuzz.py libfuzzer TARGET <libfuzzer args like -jobs=4>
```
where `TARGET` could be `simple_decompress`, `stream_round_trip`, etc.
### MSAN
Fuzzing with `libFuzzer` and `MSAN` will require building a C++ standard library
and libFuzzer with MSAN.
Fuzzing with `libFuzzer` and `MSAN` is as easy as:
```
CC=clang CXX=clang++ ./fuzz.py build all --enable-fuzzer --enable-msan
./fuzz.py libfuzzer TARGET <libfuzzer args>
```
`fuzz.py` respects the environment variables / flags `MSAN_EXTRA_CPPFLAGS`,
`MSAN_EXTRA_CFLAGS`, `MSAN_EXTRA_CXXFLAGS`, `MSAN_EXTRA_LDFLAGS` to easily pass
the extra parameters only for MSAN.
@@ -85,7 +90,7 @@ CC=afl-clang CXX=afl-clang++ ./fuzz.py build all --enable-asan --enable-ubsan
## Regression Testing
The regression rest supports the `all` target to run all the fuzzers in one
The regression test supports the `all` target to run all the fuzzers in one
command.
```
-2
View File
@@ -28,8 +28,6 @@ int LLVMFuzzerTestOneInput(const uint8_t *src, size_t size)
{
size_t const neededBufSize = ZSTD_BLOCKSIZE_MAX;
FUZZ_seed(&src, &size);
/* Allocate all buffers and contexts if not already allocated */
if (neededBufSize > bufSize) {
free(rBuf);
+15 -10
View File
@@ -20,21 +20,20 @@
#include <string.h>
#include "fuzz_helpers.h"
#include "zstd.h"
static const int kMaxClevel = 19;
#include "zstd_helpers.h"
#include "fuzz_data_producer.h"
static ZSTD_CCtx *cctx = NULL;
static ZSTD_DCtx *dctx = NULL;
static void* cBuf = NULL;
static void* rBuf = NULL;
static size_t bufSize = 0;
static uint32_t seed;
static size_t roundTripTest(void *result, size_t resultCapacity,
void *compressed, size_t compressedCapacity,
const void *src, size_t srcSize)
const void *src, size_t srcSize,
int cLevel)
{
int const cLevel = FUZZ_rand(&seed) % kMaxClevel;
ZSTD_parameters const params = ZSTD_getParams(cLevel, srcSize, 0);
size_t ret = ZSTD_compressBegin_advanced(cctx, NULL, 0, params, srcSize);
FUZZ_ZASSERT(ret);
@@ -52,12 +51,16 @@ static size_t roundTripTest(void *result, size_t resultCapacity,
int LLVMFuzzerTestOneInput(const uint8_t *src, size_t size)
{
size_t neededBufSize;
/* 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 = FUZZ_dataProducer_reserveDataPrefix(producer);
seed = FUZZ_seed(&src, &size);
neededBufSize = size;
int const cLevel = FUZZ_dataProducer_int32Range(producer, kMinClevel, kMaxClevel);
size_t neededBufSize = size;
if (size > ZSTD_BLOCKSIZE_MAX)
return 0;
size = ZSTD_BLOCKSIZE_MAX;
/* Allocate all buffers and contexts if not already allocated */
if (neededBufSize > bufSize || !cBuf || !rBuf) {
@@ -79,11 +82,13 @@ int LLVMFuzzerTestOneInput(const uint8_t *src, size_t size)
{
size_t const result =
roundTripTest(rBuf, neededBufSize, cBuf, neededBufSize, src, size);
roundTripTest(rBuf, neededBufSize, cBuf, neededBufSize, src, size,
cLevel);
FUZZ_ZASSERT(result);
FUZZ_ASSERT_MSG(result == size, "Incorrect regenerated size");
FUZZ_ASSERT_MSG(!memcmp(src, rBuf, size), "Corruption!");
}
FUZZ_dataProducer_free(producer);
#ifndef STATEFUL_FUZZING
ZSTD_freeCCtx(cctx); cctx = NULL;
ZSTD_freeDCtx(dctx); dctx = NULL;
+14 -9
View File
@@ -18,33 +18,37 @@
#include <stdio.h>
#include "fuzz_helpers.h"
#include "zstd_helpers.h"
#include "fuzz_data_producer.h"
static ZSTD_DCtx *dctx = NULL;
int LLVMFuzzerTestOneInput(const uint8_t *src, size_t size)
{
uint32_t seed = FUZZ_seed(&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 = FUZZ_dataProducer_reserveDataPrefix(producer);
FUZZ_dict_t dict;
ZSTD_DDict* ddict = NULL;
int i;
if (!dctx) {
dctx = ZSTD_createDCtx();
FUZZ_ASSERT(dctx);
}
dict = FUZZ_train(src, size, &seed);
if (FUZZ_rand32(&seed, 0, 1) == 0) {
dict = FUZZ_train(src, size, producer);
if (FUZZ_dataProducer_uint32Range(producer, 0, 1) == 0) {
ddict = ZSTD_createDDict(dict.buff, dict.size);
FUZZ_ASSERT(ddict);
} else {
FUZZ_ZASSERT(ZSTD_DCtx_loadDictionary_advanced(
dctx, dict.buff, dict.size,
(ZSTD_dictLoadMethod_e)FUZZ_rand32(&seed, 0, 1),
(ZSTD_dictContentType_e)FUZZ_rand32(&seed, 0, 2)));
(ZSTD_dictLoadMethod_e)FUZZ_dataProducer_uint32Range(producer, 0, 1),
(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_rand32(&seed, 0, 2 * size);
{
size_t const bufSize = FUZZ_dataProducer_uint32Range(producer, 0, 10 * size);
void* rBuf = malloc(bufSize);
FUZZ_ASSERT(rBuf);
if (ddict) {
@@ -55,6 +59,7 @@ int LLVMFuzzerTestOneInput(const uint8_t *src, size_t size)
free(rBuf);
}
free(dict.buff);
FUZZ_dataProducer_free(producer);
ZSTD_freeDDict(ddict);
#ifndef STATEFUL_FUZZING
ZSTD_freeDCtx(dctx); dctx = NULL;
+19 -16
View File
@@ -19,22 +19,21 @@
#include <string.h>
#include "fuzz_helpers.h"
#include "zstd_helpers.h"
static const int kMaxClevel = 19;
#include "fuzz_data_producer.h"
static ZSTD_CCtx *cctx = NULL;
static ZSTD_DCtx *dctx = NULL;
static uint32_t seed;
static size_t roundTripTest(void *result, size_t resultCapacity,
void *compressed, size_t compressedCapacity,
const void *src, size_t srcSize)
const void *src, size_t srcSize,
FUZZ_dataProducer_t *producer)
{
ZSTD_dictContentType_e dictContentType = ZSTD_dct_auto;
FUZZ_dict_t dict = FUZZ_train(src, srcSize, &seed);
FUZZ_dict_t dict = FUZZ_train(src, srcSize, producer);
size_t cSize;
if ((FUZZ_rand(&seed) & 15) == 0) {
int const cLevel = FUZZ_rand(&seed) % kMaxClevel;
if (FUZZ_dataProducer_uint32Range(producer, 0, 15) == 0) {
int const cLevel = FUZZ_dataProducer_int32Range(producer, kMinClevel, kMaxClevel);
cSize = ZSTD_compress_usingDict(cctx,
compressed, compressedCapacity,
@@ -42,20 +41,20 @@ static size_t roundTripTest(void *result, size_t resultCapacity,
dict.buff, dict.size,
cLevel);
} else {
dictContentType = FUZZ_rand32(&seed, 0, 2);
FUZZ_setRandomParameters(cctx, srcSize, &seed);
dictContentType = FUZZ_dataProducer_uint32Range(producer, 0, 2);
FUZZ_setRandomParameters(cctx, srcSize, producer);
/* Disable checksum so we can use sizes smaller than compress bound. */
FUZZ_ZASSERT(ZSTD_CCtx_setParameter(cctx, ZSTD_c_checksumFlag, 0));
FUZZ_ZASSERT(ZSTD_CCtx_loadDictionary_advanced(
cctx, dict.buff, dict.size,
(ZSTD_dictLoadMethod_e)FUZZ_rand32(&seed, 0, 1),
(ZSTD_dictLoadMethod_e)FUZZ_dataProducer_uint32Range(producer, 0, 1),
dictContentType));
cSize = ZSTD_compress2(cctx, compressed, compressedCapacity, src, srcSize);
}
FUZZ_ZASSERT(cSize);
FUZZ_ZASSERT(ZSTD_DCtx_loadDictionary_advanced(
dctx, dict.buff, dict.size,
(ZSTD_dictLoadMethod_e)FUZZ_rand32(&seed, 0, 1),
(ZSTD_dictLoadMethod_e)FUZZ_dataProducer_uint32Range(producer, 0, 1),
dictContentType));
{
size_t const ret = ZSTD_decompressDCtx(
@@ -67,17 +66,20 @@ static size_t roundTripTest(void *result, size_t resultCapacity,
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 = FUZZ_dataProducer_reserveDataPrefix(producer);
size_t const rBufSize = size;
void* rBuf = malloc(rBufSize);
size_t cBufSize = ZSTD_compressBound(size);
void* cBuf;
seed = FUZZ_seed(&src, &size);
void *cBuf;
/* Half of the time fuzz with a 1 byte smaller output size.
* This will still succeed because we force the checksum to be disabled,
* giving us 4 bytes of overhead.
*/
cBufSize -= FUZZ_rand32(&seed, 0, 1);
cBufSize -= FUZZ_dataProducer_uint32Range(producer, 0, 1);
cBuf = malloc(cBufSize);
if (!cctx) {
@@ -91,13 +93,14 @@ int LLVMFuzzerTestOneInput(const uint8_t *src, size_t size)
{
size_t const result =
roundTripTest(rBuf, rBufSize, cBuf, cBufSize, src, size);
roundTripTest(rBuf, rBufSize, cBuf, cBufSize, src, size, producer);
FUZZ_ZASSERT(result);
FUZZ_ASSERT_MSG(result == size, "Incorrect regenerated size");
FUZZ_ASSERT_MSG(!memcmp(src, rBuf, size), "Corruption!");
}
free(rBuf);
free(cBuf);
FUZZ_dataProducer_free(producer);
#ifndef STATEFUL_FUZZING
ZSTD_freeCCtx(cctx); cctx = NULL;
ZSTD_freeDCtx(dctx); dctx = NULL;
-10
View File
@@ -17,12 +17,6 @@
* 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. 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 DEBUGLEVEL:
* This is a parameter for the zstd library. Defining `DEBUGLEVEL=1`
* enables assert() statements in the zstd library. Higher levels enable
@@ -42,10 +36,6 @@
#ifndef FUZZ_H
#define FUZZ_H
#ifndef FUZZ_RNG_SEED_SIZE
# define FUZZ_RNG_SEED_SIZE 4
#endif
#include <stddef.h>
#include <stdint.h>
+38 -21
View File
@@ -24,21 +24,38 @@ def abs_join(a, *p):
return os.path.abspath(os.path.join(a, *p))
class InputType(object):
RAW_DATA = 1
COMPRESSED_DATA = 2
class FrameType(object):
ZSTD = 1
BLOCK = 2
class TargetInfo(object):
def __init__(self, input_type, frame_type=FrameType.ZSTD):
self.input_type = input_type
self.frame_type = frame_type
# Constants
FUZZ_DIR = os.path.abspath(os.path.dirname(__file__))
CORPORA_DIR = abs_join(FUZZ_DIR, 'corpora')
TARGETS = [
'simple_round_trip',
'stream_round_trip',
'block_round_trip',
'simple_decompress',
'stream_decompress',
'block_decompress',
'dictionary_round_trip',
'dictionary_decompress',
'zstd_frame_info',
'simple_compress',
]
TARGET_INFO = {
'simple_round_trip': TargetInfo(InputType.RAW_DATA),
'stream_round_trip': TargetInfo(InputType.RAW_DATA),
'block_round_trip': TargetInfo(InputType.RAW_DATA, FrameType.BLOCK),
'simple_decompress': TargetInfo(InputType.COMPRESSED_DATA),
'stream_decompress': TargetInfo(InputType.COMPRESSED_DATA),
'block_decompress': TargetInfo(InputType.COMPRESSED_DATA, FrameType.BLOCK),
'dictionary_round_trip': TargetInfo(InputType.RAW_DATA),
'dictionary_decompress': TargetInfo(InputType.COMPRESSED_DATA),
'zstd_frame_info': TargetInfo(InputType.COMPRESSED_DATA),
'simple_compress': TargetInfo(InputType.RAW_DATA),
}
TARGETS = list(TARGET_INFO.keys())
ALL_TARGETS = TARGETS + ['all']
FUZZ_RNG_SEED_SIZE = 4
@@ -67,7 +84,7 @@ MSAN_EXTRA_LDFLAGS = os.environ.get('MSAN_EXTRA_LDFLAGS', '')
def create(r):
d = os.path.abspath(r)
if not os.path.isdir(d):
os.mkdir(d)
os.makedirs(d)
return d
@@ -158,7 +175,7 @@ def compiler_version(cc, cxx):
assert(b'clang' in cxx_version_bytes)
compiler = 'clang'
elif b'gcc' in cc_version_bytes:
assert(b'gcc' in cxx_version_bytes)
assert(b'gcc' in cxx_version_bytes or b'g++' in cxx_version_bytes)
compiler = 'gcc'
if compiler is not None:
version_regex = b'([0-9])+\.([0-9])+\.([0-9])+'
@@ -643,7 +660,7 @@ def gen_parser(args):
parser.add_argument(
'--max-size-log',
type=int,
default=13,
default=18,
help='Maximum sample size to generate')
parser.add_argument(
'--seed',
@@ -699,10 +716,11 @@ def gen(args):
'-o{}'.format(decompressed),
]
if 'block_' in args.TARGET:
info = TARGET_INFO[args.TARGET]
if info.frame_type == FrameType.BLOCK:
cmd += [
'--gen-blocks',
'--max-block-size-log={}'.format(args.max_size_log)
'--max-block-size-log={}'.format(min(args.max_size_log, 17))
]
else:
cmd += ['--max-content-size-log={}'.format(args.max_size_log)]
@@ -710,10 +728,11 @@ def gen(args):
print(' '.join(cmd))
subprocess.check_call(cmd)
if '_round_trip' in args.TARGET:
if info.input_type == InputType.RAW_DATA:
print('using decompressed data in {}'.format(decompressed))
samples = decompressed
elif '_decompress' in args.TARGET:
else:
assert info.input_type == InputType.COMPRESSED_DATA
print('using compressed data in {}'.format(compressed))
samples = compressed
@@ -721,10 +740,8 @@ def gen(args):
for name in os.listdir(samples):
samplename = abs_join(samples, name)
outname = abs_join(seed, name)
rng_seed = os.urandom(args.fuzz_rng_seed_size)
with open(samplename, 'rb') as sample:
with open(outname, 'wb') as out:
out.write(rng_seed)
CHUNK_SIZE = 131072
chunk = sample.read(CHUNK_SIZE)
while len(chunk) > 0:
+85
View File
@@ -0,0 +1,85 @@
/*
* Copyright (c) 2016-present, Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under both the BSD-style license (found in the
* LICENSE file in the root directory of this source tree) and the GPLv2 (found
* in the COPYING file in the root directory of this source tree).
*/
#include "fuzz_data_producer.h"
struct FUZZ_dataProducer_s{
const uint8_t *data;
size_t size;
};
FUZZ_dataProducer_t *FUZZ_dataProducer_create(const uint8_t *data, size_t size) {
FUZZ_dataProducer_t *producer = malloc(sizeof(FUZZ_dataProducer_t));
FUZZ_ASSERT(producer != NULL);
producer->data = data;
producer->size = size;
return producer;
}
void FUZZ_dataProducer_free(FUZZ_dataProducer_t *producer) { free(producer); }
uint32_t FUZZ_dataProducer_uint32Range(FUZZ_dataProducer_t *producer, uint32_t min,
uint32_t max) {
FUZZ_ASSERT(min <= max);
uint32_t range = max - min;
uint32_t rolling = range;
uint32_t result = 0;
while (rolling > 0 && producer->size > 0) {
uint8_t next = *(producer->data + producer->size - 1);
producer->size -= 1;
result = (result << 8) | next;
rolling >>= 8;
}
if (range == 0xffffffff) {
return result;
}
return min + result % (range + 1);
}
uint32_t FUZZ_dataProducer_uint32(FUZZ_dataProducer_t *producer) {
return FUZZ_dataProducer_uint32Range(producer, 0, 0xffffffff);
}
int32_t FUZZ_dataProducer_int32Range(FUZZ_dataProducer_t *producer,
int32_t min, int32_t max)
{
FUZZ_ASSERT(min <= max);
if (min < 0)
return (int)FUZZ_dataProducer_uint32Range(producer, 0, max - min) + min;
return FUZZ_dataProducer_uint32Range(producer, min, max);
}
size_t FUZZ_dataProducer_remainingBytes(FUZZ_dataProducer_t *producer){
return producer->size;
}
size_t FUZZ_dataProducer_contract(FUZZ_dataProducer_t *producer, size_t newSize)
{
newSize = newSize > producer->size ? producer->size : newSize;
size_t remaining = producer->size - newSize;
producer->data = producer->data + remaining;
producer->size = newSize;
return remaining;
}
size_t FUZZ_dataProducer_reserveDataPrefix(FUZZ_dataProducer_t *producer)
{
size_t producerSliceSize = FUZZ_dataProducer_uint32Range(
producer, 0, producer->size);
return FUZZ_dataProducer_contract(producer, producerSliceSize);
}
+60
View File
@@ -0,0 +1,60 @@
/*
* Copyright (c) 2016-present, Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under both the BSD-style license (found in the
* LICENSE file in the root directory of this source tree) and the GPLv2 (found
* in the COPYING file in the root directory of this source tree).
*/
/**
* Helper APIs for generating random data from input data stream.
The producer reads bytes from the end of the input and appends them together
to generate a random number in the requested range. If it runs out of input
data, it will keep returning the same value (min) over and over again.
*/
#ifndef FUZZ_DATA_PRODUCER_H
#define FUZZ_DATA_PRODUCER_H
#include <stddef.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include "fuzz_helpers.h"
/* Struct used for maintaining the state of the data */
typedef struct FUZZ_dataProducer_s FUZZ_dataProducer_t;
/* Returns a data producer state struct. Use for producer initialization. */
FUZZ_dataProducer_t *FUZZ_dataProducer_create(const uint8_t *data, size_t size);
/* Frees the data producer */
void FUZZ_dataProducer_free(FUZZ_dataProducer_t *producer);
/* Returns value between [min, max] */
uint32_t FUZZ_dataProducer_uint32Range(FUZZ_dataProducer_t *producer, uint32_t min,
uint32_t max);
/* Returns a uint32 value */
uint32_t FUZZ_dataProducer_uint32(FUZZ_dataProducer_t *producer);
/* Returns a signed value between [min, max] */
int32_t FUZZ_dataProducer_int32Range(FUZZ_dataProducer_t *producer,
int32_t min, int32_t max);
/* Returns the size of the remaining bytes of data in the producer */
size_t FUZZ_dataProducer_remainingBytes(FUZZ_dataProducer_t *producer);
/* Restricts the producer to only the last newSize bytes of data.
If newSize > current data size, nothing happens. Returns the number of bytes
the producer won't use anymore, after contracting. */
size_t FUZZ_dataProducer_contract(FUZZ_dataProducer_t *producer, size_t newSize);
/* Restricts the producer to use only the last X bytes of data, where X is
a random number in the interval [0, data_size]. Returns the size of the
remaining data the producer won't use anymore (the prefix). */
size_t FUZZ_dataProducer_reserveDataPrefix(FUZZ_dataProducer_t *producer);
#endif // FUZZ_DATA_PRODUCER_H
+1 -31
View File
@@ -14,6 +14,7 @@
#ifndef FUZZ_HELPERS_H
#define FUZZ_HELPERS_H
#include "debug.h"
#include "fuzz.h"
#include "xxhash.h"
#include "zstd.h"
@@ -54,37 +55,6 @@ extern "C" {
#define FUZZ_STATIC static
#endif
/**
* Deterministically constructs a seed based on the fuzz input.
* Consumes up to the first FUZZ_RNG_SEED_SIZE bytes of the input.
*/
FUZZ_STATIC uint32_t FUZZ_seed(uint8_t const **src, size_t* size) {
uint8_t const *data = *src;
size_t const toHash = MIN(FUZZ_RNG_SEED_SIZE, *size);
*size -= toHash;
*src += toHash;
return XXH32(data, toHash, 0);
}
#define FUZZ_rotl32(x, r) (((x) << (r)) | ((x) >> (32 - (r))))
FUZZ_STATIC uint32_t FUZZ_rand(uint32_t *state) {
static const uint32_t prime1 = 2654435761U;
static const uint32_t prime2 = 2246822519U;
uint32_t rand32 = *state;
rand32 *= prime1;
rand32 += prime2;
rand32 = FUZZ_rotl32(rand32, 13);
*state = rand32;
return rand32 >> 5;
}
/* Returns a random numer in the range [min, max]. */
FUZZ_STATIC uint32_t FUZZ_rand32(uint32_t *state, uint32_t min, uint32_t max) {
uint32_t random = FUZZ_rand(state);
return min + (random % (max - min + 1));
}
#ifdef __cplusplus
}
#endif
+1
View File
@@ -36,6 +36,7 @@ int main(int argc, char const **argv) {
fprintf(stderr, "WARNING: No files passed to %s\n", argv[0]);
for (i = 0; i < numFiles; ++i) {
char const *fileName = files[i];
DEBUGLOG(3, "Running %s", fileName);
size_t const fileSize = UTIL_getFileSize(fileName);
size_t readSize;
FILE *file;
+16 -11
View File
@@ -18,28 +18,33 @@
#include <stdio.h>
#include "fuzz_helpers.h"
#include "zstd.h"
#include "zstd_helpers.h"
#include "fuzz_data_producer.h"
static ZSTD_CCtx *cctx = NULL;
int LLVMFuzzerTestOneInput(const uint8_t *src, size_t size)
{
uint32_t seed = FUZZ_seed(&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 = FUZZ_dataProducer_reserveDataPrefix(producer);
size_t const maxSize = ZSTD_compressBound(size);
int i;
size_t const bufSize = FUZZ_dataProducer_uint32Range(producer, 0, maxSize);
int const cLevel = FUZZ_dataProducer_int32Range(producer, kMinClevel, kMaxClevel);
if (!cctx) {
cctx = ZSTD_createCCtx();
FUZZ_ASSERT(cctx);
}
/* Run it 10 times over 10 output sizes. Reuse the context. */
for (i = 0; i < 10; ++i) {
int const level = (int)FUZZ_rand32(&seed, 0, 19 + 3) - 3; /* [-3, 19] */
size_t const bufSize = FUZZ_rand32(&seed, 0, maxSize);
void* rBuf = malloc(bufSize);
FUZZ_ASSERT(rBuf);
ZSTD_compressCCtx(cctx, rBuf, bufSize, src, size, level);
free(rBuf);
}
void *rBuf = malloc(bufSize);
FUZZ_ASSERT(rBuf);
ZSTD_compressCCtx(cctx, rBuf, bufSize, src, size, cLevel);
free(rBuf);
FUZZ_dataProducer_free(producer);
#ifndef STATEFUL_FUZZING
ZSTD_freeCCtx(cctx); cctx = NULL;
#endif
+14 -10
View File
@@ -17,26 +17,30 @@
#include <stdio.h>
#include "fuzz_helpers.h"
#include "zstd.h"
#include "fuzz_data_producer.h"
static ZSTD_DCtx *dctx = NULL;
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 = FUZZ_dataProducer_reserveDataPrefix(producer);
uint32_t seed = FUZZ_seed(&src, &size);
int i;
if (!dctx) {
dctx = ZSTD_createDCtx();
FUZZ_ASSERT(dctx);
}
/* Run it 10 times over 10 output sizes. Reuse the context. */
for (i = 0; i < 10; ++i) {
size_t const bufSize = FUZZ_rand32(&seed, 0, 2 * size);
void* rBuf = malloc(bufSize);
FUZZ_ASSERT(rBuf);
ZSTD_decompressDCtx(dctx, rBuf, bufSize, src, size);
free(rBuf);
}
size_t const bufSize = FUZZ_dataProducer_uint32Range(producer, 0, 10 * size);
void *rBuf = malloc(bufSize);
FUZZ_ASSERT(rBuf);
ZSTD_decompressDCtx(dctx, rBuf, bufSize, src, size);
free(rBuf);
FUZZ_dataProducer_free(producer);
#ifndef STATEFUL_FUZZING
ZSTD_freeDCtx(dctx); dctx = NULL;
+16 -10
View File
@@ -20,23 +20,23 @@
#include <string.h>
#include "fuzz_helpers.h"
#include "zstd_helpers.h"
static const int kMaxClevel = 19;
#include "fuzz_data_producer.h"
static ZSTD_CCtx *cctx = NULL;
static ZSTD_DCtx *dctx = NULL;
static uint32_t seed;
static size_t roundTripTest(void *result, size_t resultCapacity,
void *compressed, size_t compressedCapacity,
const void *src, size_t srcSize)
const void *src, size_t srcSize,
FUZZ_dataProducer_t *producer)
{
size_t cSize;
if (FUZZ_rand(&seed) & 1) {
FUZZ_setRandomParameters(cctx, srcSize, &seed);
if (FUZZ_dataProducer_uint32Range(producer, 0, 1)) {
FUZZ_setRandomParameters(cctx, srcSize, producer);
cSize = ZSTD_compress2(cctx, compressed, compressedCapacity, src, srcSize);
} else {
int const cLevel = FUZZ_rand(&seed) % kMaxClevel;
int const cLevel = FUZZ_dataProducer_int32Range(producer, kMinClevel, kMaxClevel);
cSize = ZSTD_compressCCtx(
cctx, compressed, compressedCapacity, src, srcSize, cLevel);
}
@@ -51,12 +51,17 @@ int LLVMFuzzerTestOneInput(const uint8_t *src, size_t size)
size_t cBufSize = ZSTD_compressBound(size);
void* cBuf;
seed = FUZZ_seed(&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 = FUZZ_dataProducer_reserveDataPrefix(producer);
/* 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
* field is empty, giving us 4 bytes of overhead.
*/
cBufSize -= FUZZ_rand32(&seed, 0, 1);
cBufSize -= FUZZ_dataProducer_uint32Range(producer, 0, 1);
cBuf = malloc(cBufSize);
FUZZ_ASSERT(cBuf && rBuf);
@@ -72,13 +77,14 @@ int LLVMFuzzerTestOneInput(const uint8_t *src, size_t size)
{
size_t const result =
roundTripTest(rBuf, rBufSize, cBuf, cBufSize, src, size);
roundTripTest(rBuf, rBufSize, cBuf, cBufSize, src, size, producer);
FUZZ_ZASSERT(result);
FUZZ_ASSERT_MSG(result == size, "Incorrect regenerated size");
FUZZ_ASSERT_MSG(!memcmp(src, rBuf, size), "Corruption!");
}
free(rBuf);
free(cBuf);
FUZZ_dataProducer_free(producer);
#ifndef STATEFUL_FUZZING
ZSTD_freeCCtx(cctx); cctx = NULL;
ZSTD_freeDCtx(dctx); dctx = NULL;
+15 -9
View File
@@ -19,6 +19,7 @@
#include <stdio.h>
#include "fuzz_helpers.h"
#include "zstd.h"
#include "fuzz_data_producer.h"
static size_t const kBufSize = ZSTD_BLOCKSIZE_MAX;
@@ -26,22 +27,23 @@ static ZSTD_DStream *dstream = NULL;
static void* buf = NULL;
uint32_t seed;
static ZSTD_outBuffer makeOutBuffer(void)
static ZSTD_outBuffer makeOutBuffer(FUZZ_dataProducer_t *producer)
{
ZSTD_outBuffer buffer = { buf, 0, 0 };
buffer.size = (FUZZ_rand(&seed) % kBufSize) + 1;
buffer.size = (FUZZ_dataProducer_uint32Range(producer, 1, kBufSize));
FUZZ_ASSERT(buffer.size <= kBufSize);
return buffer;
}
static ZSTD_inBuffer makeInBuffer(const uint8_t **src, size_t *size)
static ZSTD_inBuffer makeInBuffer(const uint8_t **src, size_t *size,
FUZZ_dataProducer_t *producer)
{
ZSTD_inBuffer buffer = { *src, 0, 0 };
FUZZ_ASSERT(*size > 0);
buffer.size = (FUZZ_rand(&seed) % *size) + 1;
buffer.size = (FUZZ_dataProducer_uint32Range(producer, 1, *size));
FUZZ_ASSERT(buffer.size <= *size);
*src += buffer.size;
*size -= buffer.size;
@@ -51,13 +53,16 @@ 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);
/* 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 = FUZZ_dataProducer_reserveDataPrefix(producer);
/* Allocate all buffers and contexts if not already allocated */
if (!buf) {
buf = malloc(kBufSize);
FUZZ_ASSERT(buf);
}
FUZZ_ASSERT(buf);
}
if (!dstream) {
dstream = ZSTD_createDStream();
@@ -67,9 +72,9 @@ int LLVMFuzzerTestOneInput(const uint8_t *src, size_t size)
}
while (size > 0) {
ZSTD_inBuffer in = makeInBuffer(&src, &size);
ZSTD_inBuffer in = makeInBuffer(&src, &size, producer);
while (in.pos != in.size) {
ZSTD_outBuffer out = makeOutBuffer();
ZSTD_outBuffer out = makeOutBuffer(producer);
size_t const rc = ZSTD_decompressStream(dstream, &out, &in);
if (ZSTD_isError(rc)) goto error;
}
@@ -79,5 +84,6 @@ error:
#ifndef STATEFUL_FUZZING
ZSTD_freeDStream(dstream); dstream = NULL;
#endif
FUZZ_dataProducer_free(producer);
return 0;
}
+26 -19
View File
@@ -20,31 +20,33 @@
#include <string.h>
#include "fuzz_helpers.h"
#include "zstd_helpers.h"
#include "fuzz_data_producer.h"
ZSTD_CCtx *cctx = NULL;
static ZSTD_DCtx *dctx = NULL;
static uint8_t* cBuf = NULL;
static uint8_t* rBuf = NULL;
static size_t bufSize = 0;
static uint32_t seed;
static ZSTD_outBuffer makeOutBuffer(uint8_t *dst, size_t capacity)
static ZSTD_outBuffer makeOutBuffer(uint8_t *dst, size_t capacity,
FUZZ_dataProducer_t *producer)
{
ZSTD_outBuffer buffer = { dst, 0, 0 };
FUZZ_ASSERT(capacity > 0);
buffer.size = (FUZZ_rand(&seed) % capacity) + 1;
buffer.size = (FUZZ_dataProducer_uint32Range(producer, 1, capacity));
FUZZ_ASSERT(buffer.size <= capacity);
return buffer;
}
static ZSTD_inBuffer makeInBuffer(const uint8_t **src, size_t *size)
static ZSTD_inBuffer makeInBuffer(const uint8_t **src, size_t *size,
FUZZ_dataProducer_t *producer)
{
ZSTD_inBuffer buffer = { *src, 0, 0 };
FUZZ_ASSERT(*size > 0);
buffer.size = (FUZZ_rand(&seed) % *size) + 1;
buffer.size = (FUZZ_dataProducer_uint32Range(producer, 1, *size));
FUZZ_ASSERT(buffer.size <= *size);
*src += buffer.size;
*size -= buffer.size;
@@ -53,23 +55,24 @@ static ZSTD_inBuffer makeInBuffer(const uint8_t **src, size_t *size)
}
static size_t compress(uint8_t *dst, size_t capacity,
const uint8_t *src, size_t srcSize)
const uint8_t *src, size_t srcSize,
FUZZ_dataProducer_t *producer)
{
size_t dstSize = 0;
ZSTD_CCtx_reset(cctx, ZSTD_reset_session_only);
FUZZ_setRandomParameters(cctx, srcSize, &seed);
FUZZ_setRandomParameters(cctx, srcSize, producer);
while (srcSize > 0) {
ZSTD_inBuffer in = makeInBuffer(&src, &srcSize);
ZSTD_inBuffer in = makeInBuffer(&src, &srcSize, producer);
/* Mode controls the action. If mode == -1 we pick a new mode */
int mode = -1;
while (in.pos < in.size || mode != -1) {
ZSTD_outBuffer out = makeOutBuffer(dst, capacity);
ZSTD_outBuffer out = makeOutBuffer(dst, capacity, producer);
/* Previous action finished, pick a new mode. */
if (mode == -1) mode = FUZZ_rand(&seed) % 10;
if (mode == -1) mode = FUZZ_dataProducer_uint32Range(producer, 0, 9);
switch (mode) {
case 0: /* fall-though */
case 1: /* fall-though */
case 0: /* fall-through */
case 1: /* fall-through */
case 2: {
size_t const ret =
ZSTD_compressStream2(cctx, &out, &in, ZSTD_e_flush);
@@ -85,9 +88,9 @@ static size_t compress(uint8_t *dst, size_t capacity,
/* Reset the compressor when the frame is finished */
if (ret == 0) {
ZSTD_CCtx_reset(cctx, ZSTD_reset_session_only);
if ((FUZZ_rand(&seed) & 7) == 0) {
if (FUZZ_dataProducer_uint32Range(producer, 0, 7) == 0) {
size_t const remaining = in.size - in.pos;
FUZZ_setRandomParameters(cctx, remaining, &seed);
FUZZ_setRandomParameters(cctx, remaining, producer);
}
mode = -1;
}
@@ -107,7 +110,7 @@ static size_t compress(uint8_t *dst, size_t capacity,
}
for (;;) {
ZSTD_inBuffer in = {NULL, 0, 0};
ZSTD_outBuffer out = makeOutBuffer(dst, capacity);
ZSTD_outBuffer out = makeOutBuffer(dst, capacity, producer);
size_t const ret = ZSTD_compressStream2(cctx, &out, &in, ZSTD_e_end);
FUZZ_ZASSERT(ret);
@@ -122,10 +125,13 @@ static size_t compress(uint8_t *dst, size_t capacity,
int LLVMFuzzerTestOneInput(const uint8_t *src, size_t size)
{
size_t neededBufSize;
/* 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 = FUZZ_dataProducer_reserveDataPrefix(producer);
seed = FUZZ_seed(&src, &size);
neededBufSize = ZSTD_compressBound(size) * 2;
size_t neededBufSize;
neededBufSize = ZSTD_compressBound(size) * 5;
/* Allocate all buffers and contexts if not already allocated */
if (neededBufSize > bufSize) {
@@ -146,7 +152,7 @@ int LLVMFuzzerTestOneInput(const uint8_t *src, size_t size)
}
{
size_t const cSize = compress(cBuf, neededBufSize, src, size);
size_t const cSize = compress(cBuf, neededBufSize, src, size, producer);
size_t const rSize =
ZSTD_decompressDCtx(dctx, rBuf, neededBufSize, cBuf, cSize);
FUZZ_ZASSERT(rSize);
@@ -154,6 +160,7 @@ int LLVMFuzzerTestOneInput(const uint8_t *src, size_t size)
FUZZ_ASSERT_MSG(!memcmp(src, rBuf, size), "Corruption!");
}
FUZZ_dataProducer_free(producer);
#ifndef STATEFUL_FUZZING
ZSTD_freeCCtx(cctx); cctx = NULL;
ZSTD_freeDCtx(dctx); dctx = NULL;
-4
View File
@@ -21,10 +21,6 @@
int LLVMFuzzerTestOneInput(const uint8_t *src, size_t size)
{
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
* compressed data as input. E.g. don't expect the input to be a dictionary,
* so don't fuzz ZSTD_getDictID_fromDict().
+40 -34
View File
@@ -17,53 +17,56 @@
#include "zstd.h"
#include "zdict.h"
const int kMinClevel = -3;
const int kMaxClevel = 19;
static void set(ZSTD_CCtx *cctx, ZSTD_cParameter param, int value)
{
FUZZ_ZASSERT(ZSTD_CCtx_setParameter(cctx, param, value));
}
static void setRand(ZSTD_CCtx *cctx, ZSTD_cParameter param, unsigned min,
unsigned max, uint32_t *state) {
unsigned const value = FUZZ_rand32(state, min, max);
unsigned max, FUZZ_dataProducer_t *producer) {
unsigned const value = FUZZ_dataProducer_uint32Range(producer, min, max);
set(cctx, param, value);
}
ZSTD_compressionParameters FUZZ_randomCParams(size_t srcSize, uint32_t *state)
ZSTD_compressionParameters FUZZ_randomCParams(size_t srcSize, FUZZ_dataProducer_t *producer)
{
/* Select compression parameters */
ZSTD_compressionParameters cParams;
cParams.windowLog = FUZZ_rand32(state, ZSTD_WINDOWLOG_MIN, 15);
cParams.hashLog = FUZZ_rand32(state, ZSTD_HASHLOG_MIN, 15);
cParams.chainLog = FUZZ_rand32(state, ZSTD_CHAINLOG_MIN, 16);
cParams.searchLog = FUZZ_rand32(state, ZSTD_SEARCHLOG_MIN, 9);
cParams.minMatch = FUZZ_rand32(state, ZSTD_MINMATCH_MIN,
cParams.windowLog = FUZZ_dataProducer_uint32Range(producer, ZSTD_WINDOWLOG_MIN, 15);
cParams.hashLog = FUZZ_dataProducer_uint32Range(producer, ZSTD_HASHLOG_MIN, 15);
cParams.chainLog = FUZZ_dataProducer_uint32Range(producer, ZSTD_CHAINLOG_MIN, 16);
cParams.searchLog = FUZZ_dataProducer_uint32Range(producer, ZSTD_SEARCHLOG_MIN, 9);
cParams.minMatch = FUZZ_dataProducer_uint32Range(producer, ZSTD_MINMATCH_MIN,
ZSTD_MINMATCH_MAX);
cParams.targetLength = FUZZ_rand32(state, 0, 512);
cParams.strategy = FUZZ_rand32(state, ZSTD_STRATEGY_MIN, ZSTD_STRATEGY_MAX);
cParams.targetLength = FUZZ_dataProducer_uint32Range(producer, 0, 512);
cParams.strategy = FUZZ_dataProducer_uint32Range(producer, ZSTD_STRATEGY_MIN, ZSTD_STRATEGY_MAX);
return ZSTD_adjustCParams(cParams, srcSize, 0);
}
ZSTD_frameParameters FUZZ_randomFParams(uint32_t *state)
ZSTD_frameParameters FUZZ_randomFParams(FUZZ_dataProducer_t *producer)
{
/* Select frame parameters */
ZSTD_frameParameters fParams;
fParams.contentSizeFlag = FUZZ_rand32(state, 0, 1);
fParams.checksumFlag = FUZZ_rand32(state, 0, 1);
fParams.noDictIDFlag = FUZZ_rand32(state, 0, 1);
fParams.contentSizeFlag = FUZZ_dataProducer_uint32Range(producer, 0, 1);
fParams.checksumFlag = FUZZ_dataProducer_uint32Range(producer, 0, 1);
fParams.noDictIDFlag = FUZZ_dataProducer_uint32Range(producer, 0, 1);
return fParams;
}
ZSTD_parameters FUZZ_randomParams(size_t srcSize, uint32_t *state)
ZSTD_parameters FUZZ_randomParams(size_t srcSize, FUZZ_dataProducer_t *producer)
{
ZSTD_parameters params;
params.cParams = FUZZ_randomCParams(srcSize, state);
params.fParams = FUZZ_randomFParams(state);
params.cParams = FUZZ_randomCParams(srcSize, producer);
params.fParams = FUZZ_randomFParams(producer);
return params;
}
void FUZZ_setRandomParameters(ZSTD_CCtx *cctx, size_t srcSize, uint32_t *state)
void FUZZ_setRandomParameters(ZSTD_CCtx *cctx, size_t srcSize, FUZZ_dataProducer_t *producer)
{
ZSTD_compressionParameters cParams = FUZZ_randomCParams(srcSize, state);
ZSTD_compressionParameters cParams = FUZZ_randomCParams(srcSize, producer);
set(cctx, ZSTD_c_windowLog, cParams.windowLog);
set(cctx, ZSTD_c_hashLog, cParams.hashLog);
set(cctx, ZSTD_c_chainLog, cParams.chainLog);
@@ -72,27 +75,30 @@ void FUZZ_setRandomParameters(ZSTD_CCtx *cctx, size_t srcSize, uint32_t *state)
set(cctx, ZSTD_c_targetLength, cParams.targetLength);
set(cctx, ZSTD_c_strategy, cParams.strategy);
/* Select frame parameters */
setRand(cctx, ZSTD_c_contentSizeFlag, 0, 1, state);
setRand(cctx, ZSTD_c_checksumFlag, 0, 1, state);
setRand(cctx, ZSTD_c_dictIDFlag, 0, 1, state);
setRand(cctx, ZSTD_c_contentSizeFlag, 0, 1, producer);
setRand(cctx, ZSTD_c_checksumFlag, 0, 1, producer);
setRand(cctx, ZSTD_c_dictIDFlag, 0, 1, producer);
/* Select long distance matching parameters */
setRand(cctx, ZSTD_c_enableLongDistanceMatching, 0, 1, state);
setRand(cctx, ZSTD_c_ldmHashLog, ZSTD_HASHLOG_MIN, 16, state);
setRand(cctx, ZSTD_c_enableLongDistanceMatching, 0, 1, producer);
setRand(cctx, ZSTD_c_ldmHashLog, ZSTD_HASHLOG_MIN, 16, producer);
setRand(cctx, ZSTD_c_ldmMinMatch, ZSTD_LDM_MINMATCH_MIN,
ZSTD_LDM_MINMATCH_MAX, state);
ZSTD_LDM_MINMATCH_MAX, producer);
setRand(cctx, ZSTD_c_ldmBucketSizeLog, 0, ZSTD_LDM_BUCKETSIZELOG_MAX,
state);
producer);
setRand(cctx, ZSTD_c_ldmHashRateLog, ZSTD_LDM_HASHRATELOG_MIN,
ZSTD_LDM_HASHRATELOG_MAX, state);
ZSTD_LDM_HASHRATELOG_MAX, producer);
/* Set misc parameters */
setRand(cctx, ZSTD_c_nbWorkers, 0, 2, state);
setRand(cctx, ZSTD_c_rsyncable, 0, 1, state);
setRand(cctx, ZSTD_c_forceMaxWindow, 0, 1, state);
setRand(cctx, ZSTD_c_literalCompressionMode, 0, 2, state);
setRand(cctx, ZSTD_c_forceAttachDict, 0, 2, state);
setRand(cctx, ZSTD_c_nbWorkers, 0, 2, producer);
setRand(cctx, ZSTD_c_rsyncable, 0, 1, producer);
setRand(cctx, ZSTD_c_forceMaxWindow, 0, 1, producer);
setRand(cctx, ZSTD_c_literalCompressionMode, 0, 2, producer);
setRand(cctx, ZSTD_c_forceAttachDict, 0, 2, producer);
if (FUZZ_dataProducer_uint32Range(producer, 0, 1) == 0) {
setRand(cctx, ZSTD_c_srcSizeHint, ZSTD_SRCSIZEHINT_MIN, 2 * srcSize, producer);
}
}
FUZZ_dict_t FUZZ_train(void const* src, size_t srcSize, uint32_t *state)
FUZZ_dict_t FUZZ_train(void const* src, size_t srcSize, FUZZ_dataProducer_t *producer)
{
size_t const dictSize = MAX(srcSize / 8, 1024);
size_t const totalSampleSize = dictSize * 11;
@@ -107,7 +113,7 @@ FUZZ_dict_t FUZZ_train(void const* src, size_t srcSize, uint32_t *state)
for (sample = 0; sample < nbSamples; ++sample) {
size_t const remaining = totalSampleSize - pos;
size_t const offset = FUZZ_rand32(state, 0, MAX(srcSize, 1) - 1);
size_t const offset = FUZZ_dataProducer_uint32Range(producer, 0, MAX(srcSize, 1) - 1);
size_t const limit = MIN(srcSize - offset, remaining);
size_t const toCopy = MIN(limit, remaining / (nbSamples - sample));
memcpy(samples + pos, src + offset, toCopy);
+9 -6
View File
@@ -17,17 +17,21 @@
#define ZSTD_STATIC_LINKING_ONLY
#include "zstd.h"
#include "fuzz_data_producer.h"
#include <stdint.h>
#ifdef __cplusplus
extern "C" {
#endif
void FUZZ_setRandomParameters(ZSTD_CCtx *cctx, size_t srcSize, uint32_t *state);
extern const int kMinClevel;
extern const int kMaxClevel;
ZSTD_compressionParameters FUZZ_randomCParams(size_t srcSize, uint32_t *state);
ZSTD_frameParameters FUZZ_randomFParams(uint32_t *state);
ZSTD_parameters FUZZ_randomParams(size_t srcSize, uint32_t *state);
void FUZZ_setRandomParameters(ZSTD_CCtx *cctx, size_t srcSize, FUZZ_dataProducer_t *producer);
ZSTD_compressionParameters FUZZ_randomCParams(size_t srcSize, FUZZ_dataProducer_t *producer);
ZSTD_frameParameters FUZZ_randomFParams(FUZZ_dataProducer_t *producer);
ZSTD_parameters FUZZ_randomParams(size_t srcSize, FUZZ_dataProducer_t *producer);
typedef struct {
void* buff;
@@ -38,8 +42,7 @@ typedef struct {
* NOTE: Don't use this to train production dictionaries, it is only optimized
* for speed, and doesn't care about dictionary quality.
*/
FUZZ_dict_t FUZZ_train(void const* src, size_t srcSize, uint32_t *state);
FUZZ_dict_t FUZZ_train(void const* src, size_t srcSize, FUZZ_dataProducer_t *producer);
#ifdef __cplusplus
}
+88 -3
View File
@@ -401,7 +401,7 @@ static int basicUnitTests(U32 const seed, double compressibility)
DISPLAYLEVEL(3, "test%3i : check decompressed result : ", testNb++);
{ size_t u;
for (u=0; u<CNBuffSize; u++) {
if (((BYTE*)decodedBuffer)[u] != ((BYTE*)CNBuffer)[u]) goto _output_error;;
if (((BYTE*)decodedBuffer)[u] != ((BYTE*)CNBuffer)[u]) goto _output_error;
} }
DISPLAYLEVEL(3, "OK \n");
@@ -758,7 +758,7 @@ static int basicUnitTests(U32 const seed, double compressibility)
{ size_t u;
for (u=0; u<CNBuffSize; u++) {
if (((BYTE*)decodedBuffer)[u] != ((BYTE*)CNBuffer)[u])
goto _output_error;;
goto _output_error;
} }
DISPLAYLEVEL(3, "OK \n");
@@ -839,7 +839,7 @@ static int basicUnitTests(U32 const seed, double compressibility)
DISPLAYLEVEL(3, "test%3i : check decompressed result : ", testNb++);
{ size_t u;
for (u=0; u<CNBuffSize; u++) {
if (((BYTE*)decodedBuffer)[u] != ((BYTE*)CNBuffer)[u]) goto _output_error;;
if (((BYTE*)decodedBuffer)[u] != ((BYTE*)CNBuffer)[u]) goto _output_error;
} }
DISPLAYLEVEL(3, "OK \n");
@@ -1965,6 +1965,18 @@ static int basicUnitTests(U32 const seed, double compressibility)
assert(ZSTD_getSequences(ZSTD_createCCtx(), compressedBuffer, 1000000,
CNBuffer, 1000000) == 1000000 / 131071 + 1);
/* Multiple blocks of zeros test */
#define LONGZEROSLENGTH 1000000 /* 1MB of zeros */
DISPLAYLEVEL(3, "test%3i : compress %u zeroes : ", testNb++, LONGZEROSLENGTH);
memset(CNBuffer, 0, LONGZEROSLENGTH);
CHECK_VAR(cSize, ZSTD_compress(compressedBuffer, ZSTD_compressBound(LONGZEROSLENGTH), CNBuffer, LONGZEROSLENGTH, 1) );
DISPLAYLEVEL(3, "OK (%u bytes : %.2f%%)\n", (unsigned)cSize, (double)cSize/LONGZEROSLENGTH*100);
DISPLAYLEVEL(3, "test%3i : decompress %u zeroes : ", testNb++, LONGZEROSLENGTH);
{ CHECK_NEWV(r, ZSTD_decompress(decodedBuffer, LONGZEROSLENGTH, compressedBuffer, cSize) );
if (r != LONGZEROSLENGTH) goto _output_error; }
DISPLAYLEVEL(3, "OK \n");
/* All zeroes test (test bug #137) */
#define ZEROESLENGTH 100
DISPLAYLEVEL(3, "test%3i : compress %u zeroes : ", testNb++, ZEROESLENGTH);
@@ -2142,6 +2154,79 @@ static int basicUnitTests(U32 const seed, double compressibility)
}
DISPLAYLEVEL(3, "OK \n");
DISPLAYLEVEL(3, "test%3i : table cleanliness through index reduction : ", testNb++);
{
int cLevel;
size_t approxIndex = 0;
size_t maxIndex = ((3U << 29) + (1U << ZSTD_WINDOWLOG_MAX)); /* ZSTD_CURRENT_MAX from zstd_compress_internal.h */
/* vastly overprovision space in a static context so that we can do all
* this without ever reallocating, which would reset the indices */
size_t const staticCCtxSize = 2 * ZSTD_estimateCCtxSize(22);
void* const staticCCtxBuffer = malloc(staticCCtxSize);
ZSTD_CCtx* cctx = ZSTD_initStaticCCtx(staticCCtxBuffer, staticCCtxSize);
/* bump the indices so the following compressions happen at high
* indices. */
{
ZSTD_outBuffer out = { compressedBuffer, compressedBufferSize, 0 };
ZSTD_inBuffer in = { CNBuffer, CNBuffSize, 0 };
ZSTD_CCtx_reset(cctx, ZSTD_reset_session_and_parameters);
CHECK_Z(ZSTD_CCtx_setParameter(cctx, ZSTD_c_compressionLevel, -500));
while (approxIndex <= (maxIndex / 4) * 3) {
CHECK_Z(ZSTD_compressStream2(cctx, &out, &in, ZSTD_e_flush));
approxIndex += in.pos;
CHECK(in.pos == in.size);
in.pos = 0;
out.pos = 0;
}
CHECK_Z(ZSTD_compressStream2(cctx, &out, &in, ZSTD_e_end));
}
/* spew a bunch of stuff into the table area */
for (cLevel = 1; cLevel <= 22; cLevel++) {
ZSTD_outBuffer out = { compressedBuffer, compressedBufferSize / cLevel, 0 };
ZSTD_inBuffer in = { CNBuffer, CNBuffSize, 0 };
ZSTD_CCtx_reset(cctx, ZSTD_reset_session_and_parameters);
CHECK_Z(ZSTD_CCtx_setParameter(cctx, ZSTD_c_compressionLevel, cLevel));
CHECK_Z(ZSTD_compressStream2(cctx, &out, &in, ZSTD_e_flush));
CHECK_Z(ZSTD_compressStream2(cctx, &out, &in, ZSTD_e_end));
approxIndex += in.pos;
}
/* now crank the indices so we overflow */
{
ZSTD_outBuffer out = { compressedBuffer, compressedBufferSize, 0 };
ZSTD_inBuffer in = { CNBuffer, CNBuffSize, 0 };
ZSTD_CCtx_reset(cctx, ZSTD_reset_session_and_parameters);
CHECK_Z(ZSTD_CCtx_setParameter(cctx, ZSTD_c_compressionLevel, -500));
while (approxIndex <= maxIndex) {
CHECK_Z(ZSTD_compressStream2(cctx, &out, &in, ZSTD_e_flush));
approxIndex += in.pos;
CHECK(in.pos == in.size);
in.pos = 0;
out.pos = 0;
}
CHECK_Z(ZSTD_compressStream2(cctx, &out, &in, ZSTD_e_end));
}
/* do a bunch of compressions again in low indices and ensure we don't
* hit untracked invalid indices */
for (cLevel = 1; cLevel <= 22; cLevel++) {
ZSTD_outBuffer out = { compressedBuffer, compressedBufferSize / cLevel, 0 };
ZSTD_inBuffer in = { CNBuffer, CNBuffSize, 0 };
ZSTD_CCtx_reset(cctx, ZSTD_reset_session_and_parameters);
CHECK_Z(ZSTD_CCtx_setParameter(cctx, ZSTD_c_compressionLevel, cLevel));
CHECK_Z(ZSTD_compressStream2(cctx, &out, &in, ZSTD_e_flush));
CHECK_Z(ZSTD_compressStream2(cctx, &out, &in, ZSTD_e_end));
approxIndex += in.pos;
}
ZSTD_freeCCtx(cctx);
free(staticCCtxBuffer);
}
DISPLAYLEVEL(3, "OK \n");
_end:
free(CNBuffer);
free(compressedBuffer);
Binary file not shown.
+63 -3
View File
@@ -108,7 +108,6 @@ else
fi
println "\n===> simple tests "
./datagen > tmp
@@ -242,6 +241,11 @@ $ZSTD -f tmp && die "attempt to compress a non existing file"
test -f tmp.zst # destination file should still be present
rm tmp*
println "\n===> decompression only tests "
head -c 1048576 /dev/zero > tmp
$ZSTD -d -o tmp1 "$TESTDIR/golden-decompression/rle-first-block.zst"
$DIFF -s tmp1 tmp
rm tmp*
println "test : compress multiple files"
println hello > tmp1
@@ -409,6 +413,53 @@ println "compress multiple files including a missing one (notHere) : "
$ZSTD -f tmp1 notHere tmp2 && die "missing file not detected!"
println "\n===> stream-size mode"
./datagen -g11000 > tmp
println "test : basic file compression vs sized streaming compression"
file_size=$($ZSTD -14 -f tmp -o tmp.zst && wc -c < tmp.zst)
stream_size=$(cat tmp | $ZSTD -14 --stream-size=11000 | wc -c)
if [ "$stream_size" -gt "$file_size" ]; then
die "hinted compression larger than expected"
fi
println "test : sized streaming compression and decompression"
cat tmp | $ZSTD -14 -f tmp -o --stream-size=11000 tmp.zst
$ZSTD -df tmp.zst -o tmp_decompress
cmp tmp tmp_decompress || die "difference between original and decompressed file"
println "test : incorrect stream size"
cat tmp | $ZSTD -14 -f -o tmp.zst --stream-size=11001 && die "should fail with incorrect stream size"
println "\n===> size-hint mode"
./datagen -g11000 > tmp
./datagen -g11000 > tmp2
./datagen > tmpDict
println "test : basic file compression vs hinted streaming compression"
file_size=$($ZSTD -14 -f tmp -o tmp.zst && wc -c < tmp.zst)
stream_size=$(cat tmp | $ZSTD -14 --size-hint=11000 | wc -c)
if [ "$stream_size" -ge "$file_size" ]; then
die "hinted compression larger than expected"
fi
println "test : hinted streaming compression and decompression"
cat tmp | $ZSTD -14 -f -o tmp.zst --size-hint=11000
$ZSTD -df tmp.zst -o tmp_decompress
cmp tmp tmp_decompress || die "difference between original and decompressed file"
println "test : hinted streaming compression with dictionary"
cat tmp | $ZSTD -14 -f -D tmpDict --size-hint=11000 | $ZSTD -t -D tmpDict
println "test : multiple file compression with hints and dictionary"
$ZSTD -14 -f -D tmpDict --size-hint=11000 tmp tmp2
$ZSTD -14 -f -o tmp1_.zst -D tmpDict --size-hint=11000 tmp
$ZSTD -14 -f -o tmp2_.zst -D tmpDict --size-hint=11000 tmp2
cmp tmp.zst tmp1_.zst || die "first file's output differs"
cmp tmp2.zst tmp2_.zst || die "second file's output differs"
println "test : incorrect hinted stream sizes"
cat tmp | $ZSTD -14 -f --size-hint=11050 | $ZSTD -t # slightly too high
cat tmp | $ZSTD -14 -f --size-hint=10950 | $ZSTD -t # slightly too low
cat tmp | $ZSTD -14 -f --size-hint=22000 | $ZSTD -t # considerably too high
cat tmp | $ZSTD -14 -f --size-hint=5500 | $ZSTD -t # considerably too low
println "\n===> dictionary tests "
println "- test with raw dict (content only) "
@@ -480,6 +531,15 @@ $ZSTD -o tmpDict --train "$TESTDIR"/*.c "$PRGDIR"/*.c
test -f tmpDict
$ZSTD --train "$TESTDIR"/*.c "$PRGDIR"/*.c
test -f dictionary
println "- Test dictionary training fails"
echo "000000000000000000000000000000000" > tmpz
$ZSTD --train tmpz tmpz tmpz tmpz tmpz tmpz tmpz tmpz tmpz && die "Dictionary training should fail : source is all zeros"
if [ -n "$hasMT" ]
then
$ZSTD --train -T0 tmpz tmpz tmpz tmpz tmpz tmpz tmpz tmpz tmpz && die "Dictionary training should fail : source is all zeros"
println "- Create dictionary with multithreading enabled"
$ZSTD --train -T0 "$TESTDIR"/*.c "$PRGDIR"/*.c -o tmpDict
fi
rm tmp* dictionary
@@ -583,8 +643,8 @@ $ZSTD -t tmpSplit.* && die "bad file not detected !"
println "\n===> golden files tests "
$ZSTD -t -r "$TESTDIR/files"
$ZSTD -c -r "$TESTDIR/files" | $ZSTD -t
$ZSTD -t -r "$TESTDIR/golden-compression"
$ZSTD -c -r "$TESTDIR/golden-compression" | $ZSTD -t
println "\n===> benchmark mode tests "
+9 -9
View File
@@ -33,7 +33,7 @@ silesia, level 19, compress
silesia, long distance mode, compress cctx, 4849491
silesia, multithreaded, compress cctx, 4849491
silesia, multithreaded long distance mode, compress cctx, 4849491
silesia, small window log, compress cctx, 7112784
silesia, small window log, compress cctx, 7112472
silesia, small hash log, compress cctx, 6554898
silesia, small chain log, compress cctx, 4931093
silesia, explicit params, compress cctx, 4794609
@@ -97,7 +97,7 @@ silesia, level 19, zstdcli,
silesia, long distance mode, zstdcli, 4839698
silesia, multithreaded, zstdcli, 4849539
silesia, multithreaded long distance mode, zstdcli, 4839698
silesia, small window log, zstdcli, 7123892
silesia, small window log, zstdcli, 7123580
silesia, small hash log, zstdcli, 6554946
silesia, small chain log, zstdcli, 4931141
silesia, explicit params, zstdcli, 4797048
@@ -123,7 +123,7 @@ silesia.tar, no source size, zstdcli,
silesia.tar, long distance mode, zstdcli, 4853140
silesia.tar, multithreaded, zstdcli, 4861462
silesia.tar, multithreaded long distance mode, zstdcli, 4853140
silesia.tar, small window log, zstdcli, 7127964
silesia.tar, small window log, zstdcli, 7127589
silesia.tar, small hash log, zstdcli, 6587841
silesia.tar, small chain log, zstdcli, 4943269
silesia.tar, explicit params, zstdcli, 4822318
@@ -188,7 +188,7 @@ silesia, no source size, advanced
silesia, long distance mode, advanced one pass, 4839650
silesia, multithreaded, advanced one pass, 4849491
silesia, multithreaded long distance mode, advanced one pass, 4839650
silesia, small window log, advanced one pass, 7123844
silesia, small window log, advanced one pass, 7123532
silesia, small hash log, advanced one pass, 6554898
silesia, small chain log, advanced one pass, 4931093
silesia, explicit params, advanced one pass, 4797035
@@ -214,7 +214,7 @@ silesia.tar, no source size, advanced
silesia.tar, long distance mode, advanced one pass, 4848046
silesia.tar, multithreaded, advanced one pass, 4860726
silesia.tar, multithreaded long distance mode, advanced one pass, 4847343
silesia.tar, small window log, advanced one pass, 7127924
silesia.tar, small window log, advanced one pass, 7127549
silesia.tar, small hash log, advanced one pass, 6587833
silesia.tar, small chain log, advanced one pass, 4943266
silesia.tar, explicit params, advanced one pass, 4808543
@@ -280,7 +280,7 @@ silesia, no source size, advanced
silesia, long distance mode, advanced one pass small out, 4839650
silesia, multithreaded, advanced one pass small out, 4849491
silesia, multithreaded long distance mode, advanced one pass small out, 4839650
silesia, small window log, advanced one pass small out, 7123844
silesia, small window log, advanced one pass small out, 7123532
silesia, small hash log, advanced one pass small out, 6554898
silesia, small chain log, advanced one pass small out, 4931093
silesia, explicit params, advanced one pass small out, 4797035
@@ -306,7 +306,7 @@ silesia.tar, no source size, advanced
silesia.tar, long distance mode, advanced one pass small out, 4848046
silesia.tar, multithreaded, advanced one pass small out, 4860726
silesia.tar, multithreaded long distance mode, advanced one pass small out, 4847343
silesia.tar, small window log, advanced one pass small out, 7127924
silesia.tar, small window log, advanced one pass small out, 7127549
silesia.tar, small hash log, advanced one pass small out, 6587833
silesia.tar, small chain log, advanced one pass small out, 4943266
silesia.tar, explicit params, advanced one pass small out, 4808543
@@ -372,7 +372,7 @@ silesia, no source size, advanced
silesia, long distance mode, advanced streaming, 4839650
silesia, multithreaded, advanced streaming, 4849491
silesia, multithreaded long distance mode, advanced streaming, 4839650
silesia, small window log, advanced streaming, 7123846
silesia, small window log, advanced streaming, 7123534
silesia, small hash log, advanced streaming, 6554898
silesia, small chain log, advanced streaming, 4931093
silesia, explicit params, advanced streaming, 4797048
@@ -398,7 +398,7 @@ silesia.tar, no source size, advanced
silesia.tar, long distance mode, advanced streaming, 4848046
silesia.tar, multithreaded, advanced streaming, 4861458
silesia.tar, multithreaded long distance mode, advanced streaming, 4853136
silesia.tar, small window log, advanced streaming, 7127924
silesia.tar, small window log, advanced streaming, 7127549
silesia.tar, small hash log, advanced streaming, 6587834
silesia.tar, small chain log, advanced streaming, 4943271
silesia.tar, explicit params, advanced streaming, 4808570
1 Data Config Method Total compressed size
33 silesia long distance mode compress cctx 4849491
34 silesia multithreaded compress cctx 4849491
35 silesia multithreaded long distance mode compress cctx 4849491
36 silesia small window log compress cctx 7112784 7112472
37 silesia small hash log compress cctx 6554898
38 silesia small chain log compress cctx 4931093
39 silesia explicit params compress cctx 4794609
97 silesia long distance mode zstdcli 4839698
98 silesia multithreaded zstdcli 4849539
99 silesia multithreaded long distance mode zstdcli 4839698
100 silesia small window log zstdcli 7123892 7123580
101 silesia small hash log zstdcli 6554946
102 silesia small chain log zstdcli 4931141
103 silesia explicit params zstdcli 4797048
123 silesia.tar long distance mode zstdcli 4853140
124 silesia.tar multithreaded zstdcli 4861462
125 silesia.tar multithreaded long distance mode zstdcli 4853140
126 silesia.tar small window log zstdcli 7127964 7127589
127 silesia.tar small hash log zstdcli 6587841
128 silesia.tar small chain log zstdcli 4943269
129 silesia.tar explicit params zstdcli 4822318
188 silesia long distance mode advanced one pass 4839650
189 silesia multithreaded advanced one pass 4849491
190 silesia multithreaded long distance mode advanced one pass 4839650
191 silesia small window log advanced one pass 7123844 7123532
192 silesia small hash log advanced one pass 6554898
193 silesia small chain log advanced one pass 4931093
194 silesia explicit params advanced one pass 4797035
214 silesia.tar long distance mode advanced one pass 4848046
215 silesia.tar multithreaded advanced one pass 4860726
216 silesia.tar multithreaded long distance mode advanced one pass 4847343
217 silesia.tar small window log advanced one pass 7127924 7127549
218 silesia.tar small hash log advanced one pass 6587833
219 silesia.tar small chain log advanced one pass 4943266
220 silesia.tar explicit params advanced one pass 4808543
280 silesia long distance mode advanced one pass small out 4839650
281 silesia multithreaded advanced one pass small out 4849491
282 silesia multithreaded long distance mode advanced one pass small out 4839650
283 silesia small window log advanced one pass small out 7123844 7123532
284 silesia small hash log advanced one pass small out 6554898
285 silesia small chain log advanced one pass small out 4931093
286 silesia explicit params advanced one pass small out 4797035
306 silesia.tar long distance mode advanced one pass small out 4848046
307 silesia.tar multithreaded advanced one pass small out 4860726
308 silesia.tar multithreaded long distance mode advanced one pass small out 4847343
309 silesia.tar small window log advanced one pass small out 7127924 7127549
310 silesia.tar small hash log advanced one pass small out 6587833
311 silesia.tar small chain log advanced one pass small out 4943266
312 silesia.tar explicit params advanced one pass small out 4808543
372 silesia long distance mode advanced streaming 4839650
373 silesia multithreaded advanced streaming 4849491
374 silesia multithreaded long distance mode advanced streaming 4839650
375 silesia small window log advanced streaming 7123846 7123534
376 silesia small hash log advanced streaming 6554898
377 silesia small chain log advanced streaming 4931093
378 silesia explicit params advanced streaming 4797048
398 silesia.tar long distance mode advanced streaming 4848046
399 silesia.tar multithreaded advanced streaming 4861458
400 silesia.tar multithreaded long distance mode advanced streaming 4853136
401 silesia.tar small window log advanced streaming 7127924 7127549
402 silesia.tar small hash log advanced streaming 6587834
403 silesia.tar small chain log advanced streaming 4943271
404 silesia.tar explicit params advanced streaming 4808570
+2 -2
View File
@@ -184,7 +184,7 @@ static int basicUnitTests(U32 seed, double compressibility, ZSTD_customMem custo
DISPLAYLEVEL(4, "test%3i : check decompressed result : ", testNb++);
{ size_t i;
for (i=0; i<CNBufferSize; i++) {
if (((BYTE*)decodedBuffer)[i] != ((BYTE*)CNBuffer)[i]) goto _output_error;;
if (((BYTE*)decodedBuffer)[i] != ((BYTE*)CNBuffer)[i]) goto _output_error;
} }
DISPLAYLEVEL(4, "OK \n");
@@ -213,7 +213,7 @@ static int basicUnitTests(U32 seed, double compressibility, ZSTD_customMem custo
DISPLAYLEVEL(4, "test%3i : check decompressed result : ", testNb++);
{ size_t i;
for (i=0; i<CNBufferSize; i++) {
if (((BYTE*)decodedBuffer)[i] != ((BYTE*)CNBuffer)[i]) goto _output_error;;
if (((BYTE*)decodedBuffer)[i] != ((BYTE*)CNBuffer)[i]) goto _output_error;
} }
DISPLAYLEVEL(4, "OK \n");
+2 -1
View File
@@ -481,7 +481,7 @@ static int basicUnitTests(U32 seed, double compressibility)
DISPLAYLEVEL(3, "test%3i : check decompressed result : ", testNb++);
{ size_t i;
for (i=0; i<CNBufferSize; i++) {
if (((BYTE*)decodedBuffer)[i] != ((BYTE*)CNBuffer)[i]) goto _output_error;;
if (((BYTE*)decodedBuffer)[i] != ((BYTE*)CNBuffer)[i]) goto _output_error;
} }
DISPLAYLEVEL(3, "OK \n");
@@ -2106,6 +2106,7 @@ static int fuzzerTests_newAPI(U32 seed, int nbTests, int startTest,
if (FUZ_rand(&lseed) & 3) CHECK_Z( setCCtxParameter(zc, cctxParams, ZSTD_c_ldmMinMatch, FUZ_randomClampedLength(&lseed, ZSTD_LDM_MINMATCH_MIN, ZSTD_LDM_MINMATCH_MAX), opaqueAPI) );
if (FUZ_rand(&lseed) & 3) CHECK_Z( setCCtxParameter(zc, cctxParams, ZSTD_c_ldmBucketSizeLog, FUZ_randomClampedLength(&lseed, ZSTD_LDM_BUCKETSIZELOG_MIN, ZSTD_LDM_BUCKETSIZELOG_MAX), opaqueAPI) );
if (FUZ_rand(&lseed) & 3) CHECK_Z( setCCtxParameter(zc, cctxParams, ZSTD_c_ldmHashRateLog, FUZ_randomClampedLength(&lseed, ZSTD_LDM_HASHRATELOG_MIN, ZSTD_LDM_HASHRATELOG_MAX), opaqueAPI) );
if (FUZ_rand(&lseed) & 3) CHECK_Z( setCCtxParameter(zc, cctxParams, ZSTD_c_srcSizeHint, FUZ_randomClampedLength(&lseed, ZSTD_SRCSIZEHINT_MIN, ZSTD_SRCSIZEHINT_MAX), opaqueAPI) );
}
/* mess with frame parameters */