Upgrade libprotobuf-mutator to d761b622751ae8c226db3d8daaaf4c6aab5e5243
am: 788fa8d32f

Change-Id: I68baf1fb4cdda730437d0e2ede6e5134683ca741
diff --git a/.travis.yml b/.travis.yml
index 6b55737..731b74a 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -1,6 +1,6 @@
 os: linux
-dist: trusty
-sudo: false
+dist: xenial
+sudo: true
 
 language: cpp
 
@@ -14,22 +14,20 @@
       - ubuntu-toolchain-r-test
 
 env:
-  global: CLANG_VERSION=7 GCC_VERSION=7
+  global: GCC_VERSION=7
 
 matrix:
   include:
-    - env: BUILD_TYPE=Release CC_COMPILER=clang-${CLANG_VERSION} CXX_COMPILER=clang++-${CLANG_VERSION}
+    - env: BUILD_TYPE=Release CC_COMPILER=clang CXX_COMPILER=clang++
       addons: &clang
         apt:
           packages:
             - *common_packages
-            - clang-7
+            - clang
           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}
+    - env: BUILD_TYPE=Debug CC_COMPILER=clang CXX_COMPILER=clang++
       addons: *clang
 
     - env: BUILD_TYPE=Release CC_COMPILER=gcc-${GCC_VERSION} CXX_COMPILER=g++-${GCC_VERSION}
@@ -42,9 +40,12 @@
           sources:
             - *common_sources
 
+    - env: BUILD_TYPE=Debug CC_COMPILER=gcc-${GCC_VERSION} CXX_COMPILER=g++-${GCC_VERSION}
+      addons: *gcc
+
 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
+  - travis_retry wget --no-check-certificate --quiet -O - https://cmake.org/files/v3.12/cmake-3.12.3-Linux-x86_64.tar.gz | tar --strip-components=1 -xz
   - export PATH=${TRAVIS_BUILD_DIR}/deps/bin:${PATH}
   - cd -
 
@@ -52,9 +53,10 @@
   - 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
+  - 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} -DCMAKE_INSTALL_PREFIX=/usr
 
 script:
   - export ASAN_OPTIONS=detect_leaks=0
   - ninja
   - ninja check
+  - DESTDIR="/tmp/testing/" ninja install
diff --git a/CMakeLists.txt b/CMakeLists.txt
index c018d45..d9be154 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -18,9 +18,11 @@
 enable_language(C)
 enable_language(CXX)
 
+option(LIB_PROTO_MUTATOR_TESTING "Enable test building" ON)
 option(LIB_PROTO_MUTATOR_DOWNLOAD_PROTOBUF
        "Automatically download working protobuf" OFF)
 option(LIB_PROTO_MUTATOR_WITH_ASAN "Enable address sanitizer" OFF)
+option(PKG_CONFIG_PATH "Directory to install pkgconfig file" "share/pkgconfig")
 set(LIB_PROTO_MUTATOR_FUZZER_LIBRARIES "" CACHE STRING "Fuzzing engine libs")
 
 # External dependencies
@@ -44,6 +46,21 @@
 
 include_directories(${PROJECT_SOURCE_DIR})
 
+if (MSVC)
+  option(LIB_PROTO_MUTATOR_MSVC_STATIC_RUNTIME "Link static runtime libraries" ON)
+  if (LIB_PROTO_MUTATOR_DOWNLOAD_PROTOBUF OR LIB_PROTO_MUTATOR_MSVC_STATIC_RUNTIME)
+    # This is the default for protobuf with MSVC
+    # http://www.cmake.org/Wiki/CMake_FAQ#How_can_I_build_my_MSVC_application_with_a_static_runtime.3F
+    foreach(flag_var
+        CMAKE_CXX_FLAGS CMAKE_CXX_FLAGS_DEBUG CMAKE_CXX_FLAGS_RELEASE
+        CMAKE_CXX_FLAGS_MINSIZEREL CMAKE_CXX_FLAGS_RELWITHDEBINFO)
+      if(${flag_var} MATCHES "/MD")
+        string(REGEX REPLACE "/MD" "/MT" ${flag_var} "${${flag_var}}")
+      endif(${flag_var} MATCHES "/MD")
+    endforeach(flag_var)
+  endif (LIB_PROTO_MUTATOR_DOWNLOAD_PROTOBUF OR LIB_PROTO_MUTATOR_MSVC_STATIC_RUNTIME)
+endif (MSVC)
+
 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"
@@ -64,10 +81,12 @@
 
 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 (NOT MSVC)
+  set(EXTRA_FLAGS "-fno-exceptions -Werror -Wall")
+  if (LIB_PROTO_MUTATOR_HAS_WSTRING_CONVERSION)
+    set(EXTRA_FLAGS "${EXTRA_FLAGS} -Wstring-conversion")
+  endif()
+endif(NOT MSVC)
 
 if (LIB_PROTO_MUTATOR_WITH_ASAN)
   if (LIB_PROTO_MUTATOR_HAS_SANITIZE_ADDRESS)
@@ -110,15 +129,19 @@
   include_directories(${CMAKE_CURRENT_BINARY_DIR})
 endif()
 
-enable_testing()
+set(LIB_DIR "lib${LIB_SUFFIX}")
 
-include(googletest)
+if (LIB_PROTO_MUTATOR_TESTING)
+  enable_testing()
 
-if (NOT LIB_PROTO_MUTATOR_CTEST_JOBS)
-  ProcessorCount(LIB_PROTO_MUTATOR_CTEST_JOBS)
+  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)
 endif()
-add_custom_target(check
-                  COMMAND ${CMAKE_CTEST_COMMAND} -j${LIB_PROTO_MUTATOR_CTEST_JOBS} --output-on-failure)
 
 add_subdirectory(src)
 
@@ -127,3 +150,8 @@
   add_subdirectory(examples EXCLUDE_FROM_ALL)
 endif()
 
+configure_file("libprotobuf-mutator.pc.in" "libprotobuf-mutator.pc" @ONLY)
+install(FILES "${CMAKE_BINARY_DIR}/libprotobuf-mutator.pc"
+  DESTINATION ${PKG_CONFIG_PATH})
+install(DIRECTORY ./port ./src DESTINATION include/libprotobuf-mutator
+  FILES_MATCHING PATTERN "*.h")
diff --git a/METADATA b/METADATA
index a7e9de1..fb17616 100644
--- a/METADATA
+++ b/METADATA
@@ -1,14 +1,15 @@
 name: "libprotobuf-mutator"
-description:
-    "libprotobuf-mutator is a library to randomly mutate protobuffers. It could "
-    "be used together with guided fuzzing engines, such as libFuzzer."
-
+description: "libprotobuf-mutator is a library to randomly mutate protobuffers. It could be used together with guided fuzzing engines, such as libFuzzer."
 third_party {
   url {
     type: GIT
     value: "https://github.com/google/libprotobuf-mutator"
   }
-  version: "c9a1e56750a4eef6ffca95f41f79f06979056e01"
-  last_upgrade_date { year: 2018 month: 8 day: 6 }
+  version: "d761b622751ae8c226db3d8daaaf4c6aab5e5243"
   license_type: NOTICE
+  last_upgrade_date {
+    year: 2019
+    month: 7
+    day: 30
+  }
 }
diff --git a/README.md b/README.md
index 1470339..b86b676 100644
--- a/README.md
+++ b/README.md
@@ -12,7 +12,8 @@
 
 ```
 sudo apt-get update
-sudo apt-get install binutils cmake ninja-build liblzma-dev libz-dev pkg-config
+sudo apt-get install protobuf-compiler libprotobuf-dev binutils cmake \
+  ninja-build liblzma-dev libz-dev pkg-config
 ```
 
 Compile and test everything:
@@ -31,6 +32,16 @@
 `LIB_PROTO_MUTATOR_DOWNLOAD_PROTOBUF=ON` to cmake to automatically download and
 build a working version of protobuf.
 
+Installation:
+
+```
+ninja
+sudo ninja install
+```
+
+This installs the headers, pkg-config, and static library.
+By default the headers are put in `/usr/local/include/libprotobuf-mutator`.
+
 ## Usage
 
 To use libprotobuf-mutator simply include
@@ -80,3 +91,25 @@
 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.
+
+## Users of the library
+* [Chromium](https://cs.chromium.org/search/?q=DEFINE_.*._PROTO_FUZZER%5C\()
+* [Envoy](https://github.com/envoyproxy/envoy/search?q=DEFINE_TEXT_PROTO_FUZZER+OR+DEFINE_PROTO_FUZZER+OR+DEFINE_BINARY_PROTO_FUZZER&unscoped_q=DEFINE_TEXT_PROTO_FUZZER+OR+DEFINE_PROTO_FUZZER+OR+DEFINE_BINARY_PROTO_FUZZER&type=Code)
+* [LLVM](https://github.com/llvm-mirror/clang/search?q=DEFINE_TEXT_PROTO_FUZZER+OR+DEFINE_PROTO_FUZZER+OR+DEFINE_BINARY_PROTO_FUZZER&unscoped_q=DEFINE_TEXT_PROTO_FUZZER+OR+DEFINE_PROTO_FUZZER+OR+DEFINE_BINARY_PROTO_FUZZER&type=Code)
+
+## Bugs found with help of the library
+
+### Chromium
+* [AppCache exploit](http://www.powerofcommunity.net/poc2018/ned.pdf) ([Actual still restricted bug](https://bugs.chromium.org/p/chromium/issues/detail?id=888926))
+* [Stack Buffer Overflow in QuicClientPromisedInfo](https://bugs.chromium.org/p/chromium/issues/detail?id=777728)
+* [null dereference in sqlite3ExprCompare](https://bugs.chromium.org/p/chromium/issues/detail?id=911251)
+### Envoy
+* [strftime overflow](https://github.com/envoyproxy/envoy/pull/4321)
+* [Heap-use-after-free in Envoy::Upstream::SubsetLoadBalancer::updateFallbackSubset](https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=8028)
+* [Heap-use-after-free in Envoy::Secret::SecretManagerImpl](https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=11231)
+* [Heap-buffer-overflow in Envoy::Http::HeaderString](https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=10038)
+
+## Related materials
+* [Attacking Chrome IPC: Reliably finding bugs to escape the Chrome sandbox](https://media.ccc.de/v/35c3-9579-attacking_chrome_ipc)
+* [Structure-aware fuzzing for Clang and LLVM with libprotobuf-mutator](https://www.youtube.com/watch?v=U60hC16HEDY)
+* [Structure-Aware Fuzzing with libFuzzer](https://github.com/google/fuzzer-test-suite/blob/master/tutorial/structure-aware-fuzzing.md)
diff --git a/cmake/external/googletest.cmake b/cmake/external/googletest.cmake
index 1eec203..893275e 100644
--- a/cmake/external/googletest.cmake
+++ b/cmake/external/googletest.cmake
@@ -23,11 +23,20 @@
 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)
+  if (MSVC)
+    if (CMAKE_BUILD_TYPE MATCHES Debug)
+      set(LIB_PATH ${GTEST_INSTALL_DIR}/lib/${lib}d.lib)
+    else()
+      set(LIB_PATH ${GTEST_INSTALL_DIR}/lib/${lib}.lib)
+    endif()
+  else()
+    set(LIB_PATH ${GTEST_INSTALL_DIR}/lib/lib${lib}.a)
+  endif()
+  list(APPEND GTEST_BUILD_BYPRODUCTS ${LIB_PATH})
 
   add_library(${lib} STATIC IMPORTED)
   set_property(TARGET ${lib} PROPERTY IMPORTED_LOCATION
-               ${GTEST_INSTALL_DIR}/lib/lib${lib}.a)
+               ${LIB_PATH})
   add_dependencies(${lib} ${GTEST_TARGET})
 endforeach(lib)
 
@@ -35,7 +44,7 @@
 ExternalProject_Add(${GTEST_TARGET}
     PREFIX ${GTEST_TARGET}
     GIT_REPOSITORY https://github.com/google/googletest.git
-    GIT_TAG 1b07766
+    GIT_TAG bf07131
     UPDATE_COMMAND ""
     CMAKE_CACHE_ARGS -DCMAKE_C_COMPILER:FILEPATH=${CMAKE_C_COMPILER}
                      -DCMAKE_CXX_COMPILER:FILEPATH=${CMAKE_CXX_COMPILER}
diff --git a/cmake/external/libxml2.cmake b/cmake/external/libxml2.cmake
index f31ac0e..c00ace2 100644
--- a/cmake/external/libxml2.cmake
+++ b/cmake/external/libxml2.cmake
@@ -33,7 +33,7 @@
 include (ExternalProject)
 ExternalProject_Add(${LIBXML2_TARGET}
     PREFIX ${LIBXML2_TARGET}
-    GIT_REPOSITORY https://github.com/GNOME/libxml2.git
+    GIT_REPOSITORY GIT_REPOSITORY https://gitlab.gnome.org/GNOME/libxml2
     GIT_TAG master
     UPDATE_COMMAND ""
     CONFIGURE_COMMAND ${LIBXML2_SRC_DIR}/autogen.sh --without-python
diff --git a/cmake/external/protobuf.cmake b/cmake/external/protobuf.cmake
index df79110..80bc145 100644
--- a/cmake/external/protobuf.cmake
+++ b/cmake/external/protobuf.cmake
@@ -12,6 +12,8 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
+# We only need protobuf_generate_cpp from FindProtobuf, and we are going to
+# override the rest with ExternalProject version.
 include (FindProtobuf)
 
 set(PROTOBUF_TARGET external.protobuf)
@@ -28,26 +30,40 @@
 ENDIF()
 
 foreach(lib ${PROTOBUF_LIBRARIES})
-  list(APPEND PROTOBUF_BUILD_BYPRODUCTS ${PROTOBUF_INSTALL_DIR}/lib/lib${lib}.a)
+  if (MSVC)
+    set(LIB_PATH ${PROTOBUF_INSTALL_DIR}/lib/lib${lib}.lib)
+  else()
+    set(LIB_PATH ${PROTOBUF_INSTALL_DIR}/lib/lib${lib}.a)
+  endif()
+  list(APPEND PROTOBUF_BUILD_BYPRODUCTS ${LIB_PATH})
 
   add_library(${lib} STATIC IMPORTED)
   set_property(TARGET ${lib} PROPERTY IMPORTED_LOCATION
-               ${PROTOBUF_INSTALL_DIR}/lib/lib${lib}.a)
+               ${LIB_PATH})
   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
+
+if(${CMAKE_VERSION} VERSION_LESS "3.10.0")
+  set(PROTOBUF_PROTOC_TARGET protoc)
+else()
+  set(PROTOBUF_PROTOC_TARGET protobuf::protoc)
+endif()
+
+if(NOT TARGET ${PROTOBUF_PROTOC_TARGET})
+  add_executable(${PROTOBUF_PROTOC_TARGET} IMPORTED)
+endif()
+set_property(TARGET ${PROTOBUF_PROTOC_TARGET} PROPERTY IMPORTED_LOCATION
              ${PROTOBUF_PROTOC_EXECUTABLE})
-add_dependencies(protoc ${PROTOBUF_TARGET})
+add_dependencies(${PROTOBUF_PROTOC_TARGET} ${PROTOBUF_TARGET})
 
 include (ExternalProject)
 ExternalProject_Add(${PROTOBUF_TARGET}
     PREFIX ${PROTOBUF_TARGET}
     GIT_REPOSITORY https://github.com/google/protobuf.git
-    GIT_TAG 47b7d2c
+    GIT_TAG bf0c69e
     UPDATE_COMMAND ""
     CONFIGURE_COMMAND ${CMAKE_COMMAND} ${PROTOBUF_INSTALL_DIR}/src/${PROTOBUF_TARGET}/cmake
         -G${CMAKE_GENERATOR}
diff --git a/examples/expat/CMakeLists.txt b/examples/expat/CMakeLists.txt
index f2031f5..dac1b19 100644
--- a/examples/expat/CMakeLists.txt
+++ b/examples/expat/CMakeLists.txt
@@ -34,4 +34,6 @@
                       ${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)
+if(LIB_PROTO_MUTATOR_TESTING)
+  add_dependencies(check expat_example_test)
+endif()
diff --git a/examples/libfuzzer/CMakeLists.txt b/examples/libfuzzer/CMakeLists.txt
index dc39177..2bf5788 100644
--- a/examples/libfuzzer/CMakeLists.txt
+++ b/examples/libfuzzer/CMakeLists.txt
@@ -18,7 +18,9 @@
                       ${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)
+if(LIB_PROTO_MUTATOR_TESTING)
+  add_dependencies(check libfuzzer_example_test)
+endif()
 
 protobuf_generate_cpp(LIB_FUZZER_EXAMPLE_PROTO_SRCS
                       LIB_FUZZER_EXAMPLE_PROTO_HDRS
@@ -39,5 +41,7 @@
                PROPERTY COMPILE_FLAGS ${FUZZING_FLAGS})
   set_property(TARGET ${fuzzer}
                PROPERTY LINK_FLAGS ${FUZZING_FLAGS_BINARY})
-  add_dependencies(libfuzzer_example_test ${fuzzer})
+  if(LIB_PROTO_MUTATOR_TESTING)
+    add_dependencies(libfuzzer_example_test ${fuzzer})
+  endif()
 endforeach(fuzzer)
diff --git a/examples/libxml2/CMakeLists.txt b/examples/libxml2/CMakeLists.txt
index cf9f8a2..1debc7f 100644
--- a/examples/libxml2/CMakeLists.txt
+++ b/examples/libxml2/CMakeLists.txt
@@ -35,4 +35,6 @@
                       ${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)
+if (LIB_PROTO_MUTATOR_TESTING)
+  add_dependencies(check libxml2_example_test)
+endif()
diff --git a/libprotobuf-mutator.pc.in b/libprotobuf-mutator.pc.in
new file mode 100644
index 0000000..ac5224e
--- /dev/null
+++ b/libprotobuf-mutator.pc.in
@@ -0,0 +1,8 @@
+prefix=@CMAKE_INSTALL_PREFIX@
+includedir=${prefix}/include/libprotobuf-mutator
+
+Name: libprotobuf-mutator
+Description: randomly mutate protobuffers for fuzzing
+Version: 0
+Cflags: -I${includedir} -I${includedir}/src
+Libs: -lprotobuf-mutator-libfuzzer -lprotobuf-mutator
diff --git a/port/protobuf.h b/port/protobuf.h
index eefe415..e70d42d 100644
--- a/port/protobuf.h
+++ b/port/protobuf.h
@@ -17,6 +17,7 @@
 
 #include <string>
 
+#include "google/protobuf/descriptor.pb.h"
 #include "google/protobuf/message.h"
 #include "google/protobuf/text_format.h"
 #include "google/protobuf/util/message_differencer.h"
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index 5c13d2d..19f4406 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -21,34 +21,44 @@
             utf8_fix.cc)
 target_link_libraries(protobuf-mutator
                       ${PROTOBUF_LIBRARIES})
-set_property(TARGET protobuf-mutator
-             PROPERTY COMPILE_FLAGS "${NO_FUZZING_FLAGS}")
+set_target_properties(protobuf-mutator PROPERTIES
+                      COMPILE_FLAGS "${NO_FUZZING_FLAGS}"
+                      SOVERSION 0)
 
-protobuf_generate_cpp(PROTO_SRCS PROTO_HDRS
-                      mutator_test_proto2.proto
-                      mutator_test_proto3.proto)
+if (LIB_PROTO_MUTATOR_TESTING)
+  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})
+  add_library(mutator-test-proto
+              ${PROTO_SRCS})
 
-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_executable(mutator_test
+                 mutator_test.cc
+                 utf8_fix_test.cc
+                 weighted_reservoir_sampler_test.cc)
+  target_link_libraries(mutator_test
+                        protobuf-mutator
+                        mutator-test-proto
+                        ${ZLIB_LIBRARIES}
+                        ${GTEST_BOTH_LIBRARIES}
+                        ${CMAKE_THREAD_LIBS_INIT})
 
-add_dependencies(check mutator_test)
+  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)
+endif()
+
+install(TARGETS protobuf-mutator
+        ARCHIVE DESTINATION ${LIB_DIR}
+        LIBRARY DESTINATION ${LIB_DIR})
diff --git a/src/field_instance.h b/src/field_instance.h
index 8c1c31f..11ccd27 100644
--- a/src/field_instance.h
+++ b/src/field_instance.h
@@ -146,6 +146,7 @@
             : reflection().GetEnum(*message_, descriptor_);
     *value = {static_cast<size_t>(value_descriptor->index()),
               static_cast<size_t>(value_descriptor->type()->value_count())};
+    if (value->index >= value->count) GetDefault(value);
   }
 
   void Load(std::string* value) const {
@@ -163,6 +164,18 @@
     (*value)->CopyFrom(source);
   }
 
+  template <class T>
+  bool CanStore(const T& value) const {
+    return true;
+  }
+
+  bool CanStore(const std::string& value) const {
+    if (!EnforceUtf8()) return true;
+    using protobuf::internal::WireFormatLite;
+    return WireFormatLite::VerifyUtf8String(value.data(), value.length(),
+                                            WireFormatLite::PARSE, "");
+  }
+
   std::string name() const { return descriptor_->name(); }
 
   protobuf::FieldDescriptor::CppType cpp_type() const {
@@ -183,6 +196,14 @@
                protobuf::FileDescriptor::SYNTAX_PROTO3;
   }
 
+  const protobuf::FieldDescriptor* descriptor() const { return descriptor_; }
+
+  std::string DebugString() const {
+    std::string s = descriptor_->DebugString();
+    if (is_repeated()) s += "[" + std::to_string(index_) + "]";
+    return s + " of\n" + message_->DebugString();
+  }
+
  protected:
   bool is_repeated() const { return descriptor_->is_repeated(); }
 
@@ -190,8 +211,6 @@
     return *message_->GetReflection();
   }
 
-  const protobuf::FieldDescriptor* descriptor() const { return descriptor_; }
-
   size_t index() const { return index_; }
 
  private:
diff --git a/src/libfuzzer/CMakeLists.txt b/src/libfuzzer/CMakeLists.txt
index 6677f5e..8fc78e6 100644
--- a/src/libfuzzer/CMakeLists.txt
+++ b/src/libfuzzer/CMakeLists.txt
@@ -18,5 +18,23 @@
 target_link_libraries(protobuf-mutator-libfuzzer
                       protobuf-mutator
                       ${PROTOBUF_LIBRARIES})
-set_property(TARGET protobuf-mutator-libfuzzer
-             PROPERTY COMPILE_FLAGS "${NO_FUZZING_FLAGS}")
+set_target_properties(protobuf-mutator-libfuzzer PROPERTIES
+                      COMPILE_FLAGS "${NO_FUZZING_FLAGS}"
+                      SOVERSION 0)
+
+install(TARGETS protobuf-mutator-libfuzzer
+        ARCHIVE DESTINATION ${LIB_DIR}
+        LIBRARY DESTINATION ${LIB_DIR})
+
+if (LIB_PROTO_MUTATOR_TESTING)
+  add_executable(libfuzzer_test
+                 libfuzzer_test.cc)
+  target_link_libraries(libfuzzer_test
+                        protobuf-mutator
+                        protobuf-mutator-libfuzzer
+                        mutator-test-proto
+                        ${GTEST_BOTH_LIBRARIES}
+                        ${CMAKE_THREAD_LIBS_INIT})
+  add_test(test.protobuf_libfuzzer_test libfuzzer_test --gtest_color=yes AUTO)
+  add_dependencies(check libfuzzer_test)
+endif()
diff --git a/src/libfuzzer/libfuzzer_macro.cc b/src/libfuzzer/libfuzzer_macro.cc
index 162c2ce..3e46740 100644
--- a/src/libfuzzer/libfuzzer_macro.cc
+++ b/src/libfuzzer/libfuzzer_macro.cc
@@ -181,5 +181,11 @@
                 : ParseTextMessage(data, size, input);
 }
 
+void RegisterProtoFieldMutator(
+    const protobuf::FieldDescriptor* field,
+    std::function<void(protobuf::Message*)> callback) {
+  protobuf_mutator::Mutator::RegisterCustomMutation(field, callback);
+}
+
 }  // namespace libfuzzer
 }  // namespace protobuf_mutator
diff --git a/src/libfuzzer/libfuzzer_macro.h b/src/libfuzzer/libfuzzer_macro.h
index 59ae0ba..cc1003c 100644
--- a/src/libfuzzer/libfuzzer_macro.h
+++ b/src/libfuzzer/libfuzzer_macro.h
@@ -33,6 +33,26 @@
 // significantly slower than mutator, so fuzzing rate may stay unchanged.
 #define DEFINE_BINARY_PROTO_FUZZER(arg) DEFINE_PROTO_FUZZER_IMPL(true, arg)
 
+// Registers the callback as a potential mutation performed on the parent
+// message of a field. This must be called inside an initialization code block.
+// libFuzzer suggests putting one-time-initialization in a function used to
+// initialize a static variable inside the fuzzer target. For example:
+//
+// static bool Callback(protobuf::Message* message) { ... }
+//
+// static bool OneTimeInitialization() {
+//   REGISTER_PROTO_FIELD_MUTATOR(SomeMessage, "name_of_the_field", Callback);
+//   ...
+// }
+//
+// DEFINE_PROTO_FUZZER(const SomeMessage& msg) {
+//   static bool initialized = OneTimeInitialization();
+//   ...
+// }
+#define REGISTER_PROTO_FIELD_MUTATOR(message_class, field_name, callback) \
+  protobuf_mutator::libfuzzer::RegisterProtoFieldMutator( \
+    message_class::descriptor()->FindFieldByName(#field_name), callback)
+
 // Implementation of macros above.
 #define DEFINE_CUSTOM_PROTO_MUTATOR_IMPL(use_binary, Proto)                    \
   extern "C" size_t LLVMFuzzerCustomMutator(                                   \
@@ -84,6 +104,9 @@
                             protobuf::Message* input2);
 bool LoadProtoInput(bool binary, const uint8_t* data, size_t size,
                     protobuf::Message* input);
+void RegisterProtoFieldMutator(
+    const protobuf::FieldDescriptor* field,
+    std::function<void(protobuf::Message*)> callback);
 
 }  // namespace libfuzzer
 }  // namespace protobuf_mutator
diff --git a/src/libfuzzer/libfuzzer_mutator.cc b/src/libfuzzer/libfuzzer_mutator.cc
index 0da9552..12bf16e 100644
--- a/src/libfuzzer/libfuzzer_mutator.cc
+++ b/src/libfuzzer/libfuzzer_mutator.cc
@@ -22,8 +22,36 @@
 #include "port/protobuf.h"
 #include "src/mutator.h"
 
-extern "C" size_t LLVMFuzzerMutate(uint8_t*, size_t, size_t)
-    __attribute__((weak));
+// see compiler-rt/lib/sanitizer-common/sanitizer_internal_defs.h; usage same as
+// SANITIZER_INTERFACE_WEAK_DEF with some functionality removed
+#ifdef _MSC_VER
+#if defined(_M_IX86) || defined(__i386__)
+#define WIN_SYM_PREFIX "_"
+#else
+#define WIN_SYM_PREFIX
+#endif
+
+#define STRINGIFY_(A) #A
+#define STRINGIFY(A) STRINGIFY_(A)
+
+#define WEAK_DEFAULT_NAME(Name) Name##__def
+
+// clang-format off
+#define LIB_PROTO_MUTATOR_WEAK_DEF(ReturnType, Name, ...)     \
+  __pragma(comment(linker, "/alternatename:"                  \
+           WIN_SYM_PREFIX STRINGIFY(Name) "="                 \
+           WIN_SYM_PREFIX STRINGIFY(WEAK_DEFAULT_NAME(Name))))\
+  extern "C" ReturnType Name(__VA_ARGS__);                    \
+  extern "C" ReturnType WEAK_DEFAULT_NAME(Name)(__VA_ARGS__)
+// clang-format on
+#else
+#define LIB_PROTO_MUTATOR_WEAK_DEF(ReturnType, Name, ...) \
+  extern "C" __attribute__((weak)) ReturnType Name(__VA_ARGS__)
+#endif
+
+LIB_PROTO_MUTATOR_WEAK_DEF(size_t, LLVMFuzzerMutate, uint8_t*, size_t, size_t) {
+  return 0;
+}
 
 namespace protobuf_mutator {
 namespace libfuzzer {
@@ -55,7 +83,9 @@
 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 {};
+  // Use uint16_t because on Windows, uniform_int_distribution does not support
+  // any 8 bit types.
+  if (!std::uniform_int_distribution<uint16_t>(0, 20)(*random())) return {};
   std::string result = value;
   result.resize(value.size() + size_increase_hint);
   if (result.empty()) result.push_back(0);
diff --git a/src/libfuzzer/libfuzzer_test.cc b/src/libfuzzer/libfuzzer_test.cc
new file mode 100644
index 0000000..180a02c
--- /dev/null
+++ b/src/libfuzzer/libfuzzer_test.cc
@@ -0,0 +1,28 @@
+// Copyright 2019 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 "src/libfuzzer/libfuzzer_macro.h"
+#include "src/mutator_test_proto2.pb.h"
+
+static bool reached = false;
+
+DEFINE_PROTO_FUZZER(const protobuf_mutator::Msg::EmptyMessage& message) {
+  reached = true;
+}
+
+TEST(LibFuzzerTest, Basic) {
+  LLVMFuzzerTestOneInput((const uint8_t*)"", 0);
+  EXPECT_TRUE(reached);
+}
diff --git a/src/mutator.cc b/src/mutator.cc
index 2aa9693..43b4750 100644
--- a/src/mutator.cc
+++ b/src/mutator.cc
@@ -15,10 +15,10 @@
 #include "src/mutator.h"
 
 #include <algorithm>
-#include <functional>
 #include <map>
 #include <random>
 #include <string>
+#include <vector>
 
 #include "src/field_instance.h"
 #include "src/utf8_fix.h"
@@ -120,15 +120,18 @@
   }
 };
 
-class IsEqualValueField : public FieldFunction<IsEqualValueField, bool> {
+class CanCopyAndDifferentField
+    : public FieldFunction<CanCopyAndDifferentField, 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);
+  bool ForType(const ConstFieldInstance& src,
+               const ConstFieldInstance& dst) const {
+    T s;
+    src.Load(&s);
+    if (!dst.CanStore(s)) return false;
+    T d;
+    dst.Load(&d);
+    return !IsEqual(s, d);
   }
 
  private:
@@ -312,15 +315,14 @@
         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))
+          if (CanCopyAndDifferentField()(source, match_))
             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);
+          if (CanCopyAndDifferentField()(source, match_))
+            sampler_.Try(1, source);
         }
       }
     }
@@ -368,13 +370,12 @@
   }
 
   void Mutate(bool* value) const {
-    RepeatMutate(value, std::bind(&Mutator::MutateBool, mutator_, _1), 2);
+    RepeatMutate(value, std::bind(&Mutator::MutateBool, mutator_, _1));
   }
 
   void Mutate(FieldInstance::Enum* value) const {
     RepeatMutate(&value->index,
-                 std::bind(&Mutator::MutateEnum, mutator_, _1, value->count),
-                 std::max<size_t>(value->count, 1));
+                 std::bind(&Mutator::MutateEnum, mutator_, _1, value->count));
     assert(value->index < value->count);
   }
 
@@ -391,16 +392,16 @@
   void Mutate(std::unique_ptr<Message>* message) const {
     assert(!enforce_changes_);
     assert(*message);
-    if (GetRandomBool(mutator_->random(), 100)) return;
+    if (GetRandomBool(mutator_->random(), mutator_->random_to_default_ratio_))
+      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 {
+  void RepeatMutate(T* value, F mutate) const {
     if (!enforce_changes_ &&
-        GetRandomBool(mutator_->random(), unchanged_one_out_of)) {
+        GetRandomBool(mutator_->random(), mutator_->random_to_default_ratio_)) {
       return;
     }
     T tmp = *value;
@@ -461,7 +462,9 @@
         CreateField()(mutation.field(), size_increase_hint / 2, this);
         break;
       case Mutation::Mutate:
-        MutateField()(mutation.field(), size_increase_hint / 2, this);
+        if (!ApplyCustomMutations(message, mutation.field().descriptor())) {
+          MutateField()(mutation.field(), size_increase_hint / 2, this);
+        }
         break;
       case Mutation::Delete:
         DeleteField()(mutation.field());
@@ -577,14 +580,22 @@
   }
 }
 
+void Mutator::RegisterCustomMutation(
+    const protobuf::FieldDescriptor* field,
+    std::function<void(protobuf::Message* message)> mutation) {
+  custom_mutations_[field].push_back(mutation);
+}
+
 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))
+    if (keep_initialized_ &&
+        (field->is_required() || descriptor->options().map_entry()) &&
+        !reflection->HasField(*message, field)) {
       CreateDefaultField()(FieldInstance(message, field));
+    }
 
     if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) {
       if (max_depth <= 0 && !field->is_required()) {
@@ -667,4 +678,26 @@
   return str;
 }
 
+bool Mutator::ApplyCustomMutations(protobuf::Message* message,
+                                   const protobuf::FieldDescriptor* field) {
+  auto itr = custom_mutations_.find(field);
+  if (itr == custom_mutations_.end())
+    return false;
+
+  // Randomly select one of the registered mutators. The default behavior is
+  // performed for index 0.
+  size_t field_index = GetRandomIndex(random_, itr->second.size() + 1);
+  if (field_index == itr->second.size())
+    return false;
+
+  if (GetRandomBool(random_, 100))
+    itr->second[field_index](message);
+  return true;
+}
+
+std::unordered_map<
+    const protobuf::FieldDescriptor*,
+    std::vector<std::function<void(protobuf::Message* message)>>>
+    Mutator::custom_mutations_;
+
 }  // namespace protobuf_mutator
diff --git a/src/mutator.h b/src/mutator.h
index 47139bd..61a8a3b 100644
--- a/src/mutator.h
+++ b/src/mutator.h
@@ -18,9 +18,12 @@
 #include <stddef.h>
 #include <stdint.h>
 
+#include <functional>
 #include <memory>
 #include <random>
 #include <string>
+#include <unordered_map>
+#include <vector>
 
 #include "port/protobuf.h"
 #include "src/random.h"
@@ -56,6 +59,12 @@
   void CrossOver(const protobuf::Message& message1,
                  protobuf::Message* message2);
 
+  // field: Descriptor of the field to apply the mutation to.
+  // mutation: callback function that applies the mutation.
+  static void RegisterCustomMutation(
+      const protobuf::FieldDescriptor* field,
+      std::function<void(protobuf::Message* message)> mutation);
+
  protected:
   // TODO(vitalybuka): Consider to replace with single mutate (uint8_t*, size).
   virtual int32_t MutateInt32(int32_t value);
@@ -75,6 +84,11 @@
 
   RandomEngine* random() { return random_; }
 
+  static std::unordered_map<
+      const protobuf::FieldDescriptor*,
+      std::vector<std::function<void(protobuf::Message* message)>>>
+      custom_mutations_;
+
  private:
   friend class FieldMutator;
   friend class TestMutator;
@@ -83,8 +97,10 @@
                      protobuf::Message* message2);
   std::string MutateUtf8String(const std::string& value,
                                size_t size_increase_hint);
-
+  bool ApplyCustomMutations(protobuf::Message* message,
+                            const protobuf::FieldDescriptor* field);
   bool keep_initialized_ = true;
+  size_t random_to_default_ratio_ = 100;
   RandomEngine* random_;
 };
 
diff --git a/src/mutator_test.cc b/src/mutator_test.cc
index 34766c6..060cde3 100644
--- a/src/mutator_test.cc
+++ b/src/mutator_test.cc
@@ -216,8 +216,13 @@
 
 class TestMutator : public Mutator {
  public:
-  explicit TestMutator(bool keep_initialized) : Mutator(&random_), random_(17) {
+  explicit TestMutator(bool keep_initialized,
+                       size_t random_to_default_ratio = 0)
+      : Mutator(&random_), random_(17) {
+    if (random_to_default_ratio)
+      random_to_default_ratio_ = random_to_default_ratio;
     keep_initialized_ = keep_initialized;
+    custom_mutations_.clear();
   }
 
   // Avoids dedup logic for some tests.
@@ -232,7 +237,7 @@
 
 class ReducedTestMutator : public TestMutator {
  public:
-  ReducedTestMutator() : TestMutator(false) {
+  ReducedTestMutator() : TestMutator(false, 4) {
     for (float i = 1000; i > 0.1; i /= 7) {
       values_.push_back(i);
       values_.push_back(-i);
@@ -255,13 +260,13 @@
   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>(
+    return strings_[std::uniform_int_distribution<>(
         0, strings_.size() - 1)(*random())];
   }
 
  private:
   float GetRandomValue() {
-    return values_[std::uniform_int_distribution<uint8_t>(
+    return values_[std::uniform_int_distribution<>(
         0, values_.size() - 1)(*random())];
   }
 
@@ -312,6 +317,7 @@
   EXPECT_FALSE(MessageDifferencer::Equals(from, to));
   ReducedTestMutator mutator;
   std::unique_ptr<protobuf::Message> message(from.New());
+  EXPECT_FALSE(MessageDifferencer::Equals(from, to));
   for (int j = 0; j < 1000000; ++j) {
     message->CopyFrom(from);
     mutator.Mutate(message.get(), 1000);
@@ -337,16 +343,16 @@
     EXPECT_TRUE(ParseTextMessage(text_, message));
   }
 
-  bool LoadWithoutLine(protobuf::Message* message) {
+  void 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);
+    EXPECT_TRUE(ParseTextMessage(oss.str(), message));
   }
 
-  bool LoadWithChangedLine(protobuf::Message* message, int value) {
+  void LoadWithChangedLine(protobuf::Message* message, int value) {
     auto lines = Split(text_);
     std::ostringstream oss;
     for (size_t i = 0; i != lines.size(); ++i) {
@@ -368,7 +374,7 @@
         oss << s << '\n';
       }
     }
-    return ParseTextMessage(oss.str(), message);
+    EXPECT_TRUE(ParseTextMessage(oss.str(), message));
   }
 
   std::string text_;
@@ -381,11 +387,11 @@
 // insertion/deletion.
 
 class MutatorFieldInsDelTest : public MutatorTest {};
-INSTANTIATE_TEST_CASE_P(Proto2, MutatorFieldInsDelTest,
-                        ValuesIn(GetFieldTestParams<Msg>(
-                            {kRequiredFields, kOptionalFields, kRepeatedFields,
-                             kRequiredNestedFields, kOptionalNestedFields,
-                             kRepeatedNestedFields})));
+INSTANTIATE_TEST_SUITE_P(Proto2, MutatorFieldInsDelTest,
+                         ValuesIn(GetFieldTestParams<Msg>(
+                             {kRequiredFields, kOptionalFields, kRepeatedFields,
+                              kRequiredNestedFields, kOptionalNestedFields,
+                              kRepeatedNestedFields})));
 
 TEST_P(MutatorFieldInsDelTest, DeleteField) {
   LoadMessage(m1_.get());
@@ -404,15 +410,15 @@
   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})));
+INSTANTIATE_TEST_SUITE_P(Proto2, MutatorFieldTest,
+                         ValuesIn(GetFieldTestParams<Msg>(
+                             {kRequiredFields, kOptionalFields, kRepeatedFields,
+                              kRequiredNestedFields, kOptionalNestedFields,
+                              kRepeatedNestedFields})));
+INSTANTIATE_TEST_SUITE_P(Proto3, MutatorFieldTest,
+                         ValuesIn(GetFieldTestParams<Msg3>(
+                             {kOptionalFields, kRepeatedFields,
+                              kOptionalNestedFields, kRepeatedNestedFields})));
 
 TEST_P(MutatorFieldTest, Initialized) {
   LoadWithoutLine(m1_.get());
@@ -456,15 +462,18 @@
 }
 
 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,
-                        })));
+INSTANTIATE_TEST_SUITE_P(Proto2, MutatorSingleFieldTest,
+                         ValuesIn(GetFieldTestParams<Msg>({
+                             kRequiredFields,
+                             kOptionalFields,
+                             kRequiredNestedFields,
+                             kOptionalNestedFields,
+                         })));
+INSTANTIATE_TEST_SUITE_P(Proto3, MutatorSingleFieldTest,
+                         ValuesIn(GetFieldTestParams<Msg3>({
+                             kOptionalFields,
+                             kOptionalNestedFields,
+                         })));
 
 TEST_P(MutatorSingleFieldTest, CrossOver) {
   LoadWithoutLine(m1_.get());
@@ -554,7 +563,7 @@
 TYPED_TEST(MutatorTypedTest, FailedMutations) {
   TestMutator mutator(false);
   size_t crossovers = 0;
-  for (int i = 0; i < 10000; ++i) {
+  for (int i = 0; i < 1000; ++i) {
     typename TestFixture::Message messages[2];
     typename TestFixture::Message tmp;
     for (int j = 0; j < 20; ++j) {
@@ -574,7 +583,44 @@
   }
 
   // CrossOver may fail but very rare.
-  EXPECT_LT(crossovers, 100u);
+  EXPECT_LT(crossovers, 10u);
+}
+
+TYPED_TEST(MutatorTypedTest, FieldMutator) {
+  constexpr char kInitialString[] = " ";
+  constexpr char kIndicatorString[] = "0123456789abcdef";
+  bool custom_mutation = false;
+  bool regular_mutation = false;
+
+  const protobuf::Descriptor* descriptor =
+    (typename TestFixture::Message()).GetDescriptor();
+  TestMutator mutator(false);
+  TestMutator::RegisterCustomMutation(
+      descriptor->FindFieldByName("optional_string"),
+      [kIndicatorString](protobuf::Message* message){
+        typename TestFixture::Message* test_message =
+            dynamic_cast<typename TestFixture::Message*>(message);
+        test_message->set_optional_string(kIndicatorString);
+      });
+
+  for (int j = 0; j < 100000; ++j) {
+    // Include this field to increase the probability of mutation.
+    typename TestFixture::Message message;
+    message.set_optional_string(kInitialString);
+    mutator.Mutate(&message, 1000);
+
+    if (message.optional_string() == kIndicatorString) {
+      custom_mutation = true;
+    } else if (message.optional_string() != kInitialString) {
+      regular_mutation = true;
+    }
+
+    if (custom_mutation && regular_mutation)
+      break;
+  }
+
+  EXPECT_TRUE(custom_mutation);
+  EXPECT_TRUE(regular_mutation);
 }
 
 TYPED_TEST(MutatorTypedTest, Serialization) {
@@ -594,10 +640,64 @@
   }
 }
 
+TYPED_TEST(MutatorTypedTest, DeepRecursion) {
+  typename TestFixture::Message message;
+  typename TestFixture::Message* last = &message;
+  for (int i = 0; i < 150; ++i) {
+    last = last->mutable_optional_msg();
+    std::string text = SaveMessageAsText(message);
+    std::string binary = SaveMessageAsBinary(message);
+    typename TestFixture::Message parsed;
+    EXPECT_EQ(i < 100, ParseTextMessage(SaveMessageAsText(message), &parsed));
+    EXPECT_EQ(i < 100,
+              ParseBinaryMessage(SaveMessageAsBinary(message), &parsed));
+  }
+}
+
+TYPED_TEST(MutatorTypedTest, EmptyMessage) {
+  typename TestFixture::Message::EmptyMessage message;
+  TestMutator mutator(false);
+  for (int j = 0; j < 10000; ++j) mutator.Mutate(&message, 1000);
+}
+
+TYPED_TEST(MutatorTypedTest, Regressions) {
+  typename TestFixture::Message::RegressionMessage message;
+  TestMutator mutator(false);
+  for (int j = 0; j < 10000; ++j) mutator.Mutate(&message, 1000);
+}
+
+TYPED_TEST(MutatorTypedTest, UsageExample) {
+  typename TestFixture::Message::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);
+  }
+
+  if (std::is_same<typename TestFixture::Message, Msg>::value) {
+    // 3 states for boolean and 5 for enum, including missing fields.
+    EXPECT_EQ(3u * 5u, mutations.size());
+  } else {
+    // 2 states for boolean and 4 for enum.
+    EXPECT_EQ(2u * 4u, mutations.size());
+  }
+}
+
+TYPED_TEST(MutatorTypedTest, Maps) {
+  TestMutator mutator(true);
+
+  typename TestFixture::Message::MapMessage message;
+  for (int j = 0; j < 10000; ++j) mutator.Mutate(&message, 1000);
+}
+
 class MutatorMessagesTest : public MutatorTest {};
-INSTANTIATE_TEST_CASE_P(Proto2, MutatorMessagesTest,
-                        ValuesIn(GetMessageTestParams<Msg>({kMessages})));
-INSTANTIATE_TEST_CASE_P(
+INSTANTIATE_TEST_SUITE_P(Proto2, MutatorMessagesTest,
+                         ValuesIn(GetMessageTestParams<Msg>({kMessages})));
+INSTANTIATE_TEST_SUITE_P(
     Proto3, MutatorMessagesTest,
     ValuesIn(GetMessageTestParams<Msg3>({kMessagesProto3})));
 
@@ -615,33 +715,15 @@
 
 // TODO(vitalybuka): Special tests for oneof.
 
-TEST(MutatorMessagesTest, UsageExample) {
-  SmallMessage message;
+TEST(MutatorMessagesTest, NeverCopyUnknownEnum) {
   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);
+  for (int j = 0; j < 10000; ++j) {
+    Msg3 message;
+    message.set_optional_enum(Msg3::ENUM_5);
+    message.add_repeated_enum(static_cast<Msg3::Enum>(100));
+    mutator.Mutate(&message, 100);
+    EXPECT_NE(message.optional_enum(), 100);
   }
-
-  // 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
index 8f4d078..0927775 100644
--- a/src/mutator_test_proto2.proto
+++ b/src/mutator_test_proto2.proto
@@ -93,33 +93,35 @@
     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;
+  message EmptyMessage {}
+
+  message RegressionMessage {
+    enum SingleValueEnum { ENUM_0 = 0; }
+    optional SingleValueEnum enum = 2;
   }
 
-  optional bool opt_bool = 1;
-  optional Enum opt_enum = 2;
+  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 MapMessage {
+    map<string, int32> map1 = 1;
+    map<int32, Msg> map2 = 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
index 7c7162e..5fd7507 100644
--- a/src/mutator_test_proto3.proto
+++ b/src/mutator_test_proto3.proto
@@ -70,4 +70,28 @@
     Enum oneof_enum = 67;
     Msg3 oneof_msg = 68;
   }
+
+  message EmptyMessage {}
+
+  message RegressionMessage {
+    enum SingleValueEnum { ENUM_0 = 0; }
+    SingleValueEnum enum = 2;
+  }
+
+  message SmallMessage {
+    enum Enum {
+      ENUM_0 = 0;
+      ENUM_1 = 1;
+      ENUM_2 = 2;
+      ENUM_3 = 3;
+    }
+
+    bool opt_bool = 1;
+    Enum opt_enum = 2;
+  }
+
+  message MapMessage {
+    map<string, int32> map1 = 1;
+    map<int32, Msg3> map2 = 2;
+  }
 }
diff --git a/src/random.h b/src/random.h
index d4463d3..927997b 100644
--- a/src/random.h
+++ b/src/random.h
@@ -19,7 +19,7 @@
 
 namespace protobuf_mutator {
 
-using RandomEngine = std::mt19937;
+using RandomEngine = std::minstd_rand;
 
 }  // namespace protobuf_mutator
 
diff --git a/src/text_format.cc b/src/text_format.cc
index 9990d60..d695b67 100644
--- a/src/text_format.cc
+++ b/src/text_format.cc
@@ -27,6 +27,7 @@
 bool ParseTextMessage(const std::string& data, protobuf::Message* output) {
   output->Clear();
   TextFormat::Parser parser;
+  parser.SetRecursionLimit(100);
   parser.AllowPartialMessage(true);
   if (!parser.ParseFromString(data, output)) {
     output->Clear();
diff --git a/src/utf8_fix.cc b/src/utf8_fix.cc
index 50e6efd..c451adb 100644
--- a/src/utf8_fix.cc
+++ b/src/utf8_fix.cc
@@ -47,7 +47,9 @@
     case 2:
       c &= 0x7FF;
       if (c < 0x80) {
-        c = std::uniform_int_distribution<char32_t>(0x80, 0x7FF)(*random);
+        // Use uint32_t because uniform_int_distribution does not support
+        // char32_t on Windows.
+        c = std::uniform_int_distribution<uint32_t>(0x80, 0x7FF)(*random);
       }
       StoreCode(b, c, size, 0xC0);
       break;
@@ -57,7 +59,7 @@
       // [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,
+        c = std::uniform_int_distribution<uint32_t>(0x800,
                                                     0xFFFF - halves)(*random);
         if (c >= 0xD800) c += halves;
       }
@@ -66,7 +68,7 @@
     case 4:
       c &= 0x1FFFFF;
       if (c < 0x10000 || c > 0x10FFFF) {
-        c = std::uniform_int_distribution<char32_t>(0x10000, 0x10FFFF)(*random);
+        c = std::uniform_int_distribution<uint32_t>(0x10000, 0x10FFFF)(*random);
       }
       StoreCode(b, c, size, 0xF0);
       break;
diff --git a/src/utf8_fix_test.cc b/src/utf8_fix_test.cc
index 54f09cd..474eb8c 100644
--- a/src/utf8_fix_test.cc
+++ b/src/utf8_fix_test.cc
@@ -41,11 +41,11 @@
   EXPECT_FALSE(IsStructurallyValid("\x3F\xBF"));
 }
 
-INSTANTIATE_TEST_CASE_P(Size, FixUtf8StringTest, ::testing::Range(0, 10));
+INSTANTIATE_TEST_SUITE_P(Size, FixUtf8StringTest, ::testing::Range(0, 10));
 
 TEST_P(FixUtf8StringTest, FixUtf8String) {
   RandomEngine random(GetParam());
-  std::uniform_int_distribution<uint8_t> random8(0, 0xFF);
+  std::uniform_int_distribution<> random8(0, 0xFF);
 
   std::string str(random8(random), 0);
   for (uint32_t run = 0; run < 10000; ++run) {
diff --git a/src/weighted_reservoir_sampler_test.cc b/src/weighted_reservoir_sampler_test.cc
index e524620..277087b 100644
--- a/src/weighted_reservoir_sampler_test.cc
+++ b/src/weighted_reservoir_sampler_test.cc
@@ -14,6 +14,7 @@
 
 #include "src/weighted_reservoir_sampler.h"
 
+#include <numeric>
 #include <tuple>
 #include <vector>
 
@@ -45,14 +46,14 @@
      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)));
+INSTANTIATE_TEST_SUITE_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;
+  using RandomEngine = std::minstd_rand;
   RandomEngine rand(std::get<0>(GetParam()));
   for (int i = 0; i < kRuns; ++i) {
     WeightedReservoirSampler<int, RandomEngine> sampler(&rand);