/work/toxcore/forwarding_fuzz_test.cc
Line | Count | Source |
1 | | #include "forwarding.h" |
2 | | |
3 | | #include <cassert> |
4 | | #include <cstddef> |
5 | | #include <cstring> |
6 | | #include <memory> |
7 | | #include <optional> |
8 | | |
9 | | #include "../testing/support/public/fuzz_data.hh" |
10 | | #include "../testing/support/public/fuzz_helpers.hh" |
11 | | #include "../testing/support/public/simulated_environment.hh" |
12 | | |
13 | | namespace { |
14 | | |
15 | | using tox::test::configure_fuzz_memory_source; |
16 | | using tox::test::Fuzz_Data; |
17 | | using tox::test::SimulatedEnvironment; |
18 | | |
19 | | constexpr std::uint16_t SIZE_IP_PORT = SIZE_IP6 + sizeof(std::uint16_t); |
20 | | |
21 | | template <typename T> |
22 | | using Ptr = std::unique_ptr<T, void (*)(T *)>; |
23 | | |
24 | | std::optional<std::tuple<IP_Port, IP_Port, const std::uint8_t *, std::size_t>> prepare( |
25 | | Fuzz_Data &input) |
26 | 52 | { |
27 | 52 | CONSUME_OR_RETURN_VAL(const std::uint8_t *ipp_packed, input, SIZE_IP_PORT, std::nullopt); |
28 | 50 | IP_Port ipp{}; |
29 | 50 | unpack_ip_port(&ipp, ipp_packed, SIZE_IP6, true); |
30 | | |
31 | 50 | CONSUME_OR_RETURN_VAL(const std::uint8_t *forwarder_packed, input, SIZE_IP_PORT, std::nullopt); |
32 | 45 | IP_Port forwarder{}; |
33 | 45 | unpack_ip_port(&forwarder, forwarder_packed, SIZE_IP6, true); |
34 | | |
35 | | // 2 bytes: size of the request |
36 | 45 | CONSUME_OR_RETURN_VAL( |
37 | 39 | const std::uint8_t *data_size_bytes, input, sizeof(std::uint16_t), std::nullopt); |
38 | 39 | std::uint16_t data_size; |
39 | 39 | std::memcpy(&data_size, data_size_bytes, sizeof(std::uint16_t)); |
40 | | |
41 | | // data bytes (max 64K) |
42 | 39 | CONSUME_OR_RETURN_VAL(const std::uint8_t *data, input, data_size, std::nullopt); |
43 | | |
44 | 37 | return {{ipp, forwarder, data, data_size}}; |
45 | 39 | } |
46 | | |
47 | | void TestSendForwardRequest(Fuzz_Data &input) |
48 | 26 | { |
49 | 26 | CONSUME1_OR_RETURN(const std::uint16_t, chain_length, input); |
50 | 25 | const std::uint16_t chain_keys_size = chain_length * CRYPTO_PUBLIC_KEY_SIZE; |
51 | 25 | CONSUME_OR_RETURN(const std::uint8_t *chain_keys, input, chain_keys_size); |
52 | | |
53 | 24 | const auto prep = prepare(input); |
54 | 24 | if (!prep.has_value()) { |
55 | 4 | return; |
56 | 4 | } |
57 | 20 | const auto [ipp, forwarder, data, data_size] = prep.value(); |
58 | | |
59 | 20 | SimulatedEnvironment env{12345}; |
60 | 20 | auto node = env.create_node(ipp.port); |
61 | 20 | configure_fuzz_memory_source(env.fake_memory(), input); |
62 | | |
63 | 20 | const Ptr<Logger> logger(logger_new(&node->c_memory), logger_kill); |
64 | 20 | if (logger == nullptr) { |
65 | 1 | return; |
66 | 1 | } |
67 | | |
68 | 19 | const Ptr<Networking_Core> net( |
69 | 19 | new_networking_ex(logger.get(), &node->c_memory, &node->c_network, &ipp.ip, ipp.port, |
70 | 19 | ipp.port + 100, nullptr), |
71 | 19 | kill_networking); |
72 | 19 | if (net == nullptr) { |
73 | 2 | return; |
74 | 2 | } |
75 | | |
76 | 17 | send_forward_request(net.get(), &forwarder, chain_keys, chain_length, data, data_size); |
77 | 17 | } |
78 | | |
79 | | void TestForwardReply(Fuzz_Data &input) |
80 | 30 | { |
81 | 30 | CONSUME1_OR_RETURN(const std::uint16_t, sendback_length, input); |
82 | 29 | CONSUME_OR_RETURN(const std::uint8_t *sendback, input, sendback_length); |
83 | | |
84 | 28 | const auto prep = prepare(input); |
85 | 28 | if (!prep.has_value()) { |
86 | 11 | return; |
87 | 11 | } |
88 | 17 | const auto [ipp, forwarder, data, data_size] = prep.value(); |
89 | | |
90 | 17 | SimulatedEnvironment env{12345}; |
91 | 17 | auto node = env.create_node(ipp.port); |
92 | 17 | configure_fuzz_memory_source(env.fake_memory(), input); |
93 | | |
94 | 17 | const Ptr<Logger> logger(logger_new(&node->c_memory), logger_kill); |
95 | 17 | if (logger == nullptr) { |
96 | 1 | return; |
97 | 1 | } |
98 | | |
99 | 16 | const Ptr<Networking_Core> net( |
100 | 16 | new_networking_ex(logger.get(), &node->c_memory, &node->c_network, &ipp.ip, ipp.port, |
101 | 16 | ipp.port + 100, nullptr), |
102 | 16 | kill_networking); |
103 | 16 | if (net == nullptr) { |
104 | 3 | return; |
105 | 3 | } |
106 | | |
107 | 13 | forward_reply(net.get(), &forwarder, sendback, sendback_length, data, data_size); |
108 | 13 | } |
109 | | |
110 | | } // namespace |
111 | | |
112 | | extern "C" int LLVMFuzzerTestOneInput(const std::uint8_t *data, std::size_t size); |
113 | | extern "C" int LLVMFuzzerTestOneInput(const std::uint8_t *data, std::size_t size) |
114 | 2.69k | { |
115 | 2.69k | tox::test::fuzz_select_target<TestSendForwardRequest, TestForwardReply>(data, size); |
116 | 2.69k | return 0; |
117 | 2.69k | } |