From f5543d4bbb955eca2633fdd8d8a0037c60c83d0e Mon Sep 17 00:00:00 2001 From: Simon Resch Date: Mon, 25 Aug 2025 16:39:07 +0200 Subject: [PATCH 1/2] feat: add fuzz test for compile_pattern_to_regex function --- .gitignore | 5 ++ CMakeLists.txt | 7 +- cifuzz-spark/CMakeLists.txt | 6 ++ .../fuzz_compile_pattern_to_regex.cpp | 25 +++++++ cifuzz.yaml | 74 +++++++++++++++++++ 5 files changed, 116 insertions(+), 1 deletion(-) create mode 100644 cifuzz-spark/CMakeLists.txt create mode 100644 cifuzz-spark/fuzz_compile_pattern_to_regex.cpp create mode 100644 cifuzz.yaml diff --git a/.gitignore b/.gitignore index 4feb172..1cc4411 100644 --- a/.gitignore +++ b/.gitignore @@ -272,3 +272,8 @@ analysis-cppcheck-build-dir ideas desktop.iniimages/ + +.cifuzz*/ +.sarif/ +build-vscode/ +lcov.info diff --git a/CMakeLists.txt b/CMakeLists.txt index 9caecce..8e26726 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -5,9 +5,12 @@ cmake_minimum_required(VERSION 3.14 FATAL_ERROR) project( Glob VERSION 1.0 - LANGUAGES CXX + LANGUAGES C CXX ) +find_package(cifuzz NO_SYSTEM_ENVIRONMENT_PATH) +enable_fuzz_testing() + # ---- Options ---- option(GLOB_USE_GHC_FILESYSTEM "Use ghc::filesystem instead of std::filesystem" OFF) option(GLOB_TESTS "Run glob gtests" ON) @@ -109,3 +112,5 @@ if (GLOB_TESTS) target_include_directories(glob_tests_single PRIVATE single_include) add_test(NAME glob_tests_single COMMAND glob_tests_single) endif () + +add_subdirectory(cifuzz-spark) diff --git a/cifuzz-spark/CMakeLists.txt b/cifuzz-spark/CMakeLists.txt new file mode 100644 index 0000000..c8e948f --- /dev/null +++ b/cifuzz-spark/CMakeLists.txt @@ -0,0 +1,6 @@ +#cifuzz:build-template:begin +#add_fuzz_test({{ .FuzzTestName }} {{ .FileName }}) +#target_link_libraries({{ .FuzzTestName }} PRIVATE "$") +#cifuzz:build-template:end +add_fuzz_test(fuzz_compile_pattern_to_regex fuzz_compile_pattern_to_regex.cpp) +target_link_libraries(fuzz_compile_pattern_to_regex PRIVATE "$") diff --git a/cifuzz-spark/fuzz_compile_pattern_to_regex.cpp b/cifuzz-spark/fuzz_compile_pattern_to_regex.cpp new file mode 100644 index 0000000..0cfbee9 --- /dev/null +++ b/cifuzz-spark/fuzz_compile_pattern_to_regex.cpp @@ -0,0 +1,25 @@ +#include +#include // For FUZZ_TEST and FuzzedDataProvider +#include // For std::regex and std::regex_match +#include // For std::string_view + +#include "glob/glob.h" // For glob::compile_pattern_to_regex + +FUZZ_TEST(const uint8_t *data, size_t size) { + if (size < 1) { + return; + } + + FuzzedDataProvider fdp(data, size); + std::string glob_pattern = fdp.ConsumeRandomLengthString(50); + try { + std::regex compiled_regex = glob::compile_pattern_to_regex(glob_pattern); + // Generate fuzzed file path to match against. + std::string path = fdp.ConsumeRandomLengthString(50); + std::regex_match(path, compiled_regex); + } catch (const std::regex_error &) { + // Ignore regex errors - these are expected for invalid glob patterns. + } catch (const std::length_error &) { + // Ignore length errors - these are expected for invalid glob patterns. + } +} diff --git a/cifuzz.yaml b/cifuzz.yaml new file mode 100644 index 0000000..9673988 --- /dev/null +++ b/cifuzz.yaml @@ -0,0 +1,74 @@ +## Configuration for a CI Fuzz project +## Generated on 2025-08-25 + +## The build system used to build this project. If not set, cifuzz tries to +## detect the build system automatically. +## Valid values: "bazel", "cmake", "other" +build-system: cmake +## Engine used for fuzzing, default is "libfuzzer-clang". +## Valid values: "libfuzzer-clang", "honggfuzz-clang", "honggfuzz-gcc" +engine: libfuzzer-clang +## Sanitizers to use when building fuzz tests. If not set, ASan and UBSan +## are used by default. +#sanitizers: +# - address +# - undefined + +## If the build system type is "other", this command is used to build the fuzz +## tests. +#build-command: make my_fuzz_test + +## If the build system type is "other", this command is used to list the names +## of already existing fuzz tests in your project. This allows running all fuzz +## tests in the project without listing them explicitly, supports fuzz test +## generation and enables fuzz test completion for commands. +## The listed names should be separated by whitespace and can't include +## whitespaces themselves, i.e. 'fuzz_test1 fuzz_test_2 ...' +#list-fuzz-tests-command: echo my_fuzz_test + +## Command-line arguments to pass directly to the build system to use when +## building fuzz tests. +#build-system-args: +# - -DBUILD_TESTS=ON + +## Directories containing sample inputs used as seeds for running fuzz tests. +## For general information on seed corpora, see: +## https://docs.code-intelligence.com/glossary#seed-corpus +#seed-corpus-dirs: +# - path/to/seed-corpus + +## Directories containing inputs for calculating coverage. These are used in +## addition to inputs found in the directory of the fuzz test. +#corpus-dirs: +# - path/to/corpus + +## File containing input language keywords or other interesting byte sequences +## used for running fuzz tests. +## For libFuzzer see: https://llvm.org/docs/LibFuzzer.html#dictionaries +#dict: path/to/dictionary.dct + +## Command-line arguments to pass to libFuzzer when running fuzz tests. +## See https://llvm.org/docs/LibFuzzer.html#options for possible options. +#libfuzzer-args: +# - -rss_limit_mb=4096 + +## Command-line arguments to pass to Honggfuzz when running fuzz tests. +## See https://github.com/google/honggfuzz/blob/master/docs/USAGE.md for possible options. +#honggfuzz-args: +# - --rlimit_rss=4096 + +## Maximum time to run all fuzz tests. Default is 10 minutes. The time will be +## split up evenly between multiple fuzz tests. To keep running indefinitely, +## set value to 0. +#max-fuzzing-duration: 30m + +## 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 style for command output. +## Valid values: "pretty", "plain" +#style: plain +build-file: cifuzz-spark/CMakeLists.txt From b6e7e5518ea34422445ecb8eabf22bd738c22f4b Mon Sep 17 00:00:00 2001 From: Simon Resch Date: Mon, 25 Aug 2025 17:37:16 +0200 Subject: [PATCH 2/2] fix buffer overflow in glob pattern parsing --- source/glob.cpp | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/source/glob.cpp b/source/glob.cpp index c7ac2cc..62c43b0 100644 --- a/source/glob.cpp +++ b/source/glob.cpp @@ -91,14 +91,16 @@ std::string translate(std::string_view pattern) { k = i + 1; } - while (true) { - k = pattern.find("-", k, j); - if (k == std::string_view::npos) { + while (k < j) { + auto pos = pattern.substr(k, j - k).find('-'); + if (pos == std::string_view::npos) { break; + } else { + k += pos; } chunks.push_back(std::string(pattern.begin() + i, pattern.begin() + k)); i = k + 1; - k = k + 3; + k += 3; } chunks.push_back(std::string(pattern.begin() + i, pattern.begin() + j));