diff --git a/.github/workflows/build_cmake.yml b/.github/workflows/build_cmake.yml index 763a00f..5174c5e 100644 --- a/.github/workflows/build_cmake.yml +++ b/.github/workflows/build_cmake.yml @@ -187,3 +187,51 @@ jobs: - name: Build shell: bash run: cmake --build --preset build-gcc-arm-${{ matrix.buildtype }} + + linux-fuzzing: + name: ${{ matrix.os }}, ${{ matrix.compiler.name }}, libFuzzer, ${{ matrix.buildtype }} + runs-on: ${{ matrix.os }} + strategy: + fail-fast: false # 'false' means Don't stop matrix workflows even if some matrix entry fails. + matrix: + os: [ubuntu-22.04] + buildtype: [debug] + compiler: [ {name: 'Clang 12', preset: clang-12, pkgs: 'clang-12 llvm-12'}, + {name: 'Clang 13', preset: clang-13, pkgs: 'clang-13 llvm-13'}, + {name: 'Clang 14', preset: clang-14, pkgs: 'clang-14 llvm-14'}, + {name: 'Clang 15', preset: clang-15, pkgs: 'clang-15 llvm-15'} + ] + + steps: + - uses: actions/checkout@v3 + + - name: Cache + uses: actions/cache@v3 + env: + cache-name: cache-conan-modules + with: + path: | + ${{ env.CONAN_USER_HOME }} + ~/.cache/pip + key: ${{ runner.os }}-${{ env.BUILD_TYPE }}-${{ hashFiles('CMakeLists.txt') }}-${{ hashFiles('cmake/Conan.cmake') }} + + - name: Install conan + shell: bash + run: | + python3 -m pip install --upgrade pip setuptools conan==1.59 + source ~/.profile + + - name: Install dependencies + run: | + sudo bash -c "$(wget -O - https://apt.llvm.org/llvm.sh)" + sudo apt update + sudo apt install ninja-build ${{ matrix.compiler.pkgs }} + shell: bash + + - name: Configure via CMake + shell: bash + run: cmake --preset unixlike-${{ matrix.compiler.preset }}-${{ matrix.buildtype }} + + - name: Build + shell: bash + run: cmake --build --preset build-unixlike-${{ matrix.compiler.preset }}-${{ matrix.buildtype }} diff --git a/CMakePresets.json b/CMakePresets.json index 69d1d03..cfc579a 100644 --- a/CMakePresets.json +++ b/CMakePresets.json @@ -53,6 +53,22 @@ } } }, + { + "name": "common-fuzzing-conf", + "hidden": true, + "description": "Clang 15 fuzzer test", + "binaryDir": "${sourceDir}/out/build/${presetName}", + "installDir": "${sourceDir}/out/install/${presetName}", + "cacheVariables": { + "CMAKE_BUILD_TYPE": "Debug", + "ENABLE_COVERAGE": "ON", + "ENABLE_SANITIZER_ADDRESS": "ON", + "ENABLE_SANITIZER_LEAK": "ON", + "ENABLE_SANITIZER_UNDEFINED_BEHAVIOR": "ON", + "ENABLE_SANITIZER_MEMORY": "OFF", + "ENABLE_FUZZING": "ON" + } + }, { "name": "windows-2019-msvc-debug", "generator": "Visual Studio 16 2019", @@ -350,6 +366,42 @@ "CMAKE_TRY_COMPILE_TARGET_TYPE": "STATIC_LIBRARY", "CMAKE_CROSSCOMPILING": "TRUE" } + }, + { + "name": "clang-12-fuzzing", + "description": "Clang 12 fuzzer test", + "inherits": "common-fuzzing-conf", + "cacheVariables": { + "CMAKE_C_COMPILER": "clang-12", + "CMAKE_CXX_COMPILER": "clang++-12" + } + }, + { + "name": "clang-13-fuzzing", + "description": "Clang 13 fuzzer test", + "inherits": "common-fuzzing-conf", + "cacheVariables": { + "CMAKE_C_COMPILER": "clang-13", + "CMAKE_CXX_COMPILER": "clang++-13" + } + }, + { + "name": "clang-14-fuzzing", + "description": "Clang 14 fuzzer test", + "inherits": "common-fuzzing-conf", + "cacheVariables": { + "CMAKE_C_COMPILER": "clang-14", + "CMAKE_CXX_COMPILER": "clang++-14" + } + }, + { + "name": "clang-15-fuzzing", + "description": "Clang 15 fuzzer test", + "inherits": "common-fuzzing-conf", + "cacheVariables": { + "CMAKE_C_COMPILER": "clang-15", + "CMAKE_CXX_COMPILER": "clang++-15" + } } ], "buildPresets": [ @@ -444,6 +496,22 @@ { "name": "build-gcc-arm-release", "configurePreset": "gcc-arm-release" + }, + { + "name": "build-clang-12-fuzzing", + "configurePreset": "clang-12-fuzzing" + }, + { + "name": "build-clang-13-fuzzing", + "configurePreset": "clang-13-fuzzing" + }, + { + "name": "build-clang-14-fuzzing", + "configurePreset": "clang-14-fuzzing" + }, + { + "name": "build-clang-15-fuzzing", + "configurePreset": "clang-15-fuzzing" } ], "testPresets": [ @@ -612,6 +680,34 @@ "inherits": "test-common", "configuration": "Release", "configurePreset": "win32-gcc-x64-mingw-release" + }, + { + "name": "test-clang-12-fuzzing", + "displayName": "Strict", + "description": "Enable output and stop on failure", + "inherits": "test-common", + "configurePreset": "clang-12-fuzzing" + }, + { + "name": "test-clang-13-fuzzing", + "displayName": "Strict", + "description": "Enable output and stop on failure", + "inherits": "test-common", + "configurePreset": "clang-13-fuzzing" + }, + { + "name": "test-clang-14-fuzzing", + "displayName": "Strict", + "description": "Enable output and stop on failure", + "inherits": "test-common", + "configurePreset": "clang-14-fuzzing" + }, + { + "name": "test-clang-15-fuzzing", + "displayName": "Strict", + "description": "Enable output and stop on failure", + "inherits": "test-common", + "configurePreset": "clang-15-fuzzing" } ] } diff --git a/fuzz_test/CMakeLists.txt b/fuzz_test/CMakeLists.txt index 9bef7e1..9a1fc5a 100644 --- a/fuzz_test/CMakeLists.txt +++ b/fuzz_test/CMakeLists.txt @@ -13,7 +13,7 @@ TARGET_COMPILE_OPTIONS(fuzz_tester PRIVATE -fsanitize=fuzzer,undefined,address) # Allow short runs during automated testing to see if something new breaks SET(FUZZ_RUNTIME - 10 - CACHE STRING "Number of seconds to run fuzz tests during ctest run") # Default of 10 seconds + 10 + CACHE STRING "Number of seconds to run fuzz tests during ctest run") # Default of 10 seconds ADD_TEST(NAME fuzz_tester_run COMMAND fuzz_tester -max_total_time=${FUZZ_RUNTIME}) diff --git a/fuzz_test/fuzz_tester.cpp b/fuzz_test/fuzz_tester.cpp index 7ffb452..4908136 100644 --- a/fuzz_test/fuzz_tester.cpp +++ b/fuzz_test/fuzz_tester.cpp @@ -1,20 +1,20 @@ -#include -#include -#include +#include +#include -[[nodiscard]] auto sum_values(const uint8_t *Data, size_t Size) -{ - constexpr auto scale = 1000; - - int value = 0; - for (std::size_t offset = 0; offset < Size; ++offset) { value += static_cast(*std::next(Data, static_cast(offset))) * scale; } - return value; +/* + * example comes from here: https://github.com/google/fuzzing/blob/master/tutorial/libFuzzer/fuzz_me.cc + * Documentation can be found here: https://llvm.org/docs/LibFuzzer.html + */ +bool FuzzMe(const uint8_t *Data, size_t DataSize) { + return DataSize >= 3 && + Data[0] == 'F' && + Data[1] == 'U' && + Data[2] == 'Z' && + // the following is on purpose to demonstrate an error + Data[3] == 'Z'; // :‑< } -// Fuzzer that attempts to invoke undefined behavior for signed integer overflow -// cppcheck-suppress unusedFunction symbolName=LLVMFuzzerTestOneInput -extern "C" int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) -{ - fmt::print("Value sum: {}, len{}\n", sum_values(Data, Size), Size); +extern "C" int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) { + FuzzMe(Data, Size); return 0; }