Import c9a1e56750a4eef6ffca95f41f79f06979056e01 into master
am: f9fc8f8397

Change-Id: I3d055cf1811d6d6044d4095d9d75cd95779bcc7b
diff --git a/.clang-format b/.clang-format
new file mode 100644
index 0000000..3d22e0a
--- /dev/null
+++ b/.clang-format
@@ -0,0 +1 @@
+BasedOnStyle:  Google
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..567609b
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1 @@
+build/
diff --git a/.travis.yml b/.travis.yml
new file mode 100644
index 0000000..6b55737
--- /dev/null
+++ b/.travis.yml
@@ -0,0 +1,60 @@
+os: linux
+dist: trusty
+sudo: false
+
+language: cpp
+
+addons:
+  apt:
+    packages: &common_packages
+      - ninja-build
+      - liblzma-dev
+      - libz-dev
+    sources: &common_sources
+      - ubuntu-toolchain-r-test
+
+env:
+  global: CLANG_VERSION=7 GCC_VERSION=7
+
+matrix:
+  include:
+    - env: BUILD_TYPE=Release CC_COMPILER=clang-${CLANG_VERSION} CXX_COMPILER=clang++-${CLANG_VERSION}
+      addons: &clang
+        apt:
+          packages:
+            - *common_packages
+            - clang-7
+          sources:
+            - *common_sources
+            - sourceline: 'deb http://apt.llvm.org/jessie/ llvm-toolchain-jessie main'
+              key_url: 'https://apt.llvm.org/llvm-snapshot.gpg.key'
+
+    - env: BUILD_TYPE=Debug CC_COMPILER=clang-${CLANG_VERSION} CXX_COMPILER=clang++-${CLANG_VERSION}
+      addons: *clang
+
+    - env: BUILD_TYPE=Release CC_COMPILER=gcc-${GCC_VERSION} CXX_COMPILER=g++-${GCC_VERSION}
+      addons: &gcc
+        apt:
+          packages:
+            - *common_packages
+            - g++-7
+            - gcc-7
+          sources:
+            - *common_sources
+
+install:
+  - mkdir -p deps && cd deps
+  - travis_retry wget --no-check-certificate --quiet -O - https://cmake.org/files/v3.7/cmake-3.7.1-Linux-x86_64.tar.gz | tar --strip-components=1 -xz
+  - export PATH=${TRAVIS_BUILD_DIR}/deps/bin:${PATH}
+  - cd -
+
+before_script:
+  - travis_retry wget --quiet -O - https://raw.githubusercontent.com/cpplint/cpplint/master/cpplint.py | python - --recursive src examples
+  - mkdir -p build && cd build
+  - rm -rf *
+  - cmake .. -GNinja -DLIB_PROTO_MUTATOR_WITH_ASAN=ON -DLIB_PROTO_MUTATOR_DOWNLOAD_PROTOBUF=ON -DCMAKE_C_COMPILER=${CC_COMPILER} -DCMAKE_CXX_COMPILER=${CXX_COMPILER} -DCMAKE_BUILD_TYPE=${BUILD_TYPE} -DLIB_PROTO_MUTATOR_CTEST_JOBS=8
+
+script:
+  - export ASAN_OPTIONS=detect_leaks=0
+  - ninja
+  - ninja check
diff --git a/AUTHORS b/AUTHORS
new file mode 100644
index 0000000..5ee9017
--- /dev/null
+++ b/AUTHORS
@@ -0,0 +1,8 @@
+# This is the official list of the fuzzer-test-suite project authors for copyright purposes.
+# This file is distinct from the CONTRIBUTORS file. See the latter for an explanation.
+
+# Names should be added to this file as
+#  Name or Organization
+# Email addresses for individuals are tracked elsewhere to avoid spam.
+
+Google Inc.
diff --git a/CMakeLists.txt b/CMakeLists.txt
new file mode 100644
index 0000000..c018d45
--- /dev/null
+++ b/CMakeLists.txt
@@ -0,0 +1,129 @@
+# Copyright 2016 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.
+
+cmake_minimum_required(VERSION 3.5)
+project(LibProtobufMutator CXX)
+
+enable_language(C)
+enable_language(CXX)
+
+option(LIB_PROTO_MUTATOR_DOWNLOAD_PROTOBUF
+       "Automatically download working protobuf" OFF)
+option(LIB_PROTO_MUTATOR_WITH_ASAN "Enable address sanitizer" OFF)
+set(LIB_PROTO_MUTATOR_FUZZER_LIBRARIES "" CACHE STRING "Fuzzing engine libs")
+
+# External dependencies
+set(CMAKE_MODULE_PATH ${PROJECT_SOURCE_DIR}/cmake/external)
+
+# External dependencies
+include(ProcessorCount)
+include(CheckCCompilerFlag)
+include(CheckCXXCompilerFlag)
+
+set(THREADS_PREFER_PTHREAD_FLAG ON)
+find_package(Threads)
+
+find_package(LibLZMA)
+include_directories(${LIBLZMA_INCLUDE_DIRS})
+
+find_package(ZLIB)
+include_directories(${ZLIB_INCLUDE_DIRS})
+
+set(CMAKE_CXX_STANDARD 11)
+
+include_directories(${PROJECT_SOURCE_DIR})
+
+set(CMAKE_REQUIRED_FLAGS "-fsanitize=address")
+check_cxx_compiler_flag(-fsanitize=address LIB_PROTO_MUTATOR_HAS_SANITIZE_ADDRESS)
+check_cxx_compiler_flag("-fsanitize=address -fsanitize-address-use-after-scope"
+                        LIB_PROTO_MUTATOR_HAS_SANITIZE_SCOPE)
+unset(CMAKE_REQUIRED_FLAGS)
+
+set(CMAKE_REQUIRED_FLAGS "-fsanitize-coverage=0")
+check_cxx_compiler_flag(-fsanitize-coverage= LIB_PROTO_MUTATOR_HAS_NO_COVERAGE)
+unset(CMAKE_REQUIRED_FLAGS)
+
+set(CMAKE_REQUIRED_FLAGS "-fsanitize=fuzzer-no-link")
+check_cxx_compiler_flag(-fsanitize=fuzzer-no-link LIB_PROTO_MUTATOR_HAS_SANITIZE_FUZZER)
+unset(CMAKE_REQUIRED_FLAGS)
+
+set(CMAKE_REQUIRED_FLAGS "-fno-sanitize=fuzzer")
+check_cxx_compiler_flag(-fno-sanitize=fuzzer LIB_PROTO_MUTATOR_HAS_NO_SANITIZE_FUZZER)
+unset(CMAKE_REQUIRED_FLAGS)
+
+check_cxx_compiler_flag(-Wstring-conversion LIB_PROTO_MUTATOR_HAS_WSTRING_CONVERSION)
+
+set(EXTRA_FLAGS "-fno-exceptions -Werror -Wall")
+if (LIB_PROTO_MUTATOR_HAS_WSTRING_CONVERSION)
+  set(EXTRA_FLAGS "${EXTRA_FLAGS} -Wstring-conversion")
+endif()
+
+if (LIB_PROTO_MUTATOR_WITH_ASAN)
+  if (LIB_PROTO_MUTATOR_HAS_SANITIZE_ADDRESS)
+    set(EXTRA_FLAGS "${EXTRA_FLAGS} -fsanitize=address")
+    if (LIB_PROTO_MUTATOR_HAS_SANITIZE_SCOPE)
+      set(EXTRA_FLAGS "${EXTRA_FLAGS} -fsanitize-address-use-after-scope")
+    endif()
+  endif()
+endif()
+
+# Assume CFLAGS has coverage options if LIB_PROTO_MUTATOR_FUZZER_LIBRARIES was set
+if ("${LIB_PROTO_MUTATOR_FUZZER_LIBRARIES}" STREQUAL "")
+  if (LIB_PROTO_MUTATOR_HAS_SANITIZE_FUZZER)
+    set(FUZZING_FLAGS "-fsanitize=fuzzer-no-link")
+    set(FUZZING_FLAGS_BINARY "-fsanitize=fuzzer")
+  endif()
+  if (LIB_PROTO_MUTATOR_HAS_SANITIZE_NO_FUZZER)
+    set(NO_FUZZING_FLAGS "-fno-sanitize=fuzzer")
+  endif()
+endif()
+if (LIB_PROTO_MUTATOR_HAS_NO_COVERAGE)
+  set(NO_FUZZING_FLAGS "${NO_FUZZING_FLAGS} -fsanitize-coverage=0")
+endif()
+
+set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${EXTRA_FLAGS}")
+set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${EXTRA_FLAGS}")
+
+set(PROTOBUF_CFLAGS "${CMAKE_C_FLAGS} ${NO_FUZZING_FLAGS} -w")
+set(PROTOBUF_CXXFLAGS "${CMAKE_CXX_FLAGS} ${NO_FUZZING_FLAGS} -w")
+if(CMAKE_USE_PTHREADS_INIT)
+  set(PROTOBUF_CFLAGS "${PROTOBUF_CFLAGS} -pthread")
+  set(PROTOBUF_CXXFLAGS "${PROTOBUF_CXXFLAGS} -pthread")
+endif()
+
+if (LIB_PROTO_MUTATOR_DOWNLOAD_PROTOBUF)
+  include(protobuf)
+else()
+  find_package(Protobuf REQUIRED)
+  include_directories(${PROTOBUF_INCLUDE_DIRS})
+  include_directories(${CMAKE_CURRENT_BINARY_DIR})
+endif()
+
+enable_testing()
+
+include(googletest)
+
+if (NOT LIB_PROTO_MUTATOR_CTEST_JOBS)
+  ProcessorCount(LIB_PROTO_MUTATOR_CTEST_JOBS)
+endif()
+add_custom_target(check
+                  COMMAND ${CMAKE_CTEST_COMMAND} -j${LIB_PROTO_MUTATOR_CTEST_JOBS} --output-on-failure)
+
+add_subdirectory(src)
+
+if (NOT "${LIB_PROTO_MUTATOR_FUZZER_LIBRARIES}" STREQUAL "" OR
+    NOT "${FUZZING_FLAGS}" STREQUAL "")
+  add_subdirectory(examples EXCLUDE_FROM_ALL)
+endif()
+
diff --git a/CONTRIBUTING b/CONTRIBUTING
new file mode 100644
index 0000000..1a09deb
--- /dev/null
+++ b/CONTRIBUTING
@@ -0,0 +1,27 @@
+Want to contribute? Great! First, read this page (including the small print at the end).
+
+### Before you contribute
+Before we can use your code, you must sign the
+[Google Individual Contributor License Agreement]
+(https://cla.developers.google.com/about/google-individual)
+(CLA), which you can do online. The CLA is necessary mainly because you own the
+copyright to your changes, even after your contribution becomes part of our
+codebase, so we need your permission to use and distribute your code. We also
+need to be sure of various other things—for instance that you'll tell us if you
+know that your code infringes on other people's patents. You don't have to sign
+the CLA until after you've submitted your code for review and a member has
+approved it, but you must do it before we can put your code into our codebase.
+Before you start working on a larger contribution, you should get in touch with
+us first through the issue tracker with your idea so that we can help out and
+possibly guide you. Coordinating up front makes it much easier to avoid
+frustration later on.
+
+### Code reviews
+All submissions, including submissions by project members, require review. We
+use GitHub pull requests for this purpose.
+
+### The small print
+Contributions made by corporations are covered by a different agreement than
+the one above, the
+[Software Grant and Corporate Contributor License Agreement]
+(https://cla.developers.google.com/about/google-corporate).
diff --git a/LICENSE b/LICENSE
new file mode 100644
index 0000000..d645695
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,202 @@
+
+                                 Apache License
+                           Version 2.0, January 2004
+                        http://www.apache.org/licenses/
+
+   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+   1. Definitions.
+
+      "License" shall mean the terms and conditions for use, reproduction,
+      and distribution as defined by Sections 1 through 9 of this document.
+
+      "Licensor" shall mean the copyright owner or entity authorized by
+      the copyright owner that is granting the License.
+
+      "Legal Entity" shall mean the union of the acting entity and all
+      other entities that control, are controlled by, or are under common
+      control with that entity. For the purposes of this definition,
+      "control" means (i) the power, direct or indirect, to cause the
+      direction or management of such entity, whether by contract or
+      otherwise, or (ii) ownership of fifty percent (50%) or more of the
+      outstanding shares, or (iii) beneficial ownership of such entity.
+
+      "You" (or "Your") shall mean an individual or Legal Entity
+      exercising permissions granted by this License.
+
+      "Source" form shall mean the preferred form for making modifications,
+      including but not limited to software source code, documentation
+      source, and configuration files.
+
+      "Object" form shall mean any form resulting from mechanical
+      transformation or translation of a Source form, including but
+      not limited to compiled object code, generated documentation,
+      and conversions to other media types.
+
+      "Work" shall mean the work of authorship, whether in Source or
+      Object form, made available under the License, as indicated by a
+      copyright notice that is included in or attached to the work
+      (an example is provided in the Appendix below).
+
+      "Derivative Works" shall mean any work, whether in Source or Object
+      form, that is based on (or derived from) the Work and for which the
+      editorial revisions, annotations, elaborations, or other modifications
+      represent, as a whole, an original work of authorship. For the purposes
+      of this License, Derivative Works shall not include works that remain
+      separable from, or merely link (or bind by name) to the interfaces of,
+      the Work and Derivative Works thereof.
+
+      "Contribution" shall mean any work of authorship, including
+      the original version of the Work and any modifications or additions
+      to that Work or Derivative Works thereof, that is intentionally
+      submitted to Licensor for inclusion in the Work by the copyright owner
+      or by an individual or Legal Entity authorized to submit on behalf of
+      the copyright owner. For the purposes of this definition, "submitted"
+      means any form of electronic, verbal, or written communication sent
+      to the Licensor or its representatives, including but not limited to
+      communication on electronic mailing lists, source code control systems,
+      and issue tracking systems that are managed by, or on behalf of, the
+      Licensor for the purpose of discussing and improving the Work, but
+      excluding communication that is conspicuously marked or otherwise
+      designated in writing by the copyright owner as "Not a Contribution."
+
+      "Contributor" shall mean Licensor and any individual or Legal Entity
+      on behalf of whom a Contribution has been received by Licensor and
+      subsequently incorporated within the Work.
+
+   2. Grant of Copyright License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      copyright license to reproduce, prepare Derivative Works of,
+      publicly display, publicly perform, sublicense, and distribute the
+      Work and such Derivative Works in Source or Object form.
+
+   3. Grant of Patent License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      (except as stated in this section) patent license to make, have made,
+      use, offer to sell, sell, import, and otherwise transfer the Work,
+      where such license applies only to those patent claims licensable
+      by such Contributor that are necessarily infringed by their
+      Contribution(s) alone or by combination of their Contribution(s)
+      with the Work to which such Contribution(s) was submitted. If You
+      institute patent litigation against any entity (including a
+      cross-claim or counterclaim in a lawsuit) alleging that the Work
+      or a Contribution incorporated within the Work constitutes direct
+      or contributory patent infringement, then any patent licenses
+      granted to You under this License for that Work shall terminate
+      as of the date such litigation is filed.
+
+   4. Redistribution. You may reproduce and distribute copies of the
+      Work or Derivative Works thereof in any medium, with or without
+      modifications, and in Source or Object form, provided that You
+      meet the following conditions:
+
+      (a) You must give any other recipients of the Work or
+          Derivative Works a copy of this License; and
+
+      (b) You must cause any modified files to carry prominent notices
+          stating that You changed the files; and
+
+      (c) You must retain, in the Source form of any Derivative Works
+          that You distribute, all copyright, patent, trademark, and
+          attribution notices from the Source form of the Work,
+          excluding those notices that do not pertain to any part of
+          the Derivative Works; and
+
+      (d) If the Work includes a "NOTICE" text file as part of its
+          distribution, then any Derivative Works that You distribute must
+          include a readable copy of the attribution notices contained
+          within such NOTICE file, excluding those notices that do not
+          pertain to any part of the Derivative Works, in at least one
+          of the following places: within a NOTICE text file distributed
+          as part of the Derivative Works; within the Source form or
+          documentation, if provided along with the Derivative Works; or,
+          within a display generated by the Derivative Works, if and
+          wherever such third-party notices normally appear. The contents
+          of the NOTICE file are for informational purposes only and
+          do not modify the License. You may add Your own attribution
+          notices within Derivative Works that You distribute, alongside
+          or as an addendum to the NOTICE text from the Work, provided
+          that such additional attribution notices cannot be construed
+          as modifying the License.
+
+      You may add Your own copyright statement to Your modifications and
+      may provide additional or different license terms and conditions
+      for use, reproduction, or distribution of Your modifications, or
+      for any such Derivative Works as a whole, provided Your use,
+      reproduction, and distribution of the Work otherwise complies with
+      the conditions stated in this License.
+
+   5. Submission of Contributions. Unless You explicitly state otherwise,
+      any Contribution intentionally submitted for inclusion in the Work
+      by You to the Licensor shall be under the terms and conditions of
+      this License, without any additional terms or conditions.
+      Notwithstanding the above, nothing herein shall supersede or modify
+      the terms of any separate license agreement you may have executed
+      with Licensor regarding such Contributions.
+
+   6. Trademarks. This License does not grant permission to use the trade
+      names, trademarks, service marks, or product names of the Licensor,
+      except as required for reasonable and customary use in describing the
+      origin of the Work and reproducing the content of the NOTICE file.
+
+   7. Disclaimer of Warranty. Unless required by applicable law or
+      agreed to in writing, Licensor provides the Work (and each
+      Contributor provides its Contributions) on an "AS IS" BASIS,
+      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+      implied, including, without limitation, any warranties or conditions
+      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+      PARTICULAR PURPOSE. You are solely responsible for determining the
+      appropriateness of using or redistributing the Work and assume any
+      risks associated with Your exercise of permissions under this License.
+
+   8. Limitation of Liability. In no event and under no legal theory,
+      whether in tort (including negligence), contract, or otherwise,
+      unless required by applicable law (such as deliberate and grossly
+      negligent acts) or agreed to in writing, shall any Contributor be
+      liable to You for damages, including any direct, indirect, special,
+      incidental, or consequential damages of any character arising as a
+      result of this License or out of the use or inability to use the
+      Work (including but not limited to damages for loss of goodwill,
+      work stoppage, computer failure or malfunction, or any and all
+      other commercial damages or losses), even if such Contributor
+      has been advised of the possibility of such damages.
+
+   9. Accepting Warranty or Additional Liability. While redistributing
+      the Work or Derivative Works thereof, You may choose to offer,
+      and charge a fee for, acceptance of support, warranty, indemnity,
+      or other liability obligations and/or rights consistent with this
+      License. However, in accepting such obligations, You may act only
+      on Your own behalf and on Your sole responsibility, not on behalf
+      of any other Contributor, and only if You agree to indemnify,
+      defend, and hold each Contributor harmless for any liability
+      incurred by, or claims asserted against, such Contributor by reason
+      of your accepting any such warranty or additional liability.
+
+   END OF TERMS AND CONDITIONS
+
+   APPENDIX: How to apply the Apache License to your work.
+
+      To apply the Apache License to your work, attach the following
+      boilerplate notice, with the fields enclosed by brackets "[]"
+      replaced with your own identifying information. (Don't include
+      the brackets!)  The text should be enclosed in the appropriate
+      comment syntax for the file format. We also recommend that a
+      file or class name and description of purpose be included on the
+      same "printed page" as the copyright notice for easier
+      identification within third-party archives.
+
+   Copyright [yyyy] [name of copyright owner]
+
+   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.
diff --git a/README.md b/README.md
new file mode 100644
index 0000000..1470339
--- /dev/null
+++ b/README.md
@@ -0,0 +1,82 @@
+# libprotobuf-mutator
+
+## Overview
+libprotobuf-mutator is a library to randomly mutate
+[protobuffers](https://github.com/google/protobuf). <BR>
+It could be used together with guided
+fuzzing engines, such as [libFuzzer](http://libfuzzer.info).
+
+## Quick start on Debian/Ubuntu
+
+Install prerequisites:
+
+```
+sudo apt-get update
+sudo apt-get install binutils cmake ninja-build liblzma-dev libz-dev pkg-config
+```
+
+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. <BR>
+By default, the system-installed version of
+[protobuf](https://github.com/google/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.
+
+## Usage
+
+To use libprotobuf-mutator simply include
+[mutator.h](/src/mutator.h) and
+[mutator.cc](/src/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](http://libfuzzer.info)'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
+[mutator_test.cc](/src/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](/examples/libfuzzer/libfuzzer_example.cc) as an example.
+
+## 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.
diff --git a/cmake/external/expat.cmake b/cmake/external/expat.cmake
new file mode 100644
index 0000000..6bb1769
--- /dev/null
+++ b/cmake/external/expat.cmake
@@ -0,0 +1,49 @@
+# 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.
+
+set(EXPAT_TARGET external.expat)
+set(EXPAT_INSTALL_DIR ${CMAKE_CURRENT_BINARY_DIR}/${EXPAT_TARGET})
+set(EXPAT_SRC_DIR ${EXPAT_INSTALL_DIR}/src/${EXPAT_TARGET}/expat)
+
+set(EXPAT_INCLUDE_DIRS ${EXPAT_INSTALL_DIR}/include/)
+include_directories(${EXPAT_INCLUDE_DIRS})
+
+list(APPEND EXPAT_LIBRARIES expat)
+
+foreach(lib IN LISTS EXPAT_LIBRARIES)
+  list(APPEND EXPAT_BUILD_BYPRODUCTS ${EXPAT_INSTALL_DIR}/lib/lib${lib}.a)
+
+  add_library(${lib} STATIC IMPORTED)
+  set_property(TARGET ${lib} PROPERTY IMPORTED_LOCATION
+               ${EXPAT_INSTALL_DIR}/lib/lib${lib}.a)
+  add_dependencies(${lib} ${EXPAT_TARGET})
+endforeach(lib)
+
+include (ExternalProject)
+ExternalProject_Add(${EXPAT_TARGET}
+    PREFIX ${EXPAT_TARGET}
+    GIT_REPOSITORY https://github.com/libexpat/libexpat
+    GIT_TAG master
+    UPDATE_COMMAND ""
+    CONFIGURE_COMMAND cd ${EXPAT_SRC_DIR} && ./buildconf.sh  && ./configure
+                                                    --prefix=${EXPAT_INSTALL_DIR}
+                                                    --without-xmlwf
+                                                    CC=${CMAKE_C_COMPILER}
+                                                    CXX=${CMAKE_CXX_COMPILER}
+                                                    "CFLAGS=${EXPAT_CFLAGS} -w -DXML_POOR_ENTROPY"
+                                                    "CXXFLAGS=${EXPAT_CXXFLAGS} -w -DXML_POOR_ENTROPY"
+    BUILD_COMMAND cd ${EXPAT_SRC_DIR} &&  make -j ${CPU_COUNT}
+    INSTALL_COMMAND cd ${EXPAT_SRC_DIR} &&  make install
+    BUILD_BYPRODUCTS ${EXPAT_BUILD_BYPRODUCTS}
+)
diff --git a/cmake/external/googletest.cmake b/cmake/external/googletest.cmake
new file mode 100644
index 0000000..1eec203
--- /dev/null
+++ b/cmake/external/googletest.cmake
@@ -0,0 +1,45 @@
+# Copyright 2016 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.
+
+set(GTEST_TARGET external.googletest)
+set(GTEST_INSTALL_DIR ${CMAKE_CURRENT_BINARY_DIR}/${GTEST_TARGET})
+
+set(GTEST_INCLUDE_DIRS ${GTEST_INSTALL_DIR}/include)
+include_directories(${GTEST_INCLUDE_DIRS})
+
+set(GTEST_LIBRARIES gtest)
+set(GTEST_MAIN_LIBRARIES gtest_main)
+set(GTEST_BOTH_LIBRARIES ${GTEST_LIBRARIES} ${GTEST_MAIN_LIBRARIES})
+
+foreach(lib IN LISTS GTEST_BOTH_LIBRARIES)
+  list(APPEND GTEST_BUILD_BYPRODUCTS ${GTEST_INSTALL_DIR}/lib/lib${lib}.a)
+
+  add_library(${lib} STATIC IMPORTED)
+  set_property(TARGET ${lib} PROPERTY IMPORTED_LOCATION
+               ${GTEST_INSTALL_DIR}/lib/lib${lib}.a)
+  add_dependencies(${lib} ${GTEST_TARGET})
+endforeach(lib)
+
+include (ExternalProject)
+ExternalProject_Add(${GTEST_TARGET}
+    PREFIX ${GTEST_TARGET}
+    GIT_REPOSITORY https://github.com/google/googletest.git
+    GIT_TAG 1b07766
+    UPDATE_COMMAND ""
+    CMAKE_CACHE_ARGS -DCMAKE_C_COMPILER:FILEPATH=${CMAKE_C_COMPILER}
+                     -DCMAKE_CXX_COMPILER:FILEPATH=${CMAKE_CXX_COMPILER}
+    CMAKE_ARGS ${CMAKE_ARGS}
+               -DCMAKE_INSTALL_PREFIX=${GTEST_INSTALL_DIR}
+    BUILD_BYPRODUCTS ${GTEST_BUILD_BYPRODUCTS}
+)
diff --git a/cmake/external/libxml2.cmake b/cmake/external/libxml2.cmake
new file mode 100644
index 0000000..f31ac0e
--- /dev/null
+++ b/cmake/external/libxml2.cmake
@@ -0,0 +1,48 @@
+# 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.
+
+set(LIBXML2_TARGET external.libxml2)
+set(LIBXML2_INSTALL_DIR ${CMAKE_CURRENT_BINARY_DIR}/${LIBXML2_TARGET})
+set(LIBXML2_SRC_DIR ${LIBXML2_INSTALL_DIR}/src/${LIBXML2_TARGET})
+
+set(LIBXML2_INCLUDE_DIRS ${LIBXML2_INSTALL_DIR}/include/libxml2)
+include_directories(${LIBXML2_INCLUDE_DIRS})
+
+list(APPEND LIBXML2_LIBRARIES xml2)
+
+foreach(lib IN LISTS LIBXML2_LIBRARIES)
+  list(APPEND LIBXML2_BUILD_BYPRODUCTS ${LIBXML2_INSTALL_DIR}/lib/lib${lib}.a)
+
+  add_library(${lib} STATIC IMPORTED)
+  set_property(TARGET ${lib} PROPERTY IMPORTED_LOCATION
+               ${LIBXML2_INSTALL_DIR}/lib/lib${lib}.a)
+  add_dependencies(${lib} ${LIBXML2_TARGET})
+endforeach(lib)
+
+include (ExternalProject)
+ExternalProject_Add(${LIBXML2_TARGET}
+    PREFIX ${LIBXML2_TARGET}
+    GIT_REPOSITORY https://github.com/GNOME/libxml2.git
+    GIT_TAG master
+    UPDATE_COMMAND ""
+    CONFIGURE_COMMAND ${LIBXML2_SRC_DIR}/autogen.sh --without-python
+                                                    --prefix=${LIBXML2_INSTALL_DIR}
+                                                    CC=${CMAKE_C_COMPILER}
+                                                    CXX=${CMAKE_CXX_COMPILER}
+                                                    CFLAGS=${LIBXML2_CFLAGS}
+                                                    CXXFLAGS=${LIBXML2_CXXFLAGS}
+    BUILD_COMMAND make -j ${CPU_COUNT} all
+    INSTALL_COMMAND make install
+    BUILD_BYPRODUCTS ${LIBXML2_BUILD_BYPRODUCTS}
+)
diff --git a/cmake/external/protobuf.cmake b/cmake/external/protobuf.cmake
new file mode 100644
index 0000000..df79110
--- /dev/null
+++ b/cmake/external/protobuf.cmake
@@ -0,0 +1,68 @@
+# Copyright 2016 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 (FindProtobuf)
+
+set(PROTOBUF_TARGET external.protobuf)
+set(PROTOBUF_INSTALL_DIR ${CMAKE_CURRENT_BINARY_DIR}/${PROTOBUF_TARGET})
+
+set(PROTOBUF_INCLUDE_DIRS ${PROTOBUF_INSTALL_DIR}/include)
+include_directories(${PROTOBUF_INCLUDE_DIRS})
+include_directories(${CMAKE_CURRENT_BINARY_DIR})
+
+IF(CMAKE_BUILD_TYPE MATCHES Debug)
+  set(PROTOBUF_LIBRARIES protobufd)
+ELSE()
+  set(PROTOBUF_LIBRARIES protobuf)
+ENDIF()
+
+foreach(lib ${PROTOBUF_LIBRARIES})
+  list(APPEND PROTOBUF_BUILD_BYPRODUCTS ${PROTOBUF_INSTALL_DIR}/lib/lib${lib}.a)
+
+  add_library(${lib} STATIC IMPORTED)
+  set_property(TARGET ${lib} PROPERTY IMPORTED_LOCATION
+               ${PROTOBUF_INSTALL_DIR}/lib/lib${lib}.a)
+  add_dependencies(${lib} ${PROTOBUF_TARGET})
+endforeach(lib)
+
+set(PROTOBUF_PROTOC_EXECUTABLE ${PROTOBUF_INSTALL_DIR}/bin/protoc)
+list(APPEND PROTOBUF_BUILD_BYPRODUCTS ${PROTOBUF_PROTOC_EXECUTABLE})
+add_executable(protoc IMPORTED)
+set_property(TARGET protoc PROPERTY IMPORTED_LOCATION
+             ${PROTOBUF_PROTOC_EXECUTABLE})
+add_dependencies(protoc ${PROTOBUF_TARGET})
+
+include (ExternalProject)
+ExternalProject_Add(${PROTOBUF_TARGET}
+    PREFIX ${PROTOBUF_TARGET}
+    GIT_REPOSITORY https://github.com/google/protobuf.git
+    GIT_TAG 47b7d2c
+    UPDATE_COMMAND ""
+    CONFIGURE_COMMAND ${CMAKE_COMMAND} ${PROTOBUF_INSTALL_DIR}/src/${PROTOBUF_TARGET}/cmake
+        -G${CMAKE_GENERATOR}
+        -DCMAKE_INSTALL_PREFIX=${PROTOBUF_INSTALL_DIR}
+        -DCMAKE_BUILD_TYPE=${CMAKE_BUILD_TYPE}
+        -DCMAKE_POSITION_INDEPENDENT_CODE=ON
+        -DCMAKE_C_COMPILER:FILEPATH=${CMAKE_C_COMPILER}
+        -DCMAKE_CXX_COMPILER:FILEPATH=${CMAKE_CXX_COMPILER}
+        -DCMAKE_C_FLAGS=${PROTOBUF_CFLAGS}
+        -DCMAKE_CXX_FLAGS=${PROTOBUF_CXXFLAGS}
+        -Dprotobuf_BUILD_TESTS=OFF
+    BUILD_BYPRODUCTS ${PROTOBUF_BUILD_BYPRODUCTS}
+)
+
+# cmake 3.7 uses Protobuf_ when 3.5 PROTOBUF_ prefixes.
+set(Protobuf_INCLUDE_DIRS ${PROTOBUF_INCLUDE_DIRS})
+set(Protobuf_LIBRARIES ${PROTOBUF_LIBRARIES})
+set(Protobuf_PROTOC_EXECUTABLE ${PROTOBUF_PROTOC_EXECUTABLE})
diff --git a/examples/CMakeLists.txt b/examples/CMakeLists.txt
new file mode 100644
index 0000000..d932aed
--- /dev/null
+++ b/examples/CMakeLists.txt
@@ -0,0 +1,18 @@
+# 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.
+
+add_subdirectory(xml)
+add_subdirectory(expat)
+add_subdirectory(libfuzzer)
+add_subdirectory(libxml2)
diff --git a/examples/expat/CMakeLists.txt b/examples/expat/CMakeLists.txt
new file mode 100644
index 0000000..f2031f5
--- /dev/null
+++ b/examples/expat/CMakeLists.txt
@@ -0,0 +1,37 @@
+# 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.
+
+set(EXPAT_CFLAGS "${CMAKE_C_FLAGS} ${FUZZING_FLAGS}")
+set(EXPAT_CXXFLAGS "${CMAKE_CXX_FLAGS} ${FUZZING_FLAGS}")
+include(expat)
+
+add_executable(expat_example
+               expat_example.cc)
+target_link_libraries(expat_example
+                      protobuf-mutator-xml
+                      ${LIB_PROTO_MUTATOR_FUZZER_LIBRARIES}
+                      ${EXPAT_LIBRARIES})
+set_property(TARGET expat_example
+             PROPERTY COMPILE_FLAGS ${FUZZING_FLAGS})
+set_property(TARGET expat_example
+             PROPERTY LINK_FLAGS ${FUZZING_FLAGS_BINARY})
+
+add_executable(expat_example_test
+               expat_example_test.cc)
+add_dependencies(expat_example_test expat_example)
+target_link_libraries(expat_example_test
+                      ${GTEST_BOTH_LIBRARIES}
+                      ${CMAKE_THREAD_LIBS_INIT})
+add_test(test.expat_example_test expat_example_test --gtest_color=yes AUTO)
+add_dependencies(check expat_example_test)
diff --git a/examples/expat/expat_example.cc b/examples/expat/expat_example.cc
new file mode 100644
index 0000000..97911f3
--- /dev/null
+++ b/examples/expat/expat_example.cc
@@ -0,0 +1,41 @@
+// 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 <vector>
+
+#include "expat.h"  // NOLINT
+
+#include "examples/xml/xml.pb.h"
+#include "examples/xml/xml_writer.h"
+#include "src/libfuzzer/libfuzzer_macro.h"
+
+namespace {
+protobuf_mutator::protobuf::LogSilencer log_silincer;
+std::vector<const char*> kEncodings = {{"UTF-16", "UTF-8", "ISO-8859-1",
+                                        "US-ASCII", "UTF-16BE", "UTF-16LE",
+                                        "INVALIDENCODING"}};
+}
+
+DEFINE_PROTO_FUZZER(const protobuf_mutator::xml::Input& message) {
+  std::string xml = MessageToXml(message.document());
+  int options = message.options();
+
+  int use_ns = options % 2;
+  options /= 2;
+  auto enc = kEncodings[options % kEncodings.size()];
+  XML_Parser parser =
+      use_ns ? XML_ParserCreateNS(enc, '\n') : XML_ParserCreate(enc);
+  XML_Parse(parser, xml.data(), xml.size(), true);
+  XML_ParserFree(parser);
+}
diff --git a/examples/expat/expat_example_test.cc b/examples/expat/expat_example_test.cc
new file mode 100644
index 0000000..60f1191
--- /dev/null
+++ b/examples/expat/expat_example_test.cc
@@ -0,0 +1,30 @@
+// 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 "port/gtest.h"
+
+#include "examples/fuzzer_test.h"
+
+using testing::Test;
+
+namespace {
+
+class ExpatExampleTest : public FuzzerTest {};
+
+TEST_F(ExpatExampleTest, Fuzz) {
+  EXPECT_EQ(0, RunFuzzer("expat_example", 500, 10000));
+  EXPECT_GT(CountFilesInDir(), 50);
+}
+
+}  // namespace
diff --git a/examples/fuzzer_test.h b/examples/fuzzer_test.h
new file mode 100644
index 0000000..ace1410
--- /dev/null
+++ b/examples/fuzzer_test.h
@@ -0,0 +1,68 @@
+// 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.
+
+#ifndef EXAMPLES_FUZZER_TEST_H_
+#define EXAMPLES_FUZZER_TEST_H_
+
+#include <dirent.h>
+#include <memory>
+#include <string>
+
+#include "port/gtest.h"
+
+using testing::Test;
+
+class FuzzerTest : public testing::Test {
+ protected:
+  void SetUp() override {
+    char dir_template[] = "/tmp/libxml2_example_test_XXXXXX";
+    auto dir = mkdtemp(dir_template);
+    ASSERT_TRUE(dir);
+    dir_ = std::string(dir) + "/";
+    EXPECT_EQ(0, CountFilesInDir());
+  }
+
+  void TearDown() override {
+    EXPECT_EQ(0, std::system((std::string("rm -rf ") + dir_).c_str()));
+  }
+
+  int RunFuzzer(const std::string& name, int max_len, int runs) {
+    std::string cmd = "ASAN_OPTIONS=detect_leaks=0 ./" + name;
+    cmd += " -detect_leaks=0";
+    cmd += " -len_control=0";
+    cmd += " -max_len=" + std::to_string(max_len);
+    cmd += " -runs=" + std::to_string(runs);
+    cmd += " -artifact_prefix=" + dir_;
+    cmd += " " + dir_;
+    fprintf(stderr, "%s \n", cmd.c_str());
+    return std::system(cmd.c_str());
+  }
+
+  size_t CountFilesInDir() const {
+    size_t res = 0;
+    std::unique_ptr<DIR, decltype(&closedir)> dir(opendir(dir_.c_str()),
+                                                  &closedir);
+    if (!dir) return 0;
+    while (readdir(dir.get())) {
+      ++res;
+    }
+    if (res <= 2) return 0;
+    res -= 2;  // . and ..
+    return res;
+  }
+
+  std::string dir_;
+};
+
+#endif  // EXAMPLES_FUZZER_TEST_H_
diff --git a/examples/libfuzzer/CMakeLists.txt b/examples/libfuzzer/CMakeLists.txt
new file mode 100644
index 0000000..dc39177
--- /dev/null
+++ b/examples/libfuzzer/CMakeLists.txt
@@ -0,0 +1,43 @@
+# 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.
+
+add_executable(libfuzzer_example_test
+               libfuzzer_example_test.cc)
+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-libfuzzer
+                        ${LIB_PROTO_MUTATOR_FUZZER_LIBRARIES})
+  set_property(TARGET ${fuzzer}
+               PROPERTY COMPILE_FLAGS ${FUZZING_FLAGS})
+  set_property(TARGET ${fuzzer}
+               PROPERTY LINK_FLAGS ${FUZZING_FLAGS_BINARY})
+  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..80c5cef
--- /dev/null
+++ b/examples/libfuzzer/libfuzzer_bin_example.cc
@@ -0,0 +1,31 @@
+// 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 <cmath>
+
+#include "examples/libfuzzer/libfuzzer_example.pb.h"
+#include "src/libfuzzer/libfuzzer_macro.h"
+
+protobuf_mutator::protobuf::LogSilencer log_silincer;
+
+DEFINE_BINARY_PROTO_FUZZER(const libfuzzer_example::Msg& message) {
+  // Emulate a bug.
+  if (message.optional_string() == "FooBar" &&
+      message.optional_uint64() > 100 &&
+      !std::isnan(message.optional_float()) &&
+      std::fabs(message.optional_float()) > 1000 &&
+      std::fabs(message.optional_float()) < 1E10) {
+    abort();
+  }
+}
diff --git a/examples/libfuzzer/libfuzzer_example.cc b/examples/libfuzzer/libfuzzer_example.cc
new file mode 100644
index 0000000..68bd718
--- /dev/null
+++ b/examples/libfuzzer/libfuzzer_example.cc
@@ -0,0 +1,31 @@
+// 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 <cmath>
+
+#include "examples/libfuzzer/libfuzzer_example.pb.h"
+#include "src/libfuzzer/libfuzzer_macro.h"
+
+protobuf_mutator::protobuf::LogSilencer log_silincer;
+
+DEFINE_PROTO_FUZZER(const libfuzzer_example::Msg& message) {
+  // Emulate a bug.
+  if (message.optional_string() == "FooBar" &&
+      message.optional_uint64() > 100 &&
+      !std::isnan(message.optional_float()) &&
+      std::fabs(message.optional_float()) > 1000 &&
+      std::fabs(message.optional_float()) < 1E10) {
+    abort();
+  }
+}
diff --git a/examples/libfuzzer/libfuzzer_example.proto b/examples/libfuzzer/libfuzzer_example.proto
new file mode 100644
index 0000000..71e5fc9
--- /dev/null
+++ b/examples/libfuzzer/libfuzzer_example.proto
@@ -0,0 +1,8 @@
+syntax = "proto2";
+package libfuzzer_example;
+
+message Msg {
+  optional float optional_float = 1;
+  optional uint64 optional_uint64 = 2;
+  optional string optional_string = 3;
+}
diff --git a/examples/libfuzzer/libfuzzer_example_test.cc b/examples/libfuzzer/libfuzzer_example_test.cc
new file mode 100644
index 0000000..e871d59
--- /dev/null
+++ b/examples/libfuzzer/libfuzzer_example_test.cc
@@ -0,0 +1,36 @@
+// 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 "examples/fuzzer_test.h"
+#include "port/gtest.h"
+
+namespace {
+
+const int kDefaultLibFuzzerError = 77;
+
+class LibFuzzerExampleTest : public FuzzerTest {};
+
+int GetError(int exit_code) { return WSTOPSIG(exit_code); }
+
+TEST_F(LibFuzzerExampleTest, Text) {
+  EXPECT_EQ(kDefaultLibFuzzerError,
+            GetError(RunFuzzer("libfuzzer_example", 150, 10000000)));
+}
+
+TEST_F(LibFuzzerExampleTest, Binary) {
+  EXPECT_EQ(kDefaultLibFuzzerError,
+            GetError(RunFuzzer("libfuzzer_bin_example", 150, 10000000)));
+}
+
+}  // namespace
diff --git a/examples/libxml2/CMakeLists.txt b/examples/libxml2/CMakeLists.txt
new file mode 100644
index 0000000..cf9f8a2
--- /dev/null
+++ b/examples/libxml2/CMakeLists.txt
@@ -0,0 +1,38 @@
+# 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.
+
+set(LIBXML2_CFLAGS "${CMAKE_C_FLAGS} ${FUZZING_FLAGS} -w")
+set(LIBXML2_CXXFLAGS "${CMAKE_CXX_FLAGS} ${FUZZING_FLAGS} -w")
+include(libxml2)
+add_executable(libxml2_example
+               libxml2_example.cc)
+target_link_libraries(libxml2_example
+                      protobuf-mutator-xml
+                      ${LIB_PROTO_MUTATOR_FUZZER_LIBRARIES}
+                      ${LIBXML2_LIBRARIES}
+                      ${ZLIB_LIBRARIES}
+                      ${LIBLZMA_LIBRARIES})
+set_property(TARGET libxml2_example
+             PROPERTY COMPILE_FLAGS ${FUZZING_FLAGS})
+set_property(TARGET libxml2_example
+             PROPERTY LINK_FLAGS ${FUZZING_FLAGS_BINARY})
+
+add_executable(libxml2_example_test
+               libxml2_example_test.cc)
+add_dependencies(libxml2_example_test libxml2_example)
+target_link_libraries(libxml2_example_test
+                      ${GTEST_BOTH_LIBRARIES}
+                      ${CMAKE_THREAD_LIBS_INIT})
+add_test(test.libxml2_example_test libxml2_example_test --gtest_color=yes AUTO)
+add_dependencies(check libxml2_example_test)
diff --git a/examples/libxml2/libxml2_example.cc b/examples/libxml2/libxml2_example.cc
new file mode 100644
index 0000000..9cbd442
--- /dev/null
+++ b/examples/libxml2/libxml2_example.cc
@@ -0,0 +1,53 @@
+// 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 "libxml/parser.h"
+#include "libxml/xmlsave.h"
+
+#include "examples/xml/xml.pb.h"
+#include "examples/xml/xml_writer.h"
+#include "src/libfuzzer/libfuzzer_macro.h"
+
+namespace {
+protobuf_mutator::protobuf::LogSilencer log_silincer;
+void ignore(void* ctx, const char* msg, ...) {}
+
+template <class T, class D>
+std::unique_ptr<T, D> MakeUnique(T* obj, D del) {
+  return {obj, del};
+}
+}
+
+DEFINE_PROTO_FUZZER(const protobuf_mutator::xml::Input& message) {
+  std::string xml = MessageToXml(message.document());
+  int options = message.options();
+
+  // Network requests are too slow.
+  options |= XML_PARSE_NONET;
+  // These flags can cause network or file access and hangs.
+  options &= ~(XML_PARSE_NOENT | XML_PARSE_HUGE | XML_PARSE_DTDVALID |
+               XML_PARSE_DTDLOAD | XML_PARSE_DTDATTR);
+
+  xmlSetGenericErrorFunc(nullptr, &ignore);
+
+  if (auto doc =
+          MakeUnique(xmlReadMemory(xml.c_str(), static_cast<int>(xml.size()),
+                                   "", nullptr, options),
+                     &xmlFreeDoc)) {
+    auto buf = MakeUnique(xmlBufferCreate(), &xmlBufferFree);
+    auto ctxt =
+        MakeUnique(xmlSaveToBuffer(buf.get(), nullptr, 0), &xmlSaveClose);
+    xmlSaveDoc(ctxt.get(), doc.get());
+  }
+}
diff --git a/examples/libxml2/libxml2_example_test.cc b/examples/libxml2/libxml2_example_test.cc
new file mode 100644
index 0000000..54b3628
--- /dev/null
+++ b/examples/libxml2/libxml2_example_test.cc
@@ -0,0 +1,30 @@
+// 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 "port/gtest.h"
+
+#include "examples/fuzzer_test.h"
+
+using testing::Test;
+
+namespace {
+
+class LibXml2ExampleTest : public FuzzerTest {};
+
+TEST_F(LibXml2ExampleTest, Fuzz) {
+  EXPECT_EQ(0, RunFuzzer("libxml2_example", 500, 10000));
+  EXPECT_GT(CountFilesInDir(), 100);
+}
+
+}  // namespace
diff --git a/examples/xml/CMakeLists.txt b/examples/xml/CMakeLists.txt
new file mode 100644
index 0000000..b06d224
--- /dev/null
+++ b/examples/xml/CMakeLists.txt
@@ -0,0 +1,32 @@
+# 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.
+
+# Libraries
+protobuf_generate_cpp(XML_PROTO_SRCS
+                      XML_PROTO_HDRS
+                      xml.proto)
+
+add_library(protobuf-mutator-xml
+            xml_writer.cc
+            ${XML_PROTO_SRCS})
+target_link_libraries(protobuf-mutator-xml
+                      protobuf-mutator-libfuzzer)
+set_property(TARGET protobuf-mutator-xml
+             PROPERTY COMPILE_FLAGS "${NO_FUZZING_FLAGS}")
+
+
+add_executable(xml_converter
+               xml_converter.cc)
+target_link_libraries(xml_converter
+                      protobuf-mutator-xml)
diff --git a/examples/xml/xml.proto b/examples/xml/xml.proto
new file mode 100644
index 0000000..38903dc
--- /dev/null
+++ b/examples/xml/xml.proto
@@ -0,0 +1,92 @@
+syntax = "proto2";
+package protobuf_mutator.xml;
+
+// Simplified definition of XML formant according https://www.w3.org/TR/xml/
+// Not all features are implemented and some rules are flattened.
+
+// There are no required fields to allow backward compatibility with older
+// corpus.
+
+// document ::= prolog element Misc*
+// prolog ::= XMLDecl? Misc* (doctypedecl Misc*)?
+// XMLDecl ::= '<?xml' VersionInfo EncodingDecl? SDDecl? S? '?>'
+// doctypedecl ::=
+//    '<!DOCTYPE' S Name (S ExternalID)? S? ('[' intSubset ']' S?)? '>'
+message Document {
+  // XMLDecl
+  optional string version = 1;
+  optional string encoding = 2;
+  optional bool standalone = 3;
+
+  repeated Misk misk1 = 4;
+  optional DoctypeDecl doctype = 5;
+  optional Element element = 6;
+  repeated Misk misk2 = 7;
+}
+
+message DoctypeDecl {
+  optional string name = 1;
+  optional string external_id = 2;
+  optional string int_subset = 3;
+  repeated Misk misk = 4;
+}
+
+message Misk {
+  oneof _ {
+    Pi pi = 1;
+    string comment = 2;
+  }
+}
+
+// element ::= EmptyElemTag | STag content ETag
+message Element {
+  optional Tag tag = 1;
+  // Use EmptyElemTag tag if missing, or STag and ETag otherwise.
+  repeated Content content = 2;
+}
+
+// EmptyElemTag ::= '<' Name (S Attribute)* S? '/>'
+// STag ::= '<' Name (S Attribute)* S? '>'
+// ETag ::= '</' Name S? '>'
+message Tag {
+  optional string name = 1;
+  repeated Attribute attribute = 2;
+}
+
+message Reference {
+  optional string name = 1;
+  optional bool entry = 2;
+}
+
+message Pi {
+  optional string target = 1;
+  optional string data = 2;
+}
+
+// content ::=
+//    CharData? ((element | Reference | CDSect | PI | Comment) CharData?)*
+message Content {
+  oneof _ {
+    string char_data = 1;
+    Element element = 2;
+    Reference reference = 3;
+    string cdsect = 4;
+    Misk misk = 5;
+  }
+}
+
+// Attribute ::=  Name Eq AttValue
+message Attribute {
+  optional string name = 1;
+  optional string value = 2;
+}
+
+message Input {
+  optional Document document = 1;
+
+  // Option will be sent into libxml2 parser.
+  // TODO(vitalybuka): Use proto extension. Options is libxml2 specific,
+  // other libs may need different data. At the moment mutator does not support
+  // extensions.
+  optional uint32 options = 2;
+}
diff --git a/examples/xml/xml_converter.cc b/examples/xml/xml_converter.cc
new file mode 100644
index 0000000..1c651b0
--- /dev/null
+++ b/examples/xml/xml_converter.cc
@@ -0,0 +1,128 @@
+// 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 <getopt.h>
+
+#include <fstream>
+#include <iostream>
+
+#include "examples/xml/xml.pb.h"
+#include "examples/xml/xml_writer.h"
+#include "port/protobuf.h"
+#include "src/text_format.h"
+
+using protobuf_mutator::xml::Input;
+
+namespace {
+
+struct option const kLongOptions[] = {{"reverse", no_argument, NULL, 'r'},
+                                      {"verbose", no_argument, NULL, 'v'},
+                                      {"help", no_argument, NULL, 'h'},
+                                      {NULL, 0, NULL, 0}};
+
+void PrintUsage() {
+  std::cerr << "Usage: xml_converter [OPTION]... [INFILE [OUTFILE]]\n"
+            << "Converts between proto used by fuzzer and XML.\n\n"
+            << "\t-h, --help\tPrint this help\n"
+            << "\t-r, --reverse\tConverts from XML to proto\n"
+            << "\t-v, --verbose\tPrint input\n";
+}
+
+struct Options {
+  bool reverse = false;
+  bool verbose = false;
+  std::string in_file;
+  std::string out_file;
+};
+
+bool ParseOptions(int argc, char** argv, Options* options) {
+  int c = 0;
+  while ((c = getopt_long(argc, argv, "hrv", kLongOptions, nullptr)) != -1) {
+    switch (c) {
+      case 'v':
+        options->verbose = true;
+        break;
+      case 'r':
+        options->reverse = true;
+        break;
+      case 'h':
+      default:
+        return false;
+    }
+  }
+
+  int i = optind;
+  if (i < argc) options->in_file = argv[i++];
+  if (i < argc) options->out_file = argv[i++];
+  if (i != argc) return false;
+
+  return true;
+}
+
+}  // namespace
+
+int main(int argc, char** argv) {
+  Options options;
+  if (!ParseOptions(argc, argv, &options)) {
+    PrintUsage();
+    return 1;
+  }
+
+  std::istream* cin = &std::cin;
+  std::ostream* cout = &std::cout;
+
+  std::ifstream in_file_stream;
+  if (!options.in_file.empty()) {
+    in_file_stream.open(options.in_file);
+    cin = &in_file_stream;
+  }
+
+  std::ofstream out_file_stream;
+  if (!options.out_file.empty()) {
+    out_file_stream.open(options.out_file);
+    cout = &out_file_stream;
+  }
+
+  std::string input;
+  std::vector<char> buff(1 << 20);
+  while (auto size = cin->readsome(buff.data(), buff.size())) {
+    input += std::string(buff.data(), size);
+  }
+  std::string output;
+
+  int ret = 0;
+
+  if (options.reverse) {
+    Input message;
+    message.mutable_document()->mutable_element()->add_content()->set_char_data(
+        input);
+    output = protobuf_mutator::SaveMessageAsText(message);
+  } else {
+    Input message;
+    bool is_proto = protobuf_mutator::ParseTextMessage(input.data(), &message);
+    output = MessageToXml(message.document());
+    if (!is_proto) {
+      ret = 2;
+      if (options.verbose) std::cerr << "Input is not proto\n";
+    }
+  }
+
+  if (options.verbose) {
+    std::cerr << input << "\n\n";
+    std::cerr.flush();
+  }
+  *cout << output;
+
+  return ret;
+}
diff --git a/examples/xml/xml_writer.cc b/examples/xml/xml_writer.cc
new file mode 100644
index 0000000..19df56c
--- /dev/null
+++ b/examples/xml/xml_writer.cc
@@ -0,0 +1,128 @@
+// 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 "examples/xml/xml_writer.h"
+
+#include <algorithm>
+#include <sstream>
+
+#include "examples/xml/xml.pb.h"
+
+namespace protobuf_mutator {
+namespace xml {
+
+namespace {
+
+class XmlWriter {
+ public:
+  XmlWriter();
+  std::string ToXml(const Document& doc);
+
+ private:
+  void ToXml(const std::string& name, const std::string& value);
+  void ToXml(const Element& element);
+  void ToXml(const Content& content);
+  void ToXml(const Misk& misk);
+  void ToXml(const DoctypeDecl& doctype);
+
+  std::ostringstream out_;
+};
+
+XmlWriter::XmlWriter() {}
+
+void XmlWriter::ToXml(const std::string& name, const std::string& value) {
+  char quote = (name.size() % 2) ? '"' : '\'';
+  out_ << " " << name << "=" << quote << value << quote;
+}
+
+void XmlWriter::ToXml(const Misk& misk) {
+  if (misk.has_pi()) {
+    out_ << "<?" << misk.pi().target() << misk.pi().data() << "?>";
+  }
+
+  if (misk.has_comment()) {
+    out_ << "<!--" << misk.comment() << "-->";
+  }
+}
+
+void XmlWriter::ToXml(const DoctypeDecl& doctype) {
+  out_ << "<!DOCTYPE " << doctype.name();
+  if (doctype.has_external_id()) out_ << " " << doctype.external_id();
+  if (doctype.has_int_subset()) out_ << " [" << doctype.int_subset() << "]";
+  for (int i = 0; i < doctype.misk_size(); ++i) ToXml(doctype.misk(i));
+  out_ << ">";
+}
+
+void XmlWriter::ToXml(const Content& content) {
+  if (content.has_char_data()) out_ << content.char_data();
+  if (content.has_element()) ToXml(content.element());
+  if (content.has_reference()) {
+    out_ << (content.reference().entry() ? '&' : '%')
+         << content.reference().name() << ';';
+  }
+  if (content.has_cdsect()) out_ << "<![CDATA[" << content.cdsect() << "]]>";
+
+  if (content.has_misk()) ToXml(content.misk());
+}
+
+void XmlWriter::ToXml(const Element& element) {
+  std::string tag;
+  std::string name;
+  tag += element.tag().name();
+  out_ << "<" << tag;
+
+  for (int i = 0; i < element.tag().attribute_size(); ++i) {
+    ToXml(element.tag().attribute(i).name(),
+          element.tag().attribute(i).value());
+  }
+
+  if (element.content_size() == 0) {
+    out_ << "/>";
+  } else {
+    out_ << ">";
+    for (int i = 0; i < element.content_size(); ++i) ToXml(element.content(i));
+    out_ << "</" << tag << ">";
+  }
+}
+
+std::string XmlWriter::ToXml(const Document& doc) {
+  out_.str("");
+
+  if (doc.has_version() || doc.has_encoding() || doc.has_standalone()) {
+    out_ << "<?xml";
+    if (doc.has_version())
+      ToXml("version", (doc.version().size() == 7) ? "1.0" : doc.version());
+    if (doc.has_encoding()) ToXml("encoding", doc.encoding());
+    if (doc.has_standalone())
+      ToXml("encoding", doc.standalone() ? "yes" : "no");
+    out_ << "?>";
+  }
+
+  for (int i = 0; i < doc.misk1_size(); ++i) ToXml(doc.misk1(i));
+  if (doc.has_doctype()) ToXml(doc.doctype());
+  ToXml(doc.element());
+  for (int i = 0; i < doc.misk2_size(); ++i) ToXml(doc.misk2(i));
+
+  return out_.str();
+}
+
+}  // namespace
+
+std::string MessageToXml(const Document& document) {
+  XmlWriter writer;
+  return writer.ToXml(document);
+}
+
+}  // namespace xml
+}  // namespace protobuf_mutator
diff --git a/examples/xml/xml_writer.h b/examples/xml/xml_writer.h
new file mode 100644
index 0000000..45b538d
--- /dev/null
+++ b/examples/xml/xml_writer.h
@@ -0,0 +1,29 @@
+// 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.
+
+#ifndef EXAMPLES_XML_XML_WRITER_H_
+#define EXAMPLES_XML_XML_WRITER_H_
+
+#include <string>
+
+namespace protobuf_mutator {
+namespace xml {
+
+// Converts protobuf into XML.
+std::string MessageToXml(const class Document& document);
+
+}  // namespace xml
+}  // namespace protobuf_mutator
+
+#endif  // EXAMPLES_XML_XML_WRITER_H_
diff --git a/port/gtest.h b/port/gtest.h
new file mode 100644
index 0000000..485aa98
--- /dev/null
+++ b/port/gtest.h
@@ -0,0 +1,20 @@
+// 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.
+
+#ifndef PORT_GTEST_H_
+#define PORT_GTEST_H_
+
+#include "gtest/gtest.h"
+
+#endif  // PORT_GTEST_H_
diff --git a/port/protobuf.h b/port/protobuf.h
new file mode 100644
index 0000000..eefe415
--- /dev/null
+++ b/port/protobuf.h
@@ -0,0 +1,34 @@
+// 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.
+
+#ifndef PORT_PROTOBUF_H_
+#define PORT_PROTOBUF_H_
+
+#include <string>
+
+#include "google/protobuf/message.h"
+#include "google/protobuf/text_format.h"
+#include "google/protobuf/util/message_differencer.h"
+#include "google/protobuf/wire_format.h"
+
+namespace protobuf_mutator {
+
+namespace protobuf = google::protobuf;
+
+// String type used by google::protobuf.
+using String = std::string;
+
+}  // namespace protobuf_mutator
+
+#endif  // PORT_PROTOBUF_H_
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
new file mode 100644
index 0000000..5c13d2d
--- /dev/null
+++ b/src/CMakeLists.txt
@@ -0,0 +1,54 @@
+# 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.
+
+add_subdirectory(libfuzzer)
+
+add_library(protobuf-mutator
+            binary_format.cc
+            mutator.cc
+            text_format.cc
+            utf8_fix.cc)
+target_link_libraries(protobuf-mutator
+                      ${PROTOBUF_LIBRARIES})
+set_property(TARGET protobuf-mutator
+             PROPERTY COMPILE_FLAGS "${NO_FUZZING_FLAGS}")
+
+protobuf_generate_cpp(PROTO_SRCS PROTO_HDRS
+                      mutator_test_proto2.proto
+                      mutator_test_proto3.proto)
+
+add_executable(mutator_test
+               mutator_test.cc
+               utf8_fix_test.cc
+               weighted_reservoir_sampler_test.cc
+               ${PROTO_SRCS})
+target_link_libraries(mutator_test
+                      protobuf-mutator
+                      ${ZLIB_LIBRARIES}
+                      ${GTEST_BOTH_LIBRARIES}
+                      ${CMAKE_THREAD_LIBS_INIT})
+
+ProcessorCount(CPU_COUNT)
+math(EXPR TEST_SHARDS_COUNT 2*${CPU_COUNT})
+math(EXPR TEST_SHARDS_MAX ${TEST_SHARDS_COUNT}-1)
+foreach(SHARD RANGE ${TEST_SHARDS_MAX})
+  add_test(test.protobuf_mutator_test_${SHARD} mutator_test --gtest_color=yes AUTO)
+  set_property(
+      TEST test.protobuf_mutator_test_${SHARD}
+      APPEND PROPERTY ENVIRONMENT
+      GTEST_SHARD_INDEX=${SHARD}
+      GTEST_TOTAL_SHARDS=${TEST_SHARDS_COUNT})
+endforeach(SHARD)
+
+add_dependencies(check mutator_test)
diff --git a/src/binary_format.cc b/src/binary_format.cc
new file mode 100644
index 0000000..2e9a8c7
--- /dev/null
+++ b/src/binary_format.cc
@@ -0,0 +1,50 @@
+// 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 "src/binary_format.h"
+
+namespace protobuf_mutator {
+
+using protobuf::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();
+  if (!output->ParsePartialFromString(data)) {
+    output->Clear();
+    return false;
+  }
+  return true;
+}
+
+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) {
+  String tmp;
+  if (!message.SerializePartialToString(&tmp)) return {};
+  return tmp;
+}
+
+}  // namespace protobuf_mutator
diff --git a/src/binary_format.h b/src/binary_format.h
new file mode 100644
index 0000000..1aceaad
--- /dev/null
+++ b/src/binary_format.h
@@ -0,0 +1,34 @@
+// 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.
+
+#ifndef SRC_BINARY_FORMAT_H_
+#define SRC_BINARY_FORMAT_H_
+
+#include <string>
+
+#include "port/protobuf.h"
+
+namespace protobuf_mutator {
+
+// Binary serialization of protos.
+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 protobuf_mutator
+
+#endif  // SRC_BINARY_FORMAT_H_
diff --git a/src/field_instance.h b/src/field_instance.h
new file mode 100644
index 0000000..8c1c31f
--- /dev/null
+++ b/src/field_instance.h
@@ -0,0 +1,430 @@
+// Copyright 2016 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.
+
+#ifndef SRC_FIELD_INSTANCE_H_
+#define SRC_FIELD_INSTANCE_H_
+
+#include <memory>
+#include <string>
+
+#include "port/protobuf.h"
+
+namespace protobuf_mutator {
+
+// Helper class for common protobuf fields operations.
+class ConstFieldInstance {
+ public:
+  static const size_t kInvalidIndex = -1;
+
+  struct Enum {
+    size_t index;
+    size_t count;
+  };
+
+  ConstFieldInstance()
+      : message_(nullptr), descriptor_(nullptr), index_(kInvalidIndex) {}
+
+  ConstFieldInstance(const protobuf::Message* message,
+                     const protobuf::FieldDescriptor* field, size_t index)
+      : message_(message), descriptor_(field), index_(index) {
+    assert(message_);
+    assert(descriptor_);
+    assert(index_ != kInvalidIndex);
+    assert(descriptor_->is_repeated());
+  }
+
+  ConstFieldInstance(const protobuf::Message* message,
+                     const protobuf::FieldDescriptor* field)
+      : message_(message), descriptor_(field), index_(kInvalidIndex) {
+    assert(message_);
+    assert(descriptor_);
+    assert(!descriptor_->is_repeated());
+  }
+
+  void GetDefault(int32_t* out) const {
+    *out = descriptor_->default_value_int32();
+  }
+
+  void GetDefault(int64_t* out) const {
+    *out = descriptor_->default_value_int64();
+  }
+
+  void GetDefault(uint32_t* out) const {
+    *out = descriptor_->default_value_uint32();
+  }
+
+  void GetDefault(uint64_t* out) const {
+    *out = descriptor_->default_value_uint64();
+  }
+
+  void GetDefault(double* out) const {
+    *out = descriptor_->default_value_double();
+  }
+
+  void GetDefault(float* out) const {
+    *out = descriptor_->default_value_float();
+  }
+
+  void GetDefault(bool* out) const { *out = descriptor_->default_value_bool(); }
+
+  void GetDefault(Enum* out) const {
+    const protobuf::EnumValueDescriptor* value =
+        descriptor_->default_value_enum();
+    const protobuf::EnumDescriptor* type = value->type();
+    *out = {static_cast<size_t>(value->index()),
+            static_cast<size_t>(type->value_count())};
+  }
+
+  void GetDefault(std::string* out) const {
+    *out = descriptor_->default_value_string();
+  }
+
+  void GetDefault(std::unique_ptr<protobuf::Message>* out) const {
+    out->reset(reflection()
+                   .GetMessageFactory()
+                   ->GetPrototype(descriptor_->message_type())
+                   ->New());
+  }
+
+  void Load(int32_t* value) const {
+    *value = is_repeated()
+                 ? reflection().GetRepeatedInt32(*message_, descriptor_, index_)
+                 : reflection().GetInt32(*message_, descriptor_);
+  }
+
+  void Load(int64_t* value) const {
+    *value = is_repeated()
+                 ? reflection().GetRepeatedInt64(*message_, descriptor_, index_)
+                 : reflection().GetInt64(*message_, descriptor_);
+  }
+
+  void Load(uint32_t* value) const {
+    *value = is_repeated() ? reflection().GetRepeatedUInt32(*message_,
+                                                            descriptor_, index_)
+                           : reflection().GetUInt32(*message_, descriptor_);
+  }
+
+  void Load(uint64_t* value) const {
+    *value = is_repeated() ? reflection().GetRepeatedUInt64(*message_,
+                                                            descriptor_, index_)
+                           : reflection().GetUInt64(*message_, descriptor_);
+  }
+
+  void Load(double* value) const {
+    *value = is_repeated() ? reflection().GetRepeatedDouble(*message_,
+                                                            descriptor_, index_)
+                           : reflection().GetDouble(*message_, descriptor_);
+  }
+
+  void Load(float* value) const {
+    *value = is_repeated()
+                 ? reflection().GetRepeatedFloat(*message_, descriptor_, index_)
+                 : reflection().GetFloat(*message_, descriptor_);
+  }
+
+  void Load(bool* value) const {
+    *value = is_repeated()
+                 ? reflection().GetRepeatedBool(*message_, descriptor_, index_)
+                 : reflection().GetBool(*message_, descriptor_);
+  }
+
+  void Load(Enum* value) const {
+    const protobuf::EnumValueDescriptor* value_descriptor =
+        is_repeated()
+            ? reflection().GetRepeatedEnum(*message_, descriptor_, index_)
+            : reflection().GetEnum(*message_, descriptor_);
+    *value = {static_cast<size_t>(value_descriptor->index()),
+              static_cast<size_t>(value_descriptor->type()->value_count())};
+  }
+
+  void Load(std::string* value) const {
+    *value = is_repeated() ? reflection().GetRepeatedString(*message_,
+                                                            descriptor_, index_)
+                           : reflection().GetString(*message_, descriptor_);
+  }
+
+  void Load(std::unique_ptr<protobuf::Message>* value) const {
+    const protobuf::Message& source =
+        is_repeated()
+            ? reflection().GetRepeatedMessage(*message_, descriptor_, index_)
+            : reflection().GetMessage(*message_, descriptor_);
+    value->reset(source.New());
+    (*value)->CopyFrom(source);
+  }
+
+  std::string name() const { return descriptor_->name(); }
+
+  protobuf::FieldDescriptor::CppType cpp_type() const {
+    return descriptor_->cpp_type();
+  }
+
+  const protobuf::EnumDescriptor* enum_type() const {
+    return descriptor_->enum_type();
+  }
+
+  const protobuf::Descriptor* message_type() const {
+    return descriptor_->message_type();
+  }
+
+  bool EnforceUtf8() const {
+    return descriptor_->type() == protobuf::FieldDescriptor::TYPE_STRING &&
+           descriptor()->file()->syntax() ==
+               protobuf::FileDescriptor::SYNTAX_PROTO3;
+  }
+
+ protected:
+  bool is_repeated() const { return descriptor_->is_repeated(); }
+
+  const protobuf::Reflection& reflection() const {
+    return *message_->GetReflection();
+  }
+
+  const protobuf::FieldDescriptor* descriptor() const { return descriptor_; }
+
+  size_t index() const { return index_; }
+
+ private:
+  template <class Fn, class T>
+  friend struct FieldFunction;
+
+  const protobuf::Message* message_;
+  const protobuf::FieldDescriptor* descriptor_;
+  size_t index_;
+};
+
+class FieldInstance : public ConstFieldInstance {
+ public:
+  static const size_t kInvalidIndex = -1;
+
+  FieldInstance() : ConstFieldInstance(), message_(nullptr) {}
+
+  FieldInstance(protobuf::Message* message,
+                const protobuf::FieldDescriptor* field, size_t index)
+      : ConstFieldInstance(message, field, index), message_(message) {}
+
+  FieldInstance(protobuf::Message* message,
+                const protobuf::FieldDescriptor* field)
+      : ConstFieldInstance(message, field), message_(message) {}
+
+  void Delete() const {
+    if (!is_repeated()) return reflection().ClearField(message_, descriptor());
+    int field_size = reflection().FieldSize(*message_, descriptor());
+    // API has only method to delete the last message, so we move method from
+    // the
+    // middle to the end.
+    for (int i = index() + 1; i < field_size; ++i)
+      reflection().SwapElements(message_, descriptor(), i, i - 1);
+    reflection().RemoveLast(message_, descriptor());
+  }
+
+  template <class T>
+  void Create(const T& value) const {
+    if (!is_repeated()) return Store(value);
+    InsertRepeated(value);
+  }
+
+  void Store(int32_t value) const {
+    if (is_repeated())
+      reflection().SetRepeatedInt32(message_, descriptor(), index(), value);
+    else
+      reflection().SetInt32(message_, descriptor(), value);
+  }
+
+  void Store(int64_t value) const {
+    if (is_repeated())
+      reflection().SetRepeatedInt64(message_, descriptor(), index(), value);
+    else
+      reflection().SetInt64(message_, descriptor(), value);
+  }
+
+  void Store(uint32_t value) const {
+    if (is_repeated())
+      reflection().SetRepeatedUInt32(message_, descriptor(), index(), value);
+    else
+      reflection().SetUInt32(message_, descriptor(), value);
+  }
+
+  void Store(uint64_t value) const {
+    if (is_repeated())
+      reflection().SetRepeatedUInt64(message_, descriptor(), index(), value);
+    else
+      reflection().SetUInt64(message_, descriptor(), value);
+  }
+
+  void Store(double value) const {
+    if (is_repeated())
+      reflection().SetRepeatedDouble(message_, descriptor(), index(), value);
+    else
+      reflection().SetDouble(message_, descriptor(), value);
+  }
+
+  void Store(float value) const {
+    if (is_repeated())
+      reflection().SetRepeatedFloat(message_, descriptor(), index(), value);
+    else
+      reflection().SetFloat(message_, descriptor(), value);
+  }
+
+  void Store(bool value) const {
+    if (is_repeated())
+      reflection().SetRepeatedBool(message_, descriptor(), index(), value);
+    else
+      reflection().SetBool(message_, descriptor(), value);
+  }
+
+  void Store(const Enum& value) const {
+    assert(value.index < value.count);
+    const protobuf::EnumValueDescriptor* enum_value =
+        descriptor()->enum_type()->value(value.index);
+    if (is_repeated())
+      reflection().SetRepeatedEnum(message_, descriptor(), index(), enum_value);
+    else
+      reflection().SetEnum(message_, descriptor(), enum_value);
+  }
+
+  void Store(const std::string& value) const {
+    if (is_repeated())
+      reflection().SetRepeatedString(message_, descriptor(), index(), value);
+    else
+      reflection().SetString(message_, descriptor(), value);
+  }
+
+  void Store(const std::unique_ptr<protobuf::Message>& value) const {
+    protobuf::Message* mutable_message =
+        is_repeated() ? reflection().MutableRepeatedMessage(
+                            message_, descriptor(), index())
+                      : reflection().MutableMessage(message_, descriptor());
+    mutable_message->Clear();
+    if (value) mutable_message->CopyFrom(*value);
+  }
+
+ private:
+  template <class T>
+  void InsertRepeated(const T& value) const {
+    PushBackRepeated(value);
+    size_t field_size = reflection().FieldSize(*message_, descriptor());
+    if (field_size == 1) return;
+    // API has only method to add field to the end of the list. So we add
+    // descriptor()
+    // and move it into the middle.
+    for (size_t i = field_size - 1; i > index(); --i)
+      reflection().SwapElements(message_, descriptor(), i, i - 1);
+  }
+
+  void PushBackRepeated(int32_t value) const {
+    assert(is_repeated());
+    reflection().AddInt32(message_, descriptor(), value);
+  }
+
+  void PushBackRepeated(int64_t value) const {
+    assert(is_repeated());
+    reflection().AddInt64(message_, descriptor(), value);
+  }
+
+  void PushBackRepeated(uint32_t value) const {
+    assert(is_repeated());
+    reflection().AddUInt32(message_, descriptor(), value);
+  }
+
+  void PushBackRepeated(uint64_t value) const {
+    assert(is_repeated());
+    reflection().AddUInt64(message_, descriptor(), value);
+  }
+
+  void PushBackRepeated(double value) const {
+    assert(is_repeated());
+    reflection().AddDouble(message_, descriptor(), value);
+  }
+
+  void PushBackRepeated(float value) const {
+    assert(is_repeated());
+    reflection().AddFloat(message_, descriptor(), value);
+  }
+
+  void PushBackRepeated(bool value) const {
+    assert(is_repeated());
+    reflection().AddBool(message_, descriptor(), value);
+  }
+
+  void PushBackRepeated(const Enum& value) const {
+    assert(value.index < value.count);
+    const protobuf::EnumValueDescriptor* enum_value =
+        descriptor()->enum_type()->value(value.index);
+    assert(is_repeated());
+    reflection().AddEnum(message_, descriptor(), enum_value);
+  }
+
+  void PushBackRepeated(const std::string& value) const {
+    assert(is_repeated());
+    reflection().AddString(message_, descriptor(), value);
+  }
+
+  void PushBackRepeated(const std::unique_ptr<protobuf::Message>& value) const {
+    assert(is_repeated());
+    protobuf::Message* mutable_message =
+        reflection().AddMessage(message_, descriptor());
+    mutable_message->Clear();
+    if (value) mutable_message->CopyFrom(*value);
+  }
+
+  protobuf::Message* message_;
+};
+
+template <class Fn, class R = void>
+struct FieldFunction {
+  template <class Field, class... Args>
+  R operator()(const Field& field, const Args&... args) const {
+    assert(field.descriptor());
+    using protobuf::FieldDescriptor;
+    switch (field.cpp_type()) {
+      case FieldDescriptor::CPPTYPE_INT32:
+        return static_cast<const Fn*>(this)->template ForType<int32_t>(field,
+                                                                       args...);
+      case FieldDescriptor::CPPTYPE_INT64:
+        return static_cast<const Fn*>(this)->template ForType<int64_t>(field,
+                                                                       args...);
+      case FieldDescriptor::CPPTYPE_UINT32:
+        return static_cast<const Fn*>(this)->template ForType<uint32_t>(
+            field, args...);
+      case FieldDescriptor::CPPTYPE_UINT64:
+        return static_cast<const Fn*>(this)->template ForType<uint64_t>(
+            field, args...);
+      case FieldDescriptor::CPPTYPE_DOUBLE:
+        return static_cast<const Fn*>(this)->template ForType<double>(field,
+                                                                      args...);
+      case FieldDescriptor::CPPTYPE_FLOAT:
+        return static_cast<const Fn*>(this)->template ForType<float>(field,
+                                                                     args...);
+      case FieldDescriptor::CPPTYPE_BOOL:
+        return static_cast<const Fn*>(this)->template ForType<bool>(field,
+                                                                    args...);
+      case FieldDescriptor::CPPTYPE_ENUM:
+        return static_cast<const Fn*>(this)
+            ->template ForType<ConstFieldInstance::Enum>(field, args...);
+      case FieldDescriptor::CPPTYPE_STRING:
+        return static_cast<const Fn*>(this)->template ForType<std::string>(
+            field, args...);
+      case FieldDescriptor::CPPTYPE_MESSAGE:
+        return static_cast<const Fn*>(this)
+            ->template ForType<std::unique_ptr<protobuf::Message>>(field,
+                                                                   args...);
+    }
+    assert(false && "Unknown type");
+    abort();
+  }
+};
+
+}  // namespace protobuf_mutator
+
+#endif  // SRC_FIELD_INSTANCE_H_
diff --git a/src/libfuzzer/CMakeLists.txt b/src/libfuzzer/CMakeLists.txt
new file mode 100644
index 0000000..6677f5e
--- /dev/null
+++ b/src/libfuzzer/CMakeLists.txt
@@ -0,0 +1,22 @@
+# 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.
+
+add_library(protobuf-mutator-libfuzzer
+            libfuzzer_mutator.cc
+            libfuzzer_macro.cc)
+target_link_libraries(protobuf-mutator-libfuzzer
+                      protobuf-mutator
+                      ${PROTOBUF_LIBRARIES})
+set_property(TARGET protobuf-mutator-libfuzzer
+             PROPERTY COMPILE_FLAGS "${NO_FUZZING_FLAGS}")
diff --git a/src/libfuzzer/libfuzzer_macro.cc b/src/libfuzzer/libfuzzer_macro.cc
new file mode 100644
index 0000000..162c2ce
--- /dev/null
+++ b/src/libfuzzer/libfuzzer_macro.cc
@@ -0,0 +1,185 @@
+// 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 "src/libfuzzer/libfuzzer_macro.h"
+
+#include "src/binary_format.h"
+#include "src/libfuzzer/libfuzzer_mutator.h"
+#include "src/text_format.h"
+
+namespace protobuf_mutator {
+namespace libfuzzer {
+
+namespace {
+
+class InputReader {
+ public:
+  InputReader(const uint8_t* data, size_t size) : data_(data), size_(size) {}
+  virtual ~InputReader() = default;
+
+  virtual bool Read(protobuf::Message* message) const = 0;
+
+  const uint8_t* data() const { return data_; }
+  size_t size() const { return size_; }
+
+ private:
+  const uint8_t* data_;
+  size_t size_;
+};
+
+class OutputWriter {
+ public:
+  OutputWriter(uint8_t* data, size_t size) : data_(data), size_(size) {}
+  virtual ~OutputWriter() = default;
+
+  virtual size_t Write(const protobuf::Message& message) = 0;
+
+  uint8_t* data() const { return data_; }
+  size_t size() const { return size_; }
+
+ private:
+  uint8_t* data_;
+  size_t size_;
+};
+
+class TextInputReader : public InputReader {
+ public:
+  using InputReader::InputReader;
+
+  bool Read(protobuf::Message* message) const override {
+    return ParseTextMessage(data(), size(), message);
+  }
+};
+
+class TextOutputWriter : public OutputWriter {
+ public:
+  using OutputWriter::OutputWriter;
+
+  size_t Write(const protobuf::Message& message) override {
+    return SaveMessageAsText(message, data(), size());
+  }
+};
+
+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, protobuf::Message* message) {
+  RandomEngine random(seed);
+  Mutator mutator(&random);
+  input.Read(message);
+  mutator.Mutate(message, output->size() > input.size()
+                              ? (output->size() - input.size())
+                              : 0);
+  if (size_t new_size = output->Write(*message)) {
+    assert(new_size <= output->size());
+    return new_size;
+  }
+  return 0;
+}
+
+size_t CrossOverMessages(unsigned int seed, const InputReader& input1,
+                         const InputReader& input2, OutputWriter* output,
+                         protobuf::Message* message1,
+                         protobuf::Message* message2) {
+  RandomEngine random(seed);
+  Mutator mutator(&random);
+  input1.Read(message1);
+  input2.Read(message2);
+  mutator.CrossOver(*message2, message1);
+  if (size_t new_size = output->Write(*message1)) {
+    assert(new_size <= output->size());
+    return new_size;
+  }
+  return 0;
+}
+
+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 MutateMessage(seed, input, &output, message);
+}
+
+size_t CrossOverTextMessages(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) {
+  TextInputReader input1(data1, size1);
+  TextInputReader input2(data2, size2);
+  TextOutputWriter output(out, max_out_size);
+  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
+
+size_t CustomProtoMutator(bool binary, uint8_t* data, size_t size,
+                          size_t max_size, unsigned int seed,
+                          protobuf::Message* input) {
+  auto mutate = binary ? &MutateBinaryMessage : &MutateTextMessage;
+  return mutate(data, size, max_size, seed, input);
+}
+
+size_t CustomProtoCrossOver(bool binary, 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* input1,
+                            protobuf::Message* input2) {
+  auto cross = binary ? &CrossOverBinaryMessages : &CrossOverTextMessages;
+  return cross(data1, size1, data2, size2, out, max_out_size, seed, input1,
+               input2);
+}
+
+bool LoadProtoInput(bool binary, const uint8_t* data, size_t size,
+                    protobuf::Message* input) {
+  return binary ? ParseBinaryMessage(data, size, input)
+                : ParseTextMessage(data, size, input);
+}
+
+}  // namespace libfuzzer
+}  // namespace protobuf_mutator
diff --git a/src/libfuzzer/libfuzzer_macro.h b/src/libfuzzer/libfuzzer_macro.h
new file mode 100644
index 0000000..59ae0ba
--- /dev/null
+++ b/src/libfuzzer/libfuzzer_macro.h
@@ -0,0 +1,91 @@
+// 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.
+
+#ifndef SRC_LIBFUZZER_LIBFUZZER_MACRO_H_
+#define SRC_LIBFUZZER_LIBFUZZER_MACRO_H_
+
+#include <stddef.h>
+#include <cstdint>
+#include <functional>
+#include <type_traits>
+
+#include "port/protobuf.h"
+
+// Defines custom mutator, crossover and test functions using default
+// serialization format. Default is text.
+#define DEFINE_PROTO_FUZZER(arg) DEFINE_TEXT_PROTO_FUZZER(arg)
+// Defines custom mutator, crossover and test functions using text
+// serialization. This format is more convenient to read.
+#define DEFINE_TEXT_PROTO_FUZZER(arg) DEFINE_PROTO_FUZZER_IMPL(false, arg)
+// Defines custom mutator, crossover and test functions using binary
+// serialization. This makes mutations faster. However often test function is
+// significantly slower than mutator, so fuzzing rate may stay unchanged.
+#define DEFINE_BINARY_PROTO_FUZZER(arg) DEFINE_PROTO_FUZZER_IMPL(true, arg)
+
+// Implementation of macros above.
+#define DEFINE_CUSTOM_PROTO_MUTATOR_IMPL(use_binary, Proto)                    \
+  extern "C" size_t LLVMFuzzerCustomMutator(                                   \
+      uint8_t* data, size_t size, size_t max_size, unsigned int seed) {        \
+    using protobuf_mutator::libfuzzer::CustomProtoMutator;                     \
+    Proto input;                                                               \
+    return CustomProtoMutator(use_binary, data, size, max_size, seed, &input); \
+  }
+
+#define DEFINE_CUSTOM_PROTO_CROSSOVER_IMPL(use_binary, Proto)                 \
+  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) {                 \
+    using protobuf_mutator::libfuzzer::CustomProtoCrossOver;                  \
+    Proto input1;                                                             \
+    Proto input2;                                                             \
+    return CustomProtoCrossOver(use_binary, data1, size1, data2, size2, out,  \
+                                max_out_size, seed, &input1, &input2);        \
+  }
+
+#define DEFINE_TEST_ONE_PROTO_INPUT_IMPL(use_binary, Proto)                 \
+  extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) { \
+    using protobuf_mutator::libfuzzer::LoadProtoInput;                      \
+    Proto input;                                                            \
+    if (LoadProtoInput(use_binary, data, size, &input))                     \
+      TestOneProtoInput(input);                                             \
+    return 0;                                                               \
+  }
+
+#define DEFINE_PROTO_FUZZER_IMPL(use_binary, arg)                              \
+  static void TestOneProtoInput(arg);                                          \
+  using FuzzerProtoType = std::remove_const<std::remove_reference<             \
+      std::function<decltype(TestOneProtoInput)>::argument_type>::type>::type; \
+  DEFINE_CUSTOM_PROTO_MUTATOR_IMPL(use_binary, FuzzerProtoType)                \
+  DEFINE_CUSTOM_PROTO_CROSSOVER_IMPL(use_binary, FuzzerProtoType)              \
+  DEFINE_TEST_ONE_PROTO_INPUT_IMPL(use_binary, FuzzerProtoType)                \
+  static void TestOneProtoInput(arg)
+
+namespace protobuf_mutator {
+namespace libfuzzer {
+
+size_t CustomProtoMutator(bool binary, uint8_t* data, size_t size,
+                          size_t max_size, unsigned int seed,
+                          protobuf::Message* input);
+size_t CustomProtoCrossOver(bool binary, 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* input1,
+                            protobuf::Message* input2);
+bool LoadProtoInput(bool binary, const uint8_t* data, size_t size,
+                    protobuf::Message* input);
+
+}  // namespace libfuzzer
+}  // namespace protobuf_mutator
+
+#endif  // SRC_LIBFUZZER_LIBFUZZER_MACRO_H_
diff --git a/src/libfuzzer/libfuzzer_mutator.cc b/src/libfuzzer/libfuzzer_mutator.cc
new file mode 100644
index 0000000..0da9552
--- /dev/null
+++ b/src/libfuzzer/libfuzzer_mutator.cc
@@ -0,0 +1,68 @@
+// 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 "src/libfuzzer/libfuzzer_mutator.h"
+
+#include <string.h>
+#include <cassert>
+#include <memory>
+#include <string>
+
+#include "port/protobuf.h"
+#include "src/mutator.h"
+
+extern "C" size_t LLVMFuzzerMutate(uint8_t*, size_t, size_t)
+    __attribute__((weak));
+
+namespace protobuf_mutator {
+namespace libfuzzer {
+
+namespace {
+
+template <class T>
+T MutateValue(T v) {
+  size_t size =
+      LLVMFuzzerMutate(reinterpret_cast<uint8_t*>(&v), sizeof(v), sizeof(v));
+  memset(reinterpret_cast<uint8_t*>(&v) + size, 0, sizeof(v) - size);
+  return v;
+}
+
+}  // namespace
+
+int32_t Mutator::MutateInt32(int32_t value) { return MutateValue(value); }
+
+int64_t Mutator::MutateInt64(int64_t value) { return MutateValue(value); }
+
+uint32_t Mutator::MutateUInt32(uint32_t value) { return MutateValue(value); }
+
+uint64_t Mutator::MutateUInt64(uint64_t value) { return MutateValue(value); }
+
+float Mutator::MutateFloat(float value) { return MutateValue(value); }
+
+double Mutator::MutateDouble(double value) { return MutateValue(value); }
+
+std::string Mutator::MutateString(const std::string& value,
+                                  size_t size_increase_hint) {
+  // Randomly return empty strings as LLVMFuzzerMutate does not produce them.
+  if (!std::uniform_int_distribution<uint8_t>(0, 20)(*random())) return {};
+  std::string result = value;
+  result.resize(value.size() + size_increase_hint);
+  if (result.empty()) result.push_back(0);
+  result.resize(LLVMFuzzerMutate(reinterpret_cast<uint8_t*>(&result[0]),
+                                 value.size(), result.size()));
+  return result;
+}
+
+}  // namespace libfuzzer
+}  // namespace protobuf_mutator
diff --git a/src/libfuzzer/libfuzzer_mutator.h b/src/libfuzzer/libfuzzer_mutator.h
new file mode 100644
index 0000000..45ea908
--- /dev/null
+++ b/src/libfuzzer/libfuzzer_mutator.h
@@ -0,0 +1,46 @@
+// 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.
+
+#ifndef SRC_LIBFUZZER_LIBFUZZER_MUTATOR_H_
+#define SRC_LIBFUZZER_LIBFUZZER_MUTATOR_H_
+
+#include <string>
+
+#include "src/mutator.h"
+
+namespace protobuf_mutator {
+namespace libfuzzer {
+
+// Overrides protobuf_mutator::Mutator::Mutate* methods with implementation
+// which uses libFuzzer library. protobuf_mutator::Mutator has very basic
+// implementation of this methods.
+class Mutator : public protobuf_mutator::Mutator {
+ public:
+  using protobuf_mutator::Mutator::Mutator;
+
+ protected:
+  int32_t MutateInt32(int32_t value) override;
+  int64_t MutateInt64(int64_t value) override;
+  uint32_t MutateUInt32(uint32_t value) override;
+  uint64_t MutateUInt64(uint64_t value) override;
+  float MutateFloat(float value) override;
+  double MutateDouble(double value) override;
+  std::string MutateString(const std::string& value,
+                           size_t size_increase_hint) override;
+};
+
+}  // namespace libfuzzer
+}  // namespace protobuf_mutator
+
+#endif  // SRC_LIBFUZZER_LIBFUZZER_MUTATOR_H_
diff --git a/src/mutator.cc b/src/mutator.cc
new file mode 100644
index 0000000..2aa9693
--- /dev/null
+++ b/src/mutator.cc
@@ -0,0 +1,670 @@
+// Copyright 2016 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 "src/mutator.h"
+
+#include <algorithm>
+#include <functional>
+#include <map>
+#include <random>
+#include <string>
+
+#include "src/field_instance.h"
+#include "src/utf8_fix.h"
+#include "src/weighted_reservoir_sampler.h"
+
+namespace protobuf_mutator {
+
+using protobuf::Descriptor;
+using protobuf::FieldDescriptor;
+using protobuf::FileDescriptor;
+using protobuf::Message;
+using protobuf::OneofDescriptor;
+using protobuf::Reflection;
+using protobuf::util::MessageDifferencer;
+using std::placeholders::_1;
+
+namespace {
+
+const int kMaxInitializeDepth = 200;
+const uint64_t kDefaultMutateWeight = 1000000;
+
+enum class Mutation {
+  None,
+  Add,     // Adds new field with default value.
+  Mutate,  // Mutates field contents.
+  Delete,  // Deletes field.
+  Copy,    // Copy values copied from another field.
+
+  // TODO(vitalybuka):
+  // Clone,  // Adds new field with value copied from another field.
+};
+
+// Return random integer from [0, count)
+size_t GetRandomIndex(RandomEngine* random, size_t count) {
+  assert(count > 0);
+  if (count == 1) return 0;
+  return std::uniform_int_distribution<size_t>(0, count - 1)(*random);
+}
+
+// Flips random bit in the buffer.
+void FlipBit(size_t size, uint8_t* bytes, RandomEngine* random) {
+  size_t bit = GetRandomIndex(random, size * 8);
+  bytes[bit / 8] ^= (1u << (bit % 8));
+}
+
+// Flips random bit in the value.
+template <class T>
+T FlipBit(T value, RandomEngine* random) {
+  FlipBit(sizeof(value), reinterpret_cast<uint8_t*>(&value), random);
+  return value;
+}
+
+// Return true with probability about 1-of-n.
+bool GetRandomBool(RandomEngine* random, size_t n = 2) {
+  return GetRandomIndex(random, n) == 0;
+}
+
+bool IsProto3SimpleField(const FieldDescriptor& field) {
+  assert(field.file()->syntax() == FileDescriptor::SYNTAX_PROTO3 ||
+         field.file()->syntax() == FileDescriptor::SYNTAX_PROTO2);
+  return field.file()->syntax() == FileDescriptor::SYNTAX_PROTO3 &&
+         field.cpp_type() != FieldDescriptor::CPPTYPE_MESSAGE &&
+         !field.containing_oneof() && !field.is_repeated();
+}
+
+struct CreateDefaultField : public FieldFunction<CreateDefaultField> {
+  template <class T>
+  void ForType(const FieldInstance& field) const {
+    T value;
+    field.GetDefault(&value);
+    field.Create(value);
+  }
+};
+
+struct DeleteField : public FieldFunction<DeleteField> {
+  template <class T>
+  void ForType(const FieldInstance& field) const {
+    field.Delete();
+  }
+};
+
+struct CopyField : public FieldFunction<CopyField> {
+  template <class T>
+  void ForType(const ConstFieldInstance& source,
+               const FieldInstance& field) const {
+    T value;
+    source.Load(&value);
+    field.Store(value);
+  }
+};
+
+struct AppendField : public FieldFunction<AppendField> {
+  template <class T>
+  void ForType(const ConstFieldInstance& source,
+               const FieldInstance& field) const {
+    T value;
+    source.Load(&value);
+    field.Create(value);
+  }
+};
+
+class IsEqualValueField : public FieldFunction<IsEqualValueField, bool> {
+ public:
+  template <class T>
+  bool ForType(const ConstFieldInstance& a, const ConstFieldInstance& b) const {
+    T aa;
+    a.Load(&aa);
+    T bb;
+    b.Load(&bb);
+    return IsEqual(aa, bb);
+  }
+
+ private:
+  bool IsEqual(const ConstFieldInstance::Enum& a,
+               const ConstFieldInstance::Enum& b) const {
+    assert(a.count == b.count);
+    return a.index == b.index;
+  }
+
+  bool IsEqual(const std::unique_ptr<protobuf::Message>& a,
+               const std::unique_ptr<protobuf::Message>& b) const {
+    return MessageDifferencer::Equals(*a, *b);
+  }
+
+  template <class T>
+  bool IsEqual(const T& a, const T& b) const {
+    return a == b;
+  }
+};
+
+// Selects random field and mutation from the given proto message.
+class MutationSampler {
+ public:
+  MutationSampler(bool keep_initialized, RandomEngine* random, Message* message)
+      : keep_initialized_(keep_initialized), random_(random), sampler_(random) {
+    Sample(message);
+    assert(mutation() != Mutation::None ||
+           message->GetDescriptor()->field_count() == 0);
+  }
+
+  // Returns selected field.
+  const FieldInstance& field() const { return sampler_.selected().field; }
+
+  // Returns selected mutation.
+  Mutation mutation() const { return sampler_.selected().mutation; }
+
+ private:
+  void Sample(Message* message) {
+    const Descriptor* descriptor = message->GetDescriptor();
+    const Reflection* reflection = message->GetReflection();
+
+    int field_count = descriptor->field_count();
+    for (int i = 0; i < field_count; ++i) {
+      const FieldDescriptor* field = descriptor->field(i);
+      if (const OneofDescriptor* oneof = field->containing_oneof()) {
+        // Handle entire oneof group on the first field.
+        if (field->index_in_oneof() == 0) {
+          assert(oneof->field_count());
+          const FieldDescriptor* current_field =
+              reflection->GetOneofFieldDescriptor(*message, oneof);
+          for (;;) {
+            const FieldDescriptor* add_field =
+                oneof->field(GetRandomIndex(random_, oneof->field_count()));
+            if (add_field != current_field) {
+              sampler_.Try(kDefaultMutateWeight,
+                           {{message, add_field}, Mutation::Add});
+              break;
+            }
+            if (oneof->field_count() < 2) break;
+          }
+          if (current_field) {
+            if (current_field->cpp_type() != FieldDescriptor::CPPTYPE_MESSAGE) {
+              sampler_.Try(kDefaultMutateWeight,
+                           {{message, current_field}, Mutation::Mutate});
+            }
+            sampler_.Try(kDefaultMutateWeight,
+                         {{message, current_field}, Mutation::Delete});
+            sampler_.Try(kDefaultMutateWeight,
+                         {{message, current_field}, Mutation::Copy});
+          }
+        }
+      } else {
+        if (field->is_repeated()) {
+          int field_size = reflection->FieldSize(*message, field);
+          sampler_.Try(
+              kDefaultMutateWeight,
+              {{message, field, GetRandomIndex(random_, field_size + 1)},
+               Mutation::Add});
+
+          if (field_size) {
+            size_t random_index = GetRandomIndex(random_, field_size);
+            if (field->cpp_type() != FieldDescriptor::CPPTYPE_MESSAGE) {
+              sampler_.Try(kDefaultMutateWeight,
+                           {{message, field, random_index}, Mutation::Mutate});
+            }
+            sampler_.Try(kDefaultMutateWeight,
+                         {{message, field, random_index}, Mutation::Delete});
+            sampler_.Try(kDefaultMutateWeight,
+                         {{message, field, random_index}, Mutation::Copy});
+          }
+        } else {
+          if (reflection->HasField(*message, field) ||
+              IsProto3SimpleField(*field)) {
+            if (field->cpp_type() != FieldDescriptor::CPPTYPE_MESSAGE)
+              sampler_.Try(kDefaultMutateWeight,
+                           {{message, field}, Mutation::Mutate});
+            if (!IsProto3SimpleField(*field) &&
+                (!field->is_required() || !keep_initialized_)) {
+              sampler_.Try(kDefaultMutateWeight,
+                           {{message, field}, Mutation::Delete});
+            }
+            sampler_.Try(kDefaultMutateWeight,
+                         {{message, field}, Mutation::Copy});
+          } else {
+            sampler_.Try(kDefaultMutateWeight,
+                         {{message, field}, Mutation::Add});
+          }
+        }
+      }
+
+      if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) {
+        if (field->is_repeated()) {
+          const int field_size = reflection->FieldSize(*message, field);
+          for (int j = 0; j < field_size; ++j)
+            Sample(reflection->MutableRepeatedMessage(message, field, j));
+        } else if (reflection->HasField(*message, field)) {
+          Sample(reflection->MutableMessage(message, field));
+        }
+      }
+    }
+  }
+
+  bool keep_initialized_ = false;
+
+  RandomEngine* random_;
+
+  struct Result {
+    Result() = default;
+    Result(const FieldInstance& f, Mutation m) : field(f), mutation(m) {}
+
+    FieldInstance field;
+    Mutation mutation = Mutation::None;
+  };
+  WeightedReservoirSampler<Result, RandomEngine> sampler_;
+};
+
+// Selects random field of compatible type to use for clone mutations.
+class DataSourceSampler {
+ public:
+  DataSourceSampler(const ConstFieldInstance& match, RandomEngine* random,
+                    Message* message)
+      : match_(match), random_(random), sampler_(random) {
+    Sample(message);
+  }
+
+  // Returns selected field.
+  const ConstFieldInstance& field() const {
+    assert(!IsEmpty());
+    return sampler_.selected();
+  }
+
+  bool IsEmpty() const { return sampler_.IsEmpty(); }
+
+ private:
+  void Sample(Message* message) {
+    const Descriptor* descriptor = message->GetDescriptor();
+    const Reflection* reflection = message->GetReflection();
+
+    int field_count = descriptor->field_count();
+    for (int i = 0; i < field_count; ++i) {
+      const FieldDescriptor* field = descriptor->field(i);
+      if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) {
+        if (field->is_repeated()) {
+          const int field_size = reflection->FieldSize(*message, field);
+          for (int j = 0; j < field_size; ++j) {
+            Sample(reflection->MutableRepeatedMessage(message, field, j));
+          }
+        } else if (reflection->HasField(*message, field)) {
+          Sample(reflection->MutableMessage(message, field));
+        }
+      }
+
+      if (field->cpp_type() != match_.cpp_type()) continue;
+      if (match_.cpp_type() == FieldDescriptor::CPPTYPE_ENUM) {
+        if (field->enum_type() != match_.enum_type()) continue;
+      } else if (match_.cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) {
+        if (field->message_type() != match_.message_type()) continue;
+      }
+
+      if (field->is_repeated()) {
+        if (int field_size = reflection->FieldSize(*message, field)) {
+          ConstFieldInstance source(message, field,
+                                    GetRandomIndex(random_, field_size));
+          if (match_.EnforceUtf8() && !source.EnforceUtf8()) continue;
+          if (!IsEqualValueField()(match_, source))
+            sampler_.Try(field_size, source);
+        }
+      } else {
+        if (reflection->HasField(*message, field)) {
+          ConstFieldInstance source(message, field);
+          if (match_.EnforceUtf8() && !source.EnforceUtf8()) continue;
+          if (!IsEqualValueField()(match_, source)) sampler_.Try(1, source);
+        }
+      }
+    }
+  }
+
+  ConstFieldInstance match_;
+  RandomEngine* random_;
+
+  WeightedReservoirSampler<ConstFieldInstance, RandomEngine> sampler_;
+};
+
+}  // namespace
+
+class FieldMutator {
+ public:
+  FieldMutator(size_t size_increase_hint, bool enforce_changes,
+               bool enforce_utf8_strings, Mutator* mutator)
+      : size_increase_hint_(size_increase_hint),
+        enforce_changes_(enforce_changes),
+        enforce_utf8_strings_(enforce_utf8_strings),
+        mutator_(mutator) {}
+
+  void Mutate(int32_t* value) const {
+    RepeatMutate(value, std::bind(&Mutator::MutateInt32, mutator_, _1));
+  }
+
+  void Mutate(int64_t* value) const {
+    RepeatMutate(value, std::bind(&Mutator::MutateInt64, mutator_, _1));
+  }
+
+  void Mutate(uint32_t* value) const {
+    RepeatMutate(value, std::bind(&Mutator::MutateUInt32, mutator_, _1));
+  }
+
+  void Mutate(uint64_t* value) const {
+    RepeatMutate(value, std::bind(&Mutator::MutateUInt64, mutator_, _1));
+  }
+
+  void Mutate(float* value) const {
+    RepeatMutate(value, std::bind(&Mutator::MutateFloat, mutator_, _1));
+  }
+
+  void Mutate(double* value) const {
+    RepeatMutate(value, std::bind(&Mutator::MutateDouble, mutator_, _1));
+  }
+
+  void Mutate(bool* value) const {
+    RepeatMutate(value, std::bind(&Mutator::MutateBool, mutator_, _1), 2);
+  }
+
+  void Mutate(FieldInstance::Enum* value) const {
+    RepeatMutate(&value->index,
+                 std::bind(&Mutator::MutateEnum, mutator_, _1, value->count),
+                 std::max<size_t>(value->count, 1));
+    assert(value->index < value->count);
+  }
+
+  void Mutate(std::string* value) const {
+    if (enforce_utf8_strings_) {
+      RepeatMutate(value, std::bind(&Mutator::MutateUtf8String, mutator_, _1,
+                                    size_increase_hint_));
+    } else {
+      RepeatMutate(value, std::bind(&Mutator::MutateString, mutator_, _1,
+                                    size_increase_hint_));
+    }
+  }
+
+  void Mutate(std::unique_ptr<Message>* message) const {
+    assert(!enforce_changes_);
+    assert(*message);
+    if (GetRandomBool(mutator_->random(), 100)) return;
+    mutator_->Mutate(message->get(), size_increase_hint_);
+  }
+
+ private:
+  template <class T, class F>
+  void RepeatMutate(T* value, F mutate,
+                    size_t unchanged_one_out_of = 100) const {
+    if (!enforce_changes_ &&
+        GetRandomBool(mutator_->random(), unchanged_one_out_of)) {
+      return;
+    }
+    T tmp = *value;
+    for (int i = 0; i < 10; ++i) {
+      *value = mutate(*value);
+      if (!enforce_changes_ || *value != tmp) return;
+    }
+  }
+
+  size_t size_increase_hint_;
+  size_t enforce_changes_;
+  bool enforce_utf8_strings_;
+  Mutator* mutator_;
+};
+
+namespace {
+
+struct MutateField : public FieldFunction<MutateField> {
+  template <class T>
+  void ForType(const FieldInstance& field, size_t size_increase_hint,
+               Mutator* mutator) const {
+    T value;
+    field.Load(&value);
+    FieldMutator(size_increase_hint, true, field.EnforceUtf8(), mutator)
+        .Mutate(&value);
+    field.Store(value);
+  }
+};
+
+struct CreateField : public FieldFunction<CreateField> {
+ public:
+  template <class T>
+  void ForType(const FieldInstance& field, size_t size_increase_hint,
+               Mutator* mutator) const {
+    T value;
+    field.GetDefault(&value);
+    FieldMutator field_mutator(size_increase_hint,
+                               false /* defaults could be useful */,
+                               field.EnforceUtf8(), mutator);
+    field_mutator.Mutate(&value);
+    field.Create(value);
+  }
+};
+
+}  // namespace
+
+Mutator::Mutator(RandomEngine* random) : random_(random) {}
+
+void Mutator::Mutate(Message* message, size_t size_increase_hint) {
+  bool repeat;
+  do {
+    repeat = false;
+    MutationSampler mutation(keep_initialized_, random_, message);
+    switch (mutation.mutation()) {
+      case Mutation::None:
+        break;
+      case Mutation::Add:
+        CreateField()(mutation.field(), size_increase_hint / 2, this);
+        break;
+      case Mutation::Mutate:
+        MutateField()(mutation.field(), size_increase_hint / 2, this);
+        break;
+      case Mutation::Delete:
+        DeleteField()(mutation.field());
+        break;
+      case Mutation::Copy: {
+        DataSourceSampler source(mutation.field(), random_, message);
+        if (source.IsEmpty()) {
+          repeat = true;
+          break;
+        }
+        CopyField()(source.field(), mutation.field());
+        break;
+      }
+      default:
+        assert(false && "unexpected mutation");
+    }
+  } while (repeat);
+
+  InitializeAndTrim(message, kMaxInitializeDepth);
+  assert(!keep_initialized_ || message->IsInitialized());
+}
+
+void Mutator::CrossOver(const protobuf::Message& message1,
+                        protobuf::Message* message2) {
+  // CrossOver can produce result which still equals to inputs. So we backup
+  // message2 to later comparison. message1 is already constant.
+  std::unique_ptr<protobuf::Message> message2_copy(message2->New());
+  message2_copy->CopyFrom(*message2);
+
+  CrossOverImpl(message1, message2);
+
+  InitializeAndTrim(message2, kMaxInitializeDepth);
+  assert(!keep_initialized_ || message2->IsInitialized());
+
+  // Can't call mutate from crossover because of a bug in libFuzzer.
+  return;
+  // if (MessageDifferencer::Equals(*message2_copy, *message2) ||
+  //     MessageDifferencer::Equals(message1, *message2)) {
+  //   Mutate(message2, 0);
+  // }
+}
+
+void Mutator::CrossOverImpl(const protobuf::Message& message1,
+                            protobuf::Message* message2) {
+  const Descriptor* descriptor = message2->GetDescriptor();
+  const Reflection* reflection = message2->GetReflection();
+  assert(message1.GetDescriptor() == descriptor);
+  assert(message1.GetReflection() == reflection);
+
+  for (int i = 0; i < descriptor->field_count(); ++i) {
+    const FieldDescriptor* field = descriptor->field(i);
+
+    if (field->is_repeated()) {
+      const int field_size1 = reflection->FieldSize(message1, field);
+      int field_size2 = reflection->FieldSize(*message2, field);
+      for (int j = 0; j < field_size1; ++j) {
+        ConstFieldInstance source(&message1, field, j);
+        FieldInstance destination(message2, field, field_size2++);
+        AppendField()(source, destination);
+      }
+
+      assert(field_size2 == reflection->FieldSize(*message2, field));
+
+      // Shuffle
+      for (int j = 0; j < field_size2; ++j) {
+        if (int k = GetRandomIndex(random_, field_size2 - j)) {
+          reflection->SwapElements(message2, field, j, j + k);
+        }
+      }
+
+      int keep = GetRandomIndex(random_, field_size2 + 1);
+
+      if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) {
+        int remove = field_size2 - keep;
+        // Cross some message to keep with messages to remove.
+        int cross = GetRandomIndex(random_, std::min(keep, remove) + 1);
+        for (int j = 0; j < cross; ++j) {
+          int k = GetRandomIndex(random_, keep);
+          int r = keep + GetRandomIndex(random_, remove);
+          assert(k != r);
+          CrossOverImpl(reflection->GetRepeatedMessage(*message2, field, r),
+                        reflection->MutableRepeatedMessage(message2, field, k));
+        }
+      }
+
+      for (int j = keep; j < field_size2; ++j)
+        reflection->RemoveLast(message2, field);
+      assert(keep == reflection->FieldSize(*message2, field));
+
+    } else if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) {
+      if (!reflection->HasField(message1, field)) {
+        if (GetRandomBool(random_))
+          DeleteField()(FieldInstance(message2, field));
+      } else if (!reflection->HasField(*message2, field)) {
+        if (GetRandomBool(random_)) {
+          ConstFieldInstance source(&message1, field);
+          CopyField()(source, FieldInstance(message2, field));
+        }
+      } else {
+        CrossOverImpl(reflection->GetMessage(message1, field),
+                      reflection->MutableMessage(message2, field));
+      }
+    } else {
+      if (GetRandomBool(random_)) {
+        if (reflection->HasField(message1, field)) {
+          ConstFieldInstance source(&message1, field);
+          CopyField()(source, FieldInstance(message2, field));
+        } else {
+          DeleteField()(FieldInstance(message2, field));
+        }
+      }
+    }
+  }
+}
+
+void Mutator::InitializeAndTrim(Message* message, int max_depth) {
+  const Descriptor* descriptor = message->GetDescriptor();
+  const Reflection* reflection = message->GetReflection();
+  for (int i = 0; i < descriptor->field_count(); ++i) {
+    const FieldDescriptor* field = descriptor->field(i);
+    if (keep_initialized_ && field->is_required() &&
+        !reflection->HasField(*message, field))
+      CreateDefaultField()(FieldInstance(message, field));
+
+    if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) {
+      if (max_depth <= 0 && !field->is_required()) {
+        // Clear deep optional fields to avoid stack overflow.
+        reflection->ClearField(message, field);
+        if (field->is_repeated())
+          assert(!reflection->FieldSize(*message, field));
+        else
+          assert(!reflection->HasField(*message, field));
+        continue;
+      }
+
+      if (field->is_repeated()) {
+        const int field_size = reflection->FieldSize(*message, field);
+        for (int j = 0; j < field_size; ++j) {
+          Message* nested_message =
+              reflection->MutableRepeatedMessage(message, field, j);
+          InitializeAndTrim(nested_message, max_depth - 1);
+        }
+      } else if (reflection->HasField(*message, field)) {
+        Message* nested_message = reflection->MutableMessage(message, field);
+        InitializeAndTrim(nested_message, max_depth - 1);
+      }
+    }
+  }
+}
+
+int32_t Mutator::MutateInt32(int32_t value) { return FlipBit(value, random_); }
+
+int64_t Mutator::MutateInt64(int64_t value) { return FlipBit(value, random_); }
+
+uint32_t Mutator::MutateUInt32(uint32_t value) {
+  return FlipBit(value, random_);
+}
+
+uint64_t Mutator::MutateUInt64(uint64_t value) {
+  return FlipBit(value, random_);
+}
+
+float Mutator::MutateFloat(float value) { return FlipBit(value, random_); }
+
+double Mutator::MutateDouble(double value) { return FlipBit(value, random_); }
+
+bool Mutator::MutateBool(bool value) { return !value; }
+
+size_t Mutator::MutateEnum(size_t index, size_t item_count) {
+  if (item_count <= 1) return 0;
+  return (index + 1 + GetRandomIndex(random_, item_count - 1)) % item_count;
+}
+
+std::string Mutator::MutateString(const std::string& value,
+                                  size_t size_increase_hint) {
+  std::string result = value;
+
+  while (!result.empty() && GetRandomBool(random_)) {
+    result.erase(GetRandomIndex(random_, result.size()), 1);
+  }
+
+  while (result.size() < size_increase_hint && GetRandomBool(random_)) {
+    size_t index = GetRandomIndex(random_, result.size() + 1);
+    result.insert(result.begin() + index, GetRandomIndex(random_, 1 << 8));
+  }
+
+  if (result != value) return result;
+
+  if (result.empty()) {
+    result.push_back(GetRandomIndex(random_, 1 << 8));
+    return result;
+  }
+
+  if (!result.empty())
+    FlipBit(result.size(), reinterpret_cast<uint8_t*>(&result[0]), random_);
+  return result;
+}
+
+std::string Mutator::MutateUtf8String(const std::string& value,
+                                      size_t size_increase_hint) {
+  std::string str = MutateString(value, size_increase_hint);
+  FixUtf8String(&str, random_);
+  return str;
+}
+
+}  // namespace protobuf_mutator
diff --git a/src/mutator.h b/src/mutator.h
new file mode 100644
index 0000000..47139bd
--- /dev/null
+++ b/src/mutator.h
@@ -0,0 +1,93 @@
+// Copyright 2016 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.
+
+#ifndef SRC_MUTATOR_H_
+#define SRC_MUTATOR_H_
+
+#include <stddef.h>
+#include <stdint.h>
+
+#include <memory>
+#include <random>
+#include <string>
+
+#include "port/protobuf.h"
+#include "src/random.h"
+
+namespace protobuf_mutator {
+
+// Randomly makes incremental change in the given protobuf.
+// Usage example:
+//    protobuf_mutator::Mutator mutator(1);
+//    MyMessage message;
+//    message.ParseFromString(encoded_message);
+//    mutator.Mutate(&message, 10000);
+//
+// Class implements very basic mutations of fields. E.g. it just flips bits for
+// integers, floats and strings. Also it increases, decreases size of
+// strings only by one. For better results users should override
+// protobuf_mutator::Mutator::Mutate* methods with more useful logic, e.g. using
+// library like libFuzzer.
+class Mutator {
+ public:
+  // seed: value to initialize random number generator.
+  explicit Mutator(RandomEngine* random);
+  virtual ~Mutator() = default;
+
+  // message: message to mutate.
+  // size_increase_hint: approximate number of bytes which can be added to the
+  // message. Method does not guarantee that real result size increase will be
+  // less than the value. It only changes probabilities of mutations which can
+  // cause size increase. Caller could repeat mutation if result was larger than
+  // requested.
+  void Mutate(protobuf::Message* message, size_t size_increase_hint);
+
+  void CrossOver(const protobuf::Message& message1,
+                 protobuf::Message* message2);
+
+ protected:
+  // TODO(vitalybuka): Consider to replace with single mutate (uint8_t*, size).
+  virtual int32_t MutateInt32(int32_t value);
+  virtual int64_t MutateInt64(int64_t value);
+  virtual uint32_t MutateUInt32(uint32_t value);
+  virtual uint64_t MutateUInt64(uint64_t value);
+  virtual float MutateFloat(float value);
+  virtual double MutateDouble(double value);
+  virtual bool MutateBool(bool value);
+  virtual size_t MutateEnum(size_t index, size_t item_count);
+  virtual std::string MutateString(const std::string& value,
+                                   size_t size_increase_hint);
+
+  // TODO(vitalybuka): Allow user to control proto level mutations:
+  //   * Callbacks to recursive traversal.
+  //   * Callbacks for particular proto level mutations.
+
+  RandomEngine* random() { return random_; }
+
+ private:
+  friend class FieldMutator;
+  friend class TestMutator;
+  void InitializeAndTrim(protobuf::Message* message, int max_depth);
+  void CrossOverImpl(const protobuf::Message& message1,
+                     protobuf::Message* message2);
+  std::string MutateUtf8String(const std::string& value,
+                               size_t size_increase_hint);
+
+  bool keep_initialized_ = true;
+  RandomEngine* random_;
+};
+
+}  // namespace protobuf_mutator
+
+#endif  // SRC_MUTATOR_H_
diff --git a/src/mutator_test.cc b/src/mutator_test.cc
new file mode 100644
index 0000000..34766c6
--- /dev/null
+++ b/src/mutator_test.cc
@@ -0,0 +1,647 @@
+// Copyright 2016 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 "src/mutator.h"
+
+#include <algorithm>
+#include <set>
+#include <string>
+#include <tuple>
+#include <utility>
+#include <vector>
+
+#include "port/gtest.h"
+#include "src/binary_format.h"
+#include "src/mutator_test_proto2.pb.h"
+#include "src/mutator_test_proto3.pb.h"
+#include "src/text_format.h"
+
+namespace protobuf_mutator {
+
+using protobuf::util::MessageDifferencer;
+using testing::TestWithParam;
+using testing::ValuesIn;
+
+const char kMessages[] = R"(
+  required_msg {}
+  optional_msg {}
+  repeated_msg {}
+  repeated_msg {required_sint32: 56}
+  repeated_msg {}
+  repeated_msg {
+    required_msg {}
+    optional_msg {}
+    repeated_msg {}
+    repeated_msg { required_int32: 67 }
+    repeated_msg {}
+  }
+)";
+
+const char kMessagesProto3[] = R"(
+  optional_msg {}
+  repeated_msg {}
+  repeated_msg {optional_sint32: 56}
+  repeated_msg {}
+  repeated_msg {
+    optional_msg {}
+    repeated_msg {}
+    repeated_msg { optional_int32: 67 }
+    repeated_msg {}
+  }
+)";
+
+const char kRequiredFields[] = R"(
+  required_double: 1.26685288449177e-313
+  required_float: 5.9808638e-39
+  required_int32: 67
+  required_int64: 5285068
+  required_uint32: 14486213
+  required_uint64: 520229415
+  required_sint32: 56
+  required_sint64: -6057486163525532641
+  required_fixed32: 8812173
+  required_fixed64: 273731277756
+  required_sfixed32: 43142
+  required_sfixed64: 132
+  required_bool: false
+  required_string: "qwert"
+  required_bytes: "asdf"
+)";
+
+const char kOptionalFields[] = R"(
+  optional_double: 1.93177850152856e-314
+  optional_float: 4.7397519e-41
+  optional_int32: 40020
+  optional_int64: 10
+  optional_uint32: 40
+  optional_uint64: 159
+  optional_sint32: 44015
+  optional_sint64: 17493625000076
+  optional_fixed32: 193
+  optional_fixed64: 8542688694448488723
+  optional_sfixed32: 4926
+  optional_sfixed64: 60
+  optional_bool: true
+  optional_string: "QWERT"
+  optional_bytes: "ASDF"
+  optional_enum: ENUM_5
+)";
+
+const char kRepeatedFields[] = R"(
+  repeated_double: 1.93177850152856e-314
+  repeated_double: 1.26685288449177e-313
+  repeated_float: 4.7397519e-41
+  repeated_float: 5.9808638e-39
+  repeated_int32: 40020
+  repeated_int32: 67
+  repeated_int64: 10
+  repeated_int64: 5285068
+  repeated_uint32: 40
+  repeated_uint32: 14486213
+  repeated_uint64: 159
+  repeated_uint64: 520229415
+  repeated_sint32: 44015
+  repeated_sint32: 56
+  repeated_sint64: 17493625000076
+  repeated_sint64: -6057486163525532641
+  repeated_fixed32: 193
+  repeated_fixed32: 8812173
+  repeated_fixed64: 8542688694448488723
+  repeated_fixed64: 273731277756
+  repeated_sfixed32: 4926
+  repeated_sfixed32: 43142
+  repeated_sfixed64: 60
+  repeated_sfixed64: 132
+  repeated_bool: false
+  repeated_bool: true
+  repeated_string: "QWERT"
+  repeated_string: "qwert"
+  repeated_bytes: "ASDF"
+  repeated_bytes: "asdf"
+  repeated_enum: ENUM_5
+  repeated_enum: ENUM_4
+)";
+
+const char kRequiredNestedFields[] = R"(
+  required_int32: 123
+  optional_msg {
+    required_double: 1.26685288449177e-313
+    required_float: 5.9808638e-39
+    required_int32: 67
+    required_int64: 5285068
+    required_uint32: 14486213
+    required_uint64: 520229415
+    required_sint32: 56
+    required_sint64: -6057486163525532641
+    required_fixed32: 8812173
+    required_fixed64: 273731277756
+    required_sfixed32: 43142
+    required_sfixed64: 132
+    required_bool: false
+    required_string: "qwert"
+    required_bytes: "asdf"
+  }
+)";
+
+const char kOptionalNestedFields[] = R"(
+  optional_int32: 123
+  optional_msg {
+    optional_double: 1.93177850152856e-314
+    optional_float: 4.7397519e-41
+    optional_int32: 40020
+    optional_int64: 10
+    optional_uint32: 40
+    optional_uint64: 159
+    optional_sint32: 44015
+    optional_sint64: 17493625000076
+    optional_fixed32: 193
+    optional_fixed64: 8542688694448488723
+    optional_sfixed32: 4926
+    optional_sfixed64: 60
+    optional_bool: true
+    optional_string: "QWERT"
+    optional_bytes: "ASDF"
+    optional_enum: ENUM_5
+  }
+)";
+
+const char kRepeatedNestedFields[] = R"(
+  optional_int32: 123
+  optional_msg {
+    repeated_double: 1.93177850152856e-314
+    repeated_double: 1.26685288449177e-313
+    repeated_float: 4.7397519e-41
+    repeated_float: 5.9808638e-39
+    repeated_int32: 40020
+    repeated_int32: 67
+    repeated_int64: 10
+    repeated_int64: 5285068
+    repeated_uint32: 40
+    repeated_uint32: 14486213
+    repeated_uint64: 159
+    repeated_uint64: 520229415
+    repeated_sint32: 44015
+    repeated_sint32: 56
+    repeated_sint64: 17493625000076
+    repeated_sint64: -6057486163525532641
+    repeated_fixed32: 193
+    repeated_fixed32: 8812173
+    repeated_fixed64: 8542688694448488723
+    repeated_fixed64: 273731277756
+    repeated_sfixed32: 4926
+    repeated_sfixed32: 43142
+    repeated_sfixed64: 60
+    repeated_sfixed64: 132
+    repeated_bool: false
+    repeated_bool: true
+    repeated_string: "QWERT"
+    repeated_string: "qwert"
+    repeated_bytes: "ASDF"
+    repeated_bytes: "asdf"
+    repeated_enum: ENUM_5
+    repeated_enum: ENUM_4
+  }
+)";
+
+class TestMutator : public Mutator {
+ public:
+  explicit TestMutator(bool keep_initialized) : Mutator(&random_), random_(17) {
+    keep_initialized_ = keep_initialized;
+  }
+
+  // Avoids dedup logic for some tests.
+  void NoDeDupCrossOver(const protobuf::Message& message1,
+                        protobuf::Message* message2) {
+    CrossOverImpl(message1, message2);
+  }
+
+ private:
+  RandomEngine random_;
+};
+
+class ReducedTestMutator : public TestMutator {
+ public:
+  ReducedTestMutator() : TestMutator(false) {
+    for (float i = 1000; i > 0.1; i /= 7) {
+      values_.push_back(i);
+      values_.push_back(-i);
+    }
+    values_.push_back(-1.0);
+    values_.push_back(0.0);
+    values_.push_back(1.0);
+  }
+
+ protected:
+  int32_t MutateInt32(int32_t value) override { return GetRandomValue(); }
+  int64_t MutateInt64(int64_t value) override { return GetRandomValue(); }
+  uint32_t MutateUInt32(uint32_t value) override {
+    return fabs(GetRandomValue());
+  }
+  uint64_t MutateUInt64(uint64_t value) override {
+    return fabs(GetRandomValue());
+  }
+  float MutateFloat(float value) override { return GetRandomValue(); }
+  double MutateDouble(double value) override { return GetRandomValue(); }
+  std::string MutateString(const std::string& value,
+                           size_t size_increase_hint) override {
+    return strings_[std::uniform_int_distribution<uint8_t>(
+        0, strings_.size() - 1)(*random())];
+  }
+
+ private:
+  float GetRandomValue() {
+    return values_[std::uniform_int_distribution<uint8_t>(
+        0, values_.size() - 1)(*random())];
+  }
+
+  std::vector<float> values_;
+  std::vector<std::string> strings_ = {
+      "", "\001", "\000", "a", "b", "ab",
+  };
+};
+
+std::vector<std::string> Split(const std::string& str) {
+  std::istringstream iss(str);
+  std::vector<std::string> result;
+  for (std::string line; std::getline(iss, line, '\n');) result.push_back(line);
+  return result;
+}
+
+using TestParams = std::tuple<const protobuf::Message*, const char*, size_t>;
+
+template <class T>
+std::vector<TestParams> GetFieldTestParams(
+    const std::vector<const char*>& tests) {
+  std::vector<TestParams> results;
+  for (auto t : tests) {
+    auto lines = Split(t);
+    for (size_t i = 0; i != lines.size(); ++i) {
+      if (lines[i].find(':') != std::string::npos)
+        results.push_back(std::make_tuple(&T::default_instance(), t, i));
+    }
+  }
+  return results;
+}
+
+template <class T>
+std::vector<TestParams> GetMessageTestParams(
+    const std::vector<const char*>& tests) {
+  std::vector<TestParams> results;
+  for (auto t : tests) {
+    auto lines = Split(t);
+    for (size_t i = 0; i != lines.size(); ++i) {
+      if (lines[i].find("{}") != std::string::npos)
+        results.push_back(std::make_tuple(&T::default_instance(), t, i));
+    }
+  }
+  return results;
+}
+
+bool Mutate(const protobuf::Message& from, const protobuf::Message& to) {
+  EXPECT_FALSE(MessageDifferencer::Equals(from, to));
+  ReducedTestMutator mutator;
+  std::unique_ptr<protobuf::Message> message(from.New());
+  for (int j = 0; j < 1000000; ++j) {
+    message->CopyFrom(from);
+    mutator.Mutate(message.get(), 1000);
+    if (MessageDifferencer::Equals(*message, to)) return true;
+  }
+
+  ADD_FAILURE() << "Failed to get from:\n"
+                << SaveMessageAsText(from) << "\nto:\n"
+                << SaveMessageAsText(to);
+  return false;
+}
+
+class MutatorTest : public TestWithParam<TestParams> {
+ protected:
+  void SetUp() override {
+    m1_.reset(std::get<0>(GetParam())->New());
+    m2_.reset(std::get<0>(GetParam())->New());
+    text_ = std::get<1>(GetParam());
+    line_ = std::get<2>(GetParam());
+  }
+
+  void LoadMessage(protobuf::Message* message) {
+    EXPECT_TRUE(ParseTextMessage(text_, message));
+  }
+
+  bool LoadWithoutLine(protobuf::Message* message) {
+    std::ostringstream oss;
+    auto lines = Split(text_);
+    for (size_t i = 0; i != lines.size(); ++i) {
+      if (i != line_) oss << lines[i] << '\n';
+    }
+    return ParseTextMessage(oss.str(), message);
+  }
+
+  bool LoadWithChangedLine(protobuf::Message* message, int value) {
+    auto lines = Split(text_);
+    std::ostringstream oss;
+    for (size_t i = 0; i != lines.size(); ++i) {
+      if (i != line_) {
+        oss << lines[i] << '\n';
+      } else {
+        std::string s = lines[i];
+        s.resize(s.find(':') + 2);
+
+        if (lines[i].back() == '\"') {
+          // strings
+          s += value ? "\"\\" + std::to_string(value) + "\"" : "\"\"";
+        } else if (lines[i].back() == 'e') {
+          // bools
+          s += value ? "true" : "false";
+        } else {
+          s += std::to_string(value);
+        }
+        oss << s << '\n';
+      }
+    }
+    return ParseTextMessage(oss.str(), message);
+  }
+
+  std::string text_;
+  size_t line_;
+  std::unique_ptr<protobuf::Message> m1_;
+  std::unique_ptr<protobuf::Message> m2_;
+};
+
+// These tests are irrelevant for Proto3 as it has no required fields and
+// insertion/deletion.
+
+class MutatorFieldInsDelTest : public MutatorTest {};
+INSTANTIATE_TEST_CASE_P(Proto2, MutatorFieldInsDelTest,
+                        ValuesIn(GetFieldTestParams<Msg>(
+                            {kRequiredFields, kOptionalFields, kRepeatedFields,
+                             kRequiredNestedFields, kOptionalNestedFields,
+                             kRepeatedNestedFields})));
+
+TEST_P(MutatorFieldInsDelTest, DeleteField) {
+  LoadMessage(m1_.get());
+  LoadWithoutLine(m2_.get());
+  EXPECT_TRUE(Mutate(*m1_, *m2_));
+}
+
+TEST_P(MutatorFieldInsDelTest, InsertField) {
+  LoadWithoutLine(m1_.get());
+  LoadWithChangedLine(m2_.get(), 0);
+  EXPECT_TRUE(Mutate(*m1_, *m2_));
+}
+
+class MutatorFieldTest : public MutatorTest {
+ public:
+  template <class Msg>
+  void TestCopyField();
+};
+INSTANTIATE_TEST_CASE_P(Proto2, MutatorFieldTest,
+                        ValuesIn(GetFieldTestParams<Msg>(
+                            {kRequiredFields, kOptionalFields, kRepeatedFields,
+                             kRequiredNestedFields, kOptionalNestedFields,
+                             kRepeatedNestedFields})));
+INSTANTIATE_TEST_CASE_P(Proto3, MutatorFieldTest,
+                        ValuesIn(GetFieldTestParams<Msg3>(
+                            {kOptionalFields, kRepeatedFields,
+                             kOptionalNestedFields, kRepeatedNestedFields})));
+
+TEST_P(MutatorFieldTest, Initialized) {
+  LoadWithoutLine(m1_.get());
+  TestMutator mutator(true);
+  mutator.Mutate(m1_.get(), 1000);
+  EXPECT_TRUE(m1_->IsInitialized());
+}
+
+TEST_P(MutatorFieldTest, ChangeField) {
+  LoadWithChangedLine(m1_.get(), 0);
+  LoadWithChangedLine(m2_.get(), 1);
+  EXPECT_TRUE(Mutate(*m1_, *m2_));
+  EXPECT_TRUE(Mutate(*m2_, *m1_));
+}
+
+template <class Msg>
+void MutatorFieldTest::TestCopyField() {
+  LoadWithChangedLine(m1_.get(), 7);
+  LoadWithChangedLine(m2_.get(), 0);
+
+  Msg from;
+  from.add_repeated_msg()->CopyFrom(*m1_);
+  from.add_repeated_msg()->CopyFrom(*m2_);
+
+  Msg to;
+  to.add_repeated_msg()->CopyFrom(*m1_);
+  to.add_repeated_msg()->CopyFrom(*m1_);
+  EXPECT_TRUE(Mutate(from, to));
+
+  to.Clear();
+  to.add_repeated_msg()->CopyFrom(*m2_);
+  to.add_repeated_msg()->CopyFrom(*m2_);
+  EXPECT_TRUE(Mutate(from, to));
+}
+
+TEST_P(MutatorFieldTest, CopyField) {
+  if (m1_->GetDescriptor() == Msg::descriptor())
+    TestCopyField<Msg>();
+  else
+    TestCopyField<Msg3>();
+}
+
+class MutatorSingleFieldTest : public MutatorTest {};
+INSTANTIATE_TEST_CASE_P(Proto2, MutatorSingleFieldTest,
+                        ValuesIn(GetFieldTestParams<Msg>({
+                            kRequiredFields, kOptionalFields,
+                            kRequiredNestedFields, kOptionalNestedFields,
+                        })));
+INSTANTIATE_TEST_CASE_P(Proto3, MutatorSingleFieldTest,
+                        ValuesIn(GetFieldTestParams<Msg3>({
+                            kOptionalFields, kOptionalNestedFields,
+                        })));
+
+TEST_P(MutatorSingleFieldTest, CrossOver) {
+  LoadWithoutLine(m1_.get());
+  LoadMessage(m2_.get());
+
+  EXPECT_FALSE(MessageDifferencer::Equals(*m1_, *m2_));
+  TestMutator mutator(false);
+
+  int match_m1_ = 0;
+  int match_m2_ = 0;
+  int iterations = 1000;
+  std::unique_ptr<protobuf::Message> message(m1_->New());
+  for (int j = 0; j < iterations; ++j) {
+    message->CopyFrom(*m1_);
+    mutator.NoDeDupCrossOver(*m2_, message.get());
+    if (MessageDifferencer::Equals(*message, *m2_)) ++match_m2_;
+    if (MessageDifferencer::Equals(*message, *m1_)) ++match_m1_;
+  }
+
+  EXPECT_LT(iterations * .4, match_m1_);
+  EXPECT_GE(iterations * .6, match_m1_);
+  EXPECT_LT(iterations * .4, match_m2_);
+  EXPECT_GE(iterations * .6, match_m2_);
+}
+
+template <typename T>
+class MutatorTypedTest : public ::testing::Test {
+ public:
+  using Message = T;
+};
+
+using MutatorTypedTestTypes = testing::Types<Msg, Msg3>;
+TYPED_TEST_CASE(MutatorTypedTest, MutatorTypedTestTypes);
+
+TYPED_TEST(MutatorTypedTest, CrossOverRepeated) {
+  typename TestFixture::Message m1;
+  m1.add_repeated_int32(1);
+  m1.add_repeated_int32(2);
+  m1.add_repeated_int32(3);
+
+  typename TestFixture::Message m2;
+  m2.add_repeated_int32(4);
+  m2.add_repeated_int32(5);
+  m2.add_repeated_int32(6);
+
+  int iterations = 10000;
+  std::set<std::set<int>> sets;
+  TestMutator mutator(false);
+  for (int j = 0; j < iterations; ++j) {
+    typename TestFixture::Message message;
+    message.CopyFrom(m1);
+    mutator.NoDeDupCrossOver(m2, &message);
+    sets.insert(
+        {message.repeated_int32().begin(), message.repeated_int32().end()});
+  }
+
+  EXPECT_EQ(1u << 6, sets.size());
+}
+
+TYPED_TEST(MutatorTypedTest, CrossOverRepeatedMessages) {
+  typename TestFixture::Message m1;
+  auto* rm1 = m1.add_repeated_msg();
+  rm1->add_repeated_int32(1);
+  rm1->add_repeated_int32(2);
+
+  typename TestFixture::Message m2;
+  auto* rm2 = m2.add_repeated_msg();
+  rm2->add_repeated_int32(3);
+  rm2->add_repeated_int32(4);
+  rm2->add_repeated_int32(5);
+  rm2->add_repeated_int32(6);
+
+  int iterations = 10000;
+  std::set<std::set<int>> sets;
+  TestMutator mutator(false);
+  for (int j = 0; j < iterations; ++j) {
+    typename TestFixture::Message message;
+    message.CopyFrom(m1);
+    mutator.NoDeDupCrossOver(m2, &message);
+    for (const auto& msg : message.repeated_msg())
+      sets.insert({msg.repeated_int32().begin(), msg.repeated_int32().end()});
+  }
+
+  EXPECT_EQ(1u << 6, sets.size());
+}
+
+TYPED_TEST(MutatorTypedTest, FailedMutations) {
+  TestMutator mutator(false);
+  size_t crossovers = 0;
+  for (int i = 0; i < 10000; ++i) {
+    typename TestFixture::Message messages[2];
+    typename TestFixture::Message tmp;
+    for (int j = 0; j < 20; ++j) {
+      for (auto& m : messages) {
+        tmp.CopyFrom(m);
+        mutator.Mutate(&m, 1000);
+        // Mutate must not produce the same result.
+        EXPECT_FALSE(MessageDifferencer::Equals(m, tmp));
+      }
+    }
+
+    tmp.CopyFrom(messages[1]);
+    mutator.CrossOver(messages[0], &tmp);
+    if (MessageDifferencer::Equals(tmp, messages[1]) ||
+        MessageDifferencer::Equals(tmp, messages[0]))
+      ++crossovers;
+  }
+
+  // CrossOver may fail but very rare.
+  EXPECT_LT(crossovers, 100u);
+}
+
+TYPED_TEST(MutatorTypedTest, Serialization) {
+  TestMutator mutator(false);
+  for (int i = 0; i < 10000; ++i) {
+    typename TestFixture::Message message;
+    for (int j = 0; j < 5; ++j) {
+      mutator.Mutate(&message, 1000);
+      typename TestFixture::Message parsed;
+
+      EXPECT_TRUE(ParseTextMessage(SaveMessageAsText(message), &parsed));
+      EXPECT_TRUE(MessageDifferencer::Equals(parsed, message));
+
+      EXPECT_TRUE(ParseBinaryMessage(SaveMessageAsBinary(message), &parsed));
+      EXPECT_TRUE(MessageDifferencer::Equals(parsed, message));
+    }
+  }
+}
+
+class MutatorMessagesTest : public MutatorTest {};
+INSTANTIATE_TEST_CASE_P(Proto2, MutatorMessagesTest,
+                        ValuesIn(GetMessageTestParams<Msg>({kMessages})));
+INSTANTIATE_TEST_CASE_P(
+    Proto3, MutatorMessagesTest,
+    ValuesIn(GetMessageTestParams<Msg3>({kMessagesProto3})));
+
+TEST_P(MutatorMessagesTest, DeletedMessage) {
+  LoadMessage(m1_.get());
+  LoadWithoutLine(m2_.get());
+  EXPECT_TRUE(Mutate(*m1_, *m2_));
+}
+
+TEST_P(MutatorMessagesTest, InsertMessage) {
+  LoadWithoutLine(m1_.get());
+  LoadMessage(m2_.get());
+  EXPECT_TRUE(Mutate(*m1_, *m2_));
+}
+
+// TODO(vitalybuka): Special tests for oneof.
+
+TEST(MutatorMessagesTest, UsageExample) {
+  SmallMessage message;
+  TestMutator mutator(false);
+
+  // Test that we can generate all variation of the message.
+  std::set<std::string> mutations;
+  for (int j = 0; j < 1000; ++j) {
+    mutator.Mutate(&message, 1000);
+    std::string str = SaveMessageAsText(message);
+    mutations.insert(str);
+  }
+
+  // 3 states for boolean and 5 for enum, including missing fields.
+  EXPECT_EQ(3u * 5u, mutations.size());
+}
+
+TEST(MutatorMessagesTest, EmptyMessage) {
+  EmptyMessage message;
+  TestMutator mutator(false);
+  for (int j = 0; j < 10000; ++j) mutator.Mutate(&message, 1000);
+}
+
+
+TEST(MutatorMessagesTest, Regressions) {
+  RegressionMessage message;
+  TestMutator mutator(false);
+  for (int j = 0; j < 10000; ++j) mutator.Mutate(&message, 1000);
+}
+
+}  // namespace protobuf_mutator
diff --git a/src/mutator_test_proto2.proto b/src/mutator_test_proto2.proto
new file mode 100644
index 0000000..8f4d078
--- /dev/null
+++ b/src/mutator_test_proto2.proto
@@ -0,0 +1,125 @@
+syntax = "proto2";
+package protobuf_mutator;
+
+message Msg {
+  enum Enum {
+    ENUM_0 = 0;
+    ENUM_1 = 1;
+    ENUM_2 = 2;
+    ENUM_3 = 3;
+    ENUM_4 = 4;
+    ENUM_5 = 5;
+    ENUM_6 = 6;
+    ENUM_7 = 7;
+    ENUM_8 = 8;
+    ENUM_9 = 9;
+  }
+
+  message SubMsg {
+    optional int64 optional_int64 = 1;
+  }
+
+  required double required_double = 1;
+  required float required_float = 2;
+  required int32 required_int32 = 3;
+  required int64 required_int64 = 4;
+  required uint32 required_uint32 = 5;
+  required uint64 required_uint64 = 6;
+  required sint32 required_sint32 = 7;
+  required sint64 required_sint64 = 8;
+  required fixed32 required_fixed32 = 9;
+  required fixed64 required_fixed64 = 10;
+  required sfixed32 required_sfixed32 = 11;
+  required sfixed64 required_sfixed64 = 12;
+  required bool required_bool = 13;
+  required string required_string = 14;
+  required bytes required_bytes = 15;
+  required Enum required_enum = 16;
+  required SubMsg required_msg = 17;
+
+  optional double optional_double = 18;
+  optional float optional_float = 19;
+  optional int32 optional_int32 = 20;
+  optional int64 optional_int64 = 21;
+  optional uint32 optional_uint32 = 22;
+  optional uint64 optional_uint64 = 23;
+  optional sint32 optional_sint32 = 24;
+  optional sint64 optional_sint64 = 25;
+  optional fixed32 optional_fixed32 = 26;
+  optional fixed64 optional_fixed64 = 27;
+  optional sfixed32 optional_sfixed32 = 28;
+  optional sfixed64 optional_sfixed64 = 29;
+  optional bool optional_bool = 30;
+  optional string optional_string = 31;
+  optional bytes optional_bytes = 32;
+  optional Enum optional_enum = 33;
+  optional Msg optional_msg = 34;
+
+  repeated double repeated_double = 35;
+  repeated float repeated_float = 36;
+  repeated int32 repeated_int32 = 37;
+  repeated int64 repeated_int64 = 38;
+  repeated uint32 repeated_uint32 = 39;
+  repeated uint64 repeated_uint64 = 40;
+  repeated sint32 repeated_sint32 = 41;
+  repeated sint64 repeated_sint64 = 42;
+  repeated fixed32 repeated_fixed32 = 43;
+  repeated fixed64 repeated_fixed64 = 44;
+  repeated sfixed32 repeated_sfixed32 = 45;
+  repeated sfixed64 repeated_sfixed64 = 46;
+  repeated bool repeated_bool = 47;
+  repeated string repeated_string = 48;
+  repeated bytes repeated_bytes = 49;
+  repeated Enum repeated_enum = 50;
+  repeated Msg repeated_msg = 51;
+
+  oneof OneOf {
+    double oneof_double = 52;
+    float oneof_float = 53;
+    int32 oneof_int32 = 54;
+    int64 oneof_int64 = 55;
+    uint32 oneof_uint32 = 56;
+    uint64 oneof_uint64 = 57;
+    sint32 oneof_sint32 = 58;
+    sint64 oneof_sint64 = 59;
+    fixed32 oneof_fixed32 = 60;
+    fixed64 oneof_fixed64 = 61;
+    sfixed32 oneof_sfixed32 = 62;
+    sfixed64 oneof_sfixed64 = 63;
+    bool oneof_bool = 64;
+    string oneof_string = 65;
+    bytes oneof_bytes = 66;
+    Enum oneof_enum = 67;
+    Msg oneof_msg = 68;
+  }
+
+  // TODO(vitalybuka): Tests maps.
+  // map<string, uint64> map = 69;
+  // map<int32, bytes> map2 = 71;
+
+  required group Group = 70 {
+    required bool required_bool = 1;
+    optional bool optional_bool = 2;
+    repeated bool repeated_bool = 3;
+  }
+}
+
+message SmallMessage {
+  enum Enum {
+    ENUM_0 = 0;
+    ENUM_1 = 1;
+    ENUM_2 = 2;
+    ENUM_3 = 3;
+  }
+
+  optional bool opt_bool = 1;
+  optional Enum opt_enum = 2;
+}
+
+message RegressionMessage {
+  enum SingleValueEnum { ENUM_0 = 0; }
+  optional SingleValueEnum enum = 2;
+}
+
+message EmptyMessage {
+}
diff --git a/src/mutator_test_proto3.proto b/src/mutator_test_proto3.proto
new file mode 100644
index 0000000..7c7162e
--- /dev/null
+++ b/src/mutator_test_proto3.proto
@@ -0,0 +1,73 @@
+syntax = "proto3";
+package protobuf_mutator;
+
+message Msg3 {
+  enum Enum {
+    ENUM_0 = 0;
+    ENUM_1 = 1;
+    ENUM_2 = 2;
+    ENUM_3 = 3;
+    ENUM_4 = 4;
+    ENUM_5 = 5;
+    ENUM_6 = 6;
+    ENUM_7 = 7;
+    ENUM_8 = 8;
+    ENUM_9 = 9;
+  }
+
+  double optional_double = 18;
+  float optional_float = 19;
+  int32 optional_int32 = 20;
+  int64 optional_int64 = 21;
+  uint32 optional_uint32 = 22;
+  uint64 optional_uint64 = 23;
+  sint32 optional_sint32 = 24;
+  sint64 optional_sint64 = 25;
+  fixed32 optional_fixed32 = 26;
+  fixed64 optional_fixed64 = 27;
+  sfixed32 optional_sfixed32 = 28;
+  sfixed64 optional_sfixed64 = 29;
+  bool optional_bool = 30;
+  string optional_string = 31;
+  bytes optional_bytes = 32;
+  Enum optional_enum = 33;
+  Msg3 optional_msg = 34;
+
+  repeated double repeated_double = 35;
+  repeated float repeated_float = 36;
+  repeated int32 repeated_int32 = 37;
+  repeated int64 repeated_int64 = 38;
+  repeated uint32 repeated_uint32 = 39;
+  repeated uint64 repeated_uint64 = 40;
+  repeated sint32 repeated_sint32 = 41;
+  repeated sint64 repeated_sint64 = 42;
+  repeated fixed32 repeated_fixed32 = 43;
+  repeated fixed64 repeated_fixed64 = 44;
+  repeated sfixed32 repeated_sfixed32 = 45;
+  repeated sfixed64 repeated_sfixed64 = 46;
+  repeated bool repeated_bool = 47;
+  repeated string repeated_string = 48;
+  repeated bytes repeated_bytes = 49;
+  repeated Enum repeated_enum = 50;
+  repeated Msg3 repeated_msg = 51;
+
+  oneof OneOf {
+    double oneof_double = 52;
+    float oneof_float = 53;
+    int32 oneof_int32 = 54;
+    int64 oneof_int64 = 55;
+    uint32 oneof_uint32 = 56;
+    uint64 oneof_uint64 = 57;
+    sint32 oneof_sint32 = 58;
+    sint64 oneof_sint64 = 59;
+    fixed32 oneof_fixed32 = 60;
+    fixed64 oneof_fixed64 = 61;
+    sfixed32 oneof_sfixed32 = 62;
+    sfixed64 oneof_sfixed64 = 63;
+    bool oneof_bool = 64;
+    string oneof_string = 65;
+    bytes oneof_bytes = 66;
+    Enum oneof_enum = 67;
+    Msg3 oneof_msg = 68;
+  }
+}
diff --git a/src/random.h b/src/random.h
new file mode 100644
index 0000000..d4463d3
--- /dev/null
+++ b/src/random.h
@@ -0,0 +1,26 @@
+// 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.
+
+#ifndef SRC_RANDOM_H_
+#define SRC_RANDOM_H_
+
+#include <random>
+
+namespace protobuf_mutator {
+
+using RandomEngine = std::mt19937;
+
+}  // namespace protobuf_mutator
+
+#endif  // SRC_RANDOM_H_
diff --git a/src/text_format.cc b/src/text_format.cc
new file mode 100644
index 0000000..9990d60
--- /dev/null
+++ b/src/text_format.cc
@@ -0,0 +1,54 @@
+// 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 "src/text_format.h"
+#include "port/protobuf.h"
+
+namespace protobuf_mutator {
+
+using protobuf::Message;
+using protobuf::TextFormat;
+
+bool ParseTextMessage(const uint8_t* data, size_t size, Message* output) {
+  return ParseTextMessage({data, data + size}, output);
+}
+
+bool ParseTextMessage(const std::string& data, protobuf::Message* output) {
+  output->Clear();
+  TextFormat::Parser parser;
+  parser.AllowPartialMessage(true);
+  if (!parser.ParseFromString(data, output)) {
+    output->Clear();
+    return false;
+  }
+  return true;
+}
+
+size_t SaveMessageAsText(const Message& message, uint8_t* data,
+                         size_t max_size) {
+  std::string result = SaveMessageAsText(message);
+  if (result.size() <= max_size) {
+    memcpy(data, result.data(), result.size());
+    return result.size();
+  }
+  return 0;
+}
+
+std::string SaveMessageAsText(const protobuf::Message& message) {
+  String tmp;
+  if (!protobuf::TextFormat::PrintToString(message, &tmp)) return {};
+  return tmp;
+}
+
+}  // namespace protobuf_mutator
diff --git a/src/text_format.h b/src/text_format.h
new file mode 100644
index 0000000..319e01d
--- /dev/null
+++ b/src/text_format.h
@@ -0,0 +1,34 @@
+// 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.
+
+#ifndef SRC_TEXT_FORMAT_H_
+#define SRC_TEXT_FORMAT_H_
+
+#include <string>
+
+#include "port/protobuf.h"
+
+namespace protobuf_mutator {
+
+// Text serialization of protos.
+bool ParseTextMessage(const uint8_t* data, size_t size,
+                      protobuf::Message* output);
+bool ParseTextMessage(const std::string& data, protobuf::Message* output);
+size_t SaveMessageAsText(const protobuf::Message& message, uint8_t* data,
+                         size_t max_size);
+std::string SaveMessageAsText(const protobuf::Message& message);
+
+}  // namespace protobuf_mutator
+
+#endif  // SRC_TEXT_FORMAT_H_
diff --git a/src/utf8_fix.cc b/src/utf8_fix.cc
new file mode 100644
index 0000000..50e6efd
--- /dev/null
+++ b/src/utf8_fix.cc
@@ -0,0 +1,90 @@
+// 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 "src/utf8_fix.h"
+
+#include <algorithm>
+#include <cassert>
+
+namespace protobuf_mutator {
+
+namespace {
+
+void StoreCode(char* e, char32_t code, uint8_t size, uint8_t prefix) {
+  while (--size) {
+    *(--e) = 0x80 | (code & 0x3F);
+    code >>= 6;
+  }
+  *(--e) = prefix | code;
+}
+
+char* FixCode(char* b, const char* e, RandomEngine* random) {
+  const char* start = b;
+  assert(b < e);
+
+  e = std::min<const char*>(e, b + 4);
+  char32_t c = *b++;
+  for (; b < e && (*b & 0xC0) == 0x80; ++b) {
+    c = (c << 6) + (*b & 0x3F);
+  }
+  uint8_t size = b - start;
+  switch (size) {
+    case 1:
+      c &= 0x7F;
+      StoreCode(b, c, size, 0);
+      break;
+    case 2:
+      c &= 0x7FF;
+      if (c < 0x80) {
+        c = std::uniform_int_distribution<char32_t>(0x80, 0x7FF)(*random);
+      }
+      StoreCode(b, c, size, 0xC0);
+      break;
+    case 3:
+      c &= 0xFFFF;
+
+      // [0xD800, 0xE000) are reserved for UTF-16 surrogate halves.
+      if (c < 0x800 || (c >= 0xD800 && c < 0xE000)) {
+        uint32_t halves = 0xE000 - 0xD800;
+        c = std::uniform_int_distribution<char32_t>(0x800,
+                                                    0xFFFF - halves)(*random);
+        if (c >= 0xD800) c += halves;
+      }
+      StoreCode(b, c, size, 0xE0);
+      break;
+    case 4:
+      c &= 0x1FFFFF;
+      if (c < 0x10000 || c > 0x10FFFF) {
+        c = std::uniform_int_distribution<char32_t>(0x10000, 0x10FFFF)(*random);
+      }
+      StoreCode(b, c, size, 0xF0);
+      break;
+    default:
+      assert(false && "Unexpected size of UTF-8 sequence");
+  }
+  return b;
+}
+
+}  // namespace
+
+void FixUtf8String(std::string* str, RandomEngine* random) {
+  if (str->empty()) return;
+  char* b = &(*str)[0];
+  const char* e = b + str->size();
+  while (b < e) {
+    b = FixCode(b, e, random);
+  }
+}
+
+}  // namespace protobuf_mutator
diff --git a/src/utf8_fix.h b/src/utf8_fix.h
new file mode 100644
index 0000000..6637e74
--- /dev/null
+++ b/src/utf8_fix.h
@@ -0,0 +1,28 @@
+// 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.
+
+#ifndef SRC_UTF8_FIX_H_
+#define SRC_UTF8_FIX_H_
+
+#include <string>
+
+#include "src/random.h"
+
+namespace protobuf_mutator {
+
+void FixUtf8String(std::string* str, RandomEngine* random);
+
+}  // namespace protobuf_mutator
+
+#endif  // SRC_UTF8_FIX_H_
diff --git a/src/utf8_fix_test.cc b/src/utf8_fix_test.cc
new file mode 100644
index 0000000..54f09cd
--- /dev/null
+++ b/src/utf8_fix_test.cc
@@ -0,0 +1,63 @@
+// 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 "src/utf8_fix.h"
+
+#include "port/gtest.h"
+#include "port/protobuf.h"
+
+namespace protobuf_mutator {
+
+protobuf::LogSilencer log_silincer;
+
+class FixUtf8StringTest : public ::testing::TestWithParam<int> {
+ public:
+  bool IsStructurallyValid(const std::string& s) {
+    using protobuf::internal::WireFormatLite;
+    return WireFormatLite::VerifyUtf8String(s.data(), s.length(),
+                                            WireFormatLite::PARSE, "");
+  }
+};
+
+TEST_F(FixUtf8StringTest, IsStructurallyValid) {
+  EXPECT_TRUE(IsStructurallyValid(""));
+  EXPECT_TRUE(IsStructurallyValid("abc"));
+  EXPECT_TRUE(IsStructurallyValid("\xC2\xA2"));
+  EXPECT_TRUE(IsStructurallyValid("\xE2\x82\xAC"));
+  EXPECT_TRUE(IsStructurallyValid("\xF0\x90\x8D\x88"));
+  EXPECT_FALSE(IsStructurallyValid("\xFF\xFF\xFF\xFF"));
+  EXPECT_FALSE(IsStructurallyValid("\xFF\x8F"));
+  EXPECT_FALSE(IsStructurallyValid("\x3F\xBF"));
+}
+
+INSTANTIATE_TEST_CASE_P(Size, FixUtf8StringTest, ::testing::Range(0, 10));
+
+TEST_P(FixUtf8StringTest, FixUtf8String) {
+  RandomEngine random(GetParam());
+  std::uniform_int_distribution<uint8_t> random8(0, 0xFF);
+
+  std::string str(random8(random), 0);
+  for (uint32_t run = 0; run < 10000; ++run) {
+    for (size_t i = 0; i < str.size(); ++i) str[i] = random8(random);
+    std::string fixed = str;
+    FixUtf8String(&fixed, &random);
+    if (IsStructurallyValid(str)) {
+      EXPECT_EQ(str, fixed);
+    } else {
+      EXPECT_TRUE(IsStructurallyValid(fixed));
+    }
+  }
+}
+
+}  // namespace protobuf_mutator
diff --git a/src/weighted_reservoir_sampler.h b/src/weighted_reservoir_sampler.h
new file mode 100644
index 0000000..d272bb5
--- /dev/null
+++ b/src/weighted_reservoir_sampler.h
@@ -0,0 +1,59 @@
+// Copyright 2016 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.
+
+#ifndef SRC_WEIGHTED_RESERVOIR_SAMPLER_H_
+#define SRC_WEIGHTED_RESERVOIR_SAMPLER_H_
+
+#include <cassert>
+#include <random>
+
+namespace protobuf_mutator {
+
+// Algorithm pick one item from the sequence of weighted items.
+// https://en.wikipedia.org/wiki/Reservoir_sampling#Algorithm_A-Chao
+//
+// Example:
+//   WeightedReservoirSampler<int> sampler;
+//   for(int i = 0; i < size; ++i)
+//     sampler.Pick(weight[i], i);
+//   return sampler.GetSelected();
+template <class T, class RandomEngine = std::default_random_engine>
+class WeightedReservoirSampler {
+ public:
+  explicit WeightedReservoirSampler(RandomEngine* random) : random_(random) {}
+
+  void Try(uint64_t weight, const T& item) {
+    if (Pick(weight)) selected_ = item;
+  }
+
+  const T& selected() const { return selected_; }
+
+  bool IsEmpty() const { return total_weight_ == 0; }
+
+ private:
+  bool Pick(uint64_t weight) {
+    if (weight == 0) return false;
+    total_weight_ += weight;
+    return weight == total_weight_ || std::uniform_int_distribution<uint64_t>(
+                                          1, total_weight_)(*random_) <= weight;
+  }
+
+  T selected_ = {};
+  uint64_t total_weight_ = 0;
+  RandomEngine* random_;
+};
+
+}  // namespace protobuf_mutator
+
+#endif  // SRC_WEIGHTED_RESERVOIR_SAMPLER_H_
diff --git a/src/weighted_reservoir_sampler_test.cc b/src/weighted_reservoir_sampler_test.cc
new file mode 100644
index 0000000..e524620
--- /dev/null
+++ b/src/weighted_reservoir_sampler_test.cc
@@ -0,0 +1,75 @@
+// Copyright 2016 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 "src/weighted_reservoir_sampler.h"
+
+#include <tuple>
+#include <vector>
+
+#include "port/gtest.h"
+
+using testing::TestWithParam;
+using testing::ValuesIn;
+using testing::Combine;
+using testing::Range;
+
+namespace protobuf_mutator {
+
+class WeightedReservoirSamplerTest
+    : public TestWithParam<std::tuple<int, std::vector<int>>> {};
+
+const int kRuns = 1000000;
+
+const std::vector<int> kTests[] = {
+    {1},
+    {1, 1, 1},
+    {1, 1, 0},
+    {1, 10, 100},
+    {100, 1, 10},
+    {1, 10000, 10000},
+    {1, 3, 7, 100, 105},
+    {93519, 52999, 354,   37837, 55285, 31787, 89096, 55695, 1587,
+     18233, 77557, 67632, 59348, 51250, 17417, 96856, 78568, 44296,
+     70170, 41328, 9206,  90187, 54086, 35602, 53167, 33791, 60118,
+     52962, 10327, 80513, 49526, 18326, 83662, 49644, 70903, 4910,
+     36309, 19196, 42982, 53316, 14773, 86607, 60835}};
+
+INSTANTIATE_TEST_CASE_P(AllTest, WeightedReservoirSamplerTest,
+                        Combine(Range(1, 10, 3), ValuesIn(kTests)));
+
+TEST_P(WeightedReservoirSamplerTest, Test) {
+  std::vector<int> weights = std::get<1>(GetParam());
+  std::vector<int> counts(weights.size(), 0);
+
+  using RandomEngine = std::mt19937;
+  RandomEngine rand(std::get<0>(GetParam()));
+  for (int i = 0; i < kRuns; ++i) {
+    WeightedReservoirSampler<int, RandomEngine> sampler(&rand);
+    for (size_t j = 0; j < weights.size(); ++j) sampler.Try(weights[j], j);
+    ++counts[sampler.selected()];
+  }
+
+  int sum = std::accumulate(weights.begin(), weights.end(), 0);
+  for (size_t j = 0; j < weights.size(); ++j) {
+    float expected = weights[j];
+    expected /= sum;
+
+    float actual = counts[j];
+    actual /= kRuns;
+
+    EXPECT_NEAR(expected, actual, 0.01);
+  }
+}
+
+}  // namespace protobuf_mutator