Git Product home page Git Product logo

libprotobuf-mutator's Introduction

libprotobuf-mutator

Build Status Fuzzing Status

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 protobuf-compiler libprotobuf-dev binutils cmake \
  ninja-build liblzma-dev libz-dev pkg-config autoconf libtool

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.
By default, the system-installed version of protobuf is used. However, on some systems, the system version is too old. You can pass LIB_PROTO_MUTATOR_DOWNLOAD_PROTOBUF=ON to cmake to automatically download and build a working version of protobuf.

Installation:

ninja
sudo ninja install

This installs the headers, pkg-config, and static library. By default the headers are put in /usr/local/include/libprotobuf-mutator.

Usage

To use libprotobuf-mutator simply include mutator.h and 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:
  // Optionally redefine the Mutate* methods to perform more sophisticated mutations.
}
void Mutate(MyMessage* message) {
  MyProtobufMutator mutator;
  mutator.Seed(my_random_seed);
  mutator.Mutate(message, 200);
}

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

Integrating with libFuzzer

LibFuzzerProtobufMutator can help to integrate with libFuzzer. For example

#include "src/libfuzzer/libfuzzer_macro.h"

DEFINE_PROTO_FUZZER(const MyMessageType& input) {
  // Code which needs to be fuzzed.
  ConsumeMyMessageType(input);
}

Please see libfuzzer_example.cc as an example.

Mutation post-processing (experimental)

Sometimes it's necessary to keep particular values in some fields without which the proto is going to be rejected by fuzzed code. E.g. code may expect consistency between some fields or it may use some fields as checksums. Such constraints are going to be significant bottleneck for fuzzer even if it's capable of inserting acceptable values with time.

PostProcessorRegistration can be used to avoid such issue and guide your fuzzer towards interesting code. It registers callback which will be called for each message of particular type after each mutation.

static protobuf_mutator::libfuzzer::PostProcessorRegistration<MyMessageType> reg = {
    [](MyMessageType* message, unsigned int seed) {
      TweakMyMessage(message, seed);
    }};

DEFINE_PROTO_FUZZER(const MyMessageType& input) {
  // Code which needs to be fuzzed.
  ConsumeMyMessageType(input);
}

Optional: Use seed if callback uses random numbers. It may help later with debugging.

Important: Callbacks should be deterministic and avoid modifying good messages. Callbacks are called for both: mutator generated and user provided inputs, like corpus or bug reproducer. So if callback performs unnecessary transformation it may corrupt the reproducer so it stops triggering the bug.

Note: You can add callback for any nested message and you can add multiple callbacks for the same message type.

static PostProcessorRegistration<MyMessageType> reg1 = {
    [](MyMessageType* message, unsigned int seed) {
      TweakMyMessage(message, seed);
    }};
static PostProcessorRegistration<MyMessageType> reg2 = {
    [](MyMessageType* message, unsigned int seed) {
      DifferentTweakMyMessage(message, seed);
    }};
static PostProcessorRegistration<MyMessageType::Nested> reg_nested = {
    [](MyMessageType::Nested* message, unsigned int seed) {
      TweakMyNestedMessage(message, seed);
    }};

DEFINE_PROTO_FUZZER(const MyMessageType& input) {
  // Code which needs to be fuzzed.
  ConsumeMyMessageType(input);
}

UTF-8 strings

"proto2" and "proto3" handle invalid UTF-8 strings differently. In both cases string should be UTF-8, however only "proto3" enforces that. So if fuzzer is applied to "proto2" type libprotobuf-mutator will generate any strings including invalid UTF-8. If it's a "proto3" message type, only valid UTF-8 will be used.

Extensions

Currently the library does not mutate extensions. This can be a problem if extension contains required fields so the library will not be able to change the message into valid initialized state. You can use post processing hooks to cleanup/initialize the message as workaround.

Users of the library

Grammars

Bugs found with help of the library

Chromium

Envoy

Related materials

libprotobuf-mutator's People

Contributors

allen-webb avatar ammaraskar avatar bshastry avatar dende avatar emmettneyman avatar georgthegreat avatar hctim avatar iii-i avatar jonathanmetzman avatar jorgbrown avatar kcc avatar l4l avatar lebdron avatar ligurio avatar morehouse avatar nareddyt avatar pefoley2 avatar spq avatar toshipiazza avatar tpopela avatar vadorovsky avatar vitalybuka avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

libprotobuf-mutator's Issues

unknown fields fuzzed

Hi,

I found an interesting crash on OSS-Fuzz after bumping libprotobuf-mutator to the latest commit:
https://github.com/envoyproxy/envoy/blob/011945dcf92b8a461ab4ba309fa2bebeffc15895/bazel/repository_locations.bzl#L166

https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=23823
Opening the testcase, we have

fkidd:[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[ [....]
}

Which is not a valid protobuf for the message https://github.com/envoyproxy/envoy/blob/master/test/common/http/header_map_impl_fuzz.proto

The stack trace looks something like:

#246 0x3eb856c in google::protobuf::TextFormat::Parser::ParserImpl::SkipFieldValue() /proc/self/cwd/external/com_google_protobuf/src/google/protobuf/text_format.cc:830:11
--
  | #247 0x3eb856c in google::protobuf::TextFormat::Parser::ParserImpl::SkipFieldValue() /proc/self/cwd/external/com_google_protobuf/src/google/protobuf/text_format.cc:830:11
  | #248 0x3eb856c in google::protobuf::TextFormat::Parser::ParserImpl::SkipFieldValue() /proc/self/cwd/external/com_google_protobuf/src/google/protobuf/text_format.cc:830:11
  |  
  | SUMMARY: AddressSanitizer: stack-overflow /src/llvm-project/compiler-rt/lib/asan/../sanitizer_common/sanitizer_common_interceptors.inc in strlen
  | ==1==ABORTING

I can reproduce the testcase locally, but what I'm curious about is why the testcase was generated in the first place.

Null pointer dereference when start

When I started lpm, some errors occurred.
INFO: found LLVMFuzzerCustomMutator (0x5589a0). Disabling -len_control by default.
INFO: Seed: 1522032693
INFO: Loaded 1 modules (2066 inline 8-bit counters): 2066 [0x61fba0, 0x6203b2),
INFO: Loaded 1 PC tables (2066 PCs): 2066 [0x5c53e8,0x5cd508),
INFO: -max_len is not provided; libFuzzer will not generate inputs larger than 4096 bytes
AddressSanitizer:DEADLYSIGNAL

==1903==ERROR: AddressSanitizer: SEGV on unknown address 0x000000000000 (pc 0x000000000000 bp 0x7ffe4ffb63e0 sp 0x7ffe4ffb63b8 T0)
==1903==Hint: pc points to the zero page.
==1903==The signal is caused by a READ memory access.
==1903==Hint: address points to the zero page.
#0 0x0 ()
#1 0x7f509b9d83bf (/lib/x86_64-linux-gnu/libpthread.so.0+0x153bf)

AddressSanitizer can not provide additional info.
SUMMARY: AddressSanitizer: SEGV ()
==1903==ABORTING
MS: 0 ; base unit: 0000000000000000000000000000000000000000

Call traceback is as fllow:
#0 0x0000000000000000 in ?? ()
#1 0x00000000005969cc in google::protobuf::Message::GetDescriptor (this=0x7fffffffdba0) at external.protobuf/include/google/protobuf/message.h:356
#2 0x0000000000592e3e in protobuf_mutator::(anonymous namespace)::CastToAny (message=0x7fffffffdba0) at ../src/mutator.cc:387
#3 0x0000000000592dea in protobuf_mutator::(anonymous namespace)::UnpackIfAny (message=...) at ../src/mutator.cc:399
#4 0x00000000005905dd in protobuf_mutator::(anonymous namespace)::UnpackAny (message=..., result=0x7fffffffdab8) at ../src/mutator.cc:404
#5 0x0000000000590521 in protobuf_mutator::Mutator::Fix (this=0xf7ba40 <protobuf_mutator::libfuzzer::(anonymous namespace)::GetMutator()::mutator>, message=0x7fffffffdba0) at ../src/mutator.cc:630
#6 0x000000000058532c in protobuf_mutator::libfuzzer::LoadProtoInput (binary=false, data=0x6020000000b0 "\276", size=0, input=0x7fffffffdba0) at /usr/local/include/libprotobuf-mutator/src/libfuzzer/libfuzzer_macro.cc:230
#7 0x00000000005591c1 in LLVMFuzzerTestOneInput (data=0x6020000000b0 "\276", size=0) at json_generator.cpp:11
#8 0x000000000045f732 in fuzzer::Fuzzer::ExecuteCallback(unsigned char const*, unsigned long) () at /usr/bin/../lib/gcc/x86_64-linux-gnu/9/../../../../include/c++/9/iostream:74
#9 0x0000000000460ba7 in fuzzer::Fuzzer::ReadAndExecuteSeedCorpora(std::__Fuzzer::vector<fuzzer::SizedFile, fuzzer::fuzzer_allocatorfuzzer::SizedFile >&) () at /usr/bin/../lib/gcc/x86_64-linux-gnu/9/../../../../include/c++/9/iostream:74
#10 0x000000000046101a in fuzzer::Fuzzer::Loop(std::__Fuzzer::vector<fuzzer::SizedFile, fuzzer::fuzzer_allocatorfuzzer::SizedFile >&) () at /usr/bin/../lib/gcc/x86_64-linux-gnu/9/../../../../include/c++/9/iostream:74
#11 0x0000000000450d26 in fuzzer::FuzzerDriver(int*, char***, int ()(unsigned char const, unsigned long)) () at /usr/bin/../lib/gcc/x86_64-linux-gnu/9/../../../../include/c++/9/iostream:74
#12 0x0000000000478973 in main () at /usr/bin/../lib/gcc/x86_64-linux-gnu/9/../../../../include/c++/9/iostream:74
#13 0x00007ffff77910b3 in __libc_start_main (main=0x478950

, argc=1, argv=0x7fffffffe378, init=, fini=, rtld_fini=, stack_end=0x7fffffffe368) at ../csu/libc-start.c:308
#14 0x000000000042554e in _start () at /usr/bin/../lib/gcc/x86_64-linux-gnu/9/../../../../include/c++/9/iostream:74

crash happend when call qword ptr [rcx + 0x98],The address is null.
image

clang :Ubuntu clang version 11.0.0-2~ubuntu20.04.1 Target: x86_64-pc-linux-gnu
protobuf:libprotoc 3.19.1

How to add mutator.cc and mutaotr.h into cmake build files?

Hi,

I just want to use the Mutate function in Class protobuf_mutator::Mutator to mutate a protobuf messege in my C project, according to https://github.com/google/libprotobuf-mutator#usage, I should simply include mutator.h and mutator.cc into my build files. I use cmake to generate Makefile. I just add a cmake command "include_directories(/usr/local/include/libprotobuf-mutator" into my CMakelist.txt and add a "#include "/home/my/code/libprotobuf-mutator/src/mutator.h"" into my C source file. After I execute command "cmake .. -DCMAKE_CXX_COMPILER=clang++" and "make", I got many compiler errors like "unknown type name ‘namespace’". My OS is ubuntu 18.04.

I'm very new to a lot of this.There may be a lot of problems. Maybe a example from scratch can solve my problem.

How should I do to use the Mutate function in Class protobuf_mutator::Mutator to mutate a protobuf messege in my C project? How to modify my CMakelist.txt and compiler comand or anything else?

Thanks for your help!

Mutate function produced an error

Hi,

I wrote a parser function P, a renderer function R and try to use the mutate function.

Given an input I, if I call m = P(I), and J = R(m), I am able to produce a string J = I.

If I have m = P(I), mutator.Mutate(&m, 100), J = R(m), at execution, mutator.Mutate(&m, 100) would produce a system error. The message is:

#########################################
terminate called after throwing an instance of 'std::system_error'
what(): Unknown error -1
Aborted (core dumped)
##########################################

I installed libprotobuf-mutator two years ago, and the mutator worked fine. Using the recent version, I got this error. I am not sure why I received this error.

Here is the stack trace:
################################################################
#0 __GI_raise (sig=sig@entry=6) at ../sysdeps/unix/sysv/linux/raise.c:51
#1 0x00007f8ecaeb6801 in __GI_abort () at abort.c:79
#2 0x00007f8ecb50b957 in ?? () from /usr/lib/x86_64-linux-gnu/libstdc++.so.6
#3 0x00007f8ecb511ab6 in ?? () from /usr/lib/x86_64-linux-gnu/libstdc++.so.6
#4 0x00007f8ecb511af1 in std::terminate() ()
from /usr/lib/x86_64-linux-gnu/libstdc++.so.6
#5 0x00007f8ecb511d24 in __cxa_throw ()
from /usr/lib/x86_64-linux-gnu/libstdc++.so.6
#6 0x00007f8ecb50da19 in ?? () from /usr/lib/x86_64-linux-gnu/libstdc++.so.6
#7 0x00007f8ecb97dce3 in std::call_once<void (&)(google::protobuf::internal::DescriptorTable const*), google::protobuf::internal::DescriptorTable const*&> (
__f=@0x7f8ecb988800: {void (const google::protobuf::internal::DescriptorTable )} 0x7f8ecb988800 <google::protobuf::(anonymous namespace)::AssignDescriptorsImpl(google::protobuf::internal::DescriptorTable const)>, __once=...)
at /usr/include/c++/7/mutex:698
#8 google::protobuf::internal::AssignDescriptors (table=)
at google/protobuf/generated_message_reflection.cc:2407
#9 0x00005622487fa7dd in input::Group::GetMetadataStatic() ()
#10 0x00005622487f3b85 in input::Group::GetMetadata() const ()
#11 0x000056224880e6f9 in google::protobuf::Message::GetDescriptor() const ()
#12 0x0000562248808ebe in protobuf_mutator::(anonymous namespace)::MutationSampler::Sample(google::protobuf::Message*) ()
#13 0x0000562248808dfb in protobuf_mutator::(anonymous namespace)::MutationSampl---Type to continue, or q to quit---return
er::MutationSampler(bool, std::linear_congruential_engine<unsigned long, 48271ul, 0ul, 2147483647ul>, google::protobuf::Message) ()
#14 0x0000562248809e59 in protobuf_mutator::Mutator::MutateImpl(google::protobuf::Message*, unsigned long) ()
#15 0x0000562248809b51 in protobuf_mutator::Mutator::Mutate(google::protobuf::Message*, unsigned long) ()
#16 0x00005622487a8c92 in main ()
#########################################################

Thanks!

Higher-level API

We discussed a bit how high-level api to the library could look like. My opinion is that it should look like (please ignore names):

extern "C" int LLVMFuzzerTestProto(const MyProto& proto) {
  // put your fuzzing code here and use proto as input.
  return 0;
}

// Or even
LLVM_FUZZER_PROTO(MyProto proto) {
  // put your fuzzing code here and use proto as input.
  return 0;
}

// Or maybe with registrar:
extern "C" int MyFuzzerTestProto(const MyProto& proto) {
  // put your fuzzing code here and use proto as input.
  return 0;
}
REGISTER_PROTO_FUZZER(MyFuzzerTestProto);

The important point is: the same way libfuzzer api doesn't introduce too many knowledge about fuzzing engine, this shouldn't either. If I don't care about custom proto mutations - I shouldn't bother writing code for it.

Is the use of reflection APIs in the fuzzing harness okay?

We are working with a proto definition that is context sensitive. Example is the following

message A {
   required B b = 1;
   required bool c = 2;
}

message B {
  required uint32 d = 1;
  optional string e = 2;
}

The idea is that string "e" makes sense only-if bool "c" is set. In our current implementation, the LPM fuzzing test harness does not contain state (very similar to clang-proto-fuzzer).

There are at least two ways to introduce state:

  • Add state to test harness
  • Don't add state to test harness explicitly but make use of protobuf reflection APIs

I am wondering, as authors of the framework, what do you make of what I proposed? Do you foresee any problems with the proposed approaches?

Alternatively, are you aware of other stateful LPM-based fuzzers that one could learn from?

`ninja check` fails with protobuf version 3.0.0?

Hello. I followed the instructions to install all dependencies, clone the repo and tried to ninja but ninja check fails with multiple errors. Is it possible that there could be a version mismatch for libprotobuf-dev (I am using v 3.0.0) and such?

I'm using clang-10, clang++-10 on Ubuntu 18.04.

Output:

// clone
mkdir build
cd build
cmake .. -GNinja -DCMAKE_C_COMPILER=clang-10 -DCMAKE_CXX_COMPILER=clang++-10 -DCMAKE_BUILD_TYPE=Debug
[6/65] Building CXX object src/CMakeFiles/protobuf-mutator.dir/text_format.cc.o
FAILED: src/CMakeFiles/protobuf-mutator.dir/text_format.cc.o
/usr/bin/clang++-10   -I../ -I. -Iexternal.googletest/include -fno-exceptions -Werror -Wall -Wstring-conversion -g    -fsanitize-coverage=0 -std=gnu++11 -MD -MT src/CMakeFiles/protobuf-mutator.dir/text_format.cc.o -MF src/CMakeFiles/protobuf-mutator.dir/text_format.cc.o.d -o src/CMakeFiles/protobuf-mutator.dir/text_format.cc.o -c ../src/text_format.cc
../src/text_format.cc:31:10: error: no member named 'SetRecursionLimit' in 'google::protobuf::TextFormat::Parser'
  parser.SetRecursionLimit(100);
  ~~~~~~ ^
../src/text_format.cc:33:10: error: no member named 'AllowUnknownField' in 'google::protobuf::TextFormat::Parser'
  parser.AllowUnknownField(true);
  ~~~~~~ ^
2 errors generated.
[7/65] Building CXX object src/CMakeFiles/protobuf-mutator.dir/mutator.cc.o
FAILED: src/CMakeFiles/protobuf-mutator.dir/mutator.cc.o
/usr/bin/clang++-10   -I../ -I. -Iexternal.googletest/include -fno-exceptions -Werror -Wall -Wstring-conversion -g    -fsanitize-coverage=0 -std=gnu++11 -MD -MT src/CMakeFiles/protobuf-mutator.dir/mutator.cc.o -MF src/CMakeFiles/protobuf-mutator.dir/mutator.cc.o.d -o src/CMakeFiles/protobuf-mutator.dir/mutator.cc.o -c ../src/mutator.cc
../src/mutator.cc:166:17: error: no member named 'ByteSizeLong' in 'google::protobuf::Message'; did you mean 'ByteSize'?
    return src->ByteSizeLong() - dst->ByteSizeLong();
                ^~~~~~~~~~~~
                ByteSize
/usr/include/google/protobuf/message.h:300:15: note: 'ByteSize' declared here
  virtual int ByteSize() const;
              ^
../src/mutator.cc:166:39: error: no member named 'ByteSizeLong' in 'google::protobuf::Message'; did you mean 'ByteSize'?
    return src->ByteSizeLong() - dst->ByteSizeLong();
                                      ^~~~~~~~~~~~
                                      ByteSize
/usr/include/google/protobuf/message.h:300:15: note: 'ByteSize' declared here
  virtual int ByteSize() const;
              ^
../src/mutator.cc:372:8: error: no member named 'ParseAnyTypeUrl' in 'google::protobuf::Any'; did you mean 'google::protobuf::internal::ParseAnyTypeUrl'?
  if (!Any::ParseAnyTypeUrl(std::string(any.type_url()), &type_name))
       ^~~~~~~~~~~~~~~~~~~~
       google::protobuf::internal::ParseAnyTypeUrl
/usr/include/google/protobuf/any.h:95:6: note: 'google::protobuf::internal::ParseAnyTypeUrl' declared here
bool ParseAnyTypeUrl(const string& type_url, string* full_type_name);
     ^
../src/mutator.cc:387:15: error: call to non-static member function without an object argument
  return Any::GetDescriptor() == message->GetDescriptor()
         ~~~~~^~~~~~~~~~~~~
../src/mutator.cc:393:15: error: call to non-static member function without an object argument
  return Any::GetDescriptor() == message->GetDescriptor()
         ~~~~~^~~~~~~~~~~~~
../src/mutator.cc:640:44: error: no member named 'ByteSizeLong' in 'google::protobuf::Message'; did you mean 'ByteSize'?
                 static_cast<int>(message->ByteSizeLong()));
                                           ^~~~~~~~~~~~
                                           ByteSize
/usr/include/google/protobuf/message.h:300:15: note: 'ByteSize' declared here
  virtual int ByteSize() const;
              ^
../src/mutator.cc:667:45: error: no member named 'ByteSizeLong' in 'google::protobuf::Message'; did you mean 'ByteSize'?
                 static_cast<int>(message2->ByteSizeLong()));
                                            ^~~~~~~~~~~~
                                            ByteSize
/usr/include/google/protobuf/message.h:300:15: note: 'ByteSize' declared here
  virtual int ByteSize() const;
              ^
7 errors generated.
[11/65] Performing download step (git clone) for 'external.googletest'
Cloning into 'external.googletest'...
Note: checking out '3f05f651ae3621db58468153e32016bc1397800b'.

You are in 'detached HEAD' state. You can look around, make experimental
changes and commit them, and you can discard any commits you make in this
state without impacting any branches by performing another checkout.

If you want to create a new branch to retain commits you create, you may
do so (now or later) by using -b with the checkout command again. Example:

  git checkout -b <new-branch-name>

HEAD is now at 3f05f651 Googletest export
ninja: build stopped: subcommand failed.

Using PostProcessorRegistration

Hi,

I'm trying to use PostProcessorRegistration for one of our fuzz tests following the example here:

DEFINE_PROTO_FUZZER(const libfuzzer_example::Msg& message) {

It seems like the function I register is never executed. I'm trying to clear a field that libfuzzer populates in my protobuf because we don't implement functionality for it (and otherwise it reaches a panic assert). I could always do this manually, but I figured I should try out this new functionality.

I've registered the function, which clears the comprehension expression field if it has it. Later in the test, I printed out the input protobuf, and it still keeps the comprehension expression field. Is thePostProcessorRegistration meant to mutate the protobuf inputs?

My test looks something like:

DEFINE_PROTO_FUZZER(const test::extensions::filters::common::expr::EvaluatorTestCase& input) {
  static PostProcessorRegistration reg = {
    [](test::extensions::filters::common::expr::EvaluatorTestCase* input, unsigned int /*seed*/) {
        if (input->expression().expr_kind_case() ==
            google::api::expr::v1alpha1::Expr::kComprehensionExpr) {
          input->mutable_expression()->clear_expr_kind();
        }
      }};

  // Create builder without constant folding.
  static Expr::BuilderPtr builder = Expr::createBuilder(nullptr);

  try {
    // Validate that the input has an expression.
    TestUtility::validate(input);
    ENVOY_LOG_MISC(info, "PROTOBUF {}", input.expression().DebugString());

    // Create the CEL expression.
    Expr::ExpressionPtr expr = Expr::createExpression(*builder, input.expression());

    // Create the headers and stream_info to test against.
    TestStreamInfo stream_info = makeStreamInfo(input.stream_info());
    Http::TestHeaderMapImpl request_headers = Fuzz::fromHeaders(input.request_headers());
    Http::TestHeaderMapImpl response_headers = Fuzz::fromHeaders(input.response_headers());
    Http::TestHeaderMapImpl response_trailers = Fuzz::fromHeaders(input.trailers());

    // Evaluate the CEL expression.
    Protobuf::Arena arena;
    Expr::evaluate(*expr, nullptr, stream_info, &request_headers, &response_headers,
                   &response_trailers);
    arena.Reset();
  } catch (const EnvoyException& e) {
    ENVOY_LOG_MISC(debug, "EnvoyException: {}", e.what());
  }
}

Buffer overflow error in mutator.cc

enum class Mutation : uint8_t {
  None,
  Add,     // Adds new field with default value.
  Mutate,  // Mutates field contents.
  Delete,  // Deletes field.
  Copy,    // Copy values copied from another field.
  Clone,   // Create new field with value copied from another.

  **Last = Clone,**
};

**using MutationBitset = std::bitset<static_cast<size_t>(Mutation::Last)>**;

MutationBitset is of type bitset<5>
Because Mutation::Last is 5 when converted to a size_t.
This is because it is given the same value as Clone.
Hence we can only access [0:5) index. i.e 0,1,2,3,4

bool Mutator::MutateImpl(const ConstMessages& sources, const Messages& messages,
                         bool copy_clone_only, int size_increase_hint) {
  **MutationBitset mutations;**
  if (copy_clone_only) {
    mutations[static_cast<size_t>(Mutation::Copy)] = true;
    mutations[static_cast<size_t>(Mutation::Clone)] = true;
  } else if (size_increase_hint <= 16) {
    mutations[static_cast<size_t>(Mutation::Delete)] = true;
  } else {
    mutations.set();
    mutations[static_cast<size_t>(Mutation::Copy)] = false;
    **mutations[static_cast<size_t>(Mutation::Clone)] = false **; 
  }

As a result writing, to mutations[Mutation::Clone] = false is the same as
writing to mutations[5] = false, which is writing after the allocated buffer.

Build error on fedora 30: clang-8: error: no such file or directory: 'external.googletest/lib/libgtest.a'

Trying to build the library like described in the README yields the following error for me:

FAILED: examples/libfuzzer/libfuzzer_example_test 
: && /usr/bin/clang++  -fno-exceptions -Werror -Wall -Wstring-conversion -g   examples/libfuzzer/CMakeFiles/libfuzzer_example_test.dir/libfuzzer_example_test.cc.o  -o examples/libfuzzer/libfuzzer_example_test  external.googletest/lib/libgtest.a external.googletest/lib/libgtest_main.a -pthread && :
clang-8: error: no such file or directory: 'external.googletest/lib/libgtest.a'
clang-8: error: no such file or directory: 'external.googletest/lib/libgtest_main.a'
[44/65] Performing configure step for 'external.expat'

I can find the respective files in the build directory, but not at the specified paths:

[vincent@vincent build]$ find . -name 'libgtest*.a'
./external.googletest/lib64/libgtest.a
./external.googletest/lib64/libgtest_main.a
./external.googletest/src/external.googletest-build/lib/libgtest.a
./external.googletest/src/external.googletest-build/lib/libgtest_main.a

Find my build process below. Anything I can do to fix this?

Thank you very much in advance.

I ran it like so:

[vincent@vincent build]$ LIB_PROTO_MUTATOR_DOWNLOAD_PROTOBUF=ON cmake .. -GNinja -DCMAKE_C_COMPILER=clang -DCMAKE_CXX_COMPILER=clang++ -DCMAKE_BUILD_TYPE=Debug
-- The CXX compiler identification is Clang 8.0.0
-- Check for working CXX compiler: /usr/bin/clang++
-- Check for working CXX compiler: /usr/bin/clang++ -- works
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done
-- Detecting CXX compile features
-- Detecting CXX compile features - done
-- The C compiler identification is Clang 8.0.0
-- Check for working C compiler: /usr/bin/clang
-- Check for working C compiler: /usr/bin/clang -- works
-- Detecting C compiler ABI info
-- Detecting C compiler ABI info - done
-- Detecting C compile features
-- Detecting C compile features - done
-- Looking for pthread.h
-- Looking for pthread.h - found
-- Looking for pthread_create
-- Looking for pthread_create - not found
-- Check if compiler accepts -pthread
-- Check if compiler accepts -pthread - yes
-- Found Threads: TRUE  
-- Could NOT find LibLZMA (missing: LIBLZMA_LIBRARY LIBLZMA_INCLUDE_DIR LIBLZMA_HAS_AUTO_DECODER LIBLZMA_HAS_EASY_ENCODER LIBLZMA_HAS_LZMA_PRESET) 
-- Found ZLIB: /usr/lib64/libz.so (found version "1.2.11") 
-- Performing Test LIB_PROTO_MUTATOR_HAS_SANITIZE_ADDRESS
-- Performing Test LIB_PROTO_MUTATOR_HAS_SANITIZE_ADDRESS - Success
-- Performing Test LIB_PROTO_MUTATOR_HAS_SANITIZE_SCOPE
-- Performing Test LIB_PROTO_MUTATOR_HAS_SANITIZE_SCOPE - Success
-- Performing Test LIB_PROTO_MUTATOR_HAS_NO_COVERAGE
-- Performing Test LIB_PROTO_MUTATOR_HAS_NO_COVERAGE - Success
-- Performing Test LIB_PROTO_MUTATOR_HAS_SANITIZE_FUZZER
-- Performing Test LIB_PROTO_MUTATOR_HAS_SANITIZE_FUZZER - Success
-- Performing Test LIB_PROTO_MUTATOR_HAS_NO_SANITIZE_FUZZER
-- Performing Test LIB_PROTO_MUTATOR_HAS_NO_SANITIZE_FUZZER - Success
-- Performing Test LIB_PROTO_MUTATOR_HAS_WSTRING_CONVERSION
-- Performing Test LIB_PROTO_MUTATOR_HAS_WSTRING_CONVERSION - Success
-- Found Protobuf: /usr/local/lib/libprotobuf.so;-pthread (found version "3.9.1") 
-- Configuring done
-- Generating done
-- Build files have been written to: /home/vincent/Documents/Research/fuzzing/rust_protobuf_fuzzing/libprotobuf-mutator/build

And then:

[vincent@vincent build]$ ninja check
[18/65] Performing download step (git clone) for 'external.googletest'
Cloning into 'external.googletest'...
Note: checking out 'bf07131'.

You are in 'detached HEAD' state. You can look around, make experimental
changes and commit them, and you can discard any commits you make in this
state without impacting any branches by performing another checkout.

If you want to create a new branch to retain commits you create, you may
do so (now or later) by using -b with the checkout command again. Example:

  git checkout -b <new-branch-name>

HEAD is now at bf07131c Merge pull request #2041 from ciband:chore/fix_library_json
[31/65] Performing download step (git clone) for 'external.expat'
Cloning into 'external.expat'...
Already on 'master'
Your branch is up to date with 'origin/master'.
[34/65] Performing configure step for 'external.googletest'
loading initial cache file /home/vincent/Documents/Research/fuzzing/rust_protobuf_fuzzing/libprotobuf-mutator/build/external.googletest/tmp/external.googletest-cache-Debug.cmake
-- The C compiler identification is Clang 8.0.0
-- The CXX compiler identification is Clang 8.0.0
-- Check for working C compiler: /usr/bin/clang
-- Check for working C compiler: /usr/bin/clang -- works
-- Detecting C compiler ABI info
-- Detecting C compiler ABI info - done
-- Detecting C compile features
-- Detecting C compile features - done
-- Check for working CXX compiler: /usr/bin/clang++
-- Check for working CXX compiler: /usr/bin/clang++ -- works
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done
-- Detecting CXX compile features
-- Detecting CXX compile features - done
-- Found PythonInterp: /usr/bin/python (found version "2.7.16") 
-- Looking for pthread.h
-- Looking for pthread.h - found
-- Looking for pthread_create
-- Looking for pthread_create - not found
-- Looking for pthread_create in pthreads
-- Looking for pthread_create in pthreads - not found
-- Looking for pthread_create in pthread
-- Looking for pthread_create in pthread - found
-- Found Threads: TRUE  
-- Configuring done
-- Generating done
-- Build files have been written to: /home/vincent/Documents/Research/fuzzing/rust_protobuf_fuzzing/libprotobuf-mutator/build/external.googletest/src/external.googletest-build
[35/65] Performing build step for 'external.googletest'
[1/8] Building CXX object googlemock/gtest/CMakeFiles/gtest_main.dir/src/gtest_main.cc.o
[2/8] Building CXX object googlemock/CMakeFiles/gmock_main.dir/src/gmock_main.cc.o
[3/8] Building CXX object googlemock/CMakeFiles/gmock.dir/src/gmock-all.cc.o
[4/8] Building CXX object googlemock/gtest/CMakeFiles/gtest.dir/src/gtest-all.cc.o
[5/8] Linking CXX static library lib/libgtest.a
[6/8] Linking CXX static library lib/libgtest_main.a
[7/8] Linking CXX static library lib/libgmock.a
[8/8] Linking CXX static library lib/libgmock_main.a
[36/65] Performing install step for 'external.googletest'
[0/1] Install the project...
[...]
[39/65] Linking CXX executable examples/libfuzzer/libfuzzer_example_test
FAILED: examples/libfuzzer/libfuzzer_example_test 
: && /usr/bin/clang++  -fno-exceptions -Werror -Wall -Wstring-conversion -g   examples/libfuzzer/CMakeFiles/libfuzzer_example_test.dir/libfuzzer_example_test.cc.o  -o examples/libfuzzer/libfuzzer_example_test  external.googletest/lib/libgtest.a external.googletest/lib/libgtest_main.a -pthread && :
clang-8: error: no such file or directory: 'external.googletest/lib/libgtest.a'
clang-8: error: no such file or directory: 'external.googletest/lib/libgtest_main.a'
[...]
[45/65] Performing download step (git clone) for 'external.libxml2'
Cloning into 'external.libxml2'...
warning: redirecting to https://gitlab.gnome.org/GNOME/libxml2.git/
Already on 'master'
Your branch is up to date with 'origin/master'.
ninja: build stopped: subcommand failed.

fatal error: 'google/protobuf/util/message_differencer.h' file not found

While compiling libprotobuf-mutator using command:

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

I got errors as below :

root@be6be883777e:/src/libprotobuf-mutator/build# ninja check
[12/62] Building CXX object src/CMakeFiles/protobuf-mutator.dir/text_format.cc.o
FAILED: /usr/local/bin/clang++    -I../ -I. -Iexternal.googletest/include -O1 -fno-omit-frame-pointer -gline-tables-only -DFUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION -stdlib=libc++  -fno-exceptions -Werror -Wall -Wstring-conversion -g    -fsanitize-coverage=0 -std=gnu++11 -MMD -MT src/CMakeFiles/protobuf-mutator.dir/text_format.cc.o -MF src/CMakeFiles/protobuf-mutator.dir/text_format.cc.o.d -o src/CMakeFiles/protobuf-mutator.dir/text_format.cc.o -c ../src/text_format.cc
In file included from ../src/text_format.cc:15:
In file included from ../src/text_format.h:20:
../port/protobuf.h:22:10: fatal error: 'google/protobuf/util/message_differencer.h' file not found
#include "google/protobuf/util/message_differencer.h"
         ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1 error generated.
[12/62] Building CXX object src/CMakeFiles/protobuf-mutator.dir/binary_format.cc.o
FAILED: /usr/local/bin/clang++    -I../ -I. -Iexternal.googletest/include -O1 -fno-omit-frame-pointer -gline-tables-only -DFUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION -stdlib=libc++  -fno-exceptions -Werror -Wall -Wstring-conversion -g    -fsanitize-coverage=0 -std=gnu++11 -MMD -MT src/CMakeFiles/protobuf-mutator.dir/binary_format.cc.o -MF src/CMakeFiles/protobuf-mutator.dir/binary_format.cc.o.d -o src/CMakeFiles/protobuf-mutator.dir/binary_format.cc.o -c ../src/binary_format.cc
In file included from ../src/binary_format.cc:15:
In file included from ../src/binary_format.h:20:
../port/protobuf.h:22:10: fatal error: 'google/protobuf/util/message_differencer.h' file not found
#include "google/protobuf/util/message_differencer.h"
         ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1 error generated.
[12/62] Building CXX object src/CMakeFiles/protobuf-mutator.dir/mutator.cc.o
FAILED: /usr/local/bin/clang++    -I../ -I. -Iexternal.googletest/include -O1 -fno-omit-frame-pointer -gline-tables-only -DFUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION -stdlib=libc++  -fno-exceptions -Werror -Wall -Wstring-conversion -g    -fsanitize-coverage=0 -std=gnu++11 -MMD -MT src/CMakeFiles/protobuf-mutator.dir/mutator.cc.o -MF src/CMakeFiles/protobuf-mutator.dir/mutator.cc.o.d -o src/CMakeFiles/protobuf-mutator.dir/mutator.cc.o -c ../src/mutator.cc
In file included from ../src/mutator.cc:15:
In file included from ../src/mutator.h:28:
../port/protobuf.h:22:10: fatal error: 'google/protobuf/util/message_differencer.h' file not found
#include "google/protobuf/util/message_differencer.h"
         ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1 error generated.
^Cninja: build stopped: interrupted by user.

How can I fix it?

Nullptr dereference when generating proto map value

I tried fuzzing a proto containing that contains a map<>, but ran into a segfault (original thread on a Chromium CL.)

I'm including a stack trace that I saw while working on this CL. I can make a more minimal example if you'd like, but I believe the key part is that the proto contains a map.

Thread 1 "test_json_conve" received signal SIGSEGV, Segmentation fault.
json_proto::JsonValue::IsInitialized (this=0x0) at gen/testing/libfuzzer/proto/json.pb.cc:1332
1332      switch (value_case()) {
(gdb) bt
#0  json_proto::JsonValue::IsInitialized (this=0x0) at gen/testing/libfuzzer/proto/json.pb.cc:1332
#1  0x5692cd4f in google::protobuf::internal::MapTypeHandler<(google::protobuf::internal::WireFormatLite::FieldType)11, json_proto::JsonValue>::IsInitialized (value=0x0)
    at ../../third_party/protobuf/src/google/protobuf/map_type_handler.h:636
#2  google::protobuf::internal::MapEntryImpl<json_proto::JsonObject_PairsEntry_DoNotUse, google::protobuf::Message, std::__Cr::basic_string<char, std::__Cr::char_traits<char>, std::__Cr::allocator<char> >, json_proto::JsonValue, (google::protobuf::internal::WireFormatLite::FieldType)9, (google::protobuf::internal::WireFormatLite::FieldType)11, 0>::IsInitialized
    (this=0xef12d370) at ../../third_party/protobuf/src/google/protobuf/map_entry_lite.h:353
#3  0x567e0dc3 in protobuf_mutator::Mutator::Mutate (this=0xffffa1b8, message=0xef12d370, size_increase_hint=1016) at ../../third_party/libprotobuf-mutator/src/src/mutator.cc:488
#4  0x567e64b2 in protobuf_mutator::FieldMutator::Mutate (this=<optimized out>, message=0xffff95b8) at ../../third_party/libprotobuf-mutator/src/src/mutator.cc:397
#5  protobuf_mutator::(anonymous namespace)::CreateField::ForType<std::__Cr::unique_ptr<google::protobuf::Message, std::__Cr::default_delete<google::protobuf::Message> > > (
    this=<optimized out>, field=..., size_increase_hint=<optimized out>, mutator=0xffffa1b8) at ../../third_party/libprotobuf-mutator/src/src/mutator.cc:445
#6  0x567e04a7 in protobuf_mutator::FieldFunction<protobuf_mutator::(anonymous namespace)::CreateField, void>::operator()<protobuf_mutator::FieldInstance, unsigned int, protobuf_mutator::Mutator*> (this=<optimized out>, field=..., args=<optimized out>, args=<optimized out>) at ../../third_party/libprotobuf-mutator/src/src/field_instance.h:439
#7  protobuf_mutator::Mutator::Mutate (this=0xffffa1b8, message=0xefb02940, size_increase_hint=2032) at ../../third_party/libprotobuf-mutator/src/src/mutator.cc:463
#8  0x567e64b2 in protobuf_mutator::FieldMutator::Mutate (this=<optimized out>, message=0xffff96e8) at ../../third_party/libprotobuf-mutator/src/src/mutator.cc:397
#9  protobuf_mutator::(anonymous namespace)::CreateField::ForType<std::__Cr::unique_ptr<google::protobuf::Message, std::__Cr::default_delete<google::protobuf::Message> > > (
    this=<optimized out>, field=..., size_increase_hint=<optimized out>, mutator=0xffffa1b8) at ../../third_party/libprotobuf-mutator/src/src/mutator.cc:445
#10 0x567e04a7 in protobuf_mutator::FieldFunction<protobuf_mutator::(anonymous namespace)::CreateField, void>::operator()<protobuf_mutator::FieldInstance, unsigned int, protobuf_mutator::Mutator*> (this=<optimized out>, field=..., args=<optimized out>, args=<optimized out>) at ../../third_party/libprotobuf-mutator/src/src/field_instance.h:439
#11 protobuf_mutator::Mutator::Mutate (this=0xffffa1b8, message=0xf07d3090, size_increase_hint=4064) at ../../third_party/libprotobuf-mutator/src/src/mutator.cc:463
#12 0x567df600 in protobuf_mutator::libfuzzer::(anonymous namespace)::MutateMessage (seed=<optimized out>, input=..., output=0xffffa200, message=0xf07d3090)
    at ../../third_party/libprotobuf-mutator/src/src/libfuzzer/libfuzzer_macro.cc:97
#13 0x567df331 in protobuf_mutator::libfuzzer::(anonymous namespace)::MutateTextMessage (
    data=0xeb902900 "boolean_value {\n  value: true\n}\nean_value {\n      value: false\n    }\n  }\n}\ne {\\n}\\n\"\n    }\n  }\n}\n_value {\n      value: \"\\001\\000\"\n    }\n  }\n}\n", '\276' <repeats 58 times>..., size=32, max_size=4096, seed=1353339904, message=0xf07d3090) at ../../third_party/libprotobuf-mutator/src/src/libfuzzer/libfuzzer_macro.cc:127
#14 0x567df277 in protobuf_mutator::libfuzzer::CustomProtoMutator (binary=<optimized out>,
    data=0xeb902900 "boolean_value {\n  value: true\n}\nean_value {\n      value: false\n    }\n  }\n}\ne {\\n}\\n\"\n    }\n  }\n}\n_value {\n      value: \"\\001\\000\"\n    }\n  }\n}\n", '\276' <repeats 58 times>..., size=32, max_size=4096, seed=1353339904, input=0xf07d3090) at ../../third_party/libprotobuf-mutator/src/src/libfuzzer/libfuzzer_macro.cc:165
#15 0x567c694c in LLVMFuzzerCustomMutator (
    data=0xeb902900 "boolean_value {\n  value: true\n}\nean_value {\n      value: false\n    }\n  }\n}\ne {\\n}\\n\"\n    }\n  }\n}\n_value {\n      value: \"\\001\\000\"\n    }\n  }\n}\n", '\276' <repeats 58 times>..., size=32, max_size=4096, seed=1353339904) at ../../testing/libfuzzer/fuzzers/json_fuzzer.cc:59
#16 0x568f490b in fuzzer::MutationDispatcher::Mutate_Custom (this=0xedf3e800,
    Data=0xeb902900 "boolean_value {\n  value: true\n}\nean_value {\n      value: false\n    }\n  }\n}\ne {\\n}\\n\"\n    }\n  }\n}\n_value {\n      value: \"\\001\\000\"\n    }\n  }\n}\n", '\276' <repeats 58 times>..., Size=32, MaxSize=4096) at ../../third_party/libFuzzer/src/FuzzerMutate.cpp:70
#17 0x568f7e00 in fuzzer::MutationDispatcher::MutateImpl (this=0xedf3e800,
    Data=0xeb902900 "boolean_value {\n  value: true\n}\nean_value {\n      value: false\n    }\n  }\n}\ne {\\n}\\n\"\n    }\n  }\n}\n_value {\n      value: \"\\001\\000\"\n    }\n  }\n}\n", '\276' <repeats 58 times>..., Size=32, MaxSize=4096, Mutators=...) at ../../third_party/libFuzzer/src/FuzzerMutate.cpp:516
#18 0x568f7ac5 in fuzzer::MutationDispatcher::Mutate (this=0xedf3e800,
    Data=0xeb902900 "boolean_value {\n  value: true\n}\nean_value {\n      value: false\n    }\n  }\n}\ne {\\n}\\n\"\n    }\n  }\n}\n_value {\n      value: \"\\001\\000\"\n    }\n  }\n}\n", '\276' <repeats 58 times>..., Size=32, MaxSize=4096) at ../../third_party/libFuzzer/src/FuzzerMutate.cpp:498
#19 0x5689dccf in fuzzer::Fuzzer::MutateAndTestOne (this=0xef503000) at ../../third_party/libFuzzer/src/FuzzerLoop.cpp:691
#20 0x568a1261 in fuzzer::Fuzzer::Loop (this=0xef503000, CorporaFiles=...) at ../../third_party/libFuzzer/src/FuzzerLoop.cpp:830
#21 0x5684013d in fuzzer::FuzzerDriver (argc=0xf066c490, argv=0xf066c4a0, Callback=0x567c6d60 <LLVMFuzzerTestOneInput(uint8_t const*, size_t)>)
    at ../../third_party/libFuzzer/src/FuzzerDriver.cpp:824
#22 0x568cecb1 in main (argc=1, argv=0xffffad54) at ../../third_party/libFuzzer/src/FuzzerMain.cpp:19

Note: Chromium seems to be using an oldish version of LPM (439e81f from 2019-01).

Add release tag

It will be easier for other project download source as a tarball if release tag is added.

Recursive depth on google.protobuf.Structs

Hi,

It seems like one of our fuzzers is failing because of a stack-overflow in protobuf's TextFormat::Parser. The input that libprotobuf-mutator created was a Struct that has a large recursive depth, but is not enough to trigger the max recursion limit in the parser (which is by default 2^15 - 1).
https://github.com/protocolbuffers/protobuf/blob/6fc04c3f0e07857dff1f55b884f957b4c65aea8e/src/google/protobuf/text_format.cc#L1383.

Is there some environment variable we could set to limit the recursive depth that LPM creates, or another way to handle such an input?

Thanks!

knobs to control the mutations

I'd like to have some knobs to control what mutations are performed.
To begin with, it is possible to restrict LPM to mutating the leaves?

(probably pass the knobs via an environment variable)

Ability to fail test when seed corpus cannot be parsed

I would like our fuzz test target to fail when the input in the seed corpus is malformed.

Currently, when we get the following error, the tests still pass without doing anything:

[libprotobuf ERROR external/com_google_protobuf/src/google/protobuf/text_format.cc:309] Error parsing text-format ...

This would make it easier to maintain if someone changes the proto structure without changing the seed corpus.

can I mutate two messages at once?

Hello! I have a question. Can I somehow mutate two different messages and write them to two different topics inside of one DEFINE_PROTO_FUZZER() body?
I need it because I want to fuzz a program that is subscribed to several topics, so I want to put the whole program inside a DEFINE_PROTO_FUZZER() body to use the code coverage feature of libfuzzer.

`ninja check` failed in building libxml2

any way to solve this problem?

$ ninja check
...
[65/73] Linking CXX executable examples/libxml2/libxml2_example
FAILED: examples/libxml2/libxml2_example
: && /usr/bin/clang++  -fno-exceptions -Werror -Wall -Wstring-conversion -g  -fsanitize=fuzzer examples/libxml2/CMakeFiles/libxml2_example.dir/libxml2_example.cc.o  -o examples/libxml2/libxml2_example  examples/xml/libprotobuf-mutator-xml.a  examples/libxml2/external.libxml2/lib/libxml2.a  /usr/lib/x86_64-linux-gnu/libz.so  /usr/lib/x86_64-linux-gnu/liblzma.so  src/libfuzzer/libprotobuf-mutator-libfuzzer.a  src/libprotobuf-mutator.a  external.protobuf/lib/libprotobufd.a && :
clang: error: no such file or directory: 'examples/libxml2/external.libxml2/lib/libxml2.a'
[67/73] Linking CXX executable examples/libfuzzer/libfuzzer_bin_example
ninja: build stopped: subcommand failed.

os version:

$ lsb_release -a
No LSB modules are available.
Distributor ID:	Ubuntu
Description:	Ubuntu 20.04 LTS
Release:	20.04
Codename:	focal

clang++ version:

clang version 10.0.0-4ubuntu1
Target: x86_64-pc-linux-gnu
Thread model: posix
InstalledDir: /usr/bin

Dictionaries with LPM

Hi, I had a quick question about using dictionary files and LPM. I am fuzzing a target that consumes a format string along with some other protobuf data. I'd like to include common strings that we use in format strings to populate the format string field in the protobuf. If I define a .dict field like I do for ordinary fuzzers, how will LPM interpret the data in the dictionary? Will it use it to populate string fields or will it use try to deserialize the data in the dictionary into the protobuf?

Thank you!

[Feature] The ability to register custom mutators from one proto message to another.

This is for discussion and tracking of implementing hooks to register custom mutators that can be applied by the fuzzer to transform one proto message into another.

The specific use case I have in mind is:

Consider a proto that represents a series of actions that can be allied to a target. If there is a way of representing an action in a raw form it might be useful to be able to mutate a valid action to its equivalent representation in the raw form so further mutations can be applied.

libfuzzer_example_test fails on bionic

The test fails on bionic with the bionic-flavored clang, which is version 6.0.0.

I guess that that version does not understand the option len_control, which was introduced in 7.0.0 and thus fails to generate the correct byte sequence in time.

So probably not a critical issue, but I just wanted to let others know that run into the same issue.

Full output for reference:

19/19 Test #18: test.libfuzzer_example_test ......***Failed  209.86 sec
Running main() from gtest_main.cc
[==========] Running 2 tests from 1 test case.
[----------] Global test environment set-up.
[----------] 2 tests from LibFuzzerExampleTest
[ RUN      ] LibFuzzerExampleTest.Text
ASAN_OPTIONS=detect_leaks=0 ./libfuzzer_example -detect_leaks=0 -len_control=0 -max_len=150 -runs=10000000 -artifact_prefix=/tmp/libxml2_example_test_M8TxKG/ /tmp/libxml2_example_test_M8TxKG/ 


WARNING: unrecognized flag '-len_control=0'; use -help=1 to list all flags

INFO: Seed: 2740256283
INFO: Loaded 1 modules   (9 inline 8-bit counters): 9 [0x68c1e0, 0x68c1e9), 
INFO: Loaded 1 PC tables (9 PCs): 9 [0x479f90,0x47a020), 
INFO:        0 files found in /tmp/libxml2_example_test_M8TxKG/
INFO: A corpus is not provided, starting from an empty corpus
#2	INITED cov: 2 ft: 2 corp: 1/1b exec/s: 0 rss: 34Mb
#131072	pulse  cov: 2 ft: 2 corp: 1/1b exec/s: 65536 rss: 34Mb
#262144	pulse  cov: 2 ft: 2 corp: 1/1b exec/s: 87381 rss: 34Mb
#524288	pulse  cov: 2 ft: 2 corp: 1/1b exec/s: 87381 rss: 34Mb
#1048576	pulse  cov: 2 ft: 2 corp: 1/1b exec/s: 80659 rss: 34Mb
#2097152	pulse  cov: 2 ft: 2 corp: 1/1b exec/s: 80659 rss: 34Mb
#4194304	pulse  cov: 2 ft: 2 corp: 1/1b exec/s: 77672 rss: 34Mb
#8388608	pulse  cov: 2 ft: 2 corp: 1/1b exec/s: 79891 rss: 34Mb
#10000000	DONE   cov: 2 ft: 2 corp: 1/1b exec/s: 80645 rss: 34Mb
Done 10000000 runs in 124 second(s)
../examples/libfuzzer/libfuzzer_example_test.cc:28: Failure
Expected equality of these values:
  kDefaultLibFuzzerError
    Which is: 77
  GetError(RunFuzzer("libfuzzer_example", 150, 10000000))
    Which is: 0
[  FAILED  ] LibFuzzerExampleTest.Text (124553 ms)
[ RUN      ] LibFuzzerExampleTest.Binary
ASAN_OPTIONS=detect_leaks=0 ./libfuzzer_bin_example -detect_leaks=0 -len_control=0 -max_len=150 -runs=10000000 -artifact_prefix=/tmp/libxml2_example_test_dk0DDI/ /tmp/libxml2_example_test_dk0DDI/ 


WARNING: unrecognized flag '-len_control=0'; use -help=1 to list all flags

INFO: Seed: 2725135813
INFO: Loaded 1 modules   (9 inline 8-bit counters): 9 [0x68c1e0, 0x68c1e9), 
INFO: Loaded 1 PC tables (9 PCs): 9 [0x479f90,0x47a020), 
INFO:        0 files found in /tmp/libxml2_example_test_dk0DDI/
INFO: A corpus is not provided, starting from an empty corpus
#2	INITED cov: 2 ft: 2 corp: 1/1b exec/s: 0 rss: 34Mb
#3	NEW    cov: 3 ft: 3 corp: 2/6b exec/s: 0 rss: 34Mb L: 5/5 MS: 2 EraseBytes-Custom-
#45	REDUCE cov: 3 ft: 3 corp: 2/3b exec/s: 0 rss: 34Mb L: 2/2 MS: 3 ShuffleBytes-Custom-CustomCrossOver-
#262144	pulse  cov: 3 ft: 3 corp: 2/3b exec/s: 131072 rss: 34Mb
#524288	pulse  cov: 3 ft: 3 corp: 2/3b exec/s: 131072 rss: 34Mb
#1048576	pulse  cov: 3 ft: 3 corp: 2/3b exec/s: 131072 rss: 34Mb
#2097152	pulse  cov: 3 ft: 3 corp: 2/3b exec/s: 123361 rss: 34Mb
#4194304	pulse  cov: 3 ft: 3 corp: 2/3b exec/s: 119837 rss: 34Mb
#8388608	pulse  cov: 3 ft: 3 corp: 2/3b exec/s: 118149 rss: 34Mb
#10000000	DONE   cov: 3 ft: 3 corp: 2/3b exec/s: 117647 rss: 34Mb
Done 10000000 runs in 85 second(s)
../examples/libfuzzer/libfuzzer_example_test.cc:33: Failure
Expected equality of these values:
  kDefaultLibFuzzerError
    Which is: 77
  GetError(RunFuzzer("libfuzzer_bin_example", 150, 10000000))
    Which is: 0
[  FAILED  ] LibFuzzerExampleTest.Binary (85309 ms)
[----------] 2 tests from LibFuzzerExampleTest (209862 ms total)

[----------] Global test environment tear-down
[==========] 2 tests from 1 test case ran. (209862 ms total)
[  PASSED  ] 0 tests.
[  FAILED  ] 2 tests, listed below:
[  FAILED  ] LibFuzzerExampleTest.Text
[  FAILED  ] LibFuzzerExampleTest.Binary

 2 FAILED TESTS


95% tests passed, 1 tests failed out of 19

Total Test time (real) = 222.68 sec

The following tests FAILED:
	 18 - test.libfuzzer_example_test (Failed)
Errors while running CTest
ninja: build stopped: subcommand failed.

Unknown CMake command "protobuf_generate_cpp".

I install all the prerequisites. But ninja check failed
So I just want to build a simple demo, then it comes the flowing errors.
My Linux version : ubuntu 18.04
libprotoc version: 3.0.0
clang version: 6.0.0-1ubuntu2
cmake version: 3.10.2

raven@ubuntu:~/libprotobuf-mutator/examples/libfuzzer/build$ cmake ..
CMake Error at CMakeLists.txt:25 (protobuf_generate_cpp):
  Unknown CMake command "protobuf_generate_cpp".


CMake Warning (dev) in CMakeLists.txt:
  No cmake_minimum_required command is present.  A line of code such as

    cmake_minimum_required(VERSION 3.10)

  should be added at the top of the file.  The version specified may be lower
  if you wish to support older CMake versions for this project.  For more
  information run "cmake --help-policy CMP0000".
This warning is for project developers.  Use -Wno-dev to suppress it.

-- Configuring incomplete, errors occurred!
See also "/home/raven/libprotobuf-mutator/examples/libfuzzer/build/CMakeFiles/CMakeOutput.log".

build configuration fails with LIB_PROTO_MUTATOR_TESTING=Off

When running the following cmake code the configuration fails

cmake .. -GNinja -DCMAKE_C_COMPILER=/usr/bin/clang-7 -DCMAKE_CXX_COMPILER=/usr/bin/clang++-7 -DCMAKE_BUILD_TYPE=Debug -DLIB_PROTO_MUTATOR_TESTING=Off

cmake fails with the following output:

CMake Error at examples/expat/CMakeLists.txt:37 (add_dependencies):
Cannot add target-level dependencies to non-existent target "check".

CMake Error at examples/libfuzzer/CMakeLists.txt:21 (add_dependencies):
Cannot add target-level dependencies to non-existent target "check".

CMake Error at examples/libxml2/CMakeLists.txt:38 (add_dependencies):
Cannot add target-level dependencies to non-existent target "check".

build failure

I build protobuf-mutator using the command
"cmake .. -GNinja -DCMAKE_C_COMPILER=clang -DCMAKE_CXX_COMPILER=clang++ -DCMAKE_BUILD_TYPE=Debug -DLIB_PROTO_MUTATOR_DOWNLOAD_PROTOBUF=ON
"

After this I use "ninja check" and the result is
"cd ~/pro.../usr/bin/ctest -j4 --output-on-failure
Test project ~/protobuf/libprotobuf-mutator/build"

[Feature] make install and pkg-config support

This is for discussion and tracking of adding support for make install and a pkg-config that can be used for finding headers and linking against the libprotobuf-mutator static libraries.

How to use protobuf_mutator::Mutator::Mutate

The test code I wrote is as follows:

#include "compare.pb.h"
#include "src/mutator.h"
#include <bits/stdc++.h>

using std::cin;
using std::cout;
using std::endl;

class MyMutator : public protobuf_mutator::Mutator {
};


int main(int argc, char *argv[])
{
    TEST t;
    t.set_a(101);
    t.set_b("testtest");
    cout << t.a() << endl;
    cout << t.b() << endl;

    static MyMutator mutator;
    mutator.Seed(1);
    mutator.Mutate(&t, 100);
    cout << t.a() << endl;
    cout << t.b() << endl;

    return 0;
}

Then use the following method to compile: clang++ compare.cc compare.pb.cc -lprotobuf -lprotobuf-mutator -L /usr/local/lib/ -I /usr/local/include/libprotobuf-mutator

A coredump occurs during the running.
#0 0x00000000004304d5 in TEST_default_instance ()
#1 0x000000000041137c in google::protobuf::Message::GetDescriptor (this=0x7fffffffe328) at external.protobuf/include/google/protobuf/message.h:356
#2 0x000000000040d72e in protobuf_mutator::(anonymous namespace)::CastToAny (message=0x7fffffffe328) at ../src/mutator.cc:387
#3 0x000000000040d6da in protobuf_mutator::(anonymous namespace)::UnpackIfAny (message=warning: RTTI symbol not found for class 'TEST'
...) at ../src/mutator.cc:399
#4 0x000000000040aecd in protobuf_mutator::(anonymous namespace)::UnpackAny (message=warning: RTTI symbol not found for class 'TEST'
..., result=0x7fffffffe250) at ../src/mutator.cc:404
#5 0x000000000040b688 in protobuf_mutator::Mutator::Mutate (this=0x4306e0 main::mutator, message=0x7fffffffe328, max_size_hint=100) at ../src/mutator.cc:639
#6 0x0000000000406d55 in main ()
#7 0x00007ffff77c70b3 in __libc_start_main (main=0x406b80

, argc=1, argv=0x7fffffffe468, init=, fini=, rtld_fini=, stack_end=0x7fffffffe458) at ../csu/libc-start.c:308
#8 0x0000000000406abe in _start ()

Crash when using `CustomProtoMutator` for multiple protos

I have multiple protos that I need to mutate in a libFuzzer fuzz target and am thus calling CustomProtoMutator directly instead of using the macro. However, the Swap calls in the LastMutationCache crash when trying to swap out one proto for another:

[libprotobuf FATAL external/com_google_protobuf/src/google/protobuf/generated_message_reflection.cc:614] CHECK failed: (message2->GetReflection()) == (this): Second argument to Swap() (of type "some_proto") is not compatible with this reflection object (which is for type "some_other_proto"). Note that the exact same class is required; not just the same descriptor.

Patching out the cache resolved this issue. Would it be possible to either invalidate the cache if a new proto is mutated or add a way to disable the cache in CustomProtoMutator calls?

Incompatibility with minimize_crash=1

We've been using libprotobuf-mutator happily to fuzz an implementation of a programming language. One big obstacle however has been that crash minimization doesn't seem to work properly with this.

Specifically, when running the minimization with minimize_crash=1 it looks as if the fuzzer stops using the mutator and does byte-based mutation instead, which in practice basically never shrinks the test case in an interesting way.

Is this expected? Is this a limitation of this library or of libFuzzer itself?

example for nested callback doesn't work

Fails with no matching constructor for initialization of PostProcessorRegistration<MyMessageType>.

Whereas this appears to work.

static protobuf_mutator::libfuzzer::PostProcessorRegistration<MyMessageType::Nested> reg_nested = {
  [](MyMessageType::Nested* message, unsigned int seed) {
  }};

Custom semantic mutators

Hello,

Would it be possible to permit overriding the mutate implementation of libprotobuf-mutator? Use case is semantic mutation.

Example:

input

ifstmt {
  condition {
       varref {
          id: "x"
       }
  }
...
}

converts to if (x) { do_something }. On this, I would like to define a mutation that flips the condition to if !x { do something}, the mutated protobuf input being

ifstmt {
   condition {
      not {
        varref {
           id: "x"
        }
     }
  }
}

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.