/src/curl_fuzzer/proto_fuzzer/fuzzer_main.h
Line | Count | Source |
1 | | /* |
2 | | * Copyright (C) Max Dymond, <cmeister2@gmail.com>, et al. |
3 | | * |
4 | | * SPDX-License-Identifier: curl |
5 | | */ |
6 | | |
7 | | /// @file |
8 | | /// @brief Shared byte-to-protobuf dispatch for the policy-split fuzzers. |
9 | | |
10 | | #ifndef PROTO_FUZZER_FUZZER_MAIN_H_ |
11 | | #define PROTO_FUZZER_FUZZER_MAIN_H_ |
12 | | |
13 | | #include <cstddef> |
14 | | #include <cstdint> |
15 | | |
16 | | #include "proto_fuzzer/target_profile.h" |
17 | | |
18 | | namespace proto_fuzzer { |
19 | | |
20 | | /// Decode and run one serialized Scenario. Keeping this behind an ordinary |
21 | | /// function allows each binary to expose a discoverable, same-named libFuzzer |
22 | | /// entrypoint while retaining one mutation and execution implementation. The |
23 | | /// profile is explicit so target identity remains visible at the entrypoint |
24 | | /// instead of being hidden in per-translation-unit compiler definitions. |
25 | | /// @param profile Mutation and execution policy selected by the entrypoint. |
26 | | /// @param data Serialized binary Scenario bytes. |
27 | | /// @param size Number of bytes available at data. |
28 | | /// @return Always zero, as required by libFuzzer. |
29 | | int ProtoFuzzerTestOneInput(TargetProfile profile, const std::uint8_t* data, std::size_t size); |
30 | | |
31 | | /// Mutate a serialized Scenario while preserving the selected lane's policy. |
32 | | /// @param profile Mutation and execution policy selected by the entrypoint. |
33 | | /// @param data Mutable serialized Scenario storage. |
34 | | /// @param size Current serialized size. |
35 | | /// @param max_size Capacity of data. |
36 | | /// @param seed Mutation random seed supplied by libFuzzer. |
37 | | /// @return Serialized size after mutation. |
38 | | std::size_t ProtoFuzzerCustomMutator(TargetProfile profile, std::uint8_t* data, std::size_t size, std::size_t max_size, |
39 | | unsigned int seed); |
40 | | |
41 | | /// Cross two serialized Scenarios while preserving the selected lane's policy. |
42 | | /// @param profile Mutation and execution policy selected by the entrypoint. |
43 | | /// @param data1 First serialized parent. |
44 | | /// @param size1 Size of data1. |
45 | | /// @param data2 Second serialized parent. |
46 | | /// @param size2 Size of data2. |
47 | | /// @param out Destination storage. |
48 | | /// @param max_out_size Capacity of out. |
49 | | /// @param seed Crossover random seed supplied by libFuzzer. |
50 | | /// @return Serialized child size. |
51 | | std::size_t ProtoFuzzerCustomCrossOver(TargetProfile profile, const std::uint8_t* data1, std::size_t size1, |
52 | | const std::uint8_t* data2, std::size_t size2, std::uint8_t* out, |
53 | | std::size_t max_out_size, unsigned int seed); |
54 | | |
55 | | /// Binds a concrete profile once in each thin entrypoint source. This adapter |
56 | | /// keeps libFuzzer's C ABI boilerplate uniform without making target selection |
57 | | /// an invisible compile-time side effect in the shared implementation. |
58 | | /// @tparam Profile Fixed identity of the binary exposing these callbacks. |
59 | | template <TargetProfile Profile> |
60 | | struct ProtoFuzzerEntrypoint { |
61 | | /// Forward a corpus input with the profile fixed by this binary. Keeping the |
62 | | /// profile out of the C ABI prevents libFuzzer from choosing it while still |
63 | | /// making the binding explicit in the entrypoint source. |
64 | | /// @param data Serialized binary Scenario bytes. |
65 | | /// @param size Number of bytes available at data. |
66 | | /// @return Always zero, as required by libFuzzer. |
67 | 38.5k | static int TestOneInput(const std::uint8_t* data, std::size_t size) { |
68 | 38.5k | return ProtoFuzzerTestOneInput(Profile, data, size); |
69 | 38.5k | } proto_fuzzer::ProtoFuzzerEntrypoint<(proto_fuzzer::TargetProfile)6>::TestOneInput(unsigned char const*, unsigned long) Line | Count | Source | 67 | 2.57k | static int TestOneInput(const std::uint8_t* data, std::size_t size) { | 68 | 2.57k | return ProtoFuzzerTestOneInput(Profile, data, size); | 69 | 2.57k | } |
Unexecuted instantiation: proto_fuzzer::ProtoFuzzerEntrypoint<(proto_fuzzer::TargetProfile)7>::TestOneInput(unsigned char const*, unsigned long) Unexecuted instantiation: proto_fuzzer::ProtoFuzzerEntrypoint<(proto_fuzzer::TargetProfile)8>::TestOneInput(unsigned char const*, unsigned long) Unexecuted instantiation: proto_fuzzer::ProtoFuzzerEntrypoint<(proto_fuzzer::TargetProfile)4>::TestOneInput(unsigned char const*, unsigned long) proto_fuzzer::ProtoFuzzerEntrypoint<(proto_fuzzer::TargetProfile)2>::TestOneInput(unsigned char const*, unsigned long) Line | Count | Source | 67 | 4.94k | static int TestOneInput(const std::uint8_t* data, std::size_t size) { | 68 | 4.94k | return ProtoFuzzerTestOneInput(Profile, data, size); | 69 | 4.94k | } |
proto_fuzzer::ProtoFuzzerEntrypoint<(proto_fuzzer::TargetProfile)3>::TestOneInput(unsigned char const*, unsigned long) Line | Count | Source | 67 | 3.73k | static int TestOneInput(const std::uint8_t* data, std::size_t size) { | 68 | 3.73k | return ProtoFuzzerTestOneInput(Profile, data, size); | 69 | 3.73k | } |
proto_fuzzer::ProtoFuzzerEntrypoint<(proto_fuzzer::TargetProfile)10>::TestOneInput(unsigned char const*, unsigned long) Line | Count | Source | 67 | 3.70k | static int TestOneInput(const std::uint8_t* data, std::size_t size) { | 68 | 3.70k | return ProtoFuzzerTestOneInput(Profile, data, size); | 69 | 3.70k | } |
proto_fuzzer::ProtoFuzzerEntrypoint<(proto_fuzzer::TargetProfile)0>::TestOneInput(unsigned char const*, unsigned long) Line | Count | Source | 67 | 15.8k | static int TestOneInput(const std::uint8_t* data, std::size_t size) { | 68 | 15.8k | return ProtoFuzzerTestOneInput(Profile, data, size); | 69 | 15.8k | } |
proto_fuzzer::ProtoFuzzerEntrypoint<(proto_fuzzer::TargetProfile)1>::TestOneInput(unsigned char const*, unsigned long) Line | Count | Source | 67 | 4.51k | static int TestOneInput(const std::uint8_t* data, std::size_t size) { | 68 | 4.51k | return ProtoFuzzerTestOneInput(Profile, data, size); | 69 | 4.51k | } |
Unexecuted instantiation: proto_fuzzer::ProtoFuzzerEntrypoint<(proto_fuzzer::TargetProfile)9>::TestOneInput(unsigned char const*, unsigned long) proto_fuzzer::ProtoFuzzerEntrypoint<(proto_fuzzer::TargetProfile)5>::TestOneInput(unsigned char const*, unsigned long) Line | Count | Source | 67 | 3.20k | static int TestOneInput(const std::uint8_t* data, std::size_t size) { | 68 | 3.20k | return ProtoFuzzerTestOneInput(Profile, data, size); | 69 | 3.20k | } |
|
70 | | |
71 | | /// Forward mutation through the same fixed profile used for execution so a |
72 | | /// lane cannot accumulate inputs that its runner will immediately discard. |
73 | | /// @param data Mutable serialized Scenario storage. |
74 | | /// @param size Current serialized size. |
75 | | /// @param max_size Capacity of data. |
76 | | /// @param seed Mutation random seed supplied by libFuzzer. |
77 | | /// @return Serialized size after mutation. |
78 | 0 | static std::size_t CustomMutator(std::uint8_t* data, std::size_t size, std::size_t max_size, unsigned int seed) { |
79 | 0 | return ProtoFuzzerCustomMutator(Profile, data, size, max_size, seed); |
80 | 0 | } Unexecuted instantiation: proto_fuzzer::ProtoFuzzerEntrypoint<(proto_fuzzer::TargetProfile)6>::CustomMutator(unsigned char*, unsigned long, unsigned long, unsigned int) Unexecuted instantiation: proto_fuzzer::ProtoFuzzerEntrypoint<(proto_fuzzer::TargetProfile)7>::CustomMutator(unsigned char*, unsigned long, unsigned long, unsigned int) Unexecuted instantiation: proto_fuzzer::ProtoFuzzerEntrypoint<(proto_fuzzer::TargetProfile)8>::CustomMutator(unsigned char*, unsigned long, unsigned long, unsigned int) Unexecuted instantiation: proto_fuzzer::ProtoFuzzerEntrypoint<(proto_fuzzer::TargetProfile)4>::CustomMutator(unsigned char*, unsigned long, unsigned long, unsigned int) Unexecuted instantiation: proto_fuzzer::ProtoFuzzerEntrypoint<(proto_fuzzer::TargetProfile)2>::CustomMutator(unsigned char*, unsigned long, unsigned long, unsigned int) Unexecuted instantiation: proto_fuzzer::ProtoFuzzerEntrypoint<(proto_fuzzer::TargetProfile)3>::CustomMutator(unsigned char*, unsigned long, unsigned long, unsigned int) Unexecuted instantiation: proto_fuzzer::ProtoFuzzerEntrypoint<(proto_fuzzer::TargetProfile)10>::CustomMutator(unsigned char*, unsigned long, unsigned long, unsigned int) Unexecuted instantiation: proto_fuzzer::ProtoFuzzerEntrypoint<(proto_fuzzer::TargetProfile)0>::CustomMutator(unsigned char*, unsigned long, unsigned long, unsigned int) Unexecuted instantiation: proto_fuzzer::ProtoFuzzerEntrypoint<(proto_fuzzer::TargetProfile)1>::CustomMutator(unsigned char*, unsigned long, unsigned long, unsigned int) Unexecuted instantiation: proto_fuzzer::ProtoFuzzerEntrypoint<(proto_fuzzer::TargetProfile)9>::CustomMutator(unsigned char*, unsigned long, unsigned long, unsigned int) Unexecuted instantiation: proto_fuzzer::ProtoFuzzerEntrypoint<(proto_fuzzer::TargetProfile)5>::CustomMutator(unsigned char*, unsigned long, unsigned long, unsigned int) |
81 | | |
82 | | /// Forward crossover through the fixed profile so children are normalized |
83 | | /// for the same lane as both ordinary mutations and execution. |
84 | | /// @param data1 First serialized parent. |
85 | | /// @param size1 Size of data1. |
86 | | /// @param data2 Second serialized parent. |
87 | | /// @param size2 Size of data2. |
88 | | /// @param out Destination storage. |
89 | | /// @param max_out_size Capacity of out. |
90 | | /// @param seed Crossover random seed supplied by libFuzzer. |
91 | | /// @return Serialized child size. |
92 | | static std::size_t CustomCrossOver(const std::uint8_t* data1, std::size_t size1, const std::uint8_t* data2, |
93 | | std::size_t size2, std::uint8_t* out, std::size_t max_out_size, |
94 | 0 | unsigned int seed) { |
95 | 0 | return ProtoFuzzerCustomCrossOver(Profile, data1, size1, data2, size2, out, max_out_size, seed); |
96 | 0 | } Unexecuted instantiation: proto_fuzzer::ProtoFuzzerEntrypoint<(proto_fuzzer::TargetProfile)6>::CustomCrossOver(unsigned char const*, unsigned long, unsigned char const*, unsigned long, unsigned char*, unsigned long, unsigned int) Unexecuted instantiation: proto_fuzzer::ProtoFuzzerEntrypoint<(proto_fuzzer::TargetProfile)7>::CustomCrossOver(unsigned char const*, unsigned long, unsigned char const*, unsigned long, unsigned char*, unsigned long, unsigned int) Unexecuted instantiation: proto_fuzzer::ProtoFuzzerEntrypoint<(proto_fuzzer::TargetProfile)8>::CustomCrossOver(unsigned char const*, unsigned long, unsigned char const*, unsigned long, unsigned char*, unsigned long, unsigned int) Unexecuted instantiation: proto_fuzzer::ProtoFuzzerEntrypoint<(proto_fuzzer::TargetProfile)4>::CustomCrossOver(unsigned char const*, unsigned long, unsigned char const*, unsigned long, unsigned char*, unsigned long, unsigned int) Unexecuted instantiation: proto_fuzzer::ProtoFuzzerEntrypoint<(proto_fuzzer::TargetProfile)2>::CustomCrossOver(unsigned char const*, unsigned long, unsigned char const*, unsigned long, unsigned char*, unsigned long, unsigned int) Unexecuted instantiation: proto_fuzzer::ProtoFuzzerEntrypoint<(proto_fuzzer::TargetProfile)3>::CustomCrossOver(unsigned char const*, unsigned long, unsigned char const*, unsigned long, unsigned char*, unsigned long, unsigned int) Unexecuted instantiation: proto_fuzzer::ProtoFuzzerEntrypoint<(proto_fuzzer::TargetProfile)10>::CustomCrossOver(unsigned char const*, unsigned long, unsigned char const*, unsigned long, unsigned char*, unsigned long, unsigned int) Unexecuted instantiation: proto_fuzzer::ProtoFuzzerEntrypoint<(proto_fuzzer::TargetProfile)0>::CustomCrossOver(unsigned char const*, unsigned long, unsigned char const*, unsigned long, unsigned char*, unsigned long, unsigned int) Unexecuted instantiation: proto_fuzzer::ProtoFuzzerEntrypoint<(proto_fuzzer::TargetProfile)1>::CustomCrossOver(unsigned char const*, unsigned long, unsigned char const*, unsigned long, unsigned char*, unsigned long, unsigned int) Unexecuted instantiation: proto_fuzzer::ProtoFuzzerEntrypoint<(proto_fuzzer::TargetProfile)9>::CustomCrossOver(unsigned char const*, unsigned long, unsigned char const*, unsigned long, unsigned char*, unsigned long, unsigned int) Unexecuted instantiation: proto_fuzzer::ProtoFuzzerEntrypoint<(proto_fuzzer::TargetProfile)5>::CustomCrossOver(unsigned char const*, unsigned long, unsigned char const*, unsigned long, unsigned char*, unsigned long, unsigned int) |
97 | | }; |
98 | | |
99 | | } // namespace proto_fuzzer |
100 | | |
101 | | #endif // PROTO_FUZZER_FUZZER_MAIN_H_ |