/src/CMake/Tests/Fuzzing/cmFortranParserFuzzer.cxx
Line | Count | Source |
1 | | /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying |
2 | | file LICENSE.rst or https://cmake.org/licensing for details. */ |
3 | | |
4 | | /* |
5 | | * Fuzzer for CMake's Fortran dependency scanner |
6 | | * |
7 | | * CMake runs a flex lexer and a bison parser over Fortran sources to discover |
8 | | * module dependencies: MODULE, SUBMODULE, USE and INCLUDE statements, plus the |
9 | | * preprocessor directives that guard them. This fuzzer drives that scanner. |
10 | | */ |
11 | | |
12 | | #include <cstddef> |
13 | | #include <cstdint> |
14 | | #include <cstdio> |
15 | | #include <set> |
16 | | #include <string> |
17 | | #include <vector> |
18 | | |
19 | | #include <unistd.h> |
20 | | |
21 | | #include "cmFortranParser.h" |
22 | | #include "cmSystemTools.h" |
23 | | |
24 | | static constexpr size_t kMaxInputSize = 256 * 1024; |
25 | | static std::string g_testDir; |
26 | | |
27 | | extern "C" int LLVMFuzzerInitialize(int* argc, char*** argv) |
28 | 10 | { |
29 | 10 | (void)argc; |
30 | 10 | (void)argv; |
31 | | |
32 | 10 | char tmpl[] = "/tmp/cmake_fuzz_fortran_XXXXXX"; |
33 | 10 | char* dir = mkdtemp(tmpl); |
34 | 10 | if (dir) { |
35 | 10 | g_testDir = dir; |
36 | 10 | } else { |
37 | 0 | g_testDir = "/tmp/cmake_fuzz_fortran"; |
38 | 0 | cmSystemTools::MakeDirectory(g_testDir); |
39 | 0 | } |
40 | | |
41 | 10 | return 0; |
42 | 10 | } |
43 | | |
44 | | extern "C" int LLVMFuzzerTestOneInput(uint8_t const* data, size_t size) |
45 | 3.62k | { |
46 | 3.62k | if (size == 0 || size > kMaxInputSize) { |
47 | 6 | return 0; |
48 | 6 | } |
49 | | |
50 | 3.61k | std::string const source = g_testDir + "/test.f90"; |
51 | 3.61k | { |
52 | 3.61k | FILE* fp = fopen(source.c_str(), "wb"); |
53 | 3.61k | if (!fp) { |
54 | 0 | return 0; |
55 | 0 | } |
56 | 3.61k | fwrite(data, 1, size, fp); |
57 | 3.61k | fclose(fp); |
58 | 3.61k | } |
59 | | |
60 | 0 | cmFortranCompiler compiler; |
61 | 3.61k | compiler.Id = "GNU"; |
62 | 3.61k | compiler.SModSep = "@"; |
63 | 3.61k | compiler.SModExt = ".smod"; |
64 | | |
65 | 3.61k | cmFortranSourceInfo info; |
66 | 3.61k | info.Source = source; |
67 | | |
68 | 3.61k | std::vector<std::string> const includes; |
69 | 3.61k | std::set<std::string> const defines; |
70 | | |
71 | 3.61k | cmFortranParser parser(compiler, includes, defines, info); |
72 | 3.61k | if (cmFortranParser_FilePush(&parser, source.c_str())) { |
73 | 3.61k | cmFortran_yyparse(parser.Scanner); |
74 | 3.61k | } |
75 | | |
76 | 3.61k | unlink(source.c_str()); |
77 | | |
78 | 3.61k | return 0; |
79 | 3.61k | } |