diff --git a/.devcontainer/Dockerfile b/.devcontainer/Dockerfile new file mode 100644 index 0000000..b2045e7 --- /dev/null +++ b/.devcontainer/Dockerfile @@ -0,0 +1,26 @@ +FROM mcr.microsoft.com/devcontainers/cpp:1-ubuntu-22.04 + +#ARG REINSTALL_CMAKE_VERSION_FROM_SOURCE="3.22.2" + +# Optionally install the cmake for vcpkg +#COPY ./reinstall-cmake.sh /tmp/ + +#RUN if [ "${REINSTALL_CMAKE_VERSION_FROM_SOURCE}" != "none" ]; then \ +# chmod +x /tmp/reinstall-cmake.sh && /tmp/reinstall-cmake.sh ${REINSTALL_CMAKE_VERSION_FROM_SOURCE}; \ +# fi \ +# && rm -f /tmp/reinstall-cmake.sh + +# [Optional] Uncomment this section to install additional vcpkg ports. +# RUN su vscode -c "${VCPKG_ROOT}/vcpkg install " + +# [Optional] Uncomment this section to install additional packages. +RUN apt-get update && export DEBIAN_FRONTEND=noninteractive \ + && apt-get -y install --no-install-recommends cmake clang llvm lcov +RUN --mount=type=secret,id=credentials \ + export CIFUZZ_CREDENTIALS=$(cat /run/secrets/credentials) &&\ + sh -c "$(curl -fsSL http://downloads.code-intelligence.com/assets/install-cifuzz.sh)" $CIFUZZ_CREDENTIALS latest &&\ + export CIFUZZ_CREDENTIALS="" + + +RUN sysctl vm.mmap_rnd_bits=30 +RUN cifuzz completion bash > /etc/bash_completion.d/cifuzz \ No newline at end of file diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json new file mode 100644 index 0000000..e642031 --- /dev/null +++ b/.devcontainer/devcontainer.json @@ -0,0 +1,39 @@ +// For format details, see https://aka.ms/devcontainer.json. For config options, see the +// README at: https://github.com/devcontainers/templates/tree/main/src/cpp +{ + "name": "Cifuzz", + "build": { + "dockerfile": "Dockerfile", + "options": [ + "--secret=id=credentials,env=CIFUZZ_CREDENTIALS" + ] + }, + "features": { + "ghcr.io/devcontainers-community/features/llvm:3": {} + }, + "customizations": { + "vscode": { + "extensions": [ + "ryanluker.vscode-coverage-gutters", + "ms-vscode.cpptools", + "ms-vscode.cpptools-extension-pack", + "jeff-hykin.better-cpp-syntax" + ] + } + } + + // Features to add to the dev container. More info: https://containers.dev/features. + // "features": {}, + + // Use 'forwardPorts' to make a list of ports inside the container available locally. + // "forwardPorts": [], + + // Use 'postCreateCommand' to run commands after the container is created. + // "postCreateCommand": "gcc -v", + + // Configure tool-specific properties. + // "customizations": {}, + + // Uncomment to connect as root instead. More info: https://aka.ms/dev-containers-non-root. + // "remoteUser": "root" +} diff --git a/.devcontainer/reinstall-cmake.sh b/.devcontainer/reinstall-cmake.sh new file mode 100644 index 0000000..408b81d --- /dev/null +++ b/.devcontainer/reinstall-cmake.sh @@ -0,0 +1,59 @@ +#!/usr/bin/env bash +#------------------------------------------------------------------------------------------------------------- +# Copyright (c) Microsoft Corporation. All rights reserved. +# Licensed under the MIT License. See https://go.microsoft.com/fwlink/?linkid=2090316 for license information. +#------------------------------------------------------------------------------------------------------------- +# +set -e + +CMAKE_VERSION=${1:-"none"} + +if [ "${CMAKE_VERSION}" = "none" ]; then + echo "No CMake version specified, skipping CMake reinstallation" + exit 0 +fi + +# Cleanup temporary directory and associated files when exiting the script. +cleanup() { + EXIT_CODE=$? + set +e + if [[ -n "${TMP_DIR}" ]]; then + echo "Executing cleanup of tmp files" + rm -Rf "${TMP_DIR}" + fi + exit $EXIT_CODE +} +trap cleanup EXIT + + +echo "Installing CMake..." +apt-get -y purge --auto-remove cmake +mkdir -p /opt/cmake + +architecture=$(dpkg --print-architecture) +case "${architecture}" in + arm64) + ARCH=aarch64 ;; + amd64) + ARCH=x86_64 ;; + *) + echo "Unsupported architecture ${architecture}." + exit 1 + ;; +esac + +CMAKE_BINARY_NAME="cmake-${CMAKE_VERSION}-linux-${ARCH}.sh" +CMAKE_CHECKSUM_NAME="cmake-${CMAKE_VERSION}-SHA-256.txt" +TMP_DIR=$(mktemp -d -t cmake-XXXXXXXXXX) + +echo "${TMP_DIR}" +cd "${TMP_DIR}" + +curl -sSL "https://github.com/Kitware/CMake/releases/download/v${CMAKE_VERSION}/${CMAKE_BINARY_NAME}" -O +curl -sSL "https://github.com/Kitware/CMake/releases/download/v${CMAKE_VERSION}/${CMAKE_CHECKSUM_NAME}" -O + +sha256sum -c --ignore-missing "${CMAKE_CHECKSUM_NAME}" +sh "${TMP_DIR}/${CMAKE_BINARY_NAME}" --prefix=/opt/cmake --skip-license + +ln -s /opt/cmake/bin/cmake /usr/local/bin/cmake +ln -s /opt/cmake/bin/ctest /usr/local/bin/ctest diff --git a/.github/dependabot.yml b/.github/dependabot.yml new file mode 100644 index 0000000..f33a02c --- /dev/null +++ b/.github/dependabot.yml @@ -0,0 +1,12 @@ +# To get started with Dependabot version updates, you'll need to specify which +# package ecosystems to update and where the package manifests are located. +# Please see the documentation for more information: +# https://docs.github.com/github/administering-a-repository/configuration-options-for-dependency-updates +# https://containers.dev/guide/dependabot + +version: 2 +updates: + - package-ecosystem: "devcontainers" + directory: "/" + schedule: + interval: weekly diff --git a/.gitignore b/.gitignore index 22d95f2..6209c0b 100644 --- a/.gitignore +++ b/.gitignore @@ -4,4 +4,6 @@ build cmake-build-debug /**/.cifuzz-* -/**/*fuzzer_inputs \ No newline at end of file +/**/*fuzzer_inputs + +/**/lcov.info \ No newline at end of file diff --git a/CMakeLists.txt b/CMakeLists.txt index 5dc9639..5df2020 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -14,5 +14,8 @@ set(CMAKE_MODULE_PATH ${PROJECT_SOURCE_DIR}/cmake/external) enable_testing() include(googletest) +find_package(cifuzz NO_SYSTEM_ENVIRONMENT_PATH) +enable_fuzz_testing() + add_subdirectory(src/explore_me) -add_subdirectory(src/automotive) \ No newline at end of file +add_subdirectory(src/automotive) diff --git a/CMakeUserPresets.json b/CMakeUserPresets.json new file mode 100644 index 0000000..fad5c91 --- /dev/null +++ b/CMakeUserPresets.json @@ -0,0 +1,100 @@ +{ + "version": 3, + "cmakeMinimumRequired": { + "major": 3, + "minor": 20, + "patch": 0 + }, + "configurePresets": [ + { + "name": "cifuzz (Coverage)", + "displayName": "cifuzz (Coverage)", + "binaryDir": "${sourceDir}/.cifuzz-build/replayer/gcov", + "cacheVariables": { + "CMAKE_BUILD_TYPE": "RelWithDebInfo", + "CIFUZZ_ENGINE": "replayer", + "CIFUZZ_SANITIZERS": "gcov", + "CIFUZZ_TESTING": { + "type": "BOOL", + "value": "ON" + }, + "CMAKE_BUILD_RPATH_USE_ORIGIN": { + "type": "BOOL", + "value": "ON" + } + } + }, + { + "name": "cifuzz (Fuzzing)", + "displayName": "cifuzz (Fuzzing)", + "binaryDir": "${sourceDir}/.cifuzz-build/libfuzzer/address+undefined", + "cacheVariables": { + "CMAKE_BUILD_TYPE": "RelWithDebInfo", + "CIFUZZ_ENGINE": "libfuzzer", + "CIFUZZ_SANITIZERS": "address;undefined", + "CIFUZZ_TESTING": { + "type": "BOOL", + "value": "ON" + }, + "CMAKE_BUILD_RPATH_USE_ORIGIN": { + "type": "BOOL", + "value": "ON" + } + }, + "environment": { + "CC": "clang", + "CXX": "clang++" + } + }, + { + "name": "cifuzz (Regression Test)", + "displayName": "cifuzz (Regression Test)", + "binaryDir": "${sourceDir}/.cifuzz-build/replayer/address+undefined", + "cacheVariables": { + "CMAKE_BUILD_TYPE": "RelWithDebInfo", + "CIFUZZ_ENGINE": "replayer", + "CIFUZZ_SANITIZERS": "address;undefined", + "CIFUZZ_TESTING": { + "type": "BOOL", + "value": "ON" + }, + "CMAKE_BUILD_RPATH_USE_ORIGIN": { + "type": "BOOL", + "value": "ON" + } + } + } + ], + "buildPresets": [ + { + "name": "cifuzz (Coverage)", + "displayName": "cifuzz (Coverage)", + "configurePreset": "cifuzz (Coverage)", + "configuration": "RelWithDebInfo" + }, + { + "name": "cifuzz (Fuzzing)", + "displayName": "cifuzz (Fuzzing)", + "configurePreset": "cifuzz (Fuzzing)", + "configuration": "RelWithDebInfo" + }, + { + "name": "cifuzz (Regression Test)", + "displayName": "cifuzz (Regression Test)", + "configurePreset": "cifuzz (Regression Test)", + "configuration": "RelWithDebInfo" + } + ], + "testPresets": [ + { + "name": "cifuzz (Regression Test)", + "displayName": "cifuzz (Regression Test)", + "configurePreset": "cifuzz (Regression Test)", + "filter": { + "include": { + "label": "^cifuzz_regression_test$" + } + } + } + ] +} diff --git a/README.md b/README.md index aa1aeec..b6aed4b 100644 --- a/README.md +++ b/README.md @@ -27,3 +27,6 @@ input parameters that trigger the bug. * [Automotive Example](src/automotive): An example that demonstrates the challenges of creating high-quality fuzz tests for complex projects with a large public API. We demonstrate how we can automate most of this task with CI Spark. + + +If you want to use the devcontainer environment then export your cifuzz download token to a environment var called "CIFUZZ_CREDENTIALS" like `export CIFUZZ_CREDENTIALS=[my_token]`. \ No newline at end of file diff --git a/cifuzz.yaml b/cifuzz.yaml new file mode 100644 index 0000000..91be510 --- /dev/null +++ b/cifuzz.yaml @@ -0,0 +1,46 @@ +## Configuration for a CI Fuzz project +## Generated on 2023-06-06 + +## The build system used to build this project. If not set, cifuzz tries +## to detect the build system automatically. +## Valid values: "bazel", "cmake", "maven", "gradle", "other". +#build-system: cmake + +## If the build system type is "other", this command is used by +## `cifuzz run` to build the fuzz test. +#build-command: "make my_fuzz_test" + +## Directories containing sample inputs for the code under test. +## See https://llvm.org/docs/LibFuzzer.html#corpus +#seed-corpus-dirs: +# - path/to/seed-corpus + +## A file containing input language keywords or other interesting byte +## sequences. +## See https://llvm.org/docs/LibFuzzer.html#dictionaries +#dict: path/to/dictionary.dct + +## Command-line arguments to pass to libFuzzer. +## See https://llvm.org/docs/LibFuzzer.html#options +engine-args: + - -use_value_profile=1 + +## Maximum time to run fuzz tests. The default is to run indefinitely. +timeout: 5m + +## By default, fuzz tests are executed in a sandbox to prevent accidental +## damage to the system. Set to false to run fuzz tests unsandboxed. +## Only supported on Linux. +#use-sandbox: false + +## Set to true to print output of the `cifuzz run` command as JSON. +#print-json: true + +## Set to true to disable desktop notifications +#no-notifications: true + +## Set URL of the CI App +#server: https://app.code-intelligence.com + +## Set the project name on the CI App +#project: my-project-1a2b3c4d diff --git a/src/automotive/CMakeLists.txt b/src/automotive/CMakeLists.txt index 6fc7507..ba4b591 100644 --- a/src/automotive/CMakeLists.txt +++ b/src/automotive/CMakeLists.txt @@ -11,4 +11,13 @@ target_include_directories(automotive PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/gps ${CMAKE_CURRENT_SOURCE_DIR}/key_management ${CMAKE_CURRENT_SOURCE_DIR}/time -) \ No newline at end of file +) + +add_fuzz_test(automotive_fuzzer + fuzz_test.cpp + mocks.cpp +) + +target_link_libraries(automotive_fuzzer + automotive +) diff --git a/src/automotive/fuzz_test.cpp b/src/automotive/fuzz_test.cpp new file mode 100644 index 0000000..f3b62e1 --- /dev/null +++ b/src/automotive/fuzz_test.cpp @@ -0,0 +1,209 @@ + +#include +#include + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +#include "crypto_1.h" +#include "crypto_2.h" +#include "gps_1.h" +#include "key_management_1.h" +#include "time_1.h" + +#ifdef __cplusplus +} +#endif + +void SetFDP(FuzzedDataProvider *fuzzed_data_provider); +FuzzedDataProvider *GetFDP(); +void ConsumeDataAndFillRestWithZeros(void *destination, size_t num_bytes); + +FUZZ_TEST_SETUP() {} + +FUZZ_TEST(const uint8_t *data, size_t size) { + + // Ensure a minimum data length + if (size < 100) + return; + + // Setup FuzzedDataProvider and initialize the mocklib + FuzzedDataProvider fdp(data, size); + SetFDP(&fdp); + + int number_of_functions = GetFDP()->ConsumeIntegralInRange(1, 100); + for (int i = 0; i < number_of_functions; i++) { + int function_id = GetFDP()->ConsumeIntegralInRange(0, 15); + switch (function_id) { + + case 0: { + crypto_get_state(); + break; + } + + case 1: { + get_destination_position(); + break; + } + + case 2: { + crypto_key key = {}; + ConsumeDataAndFillRestWithZeros(key.key, 64); + + crypto_verify_key(key); + break; + } + + case 3: { + current_time(); + break; + } + + case 4: { + crypto_nonce nonce_tmp = {}; + ConsumeDataAndFillRestWithZeros(nonce_tmp.nonce, 64); + nonce_tmp.time_of_creation = GetFDP()->ConsumeIntegral(); + crypto_nonce *nonce = &nonce_tmp; + + crypto_verify_nonce(nonce); + break; + } + + case 5: { + std::vector message_vec = GetFDP()->ConsumeBytes( + sizeof(uint8_t) * GetFDP()->ConsumeIntegral()); + const uint8_t *message = (const uint8_t *)message_vec.data(); + + // The parameter "len" seems to represent the length of a buffer/array. In + // this case, we usually don't want to provide fuzzer-generated lengths + // that differ from the actual length of the buffer. If you confirm that + // the parameter is a length parameter, you can get the length of the + // fuzzer-generated buffer as follows (replace "buffer" with the actual + // variable): + // int len = buffer.size(); + int len = message_vec.size(); + crypto_hmac hmac_tmp = {}; + ConsumeDataAndFillRestWithZeros(hmac_tmp.hmac, 64); + crypto_hmac *hmac = &hmac_tmp; + + crypto_verify_hmac(message, len, hmac); + break; + } + + case 6: { + crypto_nonce nonce = {}; + ConsumeDataAndFillRestWithZeros(nonce.nonce, 64); + nonce.time_of_creation = GetFDP()->ConsumeIntegral(); + + crypto_set_nonce(nonce); + break; + } + + case 7: { + std::vector message_vec = GetFDP()->ConsumeBytes( + sizeof(uint8_t) * GetFDP()->ConsumeIntegral()); + const uint8_t *message = (const uint8_t *)message_vec.data(); + + // The parameter "len" seems to represent the length of a buffer/array. In + // this case, we usually don't want to provide fuzzer-generated lengths + // that differ from the actual length of the buffer. If you confirm that + // the parameter is a length parameter, you can get the length of the + // fuzzer-generated buffer as follows (replace "buffer" with the actual + // variable): + // int len = buffer.size(); + int len = message_vec.size(); + crypto_hmac hmac_tmp = {}; + ConsumeDataAndFillRestWithZeros(hmac_tmp.hmac, 64); + crypto_hmac *hmac = &hmac_tmp; + + crypto_calculate_hmac(message, len, hmac); + break; + } + + case 8: { + GPS_position position = {}; + position.longitude_degree = GetFDP()->ConsumeIntegral(); + position.longitude_minute = GetFDP()->ConsumeIntegral(); + position.longitude_second = GetFDP()->ConsumeIntegral(); + position.latitude_degree = GetFDP()->ConsumeIntegral(); + position.latitude_minute = GetFDP()->ConsumeIntegral(); + position.latitude_second = GetFDP()->ConsumeIntegral(); + + set_destination_postition(position); + break; + } + + case 9: { + crypto_key key = {}; + ConsumeDataAndFillRestWithZeros(key.key, 64); + + crypto_set_key(key); + break; + } + + case 10: { + GPS_position position_tmp = {}; + position_tmp.longitude_degree = GetFDP()->ConsumeIntegral(); + position_tmp.longitude_minute = GetFDP()->ConsumeIntegral(); + position_tmp.longitude_second = GetFDP()->ConsumeIntegral(); + position_tmp.latitude_degree = GetFDP()->ConsumeIntegral(); + position_tmp.latitude_minute = GetFDP()->ConsumeIntegral(); + position_tmp.latitude_second = GetFDP()->ConsumeIntegral(); + GPS_position *position = &position_tmp; + + get_current_position(position); + break; + } + + case 11: { + init_crypto_module(); + break; + } + + case 12: { + std::vector key_vec = GetFDP()->ConsumeBytes( + sizeof(uint8_t) * GetFDP()->ConsumeIntegral()); + uint8_t *key = (uint8_t *)key_vec.data(); + + // The parameter "length" seems to represent the length of a buffer/array. + // In this case, we usually don't want to provide fuzzer-generated lengths + // that differ from the actual length of the buffer. If you confirm that + // the parameter is a length parameter, you can get the length of the + // fuzzer-generated buffer as follows (replace "buffer" with the actual + // variable): + // uint8_t length = buffer.size(); + uint8_t length = key_vec.size(); + + key_management_create_key(key, length); + break; + } + + case 13: { + std::vector nonce_vec = GetFDP()->ConsumeBytes( + sizeof(uint8_t) * GetFDP()->ConsumeIntegral()); + uint8_t *nonce = (uint8_t *)nonce_vec.data(); + + // The parameter "length" seems to represent the length of a buffer/array. + // In this case, we usually don't want to provide fuzzer-generated lengths + // that differ from the actual length of the buffer. If you confirm that + // the parameter is a length parameter, you can get the length of the + // fuzzer-generated buffer as follows (replace "buffer" with the actual + // variable): + // uint8_t length = buffer.size(); + uint8_t length = nonce_vec.size(); + + key_management_create_nonce(nonce, length); + break; + } + + case 14: { + crypto_init(); + break; + } + } + } +} diff --git a/src/automotive/mocks.cpp b/src/automotive/mocks.cpp new file mode 100644 index 0000000..7def44e --- /dev/null +++ b/src/automotive/mocks.cpp @@ -0,0 +1,83 @@ + +#include +#include +#include +#include + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +#include "crypto_1.h" +#include "gps_1.h" +#include "key_management_1.h" +#include "time_1.h" + +#ifdef __cplusplus +} +#endif + +static FuzzedDataProvider *gFDP; + +// This function received the fuzzer generated data from the fuzz target. +// It needs to be called at the beginning of the LLVMFuzzerTestOneInput +// function. +void SetFDP(FuzzedDataProvider *fuzzed_data_provider) { + gFDP = fuzzed_data_provider; +} + +FuzzedDataProvider *GetFDP() { return gFDP; } + +// Wrapper function for FuzzedDataProvider.h +// Writes |num_bytes| of input data to the given destination pointer. If there +// is not enough data left, writes all remaining bytes and fills the rest with +// zeros. Return value is the number of bytes written. +void ConsumeDataAndFillRestWithZeros(void *destination, size_t num_bytes) { + if (destination != nullptr) { + size_t num_consumed_bytes = GetFDP()->ConsumeData(destination, num_bytes); + if (num_bytes > num_consumed_bytes) { + size_t num_zero_bytes = num_bytes - num_consumed_bytes; + std::memset((char *)destination + num_consumed_bytes, 0, num_zero_bytes); + } + } +} + +#ifdef __cplusplus +extern "C" { +#endif + +int driver_get_current_time() { + int cifuzz_var_0 = GetFDP()->ConsumeIntegral(); + return cifuzz_var_0; +} + +uint8_t GPS_driver_obtain_current_position(uint8_t *position_as_bytes, + uint8_t *hmac_as_bytes) { + unsigned int position_as_bytes_length = 12; + ConsumeDataAndFillRestWithZeros((void *)position_as_bytes, + position_as_bytes_length); + unsigned int hmac_as_bytes_length = 64; + ConsumeDataAndFillRestWithZeros((void *)hmac_as_bytes, hmac_as_bytes_length); + uint8_t cifuzz_var_1 = GetFDP()->ConsumeIntegral(); + return cifuzz_var_1; +} + +uint8_t HSM_get_random_byte() { + uint8_t cifuzz_var_2 = GetFDP()->ConsumeIntegral(); + return cifuzz_var_2; +} + +uint8_t third_party_library_calc_hmac(const uint8_t *message, int len, + const char *key, const char *nonce, + uint8_t *hmac) { + unsigned int hmac_length = 64; + ConsumeDataAndFillRestWithZeros((void *)hmac, hmac_length); + uint8_t cifuzz_var_3 = GetFDP()->ConsumeIntegral(); + return cifuzz_var_3; +} + +#ifdef __cplusplus +} +#endif diff --git a/src/explore_me/CMakeLists.txt b/src/explore_me/CMakeLists.txt index a3c3e04..9273a3d 100644 --- a/src/explore_me/CMakeLists.txt +++ b/src/explore_me/CMakeLists.txt @@ -34,4 +34,13 @@ foreach(TestType IN ITEMS ) add_test(explore_me.${TestType} ${TestType}_test) + + add_fuzz_test(${TestType}_fuzz_test + ${TestType}_test.cpp + ) + + target_link_libraries(${TestType}_fuzz_test + explore_me + ${GTEST_BOTH_LIBRARIES} + ) endforeach(TestType ) diff --git a/src/explore_me/complex_checks_test.cpp b/src/explore_me/complex_checks_test.cpp index 190e014..81ad008 100644 --- a/src/explore_me/complex_checks_test.cpp +++ b/src/explore_me/complex_checks_test.cpp @@ -1,9 +1,11 @@ #include #include -#include #include "explore_me.h" +#ifndef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION +#include + TEST(ExploreComplexChecksTests, DeveloperTest) { EXPECT_NO_THROW(ExploreComplexChecks(0, 10, "Developer")); } @@ -11,3 +13,14 @@ TEST(ExploreComplexChecksTests, DeveloperTest) { TEST(ExploreComplexChecksTests, MaintainerTest) { EXPECT_NO_THROW(ExploreComplexChecks(20, -10, "Maintainer")); } + +#endif + +FUZZ_TEST(const uint8_t *data, size_t size) { + FuzzedDataProvider fdp(data, size); + long a = fdp.ConsumeIntegral(); + long b = fdp.ConsumeIntegral(); + std::string c = fdp.ConsumeRemainingBytesAsString(); + + ExploreComplexChecks(a, b, c); +} diff --git a/src/explore_me/simple_checks_test.cpp b/src/explore_me/simple_checks_test.cpp index 2eec307..2819401 100644 --- a/src/explore_me/simple_checks_test.cpp +++ b/src/explore_me/simple_checks_test.cpp @@ -1,9 +1,11 @@ #include #include -#include #include "explore_me.h" +#ifndef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION +#include + TEST(ExploreSimpleChecksTests, DeveloperTest) { EXPECT_NO_THROW(ExploreSimpleChecks(0, 10, "Developer")); } @@ -11,3 +13,14 @@ TEST(ExploreSimpleChecksTests, DeveloperTest) { TEST(ExploreSimpleChecksTests, MaintainerTest) { EXPECT_NO_THROW(ExploreSimpleChecks(20, -10, "Maintainer")); } + +#endif + +FUZZ_TEST(const uint8_t *data, size_t size) { + FuzzedDataProvider fdp(data, size); + int a = fdp.ConsumeIntegral(); + int b = fdp.ConsumeIntegral(); + std::string c = fdp.ConsumeRemainingBytesAsString(); + + ExploreSimpleChecks(a, b, c); +}