Message ID | 20200819061110.1320568-8-alxndr@bu.edu |
---|---|
State | Superseded |
Headers | show |
Series | None | expand |
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 <alxndr@bu.edu> Reviewed-by: Darren Kenny <darren.kenny@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
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);
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 <alxndr@bu.edu> --- tests/qtest/fuzz/fuzz.c | 13 +++++++++++++ tests/qtest/fuzz/fuzz.h | 26 ++++++++++++++++++++++++++ 2 files changed, 39 insertions(+)