diff --git a/README.md b/README.md index 6f6c481..3bfe372 100644 --- a/README.md +++ b/README.md @@ -113,6 +113,8 @@ The following command line arguments are supported: `-deterministic_only` - Prioritize deterministic mutations. Note: even with this flag, the fuzzer is still going to use nondeterministic mutations, but only after all deterministic mutations have been exhausted. It might be useful when running with a `-server` to have a single clinent instance perform deterministic mutations. +`-max_sample_size` - The maximum sample size to use. All input samples larger than `max_sample_size` get trimmed and mutators can't produce new samples which exceed that sie. Defaults to 1000000. Warning: When using shared memory sample delivery, `max_sample_size` must match the maximum sample size expected by the target, e.g. like in the test target [here](https://github.com/googleprojectzero/Jackalope/blob/3301a9ac6c6f1483f2d565d372015302e85e6ae2/test.cpp#L33). + `-keep_samples_in_memory` - Whether to always keep all samples in memory. Defaults to true. Recommended unless the corpus is too large to fit in memory. `-track_ranges` - Enable the read range tracking feature. More information [here](https://github.com/googleprojectzero/Jackalope/blob/main/README_ranges.md). diff --git a/fuzzer.cpp b/fuzzer.cpp index 746a2f0..3569a99 100644 --- a/fuzzer.cpp +++ b/fuzzer.cpp @@ -105,6 +105,8 @@ void Fuzzer::ParseOptions(int argc, char **argv) { keep_samples_in_memory = GetBinaryOption("-keep_samples_in_memory", argc, argv, true); track_ranges = GetBinaryOption("-track_ranges", argc, argv, false); + + Sample::max_size = (size_t)GetIntOption("-max_sample_size", argc, argv, DEFAULT_MAX_SAMPLE_SIZE); } void Fuzzer::SetupDirectories() { @@ -613,9 +615,9 @@ void Fuzzer::SynchronizeAndGetJob(ThreadContext* tc, FuzzerJob* job) { printf("Running input sample %s\n", filename.c_str()); job->sample = new Sample(); job->sample->Load(filename.c_str()); - if (job->sample->size > MAX_SAMPLE_SIZE) { + if (job->sample->size > Sample::max_size) { WARN("Input sample larger than maximum sample size. Will be trimmed"); - job->sample->Trim(MAX_SAMPLE_SIZE); + job->sample->Trim(Sample::max_size); } samples_pending++; } @@ -678,7 +680,7 @@ void Fuzzer::FuzzJob(ThreadContext* tc, FuzzerJob* job) { while (1) { Sample mutated_sample = *entry->sample; if (!tc->mutator->Mutate(&mutated_sample, tc->prng, tc->all_samples_local)) break; - if (mutated_sample.size > MAX_SAMPLE_SIZE) { + if (mutated_sample.size > Sample::max_size) { continue; } @@ -925,7 +927,7 @@ SampleDelivery *Fuzzer::CreateSampleDelivery(int argc, char **argv, ThreadContex #endif ReplaceTargetCmdArg(tc, "@@", shm_name.c_str()); - SHMSampleDelivery* sampleDelivery = new SHMSampleDelivery((char*)shm_name.c_str(), MAX_SAMPLE_SIZE + 4); + SHMSampleDelivery* sampleDelivery = new SHMSampleDelivery((char*)shm_name.c_str(), Sample::max_size + 4); sampleDelivery->Init(argc, argv); return sampleDelivery; } else { diff --git a/mutator.cpp b/mutator.cpp index 5773db5..47567a5 100644 --- a/mutator.cpp +++ b/mutator.cpp @@ -95,10 +95,10 @@ bool BlockFlipMutator::Mutate(Sample *inout_sample, PRNG *prng, std::vector &all_samples) { // printf("In AppendMutator::Mutate\n"); size_t old_size = inout_sample->size; - if (old_size >= MAX_SAMPLE_SIZE) return true; + if (old_size >= Sample::max_size) return true; size_t append = prng->Rand(min_append, max_append); - if ((old_size + append) > MAX_SAMPLE_SIZE) { - append = MAX_SAMPLE_SIZE - old_size; + if ((old_size + append) > Sample::max_size) { + append = Sample::max_size - old_size; } if (append <= 0) return true; size_t new_size = old_size + append; @@ -114,10 +114,10 @@ bool AppendMutator::Mutate(Sample *inout_sample, PRNG *prng, std::vector &all_samples) { // printf("In BlockInsertMutator::Mutate\n"); size_t old_size = inout_sample->size; - if (old_size >= MAX_SAMPLE_SIZE) return true; + if (old_size >= Sample::max_size) return true; size_t to_insert = prng->Rand(min_insert, max_insert); - if ((old_size + to_insert) > MAX_SAMPLE_SIZE) { - to_insert = MAX_SAMPLE_SIZE - old_size; + if ((old_size + to_insert) > Sample::max_size) { + to_insert = Sample::max_size - old_size; } size_t where = prng->Rand(0, (int)old_size); size_t new_size = old_size + to_insert; @@ -141,12 +141,12 @@ bool BlockInsertMutator::Mutate(Sample *inout_sample, PRNG *prng, std::vector &all_samples) { // printf("In BlockDuplicateMutator::Mutate\n"); - if (inout_sample->size >= MAX_SAMPLE_SIZE) return true; + if (inout_sample->size >= Sample::max_size) return true; size_t blockpos, blocksize; if (!GetRandBlock(inout_sample->size, min_block_size, max_block_size, &blockpos, &blocksize, prng)) return true; int64_t blockcount = prng->Rand(min_duplicate_cnt, max_duplicate_cnt); - if ((inout_sample->size + blockcount * blocksize) > MAX_SAMPLE_SIZE) - blockcount = (MAX_SAMPLE_SIZE - (int64_t)inout_sample->size) / blocksize; + if ((inout_sample->size + blockcount * blocksize) > Sample::max_size) + blockcount = (Sample::max_size - (int64_t)inout_sample->size) / blocksize; if (blockcount <= 0) return true; char *newbytes; newbytes = (char *)malloc(inout_sample->size + blockcount * blocksize); @@ -260,7 +260,7 @@ bool SpliceMutator::Mutate(Sample *inout_sample, PRNG *prng, std::vectorbytes); inout_sample->bytes = new_bytes; inout_sample->size = new_sample_size; - if (inout_sample->size > MAX_SAMPLE_SIZE) inout_sample->Trim(MAX_SAMPLE_SIZE); + if (inout_sample->size > Sample::max_size) inout_sample->Trim(Sample::max_size); return true; } } else if(points != 2) { @@ -280,9 +280,9 @@ bool SpliceMutator::Mutate(Sample *inout_sample, PRNG *prng, std::vectorbytes, blockstart1); memcpy(new_bytes + blockstart1, other_sample->bytes + blockstart2, blocksize2); memcpy(new_bytes + blockstart1 + blocksize2, inout_sample->bytes + blockstart3, blocksize3); - if(new_sample_size > MAX_SAMPLE_SIZE) { - new_sample_size = MAX_SAMPLE_SIZE; - new_bytes = (char *)realloc(new_bytes, MAX_SAMPLE_SIZE); + if(new_sample_size > Sample::max_size) { + new_sample_size = Sample::max_size; + new_bytes = (char *)realloc(new_bytes, Sample::max_size); } free(inout_sample->bytes); inout_sample->bytes = new_bytes; diff --git a/sample.cpp b/sample.cpp index 6d478fd..3e400d9 100644 --- a/sample.cpp +++ b/sample.cpp @@ -23,6 +23,8 @@ limitations under the License. #include "sample.h" #include "mutex.h" +size_t Sample::max_size = DEFAULT_MAX_SAMPLE_SIZE; + Sample::Sample() { size = 0; bytes = NULL; diff --git a/sample.h b/sample.h index 54e1e30..ae2863c 100644 --- a/sample.h +++ b/sample.h @@ -22,7 +22,7 @@ limitations under the License. #include "mutex.h" -#define MAX_SAMPLE_SIZE 1000000 +#define DEFAULT_MAX_SAMPLE_SIZE 1000000 class Sample { public: @@ -61,6 +61,8 @@ class Sample { void Crop(size_t from, size_t to, Sample* out); size_t FindFirstDiff(Sample &other); + + static size_t max_size; }; // a Trie-like structure whose purpose is to be able to