/work/toxcore/group_announce_fuzz_test.cc
Line | Count | Source (jump to first uncovered line) |
1 | | #include "group_announce.h" |
2 | | |
3 | | #include <cassert> |
4 | | #include <cstddef> |
5 | | #include <functional> |
6 | | #include <memory> |
7 | | #include <vector> |
8 | | |
9 | | #include "../testing/support/public/fuzz_data.hh" |
10 | | #include "../testing/support/public/simulated_environment.hh" |
11 | | #include "attributes.h" |
12 | | |
13 | | namespace { |
14 | | |
15 | | using tox::test::FakeClock; |
16 | | using tox::test::Fuzz_Data; |
17 | | using tox::test::SimulatedEnvironment; |
18 | | |
19 | | void TestUnpackAnnouncesList(Fuzz_Data &input) |
20 | 92 | { |
21 | 92 | CONSUME1_OR_RETURN(const std::uint8_t, max_count, input); |
22 | | // Always allocate at least something to avoid passing nullptr to functions below. |
23 | 91 | std::vector<GC_Announce> announces(max_count + 1); |
24 | | |
25 | | // TODO(iphydf): How do we know the packed size? |
26 | 91 | CONSUME1_OR_RETURN(const std::uint16_t, packed_size, input); |
27 | | |
28 | 90 | SimulatedEnvironment env{12345}; |
29 | 90 | auto c_mem = env.fake_memory().c_memory(); |
30 | 90 | Logger *logger = logger_new(&c_mem); |
31 | 90 | if (gca_unpack_announces_list(logger, input.data(), input.size(), announces.data(), max_count) |
32 | 90 | != -1) { |
33 | | // Always allocate at least something to avoid passing nullptr to functions below. |
34 | 55 | std::vector<std::uint8_t> packed(packed_size + 1); |
35 | 55 | std::size_t processed; |
36 | 55 | gca_pack_announces_list( |
37 | 55 | logger, packed.data(), packed_size, announces.data(), max_count, &processed); |
38 | 55 | } |
39 | 90 | logger_kill(logger); |
40 | 90 | } |
41 | | |
42 | | void TestUnpackPublicAnnounce(Fuzz_Data &input) |
43 | 7 | { |
44 | 7 | GC_Public_Announce public_announce; |
45 | | |
46 | | // TODO(iphydf): How do we know the packed size? |
47 | 7 | CONSUME1_OR_RETURN(const std::uint16_t, packed_size, input); |
48 | | |
49 | 6 | SimulatedEnvironment env{12345}; |
50 | 6 | auto c_mem = env.fake_memory().c_memory(); |
51 | 6 | Logger *logger = logger_new(&c_mem); |
52 | 6 | if (gca_unpack_public_announce(logger, input.data(), input.size(), &public_announce) != -1) { |
53 | | // Always allocate at least something to avoid passing nullptr to functions below. |
54 | 3 | std::vector<std::uint8_t> packed(packed_size + 1); |
55 | 3 | gca_pack_public_announce(logger, packed.data(), packed_size, &public_announce); |
56 | 3 | } |
57 | 6 | logger_kill(logger); |
58 | 6 | } |
59 | | |
60 | | void TestDoGca(Fuzz_Data &input) |
61 | 232 | { |
62 | 232 | SimulatedEnvironment env{12345}; |
63 | 232 | auto c_mem = env.fake_memory().c_memory(); |
64 | 232 | std::unique_ptr<Logger, void (*)(Logger *)> logger(logger_new(&c_mem), logger_kill); |
65 | | |
66 | 232 | std::unique_ptr<Mono_Time, std::function<void(Mono_Time *)>> mono_time( |
67 | 232 | mono_time_new( |
68 | 232 | &c_mem, |
69 | 232 | [](void *_Nullable user_data) -> std::uint64_t { |
70 | 232 | return static_cast<FakeClock *>(user_data)->current_time_ms(); |
71 | 232 | }, |
72 | 232 | &env.fake_clock()), |
73 | 232 | [c_mem](Mono_Time *ptr) { mono_time_free(&c_mem, ptr); }); |
74 | 232 | assert(mono_time != nullptr); |
75 | | |
76 | 232 | std::unique_ptr<GC_Announces_List, std::function<void(GC_Announces_List *)>> gca( |
77 | 232 | new_gca_list(&c_mem), [](GC_Announces_List *ptr) { kill_gca(ptr); }); |
78 | 232 | assert(gca != nullptr); |
79 | | |
80 | 4.31k | while (!input.empty()) { |
81 | 4.09k | CONSUME1_OR_RETURN(const std::uint8_t, choice, input); |
82 | 4.09k | switch (choice) { |
83 | 1.83k | case 0: { |
84 | | // Add an announce. |
85 | 1.83k | CONSUME1_OR_RETURN(const std::uint16_t, length, input); |
86 | 1.83k | CONSUME_OR_RETURN(const std::uint8_t *data, input, length); |
87 | 1.83k | GC_Public_Announce public_announce; |
88 | 1.83k | if (gca_unpack_public_announce(logger.get(), data, length, &public_announce) != -1) { |
89 | 719 | gca_add_announce(&c_mem, mono_time.get(), gca.get(), &public_announce); |
90 | 719 | } |
91 | 1.83k | break; |
92 | 1.83k | } |
93 | 369 | case 1: { |
94 | | // Advance the time by a number of tox_iteration_intervals. |
95 | 369 | CONSUME1_OR_RETURN(const std::uint8_t, iterations, input); |
96 | 368 | env.fake_clock().advance(iterations * 20); |
97 | | // Do an iteration. |
98 | 368 | do_gca(mono_time.get(), gca.get()); |
99 | 368 | break; |
100 | 369 | } |
101 | 918 | case 2: { |
102 | | // Get announces. |
103 | 918 | CONSUME1_OR_RETURN(const std::uint8_t, max_nodes, input); |
104 | | // Always allocate at least something to avoid passing nullptr to functions below. |
105 | 917 | std::vector<GC_Announce> gc_announces(max_nodes + 1); |
106 | 917 | CONSUME_OR_RETURN(const std::uint8_t *chat_id, input, CHAT_ID_SIZE); |
107 | 910 | CONSUME_OR_RETURN(const std::uint8_t *except_public_key, input, ENC_PUBLIC_KEY_SIZE); |
108 | 909 | gca_get_announces( |
109 | 909 | gca.get(), gc_announces.data(), max_nodes, chat_id, except_public_key); |
110 | 909 | break; |
111 | 910 | } |
112 | 641 | case 3: { |
113 | | // Remove a chat. |
114 | 641 | CONSUME_OR_RETURN(const std::uint8_t *chat_id, input, CHAT_ID_SIZE); |
115 | 640 | cleanup_gca(gca.get(), chat_id); |
116 | 640 | break; |
117 | 641 | } |
118 | 4.09k | } |
119 | 4.09k | } |
120 | 232 | } |
121 | | |
122 | | } // namespace |
123 | | |
124 | | extern "C" int LLVMFuzzerTestOneInput(const std::uint8_t *data, std::size_t size); |
125 | | extern "C" int LLVMFuzzerTestOneInput(const std::uint8_t *data, std::size_t size) |
126 | 2.69k | { |
127 | 2.69k | tox::test::fuzz_select_target<TestUnpackAnnouncesList, TestUnpackPublicAnnounce, TestDoGca>( |
128 | 2.69k | data, size); |
129 | 2.69k | return 0; |
130 | 2.69k | } |