Clone this repo:

Branches

  1. f3383a9 Update assert by Vitaly Buka · 6 weeks ago master
  2. b2c4fb5 Mutate message when we create new one. by Vitaly Buka · 6 weeks ago
  3. 242a20f Don't check for memory leaks in fuzzer tests. by Vitaly Buka · 6 weeks ago
  4. 0e9439f Move fallback to default value into CreateField(). by Vitaly Buka · 6 weeks ago
  5. 329fa46 Remove size control heuristic by Vitaly Buka · 6 weeks ago

libprotobuf-mutator

Overview

libprotobuf-mutator is a library to randomly mutate protobuffers.
It could be used together with guided fuzzing engines, such as libFuzzer.

Quick start on Debian/Ubuntu

Install prerequisites:

sudo apt-get update
sudo apt-get install binutils cmake ninja-build liblzma-dev libz-dev docbook2x

Compile and test everything:

mkdir build
cd build
cmake .. -GNinja -DCMAKE_C_COMPILER=clang -DCMAKE_CXX_COMPILER=clang++ -DCMAKE_BUILD_TYPE=Debug
ninja check

Clang is only needed for libFuzzer integration.

Usage

To use libprotobuf-mutator simply include protobuf_mutator.h and protobuf_mutator.cc into your build files.

The ProtobufMutator class implements mutations of the protobuf tree structure and mutations of individual fields. The field mutation logic is very basic -- for better results you should override the ProtobufMutator::Mutate* methods with more sophisticated logic, e.g. using libFuzzer's mutators.

To apply one mutation to a protobuf object do the following:

class MyProtobufMutator : public protobuf_mutator::Mutator {
 public:
  MyProtobufMutator(uint32_t seed) : protobuf_mutator::Mutator(seed) {}
  // Optionally redefine the Mutate* methods to perform more sophisticated mutations.
}
void Mutate(MyMessage* message) {
  MyProtobufMutator mutator(my_random_seed);
  mutator.Mutate(message, 200);
}

See also the ProtobufMutatorMessagesTest.UsageExample test from protobuf_mutator_test.cc.

Integrating with libFuzzer

LibFuzzerProtobufMutator can help to integrate with libFuzzer. For example

#include "libfuzzer_protobuf_mutator.h"

extern "C" size_t LLVMFuzzerCustomMutator(uint8_t* data, size_t size,
                                          size_t max_size, unsigned int seed) {
  return protobuf_mutator::MutateTextMessage<MyMessageType>(
      data, size, max_size, seed);
}

extern "C" 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) {
  return protobuf_mutator::CrossOverTextMessages<MyMessageType>(
      data1, size1, data2, size2, out, max_out_size, seed);
}

extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
  MyMessageType message;
  protobuf_mutator::ParseTextMessage(data, size, &message);
  
  // Code which needs to be fuzzed.
  ConsumeMyMessageType(message);
  return 0;
}

Please see libfuzzer_example.cc as an example.