From 1a7885a4adca5cf82b9fec44de80e7f47c26856e Mon Sep 17 00:00:00 2001 From: Nathaniel Brough Date: Mon, 8 Jan 2024 12:31:07 -0800 Subject: [PATCH 1/2] Add simple fuzz-harness --- CMakeLists.txt | 6 ++++++ fuzz/CMakeLists.txt | 16 ++++++++++++++ fuzz/fuzz_layout.cpp | 50 ++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 72 insertions(+) create mode 100644 fuzz/CMakeLists.txt create mode 100644 fuzz/fuzz_layout.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index f4ce73cc..55f1a6df 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -12,6 +12,12 @@ include(${CMAKE_CURRENT_SOURCE_DIR}/cmake/project-defaults.cmake) add_subdirectory(yoga) add_subdirectory(tests) +option(BUILD_FUZZ_TESTS "Build fuzz tests" OFF) + +if ('${CMAKE_CXX_COMPILER_ID}' MATCHES 'Clang' AND BUILD_FUZZ_TESTS) + add_subdirectory(fuzz) +endif() + # cmake install config include(GNUInstallDirs) include(CMakePackageConfigHelpers) diff --git a/fuzz/CMakeLists.txt b/fuzz/CMakeLists.txt new file mode 100644 index 00000000..8b06cb3f --- /dev/null +++ b/fuzz/CMakeLists.txt @@ -0,0 +1,16 @@ +# If google/oss-fuzz has set the fuzzing engine +if(DEFINED ENV{LIB_FUZZING_ENGINE}) + set(FUZZING_ENGINE $ENV{LIB_FUZZING_ENGINE}) + set(FUZZING_COMPILE_FLAGS "") + set(FUZZING_LINK_FLAGS "${FUZZING_ENGINE}") +else() + set(FUZZING_COMPILE_FLAGS "-fsanitize=fuzzer") + set(FUZZING_LINK_FLAGS "-fsanitize=fuzzer") +endif() + +add_executable(fuzz_layout fuzz_layout.cpp) +set_target_properties(fuzz_layout PROPERTIES + COMPILE_FLAGS "${FUZZING_COMPILE_FLAGS}" + LINK_FLAGS "${FUZZING_LINK_FLAGS}" +) +target_link_libraries(fuzz_layout yogacore) diff --git a/fuzz/fuzz_layout.cpp b/fuzz/fuzz_layout.cpp new file mode 100644 index 00000000..0ca3d2a9 --- /dev/null +++ b/fuzz/fuzz_layout.cpp @@ -0,0 +1,50 @@ +#include +#include +#include + +YGFlexDirection fuzzed_flex_direction(FuzzedDataProvider& fdp) { + return fdp.PickValueInArray({ + YGFlexDirectionColumn, + YGFlexDirectionColumnReverse, + YGFlexDirectionRow, + YGFlexDirectionRowReverse, + }); +} + +void FillFuzzedTree( + FuzzedDataProvider& fdp, + const YGConfigRef& config, + const YGNodeRef& root, + size_t depth = 0) { + constexpr size_t kMaxDepth = 20; + constexpr size_t kMaxChildren = 20; + + if (depth > kMaxDepth) { + return; + } + + size_t children = fdp.ConsumeIntegralInRange(0, kMaxChildren); + for (size_t i = 0; i < children; i++) { + const YGNodeRef child = YGNodeNewWithConfig(config); + YGNodeStyleSetFlexDirection(root, fuzzed_flex_direction(fdp)); + YGNodeStyleSetWidth(child, fdp.ConsumeFloatingPoint()); + YGNodeStyleSetGap( + child, YGGutterAll, fdp.ConsumeProbability() * 100); + YGNodeStyleSetHeight(child, fdp.ConsumeFloatingPoint()); + YGNodeInsertChild(root, child, i); + FillFuzzedTree(fdp, config, child, depth + 1); + } +} + +extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) { + FuzzedDataProvider fdp(data, size); + const YGConfigRef config = YGConfigNew(); + const YGNodeRef root = YGNodeNewWithConfig(config); + FillFuzzedTree(fdp, config, root); + + YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionLTR); + + YGNodeFreeRecursive(root); + YGConfigFree(config); + return 0; +} -- 2.50.1.windows.1 From 6a72a7a20b05cf646ae43d63994c9f6dbb5c123c Mon Sep 17 00:00:00 2001 From: Nathaniel Brough Date: Wed, 10 Jan 2024 12:55:10 -0800 Subject: [PATCH 2/2] Add fuzz build to CI --- .github/workflows/validate-cpp.yml | 20 ++++++++++++++++++++ build_fuzz_tests | 28 ++++++++++++++++++++++++++++ 2 files changed, 48 insertions(+) create mode 100755 build_fuzz_tests diff --git a/.github/workflows/validate-cpp.yml b/.github/workflows/validate-cpp.yml index c8a0f0e8..d50c697b 100644 --- a/.github/workflows/validate-cpp.yml +++ b/.github/workflows/validate-cpp.yml @@ -31,6 +31,26 @@ jobs: - name: Unit tests run: ./unit_tests ${{ matrix.mode }} + + build_fuzzers: + name: Build fuzzers [${{ matrix.toolchain }}][${{ matrix.mode }}] + runs-on: ubuntu-latest + strategy: + matrix: + mode: [Debug, Release] + toolchain: [Clang] + + steps: + - uses: actions/checkout@v3 + + - name: Setup + uses: ./.github/actions/setup-cpp + with: + toolchain: ${{ matrix.toolchain }} + + - name: Unit tests + run: ./build_fuzz_tests ${{ matrix.mode }} + benchmark: name: Benchmark [${{ matrix.toolchain }}] runs-on: ${{ (matrix.toolchain == 'MSVC') && 'windows-latest' || 'ubuntu-latest' }} diff --git a/build_fuzz_tests b/build_fuzz_tests new file mode 100755 index 00000000..eeb86d2b --- /dev/null +++ b/build_fuzz_tests @@ -0,0 +1,28 @@ +#!/usr/bin/env sh +# Copyright (c) Meta Platforms, Inc. and affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. + +if [ "$#" -eq 0 ]; then + build_type="Debug" +else + build_type="$1" +fi + +export CC=clang +export CXX=clang++ + +# Make sure libc++ isn't used, as libfuzzer is linked against stdlibc++ which causes conflicts +unset CXXFLAGS +export LDFLAGS=-lstdc++ + +if which ninja; then + set -e + cmake -B build -S . -D BUILD_FUZZ_TESTS=ON -D CMAKE_BUILD_TYPE="$build_type" -G Ninja +else + set -e + cmake -B build -S . -D BUILD_FUZZ_TESTS=ON -D CMAKE_BUILD_TYPE="$build_type" +fi + +cmake --build build --target fuzz_layout -- 2.50.1.windows.1