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