/work/testing/fuzzing/bootstrap_fuzz_test.cc
Line | Count | Source (jump to first uncovered line) |
1 | | #include <cassert> |
2 | | #include <cstdio> |
3 | | |
4 | | #include "../../toxcore/tox.h" |
5 | | #include "../../toxcore/tox_dispatch.h" |
6 | | #include "../../toxcore/tox_events.h" |
7 | | #include "fuzz_support.hh" |
8 | | #include "fuzz_tox.hh" |
9 | | |
10 | | namespace { |
11 | | |
12 | | void setup_callbacks(Tox_Dispatch *dispatch) |
13 | 0 | { |
14 | 0 | tox_events_callback_conference_connected( |
15 | 0 | dispatch, [](const Tox_Event_Conference_Connected *event, void *user_data) { |
16 | 0 | assert(event == nullptr); |
17 | 0 | }); |
18 | 0 | tox_events_callback_conference_connected( |
19 | 0 | dispatch, [](const Tox_Event_Conference_Connected *event, void *user_data) { |
20 | 0 | assert(event == nullptr); |
21 | 0 | }); |
22 | 0 | tox_events_callback_conference_invite( |
23 | 0 | dispatch, [](const Tox_Event_Conference_Invite *event, void *user_data) { |
24 | 0 | assert(event == nullptr); |
25 | 0 | }); |
26 | 0 | tox_events_callback_conference_message( |
27 | 0 | dispatch, [](const Tox_Event_Conference_Message *event, void *user_data) { |
28 | 0 | assert(event == nullptr); |
29 | 0 | }); |
30 | 0 | tox_events_callback_conference_peer_list_changed( |
31 | 0 | dispatch, [](const Tox_Event_Conference_Peer_List_Changed *event, void *user_data) { |
32 | 0 | assert(event == nullptr); |
33 | 0 | }); |
34 | 0 | tox_events_callback_conference_peer_name( |
35 | 0 | dispatch, [](const Tox_Event_Conference_Peer_Name *event, void *user_data) { |
36 | 0 | assert(event == nullptr); |
37 | 0 | }); |
38 | 0 | tox_events_callback_conference_title(dispatch, |
39 | 0 | [](const Tox_Event_Conference_Title *event, void *user_data) { assert(event == nullptr); }); |
40 | 0 | tox_events_callback_file_chunk_request( |
41 | 0 | dispatch, [](const Tox_Event_File_Chunk_Request *event, void *user_data) { |
42 | 0 | assert(event == nullptr); |
43 | 0 | }); |
44 | 0 | tox_events_callback_file_recv(dispatch, |
45 | 0 | [](const Tox_Event_File_Recv *event, void *user_data) { assert(event == nullptr); }); |
46 | 0 | tox_events_callback_file_recv_chunk(dispatch, |
47 | 0 | [](const Tox_Event_File_Recv_Chunk *event, void *user_data) { assert(event == nullptr); }); |
48 | 0 | tox_events_callback_file_recv_control( |
49 | 0 | dispatch, [](const Tox_Event_File_Recv_Control *event, void *user_data) { |
50 | 0 | assert(event == nullptr); |
51 | 0 | }); |
52 | 0 | tox_events_callback_friend_connection_status( |
53 | 0 | dispatch, [](const Tox_Event_Friend_Connection_Status *event, void *user_data) { |
54 | 0 | assert(event == nullptr); |
55 | 0 | }); |
56 | 0 | tox_events_callback_friend_lossless_packet( |
57 | 0 | dispatch, [](const Tox_Event_Friend_Lossless_Packet *event, void *user_data) { |
58 | 0 | assert(event == nullptr); |
59 | 0 | }); |
60 | 0 | tox_events_callback_friend_lossy_packet( |
61 | 0 | dispatch, [](const Tox_Event_Friend_Lossy_Packet *event, void *user_data) { |
62 | 0 | assert(event == nullptr); |
63 | 0 | }); |
64 | 0 | tox_events_callback_friend_message(dispatch, |
65 | 0 | [](const Tox_Event_Friend_Message *event, void *user_data) { assert(event == nullptr); }); |
66 | 0 | tox_events_callback_friend_name(dispatch, |
67 | 0 | [](const Tox_Event_Friend_Name *event, void *user_data) { assert(event == nullptr); }); |
68 | 0 | tox_events_callback_friend_read_receipt( |
69 | 0 | dispatch, [](const Tox_Event_Friend_Read_Receipt *event, void *user_data) { |
70 | 0 | assert(event == nullptr); |
71 | 0 | }); |
72 | 0 | tox_events_callback_friend_request( |
73 | 0 | dispatch, [](const Tox_Event_Friend_Request *event, void *user_data) { |
74 | 0 | Tox *tox = static_cast<Tox *>(user_data); |
75 | 0 | Tox_Err_Friend_Add err; |
76 | 0 | tox_friend_add_norequest(tox, tox_event_friend_request_get_public_key(event), &err); |
77 | 0 | if (!(err == TOX_ERR_FRIEND_ADD_OK || err == TOX_ERR_FRIEND_ADD_OWN_KEY |
78 | 0 | || err == TOX_ERR_FRIEND_ADD_ALREADY_SENT |
79 | 0 | || err == TOX_ERR_FRIEND_ADD_BAD_CHECKSUM |
80 | 0 | || err == TOX_ERR_FRIEND_ADD_MALLOC)) { |
81 | 0 | printf("unexpected error: %s\n", tox_err_friend_add_to_string(err)); |
82 | 0 | } |
83 | 0 | }); |
84 | 0 | tox_events_callback_friend_status(dispatch, |
85 | 0 | [](const Tox_Event_Friend_Status *event, void *user_data) { assert(event == nullptr); }); |
86 | 0 | tox_events_callback_friend_status_message( |
87 | 0 | dispatch, [](const Tox_Event_Friend_Status_Message *event, void *user_data) { |
88 | 0 | assert(event == nullptr); |
89 | 0 | }); |
90 | 0 | tox_events_callback_friend_typing(dispatch, |
91 | 0 | [](const Tox_Event_Friend_Typing *event, void *user_data) { assert(event == nullptr); }); |
92 | 0 | tox_events_callback_self_connection_status( |
93 | 0 | dispatch, [](const Tox_Event_Self_Connection_Status *event, void *user_data) { |
94 | 0 | assert(event == nullptr); |
95 | 0 | }); |
96 | 0 | } |
97 | | |
98 | | void TestBootstrap(Fuzz_Data &input) |
99 | 27 | { |
100 | | // Null system for regularly working memory allocations needed in |
101 | | // tox_events_equal. |
102 | 27 | Null_System null_sys; |
103 | 27 | Fuzz_System sys(input); |
104 | | |
105 | 27 | Ptr<Tox_Options> opts(tox_options_new(nullptr), tox_options_free); |
106 | 27 | assert(opts != nullptr); |
107 | | |
108 | 27 | tox_options_set_log_callback(opts.get(), |
109 | 27 | [](Tox *tox, Tox_Log_Level level, const char *file, uint32_t line, const char *func, |
110 | 40 | const char *message, void *user_data) { |
111 | | // Log to stdout. |
112 | 40 | if (Fuzz_Data::FUZZ_DEBUG) { |
113 | 0 | std::printf("[tox1] %c %s:%u(%s): %s\n", tox_log_level_name(level), file, line, |
114 | 0 | func, message); |
115 | 0 | } |
116 | 40 | }); |
117 | | |
118 | 27 | CONSUME1_OR_RETURN(const uint8_t, proxy_type, input); |
119 | 27 | if (proxy_type == 0) { |
120 | 8 | tox_options_set_proxy_type(opts.get(), TOX_PROXY_TYPE_NONE); |
121 | 19 | } else if (proxy_type == 1) { |
122 | 9 | tox_options_set_proxy_type(opts.get(), TOX_PROXY_TYPE_SOCKS5); |
123 | 9 | tox_options_set_proxy_host(opts.get(), "127.0.0.1"); |
124 | 9 | tox_options_set_proxy_port(opts.get(), 8080); |
125 | 10 | } else if (proxy_type == 2) { |
126 | 5 | tox_options_set_proxy_type(opts.get(), TOX_PROXY_TYPE_HTTP); |
127 | 5 | tox_options_set_proxy_host(opts.get(), "127.0.0.1"); |
128 | 5 | tox_options_set_proxy_port(opts.get(), 8080); |
129 | 5 | } |
130 | | |
131 | 27 | CONSUME1_OR_RETURN(const uint8_t, tcp_relay_enabled, input); |
132 | 23 | if (tcp_relay_enabled >= (UINT8_MAX / 2)) { |
133 | 10 | tox_options_set_tcp_port(opts.get(), 33445); |
134 | 10 | } |
135 | | |
136 | 23 | Tox_Options_Testing tox_options_testing; |
137 | 23 | tox_options_testing.operating_system = sys.sys.get(); |
138 | | |
139 | 23 | Tox_Err_New error_new; |
140 | 23 | Tox_Err_New_Testing error_new_testing; |
141 | 23 | Tox *tox = tox_new_testing(opts.get(), &error_new, &tox_options_testing, &error_new_testing); |
142 | | |
143 | 23 | if (tox == nullptr) { |
144 | | // It might fail, because some I/O happens in tox_new, and the fuzzer |
145 | | // might do things that make that I/O fail. |
146 | 23 | return; |
147 | 23 | } |
148 | | |
149 | 0 | assert(error_new == TOX_ERR_NEW_OK); |
150 | 0 | assert(error_new_testing == TOX_ERR_NEW_TESTING_OK); |
151 | | |
152 | 0 | uint8_t pub_key[TOX_PUBLIC_KEY_SIZE] = {0}; |
153 | | |
154 | | // These may fail, but that's ok. We ignore their return values. |
155 | 0 | tox_bootstrap(tox, "127.0.0.2", 33446, pub_key, nullptr); |
156 | 0 | tox_add_tcp_relay(tox, "127.0.0.2", 33446, pub_key, nullptr); |
157 | |
|
158 | 0 | tox_events_init(tox); |
159 | |
|
160 | 0 | Tox_Dispatch *dispatch = tox_dispatch_new(nullptr); |
161 | 0 | assert(dispatch != nullptr); |
162 | 0 | setup_callbacks(dispatch); |
163 | |
|
164 | 0 | size_t input_size = input.size(); |
165 | 0 | while (!input.empty()) { |
166 | 0 | Tox_Err_Events_Iterate error_iterate; |
167 | 0 | Tox_Events *events = tox_events_iterate(tox, true, &error_iterate); |
168 | 0 | assert(tox_events_equal(null_sys.sys.get(), events, events)); |
169 | 0 | tox_dispatch_invoke(dispatch, events, tox); |
170 | 0 | tox_events_free(events); |
171 | | // Move the clock forward a decent amount so all the time-based checks |
172 | | // trigger more quickly. |
173 | 0 | sys.clock += 200; |
174 | | |
175 | | // If no input was consumed, something went wrong. |
176 | 0 | assert(input_size != input.size()); |
177 | | |
178 | 0 | input_size = input.size(); |
179 | 0 | } |
180 | | |
181 | 0 | tox_dispatch_free(dispatch); |
182 | 0 | tox_kill(tox); |
183 | 0 | } |
184 | | |
185 | | } |
186 | | |
187 | | extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size); |
188 | | extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) |
189 | 2.57k | { |
190 | 2.57k | Fuzz_Data input{data, size}; |
191 | 2.57k | TestBootstrap(input); |
192 | 2.57k | return 0; // Non-zero return values are reserved for future use. |
193 | 2.57k | } |