Tests/Fuzzing: Add cmGccDepfileFuzzer

Fuzz the CMake GCC-style dependency file parser.
Tests parsing of .d files from compiler output.
This commit is contained in:
Leslie P. Polzer
2026-01-20 14:06:35 -05:00
committed by Brad King
parent a894432922
commit 286cb834f8
3 changed files with 124 additions and 0 deletions
+3
View File
@@ -70,3 +70,6 @@ add_fuzzer(cmPkgConfigParserFuzzer cmPkgConfigParserFuzzer.cxx)
# JSON parser fuzzer
add_fuzzer(cmJSONParserFuzzer cmJSONParserFuzzer.cxx)
# GCC dependency file fuzzer
add_fuzzer(cmGccDepfileFuzzer cmGccDepfileFuzzer.cxx)
+45
View File
@@ -0,0 +1,45 @@
# GCC depfile dictionary
# Target separator
":"
# Dependency continuation
"\\"
# Whitespace
" "
"\x09"
"\x0a"
# Common file extensions
".o"
".obj"
".d"
".cpp"
".c"
".h"
".hpp"
".hxx"
# Escape sequences
"\\ "
"\\#"
"\\:"
# Special characters
"#"
"$"
# Common paths
"/usr/include/"
"/usr/local/include/"
"../include/"
"./src/"
# Common headers
"stdio.h"
"stdlib.h"
"string.h"
"iostream"
"vector"
"string"
+76
View File
@@ -0,0 +1,76 @@
/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
file LICENSE.rst or https://cmake.org/licensing for details. */
/*
* Fuzzer for CMake's GCC dependency file parser
*
* GCC generates .d files with make-style dependencies.
* This fuzzer tests parsing of these files.
*/
#include <cstddef>
#include <cstdint>
#include <cstdio>
#include <string>
#include <unistd.h>
#include "cmGccDepfileReader.h"
#include "cmSystemTools.h"
static constexpr size_t kMaxInputSize = 256 * 1024;
static std::string g_testDir;
extern "C" int LLVMFuzzerInitialize(int* argc, char*** argv)
{
(void)argc;
(void)argv;
char tmpl[] = "/tmp/cmake_fuzz_depfile_XXXXXX";
char* dir = mkdtemp(tmpl);
if (dir) {
g_testDir = dir;
} else {
g_testDir = "/tmp/cmake_fuzz_depfile";
cmSystemTools::MakeDirectory(g_testDir);
}
return 0;
}
extern "C" int LLVMFuzzerTestOneInput(uint8_t const* data, size_t size)
{
if (size == 0 || size > kMaxInputSize) {
return 0;
}
// Write input to temp file
std::string depFile = g_testDir + "/test.d";
{
FILE* fp = fopen(depFile.c_str(), "wb");
if (!fp)
return 0;
fwrite(data, 1, size, fp);
fclose(fp);
}
// Parse the depfile
auto result = cmReadGccDepfile(depFile.c_str());
// Examine results if parsing succeeded
if (result) {
for (auto const& entry : *result) {
for (auto const& rule : entry.rules) {
(void)rule;
}
for (auto const& path : entry.paths) {
(void)path;
}
}
}
// Clean up
unlink(depFile.c_str());
return 0;
}