fuzz: Add support for custom crossover functions

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>
Message-Id: <20201023150746.107063-8-alxndr@bu.edu>
Signed-off-by: Thomas Huth <thuth@redhat.com>
This commit is contained in:
Alexander Bulekov 2020-10-23 11:07:36 -04:00 committed by Thomas Huth
parent a3c20e91de
commit f81cb729be
2 changed files with 40 additions and 0 deletions

View File

@ -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 */ /* Executed for each fuzzing-input */
int LLVMFuzzerTestOneInput(const unsigned char *Data, size_t Size) int LLVMFuzzerTestOneInput(const unsigned char *Data, size_t Size)
{ {

View File

@ -77,6 +77,29 @@ typedef struct FuzzTarget {
*/ */
void(*fuzz)(QTestState *, const unsigned char *, size_t); 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; } FuzzTarget;
void flush_events(QTestState *); void flush_events(QTestState *);
@ -91,6 +114,10 @@ void fuzz_qtest_set_serialize(bool option);
*/ */
void fuzz_add_target(const FuzzTarget *target); 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 LLVMFuzzerTestOneInput(const unsigned char *Data, size_t Size);
int LLVMFuzzerInitialize(int *argc, char ***argv, char ***envp); int LLVMFuzzerInitialize(int *argc, char ***argv, char ***envp);