Support binary serialization of protos.
diff --git a/examples/libfuzzer/CMakeLists.txt b/examples/libfuzzer/CMakeLists.txt
index 173363c..f6f2dbf 100644
--- a/examples/libfuzzer/CMakeLists.txt
+++ b/examples/libfuzzer/CMakeLists.txt
@@ -12,26 +12,32 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
-protobuf_generate_cpp(LIB_FUZZER_EXAMPLE_PROTO_SRCS
-                      LIB_FUZZER_EXAMPLE_PROTO_HDRS
-                      libfuzzer_example.proto)
-add_executable(libfuzzer_example
-               libfuzzer_example.cc
-               ${LIB_FUZZER_EXAMPLE_PROTO_SRCS})
-target_link_libraries(libfuzzer_example
-                      protobuf-mutator
-                      ${LIB_PROTO_MUTATOR_FUZZER_LIBRARIES})
-set_property(TARGET libfuzzer_example
-             PROPERTY COMPILE_FLAGS ${FUZZING_FLAGS})
-set_property(TARGET libfuzzer_example
-             PROPERTY LINK_FLAGS ${FUZZING_FLAGS})
-
 add_executable(libfuzzer_example_test
                libfuzzer_example_test.cc)
-add_dependencies(libfuzzer_example_test libfuzzer_example)
 target_link_libraries(libfuzzer_example_test
                       ${GTEST_BOTH_LIBRARIES}
                       ${CMAKE_THREAD_LIBS_INIT})
 add_test(test.libfuzzer_example_test libfuzzer_example_test --gtest_color=yes AUTO)
-
 add_dependencies(check libfuzzer_example_test)
+
+protobuf_generate_cpp(LIB_FUZZER_EXAMPLE_PROTO_SRCS
+                      LIB_FUZZER_EXAMPLE_PROTO_HDRS
+                      libfuzzer_example.proto)
+
+add_library(fuzzer-example-proto
+            ${LIB_FUZZER_EXAMPLE_PROTO_SRCS})
+set_property(TARGET fuzzer-example-proto
+             PROPERTY COMPILE_FLAGS ${NO_FUZZING_FLAGS})
+
+foreach(fuzzer libfuzzer_example libfuzzer_bin_example)
+  add_executable(${fuzzer} ${fuzzer}.cc)
+  target_link_libraries(${fuzzer}
+                        fuzzer-example-proto
+                        protobuf-mutator
+                        ${LIB_PROTO_MUTATOR_FUZZER_LIBRARIES})
+  set_property(TARGET ${fuzzer}
+               PROPERTY COMPILE_FLAGS ${FUZZING_FLAGS})
+  set_property(TARGET ${fuzzer}
+               PROPERTY LINK_FLAGS ${FUZZING_FLAGS})
+  add_dependencies(libfuzzer_example_test ${fuzzer})
+endforeach(fuzzer)
diff --git a/examples/libfuzzer/libfuzzer_bin_example.cc b/examples/libfuzzer/libfuzzer_bin_example.cc
new file mode 100644
index 0000000..87dd7fd
--- /dev/null
+++ b/examples/libfuzzer/libfuzzer_bin_example.cc
@@ -0,0 +1,47 @@
+// Copyright 2017 Google Inc. All rights reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include <cstddef>
+#include <cstdint>
+
+#include "examples/libfuzzer/libfuzzer_example.pb.h"
+#include "src/libfuzzer_protobuf_mutator.h"
+
+using libfuzzer_example::Msg;
+
+extern "C" size_t LLVMFuzzerCustomMutator(uint8_t* data, size_t size,
+                                          size_t max_size, unsigned int seed) {
+  return protobuf_mutator::MutateBinaryMessage<Msg>(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::CrossOverBinaryMessages<Msg>(
+      data1, size1, data2, size2, out, max_out_size, seed);
+}
+
+extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
+  libfuzzer_example::Msg message;
+  protobuf_mutator::ParseBinaryMessage(data, size, &message);
+
+  // Emulate a bug.
+  if (message.optional_bool() &&
+      std::hash<std::string>()(message.optional_string()) % 1000 == 9) {
+    abort();
+  }
+
+  return 0;
+}
diff --git a/examples/libfuzzer/libfuzzer_example_test.cc b/examples/libfuzzer/libfuzzer_example_test.cc
index 8401a9e..a142553 100644
--- a/examples/libfuzzer/libfuzzer_example_test.cc
+++ b/examples/libfuzzer/libfuzzer_example_test.cc
@@ -32,3 +32,17 @@
   // Cleanup.
   EXPECT_EQ(0, std::system((std::string("rm -rf ") + dir).c_str()));
 }
+
+TEST(LibFuzzerExampleTest, CrashBinary) {
+  char dir_template[] = "/tmp/libfuzzer_example_test_XXXXXX";
+  auto dir = mkdtemp(dir_template);
+  ASSERT_TRUE(dir);
+
+  std::string cmd = "./libfuzzer_bin_example -max_len=150 -artifact_prefix=" +
+                    std::string(dir) + "/ " + dir + "/";
+  int retvalue = std::system(cmd.c_str());
+  EXPECT_EQ(kDefaultLibFuzzerError, WSTOPSIG(retvalue));
+
+  // Cleanup.
+  EXPECT_EQ(0, std::system((std::string("rm -rf ") + dir).c_str()));
+}
diff --git a/port/protobuf.h b/port/protobuf.h
index a0311df..6c5bc78 100644
--- a/port/protobuf.h
+++ b/port/protobuf.h
@@ -32,6 +32,13 @@
   if (!protobuf::TextFormat::PrintToString(message, &tmp)) return {};
   return tmp;
 }
+
+inline std::string MessageToBinaryString(const protobuf::Message& message) {
+  std::string tmp;
+  if (!message.SerializeToString(&tmp)) return {};
+  return tmp;
+}
+
 }  // namespace protobuf_mutator
 
 #endif  // PORT_PROTOBUF_H_
diff --git a/src/libfuzzer_protobuf_mutator.cc b/src/libfuzzer_protobuf_mutator.cc
index ffe4e41..8445866 100644
--- a/src/libfuzzer_protobuf_mutator.cc
+++ b/src/libfuzzer_protobuf_mutator.cc
@@ -88,8 +88,26 @@
   }
 };
 
-size_t MutateTextMessage(unsigned int seed, const InputReader& input,
-                         OutputWriter* output, Message* message) {
+class BinaryInputReader : public InputReader {
+ public:
+  using InputReader::InputReader;
+
+  bool Read(protobuf::Message* message) const override {
+    return ParseBinaryMessage(data(), size(), message);
+  }
+};
+
+class BinaryOutputWriter : public OutputWriter {
+ public:
+  using OutputWriter::OutputWriter;
+
+  size_t Write(const protobuf::Message& message) override {
+    return SaveMessageAsBinary(message, data(), size());
+  }
+};
+
+size_t MutateMessage(unsigned int seed, const InputReader& input,
+                     OutputWriter* output, Message* message) {
   protobuf_mutator::LibFuzzerProtobufMutator mutator(seed);
   for (int i = 0; i < 100; ++i) {
     input.Read(message);
@@ -104,10 +122,10 @@
   return 0;
 }
 
-size_t CrossOverTextMessages(unsigned int seed, const InputReader& input1,
-                             const InputReader& input2, OutputWriter* output,
-                             protobuf::Message* message1,
-                             protobuf::Message* message2) {
+size_t CrossOverMessages(unsigned int seed, const InputReader& input1,
+                         const InputReader& input2, OutputWriter* output,
+                         protobuf::Message* message1,
+                         protobuf::Message* message2) {
   protobuf_mutator::LibFuzzerProtobufMutator mutator(seed);
   input2.Read(message2);
   for (int i = 0; i < 100; ++i) {
@@ -184,13 +202,36 @@
   return MessageToTextString(message);
 }
 
+bool ParseBinaryMessage(const uint8_t* data, size_t size, Message* output) {
+  return ParseBinaryMessage({data, data + size}, output);
+}
+
+bool ParseBinaryMessage(const std::string& data, protobuf::Message* output) {
+  output->Clear();
+  return output->ParsePartialFromString(data);
+}
+
+size_t SaveMessageAsBinary(const Message& message, uint8_t* data,
+                           size_t max_size) {
+  std::string result = SaveMessageAsBinary(message);
+  if (result.size() <= max_size) {
+    memcpy(data, result.data(), result.size());
+    return result.size();
+  }
+  return 0;
+}
+
+std::string SaveMessageAsBinary(const protobuf::Message& message) {
+  return MessageToBinaryString(message);
+}
+
 namespace internal {
 
 size_t MutateTextMessage(uint8_t* data, size_t size, size_t max_size,
                          unsigned int seed, protobuf::Message* message) {
   TextInputReader input(data, size);
   TextOutputWriter output(data, max_size);
-  return MutateTextMessage(seed, input, &output, message);
+  return MutateMessage(seed, input, &output, message);
 }
 
 size_t CrossOverTextMessages(const uint8_t* data1, size_t size1,
@@ -201,8 +242,25 @@
   TextInputReader input1(data1, size1);
   TextInputReader input2(data2, size2);
   TextOutputWriter output(out, max_out_size);
-  return CrossOverTextMessages(seed, input1, input2, &output, message1,
-                               message2);
+  return CrossOverMessages(seed, input1, input2, &output, message1, message2);
+}
+
+size_t MutateBinaryMessage(uint8_t* data, size_t size, size_t max_size,
+                           unsigned int seed, protobuf::Message* message) {
+  BinaryInputReader input(data, size);
+  BinaryOutputWriter output(data, max_size);
+  return MutateMessage(seed, input, &output, message);
+}
+
+size_t CrossOverBinaryMessages(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,
+                               protobuf::Message* message1,
+                               protobuf::Message* message2) {
+  BinaryInputReader input1(data1, size1);
+  BinaryInputReader input2(data2, size2);
+  BinaryOutputWriter output(out, max_out_size);
+  return CrossOverMessages(seed, input1, input2, &output, message1, message2);
 }
 
 }  // namespace internal
diff --git a/src/libfuzzer_protobuf_mutator.h b/src/libfuzzer_protobuf_mutator.h
index 59aea68..9d1cd38 100644
--- a/src/libfuzzer_protobuf_mutator.h
+++ b/src/libfuzzer_protobuf_mutator.h
@@ -50,6 +50,14 @@
                          size_t max_size);
 std::string SaveMessageAsText(const protobuf::Message& message);
 
+// Same as above but for binary serialization.
+bool ParseBinaryMessage(const uint8_t* data, size_t size,
+                        protobuf::Message* output);
+bool ParseBinaryMessage(const std::string& data, protobuf::Message* output);
+size_t SaveMessageAsBinary(const protobuf::Message& message, uint8_t* data,
+                           size_t max_size);
+std::string SaveMessageAsBinary(const protobuf::Message& message);
+
 namespace internal {
 size_t MutateTextMessage(uint8_t* data, size_t size, size_t max_size,
                          unsigned int seed, protobuf::Message* message);
@@ -58,6 +66,13 @@
                              size_t max_out_size, unsigned int seed,
                              protobuf::Message* message1,
                              protobuf::Message* message2);
+size_t MutateBinaryMessage(uint8_t* data, size_t size, size_t max_size,
+                           unsigned int seed, protobuf::Message* message);
+size_t CrossOverBinaryMessages(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,
+                               protobuf::Message* message1,
+                               protobuf::Message* message2);
 }  // namespace internal
 
 // Mutates proto serialized as text.
@@ -80,6 +95,26 @@
                                          &message2);
 }
 
+// Mutates proto serialized as binary.
+template <class MessageType>
+size_t MutateBinaryMessage(uint8_t* data, size_t size, size_t max_size,
+                           unsigned int seed) {
+  MessageType message;
+  return internal::MutateBinaryMessage(data, size, max_size, seed, &message);
+}
+
+// Crossover two protos serialized as binary.
+template <class MessageType>
+size_t CrossOverBinaryMessages(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) {
+  MessageType message1;
+  MessageType message2;
+  return internal::CrossOverBinaryMessages(data1, size1, data2, size2, out,
+                                           max_out_size, seed, &message1,
+                                           &message2);
+}
+
 }  // namespace protobuf_mutator
 
 #endif  // SRC_LIBFUZZER_PROTOBUF_MUTATOR_H_