On Wednesday, 2020-08-19 at 02:11:02 -04, Alexander Bulekov wrote: > libfuzzer supports a "custom crossover function". Libfuzzer often tries > to blend two inputs to create a new interesting input. Sometimes, we > have a better idea about how to blend inputs together. This change > allows fuzzers to specify a custom function for blending two inputs > together. > > Signed-off-by: Alexander Bulekov <alx...@bu.edu>
Reviewed-by: Darren Kenny <darren.ke...@oracle.com> > --- > tests/qtest/fuzz/fuzz.c | 13 +++++++++++++ > tests/qtest/fuzz/fuzz.h | 26 ++++++++++++++++++++++++++ > 2 files changed, 39 insertions(+) > > diff --git a/tests/qtest/fuzz/fuzz.c b/tests/qtest/fuzz/fuzz.c > index 8234b68754..248fab5f37 100644 > --- a/tests/qtest/fuzz/fuzz.c > +++ b/tests/qtest/fuzz/fuzz.c > @@ -118,6 +118,19 @@ static FuzzTarget *fuzz_get_target(char* name) > } > > > +/* Sometimes called by libfuzzer to mutate two inputs into one */ > +size_t LLVMFuzzerCustomCrossOver(const uint8_t *data1, size_t size1, > + const uint8_t *data2, size_t size2, > + uint8_t *out, size_t max_out_size, > + unsigned int seed) > +{ > + if(fuzz_target->crossover) { > + return fuzz_target->crossover(data1, size1, data2, size2, out, > + max_out_size, seed); > + } > + return 0; > +} > + > /* Executed for each fuzzing-input */ > int LLVMFuzzerTestOneInput(const unsigned char *Data, size_t Size) > { > diff --git a/tests/qtest/fuzz/fuzz.h b/tests/qtest/fuzz/fuzz.h > index 9ca3d107c5..d36642b5ec 100644 > --- a/tests/qtest/fuzz/fuzz.h > +++ b/tests/qtest/fuzz/fuzz.h > @@ -77,6 +77,28 @@ typedef struct FuzzTarget { > */ > void(*fuzz)(QTestState *, const unsigned char *, size_t); > > + /* > + * The fuzzer can specify a "Custom Crossover" function for combining two > + * inputs from the corpus. This function is sometimes called by libfuzzer > + * when mutating inputs. > + * > + * data1: location of first input > + * size1: length of first input > + * data1: location of second input > + * size1: length of second input > + * out: where to place the resulting, mutated input > + * max_out_size: the maximum length of the input that can be placed in > out > + * seed: the seed that should be used to make mutations deterministic, > when needed > + * > + * See libfuzzer's LLVMFuzzerCustomCrossOver API for more info. > + * > + * Can be NULL > + */ > + size_t(*crossover)(const uint8_t *data1, size_t size1, > + const uint8_t *data2, size_t size2, > + uint8_t *out, size_t max_out_size, > + unsigned int seed); > + > } FuzzTarget; > > void flush_events(QTestState *); > @@ -91,6 +113,10 @@ void fuzz_qtest_set_serialize(bool option); > */ > void fuzz_add_target(const FuzzTarget *target); > > +size_t LLVMFuzzerCustomCrossOver(const uint8_t *data1, size_t size1, > + const uint8_t *data2, size_t size2, > + uint8_t *out, size_t max_out_size, > + unsigned int seed); > int LLVMFuzzerTestOneInput(const unsigned char *Data, size_t Size); > int LLVMFuzzerInitialize(int *argc, char ***argv, char ***envp); > > -- > 2.27.0