/src/CMake/Tests/Fuzzing/cmGeneratorExpressionEvalFuzzer.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 generator expression evaluation. |
6 | | * |
7 | | * cmGeneratorExpressionFuzzer only tokenizes and preprocesses $<...>, and |
8 | | * cmScriptFuzzer runs in script mode where no generator exists, so the |
9 | | * evaluator (cmGeneratorExpressionNode.cxx, the DAG checker, and the |
10 | | * transitive-property / link-interface code in cmGeneratorTarget) is never |
11 | | * reached by any fuzzer. |
12 | | * |
13 | | * Each input gets a fresh project-mode fixture: a base cmGlobalGenerator, a |
14 | | * makefile populated from a fixed listfile (interface, imported, alias, |
15 | | * object, static, executable and custom targets with genex-bearing usage |
16 | | * requirements), and generator targets created the same way as |
17 | | * "cmake --find-package" does. C and CXX are marked enabled with |
18 | | * GNU-like compiler variables so that language- and compiler-dependent |
19 | | * expressions have something to evaluate against. No compiler is run. |
20 | | * |
21 | | * Input layout: |
22 | | * byte 0: bits 0-1 mode, bits 2-4 head target, bits 5-6 config, |
23 | | * bit 7 EvaluateForBuildsystem |
24 | | * byte 1: bits 0-2 language, bits 3-4 property, bits 5-7 current target |
25 | | * rest: generator expression (or property value in Injection mode) |
26 | | * |
27 | | * Modes (see Mode below): |
28 | | * Evaluate cmGeneratorExpression::Evaluate |
29 | | * Compiled Parse once, evaluate for two configs, query collected |
30 | | * metadata Interpreter cmGeneratorExpressionInterpreter with a |
31 | | * transitive-property DAG Injection Store the input in a usage-requirement |
32 | | * property of a fixture target, then read it back through a consumer so it is |
33 | | * evaluated transitively |
34 | | */ |
35 | | |
36 | | #include <cstddef> |
37 | | #include <cstdint> |
38 | | #include <cstdio> |
39 | | #include <cstdlib> |
40 | | #include <map> |
41 | | #include <memory> |
42 | | #include <string> |
43 | | #include <utility> |
44 | | |
45 | | #include <cm/memory> |
46 | | |
47 | | #include "cmGenExContext.h" |
48 | | #include "cmGeneratorExpression.h" |
49 | | #include "cmGlobalGenerator.h" |
50 | | #include "cmLocalGenerator.h" |
51 | | #include "cmMakefile.h" |
52 | | #include "cmMessageMetadata.h" |
53 | | #include "cmState.h" |
54 | | #include "cmStateDirectory.h" |
55 | | #include "cmStateSnapshot.h" |
56 | | #include "cmSystemTools.h" |
57 | | #include "cmTarget.h" |
58 | | #include "cmake.h" |
59 | | |
60 | | static constexpr size_t kHeaderSize = 2; |
61 | | // Evaluation is recursive in nesting depth; keep inputs short. |
62 | | static constexpr size_t kMaxExprSize = 4 * 1024; |
63 | | |
64 | | static std::string g_srcDir; |
65 | | static std::string g_binDir; |
66 | | |
67 | | namespace { |
68 | | |
69 | | // Stand-in for the variables project() would load after compiler detection. |
70 | | char const kToolchain[] = R"cmake( |
71 | | cmake_minimum_required(VERSION 4.0) |
72 | | set(CMAKE_SYSTEM_NAME Linux) |
73 | | set(CMAKE_SYSTEM_PROCESSOR x86_64) |
74 | | set(CMAKE_BUILD_TYPE Debug) |
75 | | set_property(GLOBAL PROPERTY TARGET_SUPPORTS_SHARED_LIBS TRUE) |
76 | | set(CMAKE_STATIC_LIBRARY_PREFIX lib) |
77 | | set(CMAKE_STATIC_LIBRARY_SUFFIX .a) |
78 | | set(CMAKE_SHARED_LIBRARY_PREFIX lib) |
79 | | set(CMAKE_SHARED_LIBRARY_SUFFIX .so) |
80 | | set(CMAKE_SHARED_MODULE_PREFIX lib) |
81 | | set(CMAKE_SHARED_MODULE_SUFFIX .so) |
82 | | set(CMAKE_EXECUTABLE_SUFFIX "") |
83 | | foreach(lang IN ITEMS C CXX) |
84 | | set(CMAKE_${lang}_COMPILER_ID GNU) |
85 | | set(CMAKE_${lang}_COMPILER_VERSION 13.2.0) |
86 | | set(CMAKE_${lang}_COMPILER_FRONTEND_VARIANT GNU) |
87 | | set(CMAKE_${lang}_COMPILER_LINKER_ID GNU) |
88 | | set(CMAKE_${lang}_COMPILER_LINKER_FRONTEND_VARIANT GNU) |
89 | | set(CMAKE_${lang}_OUTPUT_EXTENSION .o) |
90 | | set(CMAKE_${lang}_STANDARD_DEFAULT 17) |
91 | | endforeach() |
92 | | set(CMAKE_C_COMPILER /usr/bin/cc) |
93 | | set(CMAKE_C_SOURCE_FILE_EXTENSIONS c m) |
94 | | set(CMAKE_C_IGNORE_EXTENSIONS h H o O obj OBJ def DEF rc RC) |
95 | | set(CMAKE_C_LINKER_PREFERENCE 10) |
96 | | set(CMAKE_C_COMPILE_FEATURES |
97 | | c_std_90 c_std_99 c_std_11 c_std_17 c_std_23 |
98 | | c_function_prototypes c_restrict c_static_assert c_variadic_macros) |
99 | | set(CMAKE_CXX_COMPILER /usr/bin/c++) |
100 | | set(CMAKE_CXX_SOURCE_FILE_EXTENSIONS |
101 | | C M c++ cc cpp cxx mm mpp CPP ixx cppm ccm cxxm c++m) |
102 | | set(CMAKE_CXX_IGNORE_EXTENSIONS inl h hpp HPP H o O obj OBJ def DEF rc RC) |
103 | | set(CMAKE_CXX_LINKER_PREFERENCE 30) |
104 | | set(CMAKE_CXX_LINKER_PREFERENCE_PROPAGATES 1) |
105 | | set(CMAKE_CXX_COMPILE_FEATURES |
106 | | cxx_std_98 cxx_std_11 cxx_std_14 cxx_std_17 cxx_std_20 cxx_std_23 |
107 | | cxx_auto_type cxx_constexpr cxx_lambdas cxx_nullptr cxx_variadic_templates) |
108 | | )cmake"; |
109 | | |
110 | | char const kProject[] = R"cmake( |
111 | | cmake_minimum_required(VERSION 4.0) |
112 | | |
113 | | add_library(fuzz_iface INTERFACE) |
114 | | target_compile_definitions(fuzz_iface INTERFACE |
115 | | IFACE_DEF=1 |
116 | | $<$<CONFIG:Debug>:IFACE_DEBUG> |
117 | | $<$<COMPILE_LANGUAGE:CXX>:IFACE_CXX>) |
118 | | target_include_directories(fuzz_iface INTERFACE |
119 | | $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include> |
120 | | $<INSTALL_INTERFACE:include>) |
121 | | target_compile_options(fuzz_iface INTERFACE |
122 | | $<$<COMPILE_LANG_AND_ID:CXX,GNU,Clang>:-Wall>) |
123 | | target_link_options(fuzz_iface INTERFACE |
124 | | $<$<LINK_LANGUAGE:CXX>:-Wl,--as-needed>) |
125 | | target_sources(fuzz_iface INTERFACE |
126 | | FILE_SET HEADERS BASE_DIRS ${CMAKE_CURRENT_SOURCE_DIR} |
127 | | FILES ${CMAKE_CURRENT_SOURCE_DIR}/fuzz.h) |
128 | | set_target_properties(fuzz_iface PROPERTIES |
129 | | INTERFACE_FUZZ_BOOL ON |
130 | | INTERFACE_FUZZ_STRING fuzz |
131 | | INTERFACE_FUZZ_NUMBER 3 |
132 | | INTERFACE_FUZZ_CUSTOM "custom;$<CONFIG>" |
133 | | COMPATIBLE_INTERFACE_BOOL FUZZ_BOOL |
134 | | COMPATIBLE_INTERFACE_STRING FUZZ_STRING |
135 | | COMPATIBLE_INTERFACE_NUMBER_MAX FUZZ_NUMBER |
136 | | TRANSITIVE_COMPILE_PROPERTIES FUZZ_CUSTOM) |
137 | | |
138 | | add_library(fuzz_dep INTERFACE) |
139 | | target_link_libraries(fuzz_dep INTERFACE |
140 | | fuzz_iface |
141 | | $<LINK_ONLY:fuzz_imported_static> |
142 | | $<$<CONFIG:Release>:Fuzz::shared>) |
143 | | |
144 | | add_library(fuzz_imported_static STATIC IMPORTED) |
145 | | set_target_properties(fuzz_imported_static PROPERTIES |
146 | | IMPORTED_CONFIGURATIONS "DEBUG;RELEASE" |
147 | | IMPORTED_LOCATION_DEBUG /opt/fuzz/lib/libfuzz_d.a |
148 | | IMPORTED_LOCATION_RELEASE /opt/fuzz/lib/libfuzz.a |
149 | | MAP_IMPORTED_CONFIG_RELWITHDEBINFO Release |
150 | | IMPORTED_LINK_INTERFACE_LANGUAGES C |
151 | | INTERFACE_COMPILE_DEFINITIONS IMPORTED_STATIC) |
152 | | |
153 | | add_library(fuzz_imported_shared SHARED IMPORTED GLOBAL) |
154 | | set_target_properties(fuzz_imported_shared PROPERTIES |
155 | | IMPORTED_LOCATION /opt/fuzz/lib/libfuzz_shared.so.1.2.3 |
156 | | IMPORTED_SONAME libfuzz_shared.so.1 |
157 | | INTERFACE_INCLUDE_DIRECTORIES /opt/fuzz/include |
158 | | INTERFACE_LINK_LIBRARIES fuzz_imported_static) |
159 | | add_library(Fuzz::shared ALIAS fuzz_imported_shared) |
160 | | |
161 | | add_executable(fuzz_imported_exe IMPORTED) |
162 | | set_property(TARGET fuzz_imported_exe PROPERTY |
163 | | IMPORTED_LOCATION /opt/fuzz/bin/fuzz_tool) |
164 | | |
165 | | add_library(fuzz_obj OBJECT fuzz.c fuzz.cpp) |
166 | | target_compile_definitions(fuzz_obj PRIVATE OBJ_DEF) |
167 | | |
168 | | add_library(fuzz_static STATIC fuzz.c) |
169 | | target_link_libraries(fuzz_static |
170 | | PUBLIC fuzz_dep |
171 | | PRIVATE fuzz_obj Fuzz::shared) |
172 | | set_target_properties(fuzz_static PROPERTIES |
173 | | OUTPUT_NAME fuzzy |
174 | | OUTPUT_NAME_DEBUG fuzzy_d |
175 | | POSITION_INDEPENDENT_CODE ON |
176 | | COMPILE_DEFINITIONS "STATIC_OWN=$<CONFIG>") |
177 | | add_library(Fuzz::static ALIAS fuzz_static) |
178 | | |
179 | | add_executable(fuzz_exe fuzz.cpp) |
180 | | target_link_libraries(fuzz_exe PRIVATE Fuzz::static) |
181 | | set_property(TARGET fuzz_exe PROPERTY FUZZ_STRING fuzz) |
182 | | |
183 | | add_custom_target(fuzz_custom |
184 | | COMMAND fuzz_imported_exe $<TARGET_FILE:fuzz_exe>) |
185 | | |
186 | | set_source_files_properties(fuzz.c PROPERTIES |
187 | | COMPILE_DEFINITIONS "SRC_DEF=$<CONFIG>" |
188 | | FUZZ_SRC_PROP value) |
189 | | set_property(GLOBAL PROPERTY FUZZ_GLOBAL "global;value") |
190 | | set_property(DIRECTORY PROPERTY FUZZ_DIR_PROP dir) |
191 | | )cmake"; |
192 | | |
193 | | char const* const kConfigs[] = { "", "Debug", "Release", "RelWithDebInfo" }; |
194 | | |
195 | | char const* const kLanguages[] = { "", "C", "CXX", "CUDA", |
196 | | "Fortran", "HIP", "OBJC", "Swift" }; |
197 | | |
198 | | // Index 0 means "no target". |
199 | | char const* const kTargets[] = { |
200 | | nullptr, "fuzz_exe", "fuzz_static", |
201 | | "fuzz_obj", "fuzz_iface", "fuzz_imported_static", |
202 | | "Fuzz::shared", "fuzz_custom", |
203 | | }; |
204 | | |
205 | | char const* const kFixtureTargets[] = { |
206 | | "fuzz_exe", "fuzz_static", "Fuzz::static", |
207 | | "fuzz_obj", "fuzz_iface", "fuzz_dep", |
208 | | "fuzz_imported_exe", "fuzz_imported_static", "fuzz_imported_shared", |
209 | | "Fuzz::shared", "fuzz_custom", |
210 | | }; |
211 | | |
212 | | // Properties that generators pass to cmGeneratorExpressionInterpreter. |
213 | | char const* const kInterpreterProperties[] = { |
214 | | "COMPILE_OPTIONS", |
215 | | "COMPILE_DEFINITIONS", |
216 | | "INCLUDE_DIRECTORIES", |
217 | | "COMPILE_FLAGS", |
218 | | }; |
219 | | |
220 | | struct Injection |
221 | | { |
222 | | char const* Target; |
223 | | char const* Property; |
224 | | // Evaluated with fuzz_exe as head so the injected value is reached |
225 | | // through the link closure. |
226 | | char const* Reader; |
227 | | }; |
228 | | |
229 | | Injection const kInjections[] = { |
230 | | { "fuzz_dep", "INTERFACE_COMPILE_DEFINITIONS", |
231 | | "$<TARGET_PROPERTY:COMPILE_DEFINITIONS>" }, |
232 | | { "fuzz_dep", "INTERFACE_INCLUDE_DIRECTORIES", |
233 | | "$<TARGET_PROPERTY:INCLUDE_DIRECTORIES>" }, |
234 | | { "fuzz_dep", "INTERFACE_LINK_LIBRARIES", |
235 | | "$<TARGET_PROPERTY:COMPILE_OPTIONS>" }, |
236 | | { "fuzz_exe", "LINK_LIBRARIES", "$<TARGET_PROPERTY:LINK_OPTIONS>" }, |
237 | | }; |
238 | | |
239 | | // Which evaluation entry point the input exercises (bits 0-1 of byte 0). |
240 | | enum class Mode |
241 | | { |
242 | | Evaluate, // cmGeneratorExpression::Evaluate (one-shot) |
243 | | Compiled, // Parse once, evaluate for two configs, query metadata |
244 | | Interpreter, // cmGeneratorExpressionInterpreter (generator property path) |
245 | | Injection, // Store in a usage requirement, evaluate transitively |
246 | | }; |
247 | | |
248 | | bool WriteFile(std::string const& path, char const* content) |
249 | 6 | { |
250 | 6 | FILE* fp = fopen(path.c_str(), "wb"); |
251 | 6 | if (!fp) { |
252 | 0 | return false; |
253 | 0 | } |
254 | 6 | bool const ok = fputs(content, fp) >= 0; |
255 | 6 | fclose(fp); |
256 | 6 | return ok; |
257 | 6 | } |
258 | | |
259 | | struct Fixture |
260 | | { |
261 | | cmake CMake{ cmState::Role::Project }; |
262 | | cmGlobalGenerator* GG = nullptr; |
263 | | cmMakefile* MF = nullptr; |
264 | | cmLocalGenerator* LG = nullptr; |
265 | | |
266 | | bool Build(Injection const* inject, std::string const& value) |
267 | 5.92k | { |
268 | 5.92k | this->CMake.SetHomeDirectory(g_srcDir); |
269 | 5.92k | this->CMake.SetHomeOutputDirectory(g_binDir); |
270 | 5.92k | this->CMake.SetGlobalGenerator( |
271 | 5.92k | cm::make_unique<cmGlobalGenerator>(&this->CMake)); |
272 | 5.92k | this->GG = this->CMake.GetGlobalGenerator(); |
273 | | |
274 | 5.92k | cmStateSnapshot snapshot = this->CMake.GetCurrentSnapshot(); |
275 | 5.92k | snapshot.GetDirectory().SetCurrentSource(g_srcDir); |
276 | 5.92k | snapshot.GetDirectory().SetCurrentBinary(g_binDir); |
277 | 5.92k | snapshot.SetDefaultDefinitions(); |
278 | | |
279 | 5.92k | auto mf = cm::make_unique<cmMakefile>(this->GG, snapshot); |
280 | 5.92k | this->MF = mf.get(); |
281 | 5.92k | this->GG->AddMakefile(std::move(mf)); |
282 | | |
283 | 5.92k | if (!this->MF->ReadListFileAsString(kToolchain, "fuzz_toolchain.cmake")) { |
284 | 0 | return false; |
285 | 0 | } |
286 | 5.92k | this->GG->SetLanguageEnabled("C", this->MF); |
287 | 5.92k | this->GG->SetLanguageEnabled("CXX", this->MF); |
288 | 5.92k | if (!this->MF->ReadListFileAsString(kProject, "CMakeLists.txt") || |
289 | 5.92k | cmSystemTools::GetFatalErrorOccurred()) { |
290 | 0 | return false; |
291 | 0 | } |
292 | | |
293 | 5.92k | if (inject) { |
294 | 4.05k | cmTarget* target = this->MF->FindLocalNonAliasTarget(inject->Target); |
295 | 4.05k | if (!target) { |
296 | 0 | return false; |
297 | 0 | } |
298 | 4.05k | target->SetProperty(inject->Property, value); |
299 | 4.05k | } |
300 | | |
301 | 5.92k | this->GG->CreateGenerationObjects(); |
302 | 5.92k | if (this->GG->GetLocalGenerators().empty()) { |
303 | 0 | return false; |
304 | 0 | } |
305 | 5.92k | this->LG = this->GG->GetLocalGenerators().front().get(); |
306 | 5.92k | return true; |
307 | 5.92k | } |
308 | | |
309 | | cmGeneratorTarget const* Find(char const* name) const |
310 | 10.7k | { |
311 | 10.7k | return name ? this->LG->FindGeneratorTargetToUse(name) : nullptr; |
312 | 10.7k | } |
313 | | }; |
314 | | |
315 | | } // namespace |
316 | | |
317 | | extern "C" int LLVMFuzzerInitialize(int* argc, char*** argv) |
318 | 2 | { |
319 | 2 | (void)argc; |
320 | 2 | (void)argv; |
321 | | |
322 | 2 | char tmpl[] = "/tmp/cmake_fuzz_genex_eval_XXXXXX"; |
323 | 2 | char* dir = mkdtemp(tmpl); |
324 | 2 | g_srcDir = dir ? dir : "/tmp/cmake_fuzz_genex_eval"; |
325 | 2 | g_binDir = g_srcDir + "/build"; |
326 | 2 | cmSystemTools::MakeDirectory(g_srcDir + "/include"); |
327 | 2 | cmSystemTools::MakeDirectory(g_binDir); |
328 | 2 | WriteFile(g_srcDir + "/fuzz.c", "int fuzz_c(void) { return 0; }\n"); |
329 | 2 | WriteFile(g_srcDir + "/fuzz.cpp", "int main() { return 0; }\n"); |
330 | 2 | WriteFile(g_srcDir + "/fuzz.h", "#pragma once\n"); |
331 | | |
332 | | // A broken fixture would make every input a no-op, so fail loudly here |
333 | | // while diagnostics are still printed. |
334 | 2 | { |
335 | 2 | Fixture fx; |
336 | 2 | bool ok = fx.Build(nullptr, std::string()) && |
337 | 2 | !cmSystemTools::GetFatalErrorOccurred(); |
338 | 22 | for (char const* name : kFixtureTargets) { |
339 | 22 | if (ok && !fx.Find(name)) { |
340 | 0 | fprintf(stderr, "fixture target missing: %s\n", name); |
341 | 0 | ok = false; |
342 | 0 | } |
343 | 22 | } |
344 | 2 | if (!ok) { |
345 | 0 | fprintf(stderr, "cmGeneratorExpressionEvalFuzzer: fixture failed\n"); |
346 | 0 | abort(); |
347 | 0 | } |
348 | 2 | } |
349 | 2 | cmSystemTools::ResetErrorOccurredFlag(); |
350 | | |
351 | 2 | cmSystemTools::SetMessageCallback( |
352 | 13.1k | [](std::string const&, cmMessageMetadata const&) {}); |
353 | 2 | cmSystemTools::SetStdoutCallback([](std::string const&) {}); |
354 | 2 | cmSystemTools::SetStderrCallback([](std::string const&) {}); |
355 | | |
356 | 2 | return 0; |
357 | 2 | } |
358 | | |
359 | | extern "C" int LLVMFuzzerTestOneInput(uint8_t const* data, size_t size) |
360 | 5.92k | { |
361 | 5.92k | if (size < kHeaderSize || size > kHeaderSize + kMaxExprSize) { |
362 | 1 | return 0; |
363 | 1 | } |
364 | | |
365 | 5.92k | uint8_t const sel0 = data[0]; |
366 | 5.92k | uint8_t const sel1 = data[1]; |
367 | 5.92k | Mode const mode = static_cast<Mode>(sel0 & 0x3u); |
368 | 5.92k | char const* const headName = kTargets[(sel0 >> 2) & 0x7u]; |
369 | 5.92k | std::string const config = kConfigs[(sel0 >> 5) & 0x3u]; |
370 | 5.92k | std::string const otherConfig = kConfigs[((sel0 >> 5) + 1) & 0x3u]; |
371 | 5.92k | bool const forBuildsystem = (sel0 & 0x80u) != 0; |
372 | 5.92k | std::string const language = kLanguages[sel1 & 0x7u]; |
373 | 5.92k | unsigned const propIndex = (sel1 >> 3) & 0x3u; |
374 | 5.92k | char const* const currentName = kTargets[(sel1 >> 5) & 0x7u]; |
375 | | |
376 | 5.92k | std::string expr(reinterpret_cast<char const*>(data + kHeaderSize), |
377 | 5.92k | size - kHeaderSize); |
378 | | |
379 | | // The fatal-error flag is global and would stop the next fixture's |
380 | | // listfile from running. |
381 | 5.92k | cmSystemTools::ResetErrorOccurredFlag(); |
382 | 5.92k | { |
383 | 5.92k | Fixture fx; |
384 | 5.92k | Injection const* inject = |
385 | 5.92k | mode == Mode::Injection ? &kInjections[propIndex] : nullptr; |
386 | 5.92k | if (fx.Build(inject, expr)) { |
387 | 5.92k | cmGeneratorTarget const* head = fx.Find(headName); |
388 | | |
389 | 5.92k | switch (mode) { |
390 | 939 | case Mode::Evaluate: { |
391 | 939 | (void)cmGeneratorExpression::Evaluate( |
392 | 939 | std::move(expr), fx.LG, config, head, nullptr, nullptr, language); |
393 | 939 | } break; |
394 | | |
395 | 552 | case Mode::Compiled: { |
396 | 552 | cmGeneratorExpression ge(fx.CMake); |
397 | 552 | std::unique_ptr<cmCompiledGeneratorExpression> cge = |
398 | 552 | ge.Parse(std::move(expr)); |
399 | 552 | cge->SetEvaluateForBuildsystem(forBuildsystem); |
400 | 552 | cmGeneratorTarget const* current = fx.Find(currentName); |
401 | | |
402 | 552 | cm::GenEx::Context ctx(fx.LG, config, language); |
403 | 552 | (void)cge->Evaluate(ctx, nullptr, head, current); |
404 | 552 | (void)cge->GetTargets(); |
405 | 552 | (void)cge->GetAllTargetsSeen(); |
406 | 552 | (void)cge->GetSeenTargetProperties(); |
407 | 552 | (void)cge->GetHadContextSensitiveCondition(); |
408 | 552 | (void)cge->GetHadHeadSensitiveCondition(); |
409 | 552 | (void)cge->GetHadLinkLanguageSensitiveCondition(); |
410 | 552 | (void)cge->GetSourceSensitiveTargets(); |
411 | 552 | if (head) { |
412 | 491 | std::map<std::string, std::string> standards; |
413 | 491 | cge->GetMaxLanguageStandard(head, standards); |
414 | 491 | } |
415 | | |
416 | 552 | cm::GenEx::Context otherCtx(fx.LG, otherConfig, language); |
417 | 552 | (void)cge->Evaluate(otherCtx, nullptr, head, current); |
418 | 552 | } break; |
419 | | |
420 | 375 | case Mode::Interpreter: { |
421 | 375 | if (!head) { |
422 | 158 | head = fx.Find("fuzz_exe"); |
423 | 158 | } |
424 | 375 | cmGeneratorExpressionInterpreter interpreter(fx.LG, config, head, |
425 | 375 | language); |
426 | 375 | (void)interpreter.Evaluate(std::move(expr), |
427 | 375 | kInterpreterProperties[propIndex]); |
428 | 375 | } break; |
429 | | |
430 | 4.05k | case Mode::Injection: { |
431 | 4.05k | Injection const& inj = kInjections[propIndex]; |
432 | 4.05k | (void)cmGeneratorExpression::Evaluate(inj.Reader, fx.LG, config, |
433 | 4.05k | fx.Find("fuzz_exe"), nullptr, |
434 | 4.05k | nullptr, language); |
435 | 4.05k | std::string direct = "$<TARGET_PROPERTY:"; |
436 | 4.05k | direct += inj.Target; |
437 | 4.05k | direct += ','; |
438 | 4.05k | direct += inj.Property; |
439 | 4.05k | direct += '>'; |
440 | 4.05k | (void)cmGeneratorExpression::Evaluate(std::move(direct), fx.LG, |
441 | 4.05k | config); |
442 | 4.05k | } break; |
443 | 5.92k | } |
444 | 5.92k | } |
445 | 5.92k | } |
446 | 5.92k | cmSystemTools::ResetErrorOccurredFlag(); |
447 | | |
448 | 5.92k | return 0; |
449 | 5.92k | } |