diff options
author | android-build-team Robot <android-build-team-robot@google.com> | 2020-04-28 20:23:28 +0000 |
---|---|---|
committer | android-build-team Robot <android-build-team-robot@google.com> | 2020-04-28 20:23:28 +0000 |
commit | 3b68eeaa4f42a22239bc885017b73733ef626c2d (patch) | |
tree | 5f093ed4cbdec8bd1d307db508a2033713682cfe | |
parent | dc2abb582a983e628877765255ad77e82d52825f (diff) | |
parent | 19b7bf3edcedaea88dff58cc0d0bd595846a9db5 (diff) | |
download | libprotobuf-mutator-android12-mainline-tzdata-release.tar.gz |
Snap for 6439596 from 19b7bf3edcedaea88dff58cc0d0bd595846a9db5 to qt-aml-tzdata-releaseq_tzdata_aml_297100400q_tzdata_aml_297100300q_tzdata_aml_297100000q_tzdata_aml_296200000q_tzdata_aml_295600118q_tzdata_aml_295600110q_tzdata_aml_295500002q_tzdata_aml_295500001q_tzdata_aml_294400310android-mainline-12.0.0_r54android-mainline-12.0.0_r111android-mainline-10.0.0_r13android-mainline-10.0.0_r12android-mainline-10.0.0_r11q_tzdata_aml_297100000android12-mainline-tzdata-releaseandroid10-mainline-tzdata-releaseandroid10-android13-mainline-tzdata-release
Change-Id: I49c52a900789a92bf85cfa0568f087a199317389
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") @@ -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 - } } @@ -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 @@ -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); |