aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorandroid-build-team Robot <android-build-team-robot@google.com>2020-04-28 20:23:28 +0000
committerandroid-build-team Robot <android-build-team-robot@google.com>2020-04-28 20:23:28 +0000
commit3b68eeaa4f42a22239bc885017b73733ef626c2d (patch)
tree5f093ed4cbdec8bd1d307db508a2033713682cfe
parentdc2abb582a983e628877765255ad77e82d52825f (diff)
parent19b7bf3edcedaea88dff58cc0d0bd595846a9db5 (diff)
downloadlibprotobuf-mutator-android12-mainline-tzdata-release.tar.gz
Change-Id: I49c52a900789a92bf85cfa0568f087a199317389
-rw-r--r--.travis.yml22
-rw-r--r--Android.bp43
-rw-r--r--CMakeLists.txt48
-rw-r--r--METADATA13
-rw-r--r--OWNERS7
-rw-r--r--README.md41
-rw-r--r--cmake/external/googletest.cmake15
-rw-r--r--cmake/external/libxml2.cmake2
-rw-r--r--cmake/external/protobuf.cmake28
-rw-r--r--examples/expat/CMakeLists.txt4
-rw-r--r--examples/libfuzzer/CMakeLists.txt8
-rw-r--r--examples/libfuzzer/libfuzzer_bin_example.cc13
-rw-r--r--examples/libfuzzer/libfuzzer_example.cc13
-rw-r--r--examples/libxml2/CMakeLists.txt4
-rw-r--r--libprotobuf-mutator.pc.in8
-rw-r--r--port/protobuf.h1
-rw-r--r--src/CMakeLists.txt72
-rw-r--r--src/field_instance.h23
-rw-r--r--src/libfuzzer/CMakeLists.txt22
-rw-r--r--src/libfuzzer/libfuzzer_macro.cc25
-rw-r--r--src/libfuzzer/libfuzzer_macro.h37
-rw-r--r--src/libfuzzer/libfuzzer_mutator.cc37
-rw-r--r--src/libfuzzer/libfuzzer_test.cc28
-rw-r--r--src/mutator.cc144
-rw-r--r--src/mutator.h32
-rw-r--r--src/mutator_test.cc197
-rw-r--r--src/mutator_test_proto2.proto40
-rw-r--r--src/mutator_test_proto3.proto24
-rw-r--r--src/random.h2
-rw-r--r--src/text_format.cc2
-rw-r--r--src/utf8_fix.cc8
-rw-r--r--src/utf8_fix_test.cc4
-rw-r--r--src/weighted_reservoir_sampler_test.cc11
33 files changed, 259 insertions, 719 deletions
diff --git a/.travis.yml b/.travis.yml
index 731b74a..6b55737 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -1,6 +1,6 @@
os: linux
-dist: xenial
-sudo: true
+dist: trusty
+sudo: false
language: cpp
@@ -14,20 +14,22 @@ addons:
- ubuntu-toolchain-r-test
env:
- global: GCC_VERSION=7
+ global: CLANG_VERSION=7 GCC_VERSION=7
matrix:
include:
- - env: BUILD_TYPE=Release CC_COMPILER=clang CXX_COMPILER=clang++
+ - env: BUILD_TYPE=Release CC_COMPILER=clang-${CLANG_VERSION} CXX_COMPILER=clang++-${CLANG_VERSION}
addons: &clang
apt:
packages:
- *common_packages
- - clang
+ - 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 CXX_COMPILER=clang++
+ - 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}
@@ -40,12 +42,9 @@ matrix:
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.12/cmake-3.12.3-Linux-x86_64.tar.gz | tar --strip-components=1 -xz
+ - 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 -
@@ -53,10 +52,9 @@ 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} -DCMAKE_INSTALL_PREFIX=/usr
+ - 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
- - DESTDIR="/tmp/testing/" ninja install
diff --git a/Android.bp b/Android.bp
deleted file mode 100644
index 57d499a..0000000
--- a/Android.bp
+++ /dev/null
@@ -1,43 +0,0 @@
-/*
- * Copyright 2019 The Android Open Source Project
- *
- * 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.
- */
-
-cc_library {
- name: "libprotobuf-mutator",
- host_supported: true,
- vendor_available: true,
- srcs: [
- "src/binary_format.cc",
- "src/libfuzzer/libfuzzer_macro.cc",
- "src/libfuzzer/libfuzzer_mutator.cc",
- "src/mutator.cc",
- "src/text_format.cc",
- "src/utf8_fix.cc",
- ],
- shared_libs: ["libprotobuf-cpp-full"],
- export_include_dirs: ["."],
- cflags: [
- "-Wno-unused-parameter",
- ],
-
- // We explicitly disable sanitization on LPM for performance reasons. We
- // aren't interested in the coverage feedback in LPM itself, only the
- // libraries that are being exercised. Disabling all sanitizers also
- // increases performance, as we aren't looking for bugs in the mutator
- // (which is particularly hot code in LPM binaries).
- sanitize: {
- never: true,
- },
-}
diff --git a/CMakeLists.txt b/CMakeLists.txt
index d9be154..c018d45 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -18,11 +18,9 @@ project(LibProtobufMutator CXX)
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
@@ -46,21 +44,6 @@ set(CMAKE_CXX_STANDARD 11)
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"
@@ -81,12 +64,10 @@ unset(CMAKE_REQUIRED_FLAGS)
check_cxx_compiler_flag(-Wstring-conversion LIB_PROTO_MUTATOR_HAS_WSTRING_CONVERSION)
-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)
+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)
@@ -129,19 +110,15 @@ else()
include_directories(${CMAKE_CURRENT_BINARY_DIR})
endif()
-set(LIB_DIR "lib${LIB_SUFFIX}")
+enable_testing()
-if (LIB_PROTO_MUTATOR_TESTING)
- enable_testing()
+include(googletest)
- 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)
+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)
@@ -150,8 +127,3 @@ if (NOT "${LIB_PROTO_MUTATOR_FUZZER_LIBRARIES}" STREQUAL "" OR
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 975ee06..a7e9de1 100644
--- a/METADATA
+++ b/METADATA
@@ -1,15 +1,14 @@
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: "62c5c91a2bfd675fa99cf61f6747fd227da8983a"
+ version: "c9a1e56750a4eef6ffca95f41f79f06979056e01"
+ last_upgrade_date { year: 2018 month: 8 day: 6 }
license_type: NOTICE
- last_upgrade_date {
- year: 2019
- month: 9
- day: 28
- }
}
diff --git a/OWNERS b/OWNERS
index 0d64ac4..3b2cf73 100644
--- a/OWNERS
+++ b/OWNERS
@@ -1,5 +1,2 @@
-include platform/system/core:/janitors/OWNERS
-
-# Owners from upstream & dynamic-tools@
-vitalybuka@google.com
-mitchp@google.com
+yim@google.com
+jiwonshin@google.com
diff --git a/README.md b/README.md
index 02683cd..1470339 100644
--- a/README.md
+++ b/README.md
@@ -1,12 +1,10 @@
# libprotobuf-mutator
-[![TravisCI Build Status](https://travis-ci.org/google/libprotobuf-mutator.svg?branch=master)](https://travis-ci.org/google/libprotobuf-mutator)
-[![Fuzzing Status](https://oss-fuzz-build-logs.storage.googleapis.com/badges/libprotobuf-mutator.svg)](https://oss-fuzz-build-logs.storage.googleapis.com/index.html#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).
+It could be used together with guided
+fuzzing engines, such as [libFuzzer](http://libfuzzer.info).
## Quick start on Debian/Ubuntu
@@ -14,8 +12,7 @@ Install prerequisites:
```
sudo apt-get update
-sudo apt-get install protobuf-compiler libprotobuf-dev binutils cmake \
- ninja-build liblzma-dev libz-dev pkg-config autoconf libtool
+sudo apt-get install binutils cmake ninja-build liblzma-dev libz-dev pkg-config
```
Compile and test everything:
@@ -34,16 +31,6 @@ systems, the system version is too old. You can pass
`LIB_PROTO_MUTATOR_DOWNLOAD_PROTOBUF=ON` to cmake to automatically download and
build a working version of protobuf.
-Installation:
-
-```
-ninja
-sudo ninja install
-```
-
-This installs the headers, pkg-config, and static library.
-By default the headers are put in `/usr/local/include/libprotobuf-mutator`.
-
## Usage
To use libprotobuf-mutator simply include
@@ -93,25 +80,3 @@ Please see [libfuzzer_example.cc](/examples/libfuzzer/libfuzzer_example.cc) as a
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 fe71115..1eec203 100644
--- a/cmake/external/googletest.cmake
+++ b/cmake/external/googletest.cmake
@@ -23,20 +23,11 @@ set(GTEST_MAIN_LIBRARIES gtest_main)
set(GTEST_BOTH_LIBRARIES ${GTEST_LIBRARIES} ${GTEST_MAIN_LIBRARIES})
foreach(lib IN LISTS GTEST_BOTH_LIBRARIES)
- 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})
+ list(APPEND GTEST_BUILD_BYPRODUCTS ${GTEST_INSTALL_DIR}/lib/lib${lib}.a)
add_library(${lib} STATIC IMPORTED)
set_property(TARGET ${lib} PROPERTY IMPORTED_LOCATION
- ${LIB_PATH})
+ ${GTEST_INSTALL_DIR}/lib/lib${lib}.a)
add_dependencies(${lib} ${GTEST_TARGET})
endforeach(lib)
@@ -44,7 +35,7 @@ include (ExternalProject)
ExternalProject_Add(${GTEST_TARGET}
PREFIX ${GTEST_TARGET}
GIT_REPOSITORY https://github.com/google/googletest.git
- GIT_TAG 3f05f651ae3621db58468153e32016bc1397800b
+ GIT_TAG 1b07766
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 c00ace2..f31ac0e 100644
--- a/cmake/external/libxml2.cmake
+++ b/cmake/external/libxml2.cmake
@@ -33,7 +33,7 @@ endforeach(lib)
include (ExternalProject)
ExternalProject_Add(${LIBXML2_TARGET}
PREFIX ${LIBXML2_TARGET}
- GIT_REPOSITORY GIT_REPOSITORY https://gitlab.gnome.org/GNOME/libxml2
+ GIT_REPOSITORY https://github.com/GNOME/libxml2.git
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 50277b6..df79110 100644
--- a/cmake/external/protobuf.cmake
+++ b/cmake/external/protobuf.cmake
@@ -12,8 +12,6 @@
# 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)
@@ -30,40 +28,26 @@ ELSE()
ENDIF()
foreach(lib ${PROTOBUF_LIBRARIES})
- 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})
+ list(APPEND PROTOBUF_BUILD_BYPRODUCTS ${PROTOBUF_INSTALL_DIR}/lib/lib${lib}.a)
add_library(${lib} STATIC IMPORTED)
set_property(TARGET ${lib} PROPERTY IMPORTED_LOCATION
- ${LIB_PATH})
+ ${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})
-
-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
+add_executable(protoc IMPORTED)
+set_property(TARGET protoc PROPERTY IMPORTED_LOCATION
${PROTOBUF_PROTOC_EXECUTABLE})
-add_dependencies(${PROTOBUF_PROTOC_TARGET} ${PROTOBUF_TARGET})
+add_dependencies(protoc ${PROTOBUF_TARGET})
include (ExternalProject)
ExternalProject_Add(${PROTOBUF_TARGET}
PREFIX ${PROTOBUF_TARGET}
GIT_REPOSITORY https://github.com/google/protobuf.git
- GIT_TAG 1363bf9c051af36c555c23d734a204246c215697
+ GIT_TAG 47b7d2c
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 dac1b19..f2031f5 100644
--- a/examples/expat/CMakeLists.txt
+++ b/examples/expat/CMakeLists.txt
@@ -34,6 +34,4 @@ 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)
-if(LIB_PROTO_MUTATOR_TESTING)
- add_dependencies(check expat_example_test)
-endif()
+add_dependencies(check expat_example_test)
diff --git a/examples/libfuzzer/CMakeLists.txt b/examples/libfuzzer/CMakeLists.txt
index 2bf5788..dc39177 100644
--- a/examples/libfuzzer/CMakeLists.txt
+++ b/examples/libfuzzer/CMakeLists.txt
@@ -18,9 +18,7 @@ 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)
-if(LIB_PROTO_MUTATOR_TESTING)
- add_dependencies(check libfuzzer_example_test)
-endif()
+add_dependencies(check libfuzzer_example_test)
protobuf_generate_cpp(LIB_FUZZER_EXAMPLE_PROTO_SRCS
LIB_FUZZER_EXAMPLE_PROTO_HDRS
@@ -41,7 +39,5 @@ foreach(fuzzer libfuzzer_example libfuzzer_bin_example)
PROPERTY COMPILE_FLAGS ${FUZZING_FLAGS})
set_property(TARGET ${fuzzer}
PROPERTY LINK_FLAGS ${FUZZING_FLAGS_BINARY})
- if(LIB_PROTO_MUTATOR_TESTING)
- add_dependencies(libfuzzer_example_test ${fuzzer})
- endif()
+ add_dependencies(libfuzzer_example_test ${fuzzer})
endforeach(fuzzer)
diff --git a/examples/libfuzzer/libfuzzer_bin_example.cc b/examples/libfuzzer/libfuzzer_bin_example.cc
index dae46da..80c5cef 100644
--- a/examples/libfuzzer/libfuzzer_bin_example.cc
+++ b/examples/libfuzzer/libfuzzer_bin_example.cc
@@ -20,18 +20,9 @@
protobuf_mutator::protobuf::LogSilencer log_silincer;
DEFINE_BINARY_PROTO_FUZZER(const libfuzzer_example::Msg& message) {
- static PostProcessorRegistration reg = {
- [](libfuzzer_example::Msg* message, unsigned int seed) {
- if (seed % 2) {
- message->set_optional_uint64(
- std::hash<std::string>{}(message->optional_string()));
- }
- }};
-
// Emulate a bug.
- if (message.optional_uint64() ==
- std::hash<std::string>{}(message.optional_string()) &&
- message.optional_string() == "abcdefghijklmnopqrstuvwxyz" &&
+ 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) {
diff --git a/examples/libfuzzer/libfuzzer_example.cc b/examples/libfuzzer/libfuzzer_example.cc
index 1520840..68bd718 100644
--- a/examples/libfuzzer/libfuzzer_example.cc
+++ b/examples/libfuzzer/libfuzzer_example.cc
@@ -20,18 +20,9 @@
protobuf_mutator::protobuf::LogSilencer log_silincer;
DEFINE_PROTO_FUZZER(const libfuzzer_example::Msg& message) {
- static PostProcessorRegistration reg = {
- [](libfuzzer_example::Msg* message, unsigned int seed) {
- if (seed % 2) {
- message->set_optional_uint64(
- std::hash<std::string>{}(message->optional_string()));
- }
- }};
-
// Emulate a bug.
- if (message.optional_uint64() ==
- std::hash<std::string>{}(message.optional_string()) &&
- message.optional_string() == "abcdefghijklmnopqrstuvwxyz" &&
+ 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) {
diff --git a/examples/libxml2/CMakeLists.txt b/examples/libxml2/CMakeLists.txt
index 1debc7f..cf9f8a2 100644
--- a/examples/libxml2/CMakeLists.txt
+++ b/examples/libxml2/CMakeLists.txt
@@ -35,6 +35,4 @@ 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)
-if (LIB_PROTO_MUTATOR_TESTING)
- add_dependencies(check libxml2_example_test)
-endif()
+add_dependencies(check libxml2_example_test)
diff --git a/libprotobuf-mutator.pc.in b/libprotobuf-mutator.pc.in
deleted file mode 100644
index ac5224e..0000000
--- a/libprotobuf-mutator.pc.in
+++ /dev/null
@@ -1,8 +0,0 @@
-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 e70d42d..eefe415 100644
--- a/port/protobuf.h
+++ b/port/protobuf.h
@@ -17,7 +17,6 @@
#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 19f4406..5c13d2d 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -21,44 +21,34 @@ add_library(protobuf-mutator
utf8_fix.cc)
target_link_libraries(protobuf-mutator
${PROTOBUF_LIBRARIES})
-set_target_properties(protobuf-mutator PROPERTIES
- COMPILE_FLAGS "${NO_FUZZING_FLAGS}"
- SOVERSION 0)
-
-if (LIB_PROTO_MUTATOR_TESTING)
- protobuf_generate_cpp(PROTO_SRCS PROTO_HDRS
- mutator_test_proto2.proto
- mutator_test_proto3.proto)
-
- add_library(mutator-test-proto
- ${PROTO_SRCS})
-
- 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})
-
- 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})
+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/field_instance.h b/src/field_instance.h
index 11ccd27..8c1c31f 100644
--- a/src/field_instance.h
+++ b/src/field_instance.h
@@ -146,7 +146,6 @@ class ConstFieldInstance {
: 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 {
@@ -164,18 +163,6 @@ class ConstFieldInstance {
(*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 {
@@ -196,14 +183,6 @@ class ConstFieldInstance {
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(); }
@@ -211,6 +190,8 @@ class ConstFieldInstance {
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 8fc78e6..6677f5e 100644
--- a/src/libfuzzer/CMakeLists.txt
+++ b/src/libfuzzer/CMakeLists.txt
@@ -18,23 +18,5 @@ add_library(protobuf-mutator-libfuzzer
target_link_libraries(protobuf-mutator-libfuzzer
protobuf-mutator
${PROTOBUF_LIBRARIES})
-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()
+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
index 5f9023f..162c2ce 100644
--- a/src/libfuzzer/libfuzzer_macro.cc
+++ b/src/libfuzzer/libfuzzer_macro.cc
@@ -89,18 +89,14 @@ class BinaryOutputWriter : public OutputWriter {
}
};
-Mutator* GetMutator() {
- static Mutator mutator;
- return &mutator;
-}
-
size_t MutateMessage(unsigned int seed, const InputReader& input,
OutputWriter* output, protobuf::Message* message) {
- GetMutator()->Seed(seed);
+ RandomEngine random(seed);
+ Mutator mutator(&random);
input.Read(message);
- GetMutator()->Mutate(message, output->size() > input.size()
- ? (output->size() - input.size())
- : 0);
+ 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;
@@ -112,10 +108,11 @@ size_t CrossOverMessages(unsigned int seed, const InputReader& input1,
const InputReader& input2, OutputWriter* output,
protobuf::Message* message1,
protobuf::Message* message2) {
- GetMutator()->Seed(seed);
+ RandomEngine random(seed);
+ Mutator mutator(&random);
input1.Read(message1);
input2.Read(message2);
- GetMutator()->CrossOver(*message2, message1);
+ mutator.CrossOver(*message2, message1);
if (size_t new_size = output->Write(*message1)) {
assert(new_size <= output->size());
return new_size;
@@ -184,11 +181,5 @@ bool LoadProtoInput(bool binary, const uint8_t* data, size_t size,
: ParseTextMessage(data, size, input);
}
-void RegisterPostProcessorImpl(
- std::function<void(protobuf::Message* message, unsigned int seed)>
- callback) {
- GetMutator()->RegisterPostProcessor(callback);
-}
-
} // namespace libfuzzer
} // namespace protobuf_mutator
diff --git a/src/libfuzzer/libfuzzer_macro.h b/src/libfuzzer/libfuzzer_macro.h
index a7d26ab..59ae0ba 100644
--- a/src/libfuzzer/libfuzzer_macro.h
+++ b/src/libfuzzer/libfuzzer_macro.h
@@ -16,7 +16,6 @@
#define SRC_LIBFUZZER_LIBFUZZER_MACRO_H_
#include <stddef.h>
-
#include <cstdint>
#include <functional>
#include <type_traits>
@@ -34,21 +33,6 @@
// 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 Modify(
-// SomeMessage* message /* Fix or additionally modify the message */,
-// unsigned int seed /* If random generator is needed use this seed */) {
-// ...
-// }
-//
-// DEFINE_PROTO_FUZZER(const SomeMessage& msg) {
-// static PostProcessorRegistration reg(&Modify);
-// }
-
// Implementation of macros above.
#define DEFINE_CUSTOM_PROTO_MUTATOR_IMPL(use_binary, Proto) \
extern "C" size_t LLVMFuzzerCustomMutator( \
@@ -78,10 +62,6 @@
return 0; \
}
-#define DEFINE_POST_PROCESS_PROTO_MUTATION_IMPL(Proto) \
- using PostProcessorRegistration = \
- protobuf_mutator::libfuzzer::PostProcessorRegistration<Proto>;
-
#define DEFINE_PROTO_FUZZER_IMPL(use_binary, arg) \
static void TestOneProtoInput(arg); \
using FuzzerProtoType = std::remove_const<std::remove_reference< \
@@ -89,7 +69,6 @@
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) \
- DEFINE_POST_PROCESS_PROTO_MUTATION_IMPL(FuzzerProtoType) \
static void TestOneProtoInput(arg)
namespace protobuf_mutator {
@@ -106,22 +85,6 @@ size_t CustomProtoCrossOver(bool binary, const uint8_t* data1, size_t size1,
bool LoadProtoInput(bool binary, const uint8_t* data, size_t size,
protobuf::Message* input);
-void RegisterPostProcessorImpl(
- std::function<void(protobuf::Message* message, unsigned int seed)>
- callback);
-
-template <class Proto>
-struct PostProcessorRegistration {
- PostProcessorRegistration(
- const std::function<void(Proto* message, unsigned int seed)>& callback) {
- protobuf_mutator::libfuzzer::RegisterPostProcessorImpl(
- [callback](protobuf_mutator::protobuf::Message* message,
- unsigned int seed) {
- callback(static_cast<Proto*>(message), seed);
- });
- }
-};
-
} // namespace libfuzzer
} // namespace protobuf_mutator
diff --git a/src/libfuzzer/libfuzzer_mutator.cc b/src/libfuzzer/libfuzzer_mutator.cc
index 979cebf..0da9552 100644
--- a/src/libfuzzer/libfuzzer_mutator.cc
+++ b/src/libfuzzer/libfuzzer_mutator.cc
@@ -15,7 +15,6 @@
#include "src/libfuzzer/libfuzzer_mutator.h"
#include <string.h>
-
#include <cassert>
#include <memory>
#include <string>
@@ -23,36 +22,8 @@
#include "port/protobuf.h"
#include "src/mutator.h"
-// 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;
-}
+extern "C" size_t LLVMFuzzerMutate(uint8_t*, size_t, size_t)
+ __attribute__((weak));
namespace protobuf_mutator {
namespace libfuzzer {
@@ -84,9 +55,7 @@ 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.
- // 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 {};
+ 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);
diff --git a/src/libfuzzer/libfuzzer_test.cc b/src/libfuzzer/libfuzzer_test.cc
deleted file mode 100644
index 180a02c..0000000
--- a/src/libfuzzer/libfuzzer_test.cc
+++ /dev/null
@@ -1,28 +0,0 @@
-// 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 e3c9b39..2aa9693 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,18 +120,15 @@ struct AppendField : public FieldFunction<AppendField> {
}
};
-class CanCopyAndDifferentField
- : public FieldFunction<CanCopyAndDifferentField, bool> {
+class IsEqualValueField : public FieldFunction<IsEqualValueField, bool> {
public:
template <class T>
- 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);
+ bool ForType(const ConstFieldInstance& a, const ConstFieldInstance& b) const {
+ T aa;
+ a.Load(&aa);
+ T bb;
+ b.Load(&bb);
+ return IsEqual(aa, bb);
}
private:
@@ -225,10 +222,9 @@ class MutationSampler {
} else {
if (reflection->HasField(*message, field) ||
IsProto3SimpleField(*field)) {
- if (field->cpp_type() != FieldDescriptor::CPPTYPE_MESSAGE) {
+ 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,
@@ -316,14 +312,15 @@ class DataSourceSampler {
if (int field_size = reflection->FieldSize(*message, field)) {
ConstFieldInstance source(message, field,
GetRandomIndex(random_, field_size));
- if (CanCopyAndDifferentField()(source, match_))
+ 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 (CanCopyAndDifferentField()(source, match_))
- sampler_.Try(1, source);
+ if (match_.EnforceUtf8() && !source.EnforceUtf8()) continue;
+ if (!IsEqualValueField()(match_, source)) sampler_.Try(1, source);
}
}
}
@@ -371,12 +368,13 @@ class FieldMutator {
}
void Mutate(bool* value) const {
- RepeatMutate(value, std::bind(&Mutator::MutateBool, mutator_, _1));
+ 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::bind(&Mutator::MutateEnum, mutator_, _1, value->count),
+ std::max<size_t>(value->count, 1));
assert(value->index < value->count);
}
@@ -393,16 +391,16 @@ class FieldMutator {
void Mutate(std::unique_ptr<Message>* message) const {
assert(!enforce_changes_);
assert(*message);
- if (GetRandomBool(mutator_->random(), mutator_->random_to_default_ratio_))
- return;
- mutator_->MutateImpl(message->get(), size_increase_hint_);
+ 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) const {
+ void RepeatMutate(T* value, F mutate,
+ size_t unchanged_one_out_of = 100) const {
if (!enforce_changes_ &&
- GetRandomBool(mutator_->random(), mutator_->random_to_default_ratio_)) {
+ GetRandomBool(mutator_->random(), unchanged_one_out_of)) {
return;
}
T tmp = *value;
@@ -449,43 +447,41 @@ struct CreateField : public FieldFunction<CreateField> {
} // namespace
-void Mutator::Seed(uint32_t value) { random_.seed(value); }
+Mutator::Mutator(RandomEngine* random) : random_(random) {}
void Mutator::Mutate(Message* message, size_t size_increase_hint) {
- MutateImpl(message, size_increase_hint);
-
- InitializeAndTrim(message, kMaxInitializeDepth);
- assert(!keep_initialized_ || message->IsInitialized());
-
- if (post_process_) post_process_(message, random_());
-}
-
-void Mutator::MutateImpl(Message* message, size_t size_increase_hint) {
- for (;;) {
- MutationSampler mutation(keep_initialized_, &random_, message);
+ bool repeat;
+ do {
+ repeat = false;
+ MutationSampler mutation(keep_initialized_, random_, message);
switch (mutation.mutation()) {
case Mutation::None:
- return;
+ break;
case Mutation::Add:
CreateField()(mutation.field(), size_increase_hint / 2, this);
- return;
+ break;
case Mutation::Mutate:
MutateField()(mutation.field(), size_increase_hint / 2, this);
- return;
+ break;
case Mutation::Delete:
DeleteField()(mutation.field());
- return;
+ break;
case Mutation::Copy: {
- DataSourceSampler source(mutation.field(), &random_, message);
- if (source.IsEmpty()) break;
+ DataSourceSampler source(mutation.field(), random_, message);
+ if (source.IsEmpty()) {
+ repeat = true;
+ break;
+ }
CopyField()(source.field(), mutation.field());
- return;
+ break;
}
default:
assert(false && "unexpected mutation");
- return;
}
- }
+ } while (repeat);
+
+ InitializeAndTrim(message, kMaxInitializeDepth);
+ assert(!keep_initialized_ || message->IsInitialized());
}
void Mutator::CrossOver(const protobuf::Message& message1,
@@ -500,9 +496,8 @@ void Mutator::CrossOver(const protobuf::Message& message1,
InitializeAndTrim(message2, kMaxInitializeDepth);
assert(!keep_initialized_ || message2->IsInitialized());
- if (post_process_) post_process_(message2, random_());
-
// 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);
@@ -532,20 +527,20 @@ void Mutator::CrossOverImpl(const protobuf::Message& message1,
// Shuffle
for (int j = 0; j < field_size2; ++j) {
- if (int k = GetRandomIndex(&random_, 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);
+ 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);
+ 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);
+ 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));
@@ -558,10 +553,10 @@ void Mutator::CrossOverImpl(const protobuf::Message& message1,
} else if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) {
if (!reflection->HasField(message1, field)) {
- if (GetRandomBool(&random_))
+ if (GetRandomBool(random_))
DeleteField()(FieldInstance(message2, field));
} else if (!reflection->HasField(*message2, field)) {
- if (GetRandomBool(&random_)) {
+ if (GetRandomBool(random_)) {
ConstFieldInstance source(&message1, field);
CopyField()(source, FieldInstance(message2, field));
}
@@ -570,7 +565,7 @@ void Mutator::CrossOverImpl(const protobuf::Message& message1,
reflection->MutableMessage(message2, field));
}
} else {
- if (GetRandomBool(&random_)) {
+ if (GetRandomBool(random_)) {
if (reflection->HasField(message1, field)) {
ConstFieldInstance source(&message1, field);
CopyField()(source, FieldInstance(message2, field));
@@ -582,21 +577,14 @@ void Mutator::CrossOverImpl(const protobuf::Message& message1,
}
}
-void Mutator::RegisterPostProcessor(PostProcess post_process) {
- assert(!post_process_);
- post_process_ = post_process;
-}
-
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() || descriptor->options().map_entry()) &&
- !reflection->HasField(*message, field)) {
+ 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()) {
@@ -624,58 +612,58 @@ void Mutator::InitializeAndTrim(Message* message, int max_depth) {
}
}
-int32_t Mutator::MutateInt32(int32_t value) { return FlipBit(value, &random_); }
+int32_t Mutator::MutateInt32(int32_t value) { return FlipBit(value, random_); }
-int64_t Mutator::MutateInt64(int64_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_);
+ return FlipBit(value, random_);
}
uint64_t Mutator::MutateUInt64(uint64_t value) {
- return FlipBit(value, &random_);
+ return FlipBit(value, random_);
}
-float Mutator::MutateFloat(float value) { return FlipBit(value, &random_); }
+float Mutator::MutateFloat(float value) { return FlipBit(value, random_); }
-double Mutator::MutateDouble(double 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;
+ 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.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));
+ 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));
+ result.push_back(GetRandomIndex(random_, 1 << 8));
return result;
}
if (!result.empty())
- FlipBit(result.size(), reinterpret_cast<uint8_t*>(&result[0]), &random_);
+ 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_);
+ FixUtf8String(&str, random_);
return str;
}
diff --git a/src/mutator.h b/src/mutator.h
index 73e1966..47139bd 100644
--- a/src/mutator.h
+++ b/src/mutator.h
@@ -18,12 +18,9 @@
#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"
@@ -45,12 +42,9 @@ namespace protobuf_mutator {
class Mutator {
public:
// seed: value to initialize random number generator.
- Mutator() = default;
+ explicit Mutator(RandomEngine* random);
virtual ~Mutator() = default;
- // Initialized internal random number generator.
- void Seed(uint32_t value);
-
// 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
@@ -62,16 +56,6 @@ class Mutator {
void CrossOver(const protobuf::Message& message1,
protobuf::Message* message2);
- // Callback to postprocess mutations.
- // Implementation should use seed to initialize random number generators.
- using PostProcess =
- std::function<void(protobuf::Message* message, unsigned int seed)>;
-
- // Register callback which will be called after every message mutation.
- // In this callback fuzzer may adjust content of the message or mutate some
- // fields in some fuzzer specific way.
- void RegisterPostProcessor(PostProcess post_process);
-
protected:
// TODO(vitalybuka): Consider to replace with single mutate (uint8_t*, size).
virtual int32_t MutateInt32(int32_t value);
@@ -85,23 +69,23 @@ class Mutator {
virtual std::string MutateString(const std::string& value,
size_t size_increase_hint);
- RandomEngine* random() { return &random_; }
+ // 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 MutateImpl(protobuf::Message* message, size_t size_increase_hint);
void CrossOverImpl(const protobuf::Message& message1,
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_;
- PostProcess post_process_;
+ RandomEngine* random_;
};
} // namespace protobuf_mutator
diff --git a/src/mutator_test.cc b/src/mutator_test.cc
index 0ae37aa..34766c6 100644
--- a/src/mutator_test.cc
+++ b/src/mutator_test.cc
@@ -216,11 +216,7 @@ const char kRepeatedNestedFields[] = R"(
class TestMutator : public Mutator {
public:
- explicit TestMutator(bool keep_initialized,
- size_t random_to_default_ratio = 0) {
- Seed(17);
- if (random_to_default_ratio)
- random_to_default_ratio_ = random_to_default_ratio;
+ explicit TestMutator(bool keep_initialized) : Mutator(&random_), random_(17) {
keep_initialized_ = keep_initialized;
}
@@ -236,7 +232,7 @@ class TestMutator : public Mutator {
class ReducedTestMutator : public TestMutator {
public:
- ReducedTestMutator() : TestMutator(false, 4) {
+ ReducedTestMutator() : TestMutator(false) {
for (float i = 1000; i > 0.1; i /= 7) {
values_.push_back(i);
values_.push_back(-i);
@@ -259,13 +255,13 @@ class ReducedTestMutator : public TestMutator {
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<>(
+ return strings_[std::uniform_int_distribution<uint8_t>(
0, strings_.size() - 1)(*random())];
}
private:
float GetRandomValue() {
- return values_[std::uniform_int_distribution<>(
+ return values_[std::uniform_int_distribution<uint8_t>(
0, values_.size() - 1)(*random())];
}
@@ -316,7 +312,6 @@ 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());
- EXPECT_FALSE(MessageDifferencer::Equals(from, to));
for (int j = 0; j < 1000000; ++j) {
message->CopyFrom(from);
mutator.Mutate(message.get(), 1000);
@@ -342,16 +337,16 @@ class MutatorTest : public TestWithParam<TestParams> {
EXPECT_TRUE(ParseTextMessage(text_, message));
}
- void LoadWithoutLine(protobuf::Message* 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';
}
- EXPECT_TRUE(ParseTextMessage(oss.str(), message));
+ return ParseTextMessage(oss.str(), message);
}
- void LoadWithChangedLine(protobuf::Message* message, int value) {
+ bool LoadWithChangedLine(protobuf::Message* message, int value) {
auto lines = Split(text_);
std::ostringstream oss;
for (size_t i = 0; i != lines.size(); ++i) {
@@ -373,7 +368,7 @@ class MutatorTest : public TestWithParam<TestParams> {
oss << s << '\n';
}
}
- EXPECT_TRUE(ParseTextMessage(oss.str(), message));
+ return ParseTextMessage(oss.str(), message);
}
std::string text_;
@@ -386,11 +381,11 @@ class MutatorTest : public TestWithParam<TestParams> {
// insertion/deletion.
class MutatorFieldInsDelTest : public MutatorTest {};
-INSTANTIATE_TEST_SUITE_P(Proto2, MutatorFieldInsDelTest,
- ValuesIn(GetFieldTestParams<Msg>(
- {kRequiredFields, kOptionalFields, kRepeatedFields,
- kRequiredNestedFields, kOptionalNestedFields,
- kRepeatedNestedFields})));
+INSTANTIATE_TEST_CASE_P(Proto2, MutatorFieldInsDelTest,
+ ValuesIn(GetFieldTestParams<Msg>(
+ {kRequiredFields, kOptionalFields, kRepeatedFields,
+ kRequiredNestedFields, kOptionalNestedFields,
+ kRepeatedNestedFields})));
TEST_P(MutatorFieldInsDelTest, DeleteField) {
LoadMessage(m1_.get());
@@ -409,15 +404,15 @@ class MutatorFieldTest : public MutatorTest {
template <class Msg>
void TestCopyField();
};
-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})));
+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());
@@ -461,18 +456,15 @@ TEST_P(MutatorFieldTest, CopyField) {
}
class MutatorSingleFieldTest : public MutatorTest {};
-INSTANTIATE_TEST_SUITE_P(Proto2, MutatorSingleFieldTest,
- ValuesIn(GetFieldTestParams<Msg>({
- kRequiredFields,
- kOptionalFields,
- kRequiredNestedFields,
- kOptionalNestedFields,
- })));
-INSTANTIATE_TEST_SUITE_P(Proto3, MutatorSingleFieldTest,
- ValuesIn(GetFieldTestParams<Msg3>({
- kOptionalFields,
- kOptionalNestedFields,
- })));
+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());
@@ -505,7 +497,7 @@ class MutatorTypedTest : public ::testing::Test {
};
using MutatorTypedTestTypes = testing::Types<Msg, Msg3>;
-TYPED_TEST_SUITE(MutatorTypedTest, MutatorTypedTestTypes);
+TYPED_TEST_CASE(MutatorTypedTest, MutatorTypedTestTypes);
TYPED_TEST(MutatorTypedTest, CrossOverRepeated) {
typename TestFixture::Message m1;
@@ -562,7 +554,7 @@ TYPED_TEST(MutatorTypedTest, CrossOverRepeatedMessages) {
TYPED_TEST(MutatorTypedTest, FailedMutations) {
TestMutator mutator(false);
size_t crossovers = 0;
- for (int i = 0; i < 1000; ++i) {
+ for (int i = 0; i < 10000; ++i) {
typename TestFixture::Message messages[2];
typename TestFixture::Message tmp;
for (int j = 0; j < 20; ++j) {
@@ -582,40 +574,7 @@ TYPED_TEST(MutatorTypedTest, FailedMutations) {
}
// CrossOver may fail but very rare.
- EXPECT_LT(crossovers, 10u);
-}
-
-TYPED_TEST(MutatorTypedTest, RegisterPostProcessor) {
- constexpr char kInitialString[] = " ";
- constexpr char kIndicatorString[] = "0123456789abcdef";
- bool custom_mutation = false;
- bool regular_mutation = false;
-
- TestMutator mutator(false);
- mutator.RegisterPostProcessor(
- [kIndicatorString](protobuf::Message* message, uint32_t seed) {
- typename TestFixture::Message* test_message =
- static_cast<typename TestFixture::Message*>(message);
- if (seed % 2) 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);
+ EXPECT_LT(crossovers, 100u);
}
TYPED_TEST(MutatorTypedTest, Serialization) {
@@ -635,34 +594,29 @@ TYPED_TEST(MutatorTypedTest, Serialization) {
}
}
-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));
- }
-}
+class MutatorMessagesTest : public MutatorTest {};
+INSTANTIATE_TEST_CASE_P(Proto2, MutatorMessagesTest,
+ ValuesIn(GetMessageTestParams<Msg>({kMessages})));
+INSTANTIATE_TEST_CASE_P(
+ Proto3, MutatorMessagesTest,
+ ValuesIn(GetMessageTestParams<Msg3>({kMessagesProto3})));
-TYPED_TEST(MutatorTypedTest, EmptyMessage) {
- typename TestFixture::Message::EmptyMessage message;
- TestMutator mutator(false);
- for (int j = 0; j < 10000; ++j) mutator.Mutate(&message, 1000);
+TEST_P(MutatorMessagesTest, DeletedMessage) {
+ LoadMessage(m1_.get());
+ LoadWithoutLine(m2_.get());
+ EXPECT_TRUE(Mutate(*m1_, *m2_));
}
-TYPED_TEST(MutatorTypedTest, Regressions) {
- typename TestFixture::Message::RegressionMessage message;
- TestMutator mutator(false);
- for (int j = 0; j < 10000; ++j) mutator.Mutate(&message, 1000);
+TEST_P(MutatorMessagesTest, InsertMessage) {
+ LoadWithoutLine(m1_.get());
+ LoadMessage(m2_.get());
+ EXPECT_TRUE(Mutate(*m1_, *m2_));
}
-TYPED_TEST(MutatorTypedTest, UsageExample) {
- typename TestFixture::Message::SmallMessage message;
+// TODO(vitalybuka): Special tests for oneof.
+
+TEST(MutatorMessagesTest, UsageExample) {
+ SmallMessage message;
TestMutator mutator(false);
// Test that we can generate all variation of the message.
@@ -673,52 +627,21 @@ TYPED_TEST(MutatorTypedTest, UsageExample) {
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());
- }
+ // 3 states for boolean and 5 for enum, including missing fields.
+ EXPECT_EQ(3u * 5u, mutations.size());
}
-TYPED_TEST(MutatorTypedTest, Maps) {
- TestMutator mutator(true);
-
- typename TestFixture::Message::MapMessage message;
+TEST(MutatorMessagesTest, EmptyMessage) {
+ EmptyMessage message;
+ TestMutator mutator(false);
for (int j = 0; j < 10000; ++j) mutator.Mutate(&message, 1000);
}
-class MutatorMessagesTest : public MutatorTest {};
-INSTANTIATE_TEST_SUITE_P(Proto2, MutatorMessagesTest,
- ValuesIn(GetMessageTestParams<Msg>({kMessages})));
-INSTANTIATE_TEST_SUITE_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, NeverCopyUnknownEnum) {
+TEST(MutatorMessagesTest, Regressions) {
+ RegressionMessage message;
TestMutator mutator(false);
- 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);
- }
+ 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 0927775..8f4d078 100644
--- a/src/mutator_test_proto2.proto
+++ b/src/mutator_test_proto2.proto
@@ -93,35 +93,33 @@ message Msg {
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 EmptyMessage {}
-
- message RegressionMessage {
- enum SingleValueEnum { ENUM_0 = 0; }
- optional SingleValueEnum 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 SmallMessage {
+ enum Enum {
+ ENUM_0 = 0;
+ ENUM_1 = 1;
+ ENUM_2 = 2;
+ ENUM_3 = 3;
}
- message MapMessage {
- map<string, int32> map1 = 1;
- map<int32, Msg> map2 = 2;
- }
+ 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
index 5fd7507..7c7162e 100644
--- a/src/mutator_test_proto3.proto
+++ b/src/mutator_test_proto3.proto
@@ -70,28 +70,4 @@ message Msg3 {
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 927997b..d4463d3 100644
--- a/src/random.h
+++ b/src/random.h
@@ -19,7 +19,7 @@
namespace protobuf_mutator {
-using RandomEngine = std::minstd_rand;
+using RandomEngine = std::mt19937;
} // namespace protobuf_mutator
diff --git a/src/text_format.cc b/src/text_format.cc
index 94e6a79..9990d60 100644
--- a/src/text_format.cc
+++ b/src/text_format.cc
@@ -13,7 +13,6 @@
// limitations under the License.
#include "src/text_format.h"
-
#include "port/protobuf.h"
namespace protobuf_mutator {
@@ -28,7 +27,6 @@ bool ParseTextMessage(const uint8_t* data, size_t size, Message* output) {
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 c451adb..50e6efd 100644
--- a/src/utf8_fix.cc
+++ b/src/utf8_fix.cc
@@ -47,9 +47,7 @@ char* FixCode(char* b, const char* e, RandomEngine* random) {
case 2:
c &= 0x7FF;
if (c < 0x80) {
- // Use uint32_t because uniform_int_distribution does not support
- // char32_t on Windows.
- c = std::uniform_int_distribution<uint32_t>(0x80, 0x7FF)(*random);
+ c = std::uniform_int_distribution<char32_t>(0x80, 0x7FF)(*random);
}
StoreCode(b, c, size, 0xC0);
break;
@@ -59,7 +57,7 @@ char* FixCode(char* b, const char* e, RandomEngine* random) {
// [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<uint32_t>(0x800,
+ c = std::uniform_int_distribution<char32_t>(0x800,
0xFFFF - halves)(*random);
if (c >= 0xD800) c += halves;
}
@@ -68,7 +66,7 @@ char* FixCode(char* b, const char* e, RandomEngine* random) {
case 4:
c &= 0x1FFFFF;
if (c < 0x10000 || c > 0x10FFFF) {
- c = std::uniform_int_distribution<uint32_t>(0x10000, 0x10FFFF)(*random);
+ c = std::uniform_int_distribution<char32_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 474eb8c..54f09cd 100644
--- a/src/utf8_fix_test.cc
+++ b/src/utf8_fix_test.cc
@@ -41,11 +41,11 @@ TEST_F(FixUtf8StringTest, IsStructurallyValid) {
EXPECT_FALSE(IsStructurallyValid("\x3F\xBF"));
}
-INSTANTIATE_TEST_SUITE_P(Size, FixUtf8StringTest, ::testing::Range(0, 10));
+INSTANTIATE_TEST_CASE_P(Size, FixUtf8StringTest, ::testing::Range(0, 10));
TEST_P(FixUtf8StringTest, FixUtf8String) {
RandomEngine random(GetParam());
- std::uniform_int_distribution<> random8(0, 0xFF);
+ std::uniform_int_distribution<uint8_t> 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 968b613..e524620 100644
--- a/src/weighted_reservoir_sampler_test.cc
+++ b/src/weighted_reservoir_sampler_test.cc
@@ -14,16 +14,15 @@
#include "src/weighted_reservoir_sampler.h"
-#include <numeric>
#include <tuple>
#include <vector>
#include "port/gtest.h"
-using testing::Combine;
-using testing::Range;
using testing::TestWithParam;
using testing::ValuesIn;
+using testing::Combine;
+using testing::Range;
namespace protobuf_mutator {
@@ -46,14 +45,14 @@ const std::vector<int> kTests[] = {
52962, 10327, 80513, 49526, 18326, 83662, 49644, 70903, 4910,
36309, 19196, 42982, 53316, 14773, 86607, 60835}};
-INSTANTIATE_TEST_SUITE_P(AllTest, WeightedReservoirSamplerTest,
- Combine(Range(1, 10, 3), ValuesIn(kTests)));
+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::minstd_rand;
+ using RandomEngine = std::mt19937;
RandomEngine rand(std::get<0>(GetParam()));
for (int i = 0; i < kRuns; ++i) {
WeightedReservoirSampler<int, RandomEngine> sampler(&rand);