Search code examples
clangfuzzinglibfuzzer

How to use libfuzzers custom mutators API?


Libfuzzer offers two APIs to develop custom mutators.

size_t LLVMFuzzerCustomMutator(uint8_t *Data, size_t Size, size_t MaxSize, unsigned int Seed)
size_t LLVMFuzzerCustomCrossOver(const uint8_t *Data1, size_t Size1, const uint8_t *Data2, size_t Size2, uint8_t *Out, size_t MaxOutSize, unsigned int Seed)

How are these APIs supposed to be used? The fuzzer is required to be deterministic. How do I ensure that with the custom mutators?


Solution

  • You just need to implement those functions alongside your LLVMFuzzerTestOneInput.

    The google/fuzzing repository has a tutorial on how to implement structure-aware fuzzing.

    Also, you could take inspiration from CustomMutatorTest.cpp, and CustomCrossOverTest.cpp, from the LLVM repository.

    The fuzzer is required to be deterministic.

    Right, but here you will be writing the mutation functions, which are different; Mutations will happen before your LLVMFuzzerTestOneInput is called.

    However, they have an analogous requirement. As outlined in the source code, alongside LLVMFuzzerCustomMutator, and LLVMFuzzerCustomCrossOver respectively:

    Optional user-provided custom mutator. Mutates raw data in [Data, Data+Size) inplace. Returns the new size, which is not greater than MaxSize. Given the same Seed produces the same mutation.

    Optional user-provided custom cross-over function. Combines pieces of Data1 & Data2 together into Out. Returns the new size, which is not greater than MaxOutSize. Should produce the same mutation given the same Seed.

    i.e. Two calls to a mutation function with the same Data and seed should produce the same result.

    One last thing: you don't need to implement both functions; LLVMFuzzerCustomMutator should be enough in most cases.