/src/coturn/fuzzing/FuzzStunClient.c
Line | Count | Source |
1 | | /* |
2 | | * SPDX-License-Identifier: BSD-3-Clause |
3 | | * |
4 | | * https://opensource.org/license/bsd-3-clause |
5 | | * |
6 | | * Multi-harness libFuzzer entry point for client-side STUN parsing, |
7 | | * TCP framing, and address codec. |
8 | | * |
9 | | * Every iteration runs all sub-harnesses in sequence on the same input. |
10 | | * Keeping everything behind a single binary allows the upstream OSS-Fuzz |
11 | | * build recipe (which only copies FuzzStun and FuzzStunClient) to stay |
12 | | * unchanged. |
13 | | */ |
14 | | |
15 | | #include <stdbool.h> |
16 | | #include <stdint.h> |
17 | | #include <string.h> |
18 | | |
19 | | #include "apputils.h" |
20 | | #include "ns_turn_msg.h" |
21 | | #include "ns_turn_msg_addr.h" |
22 | | #include "ns_turn_msg_defs.h" |
23 | | #include "ns_turn_utils.h" |
24 | | #include "stun_buffer.h" |
25 | | |
26 | 676k | static uint8_t fuzz_byte(const uint8_t *Data, size_t Size, size_t idx) { return Size ? Data[idx % Size] : 0; } |
27 | | |
28 | 85.0k | static uint16_t fuzz_u16(const uint8_t *Data, size_t Size, size_t idx) { |
29 | 85.0k | return (uint16_t)(((uint16_t)fuzz_byte(Data, Size, idx) << 8) | (uint16_t)fuzz_byte(Data, Size, idx + 1)); |
30 | 85.0k | } |
31 | | |
32 | 28.8k | static uint32_t fuzz_u32(const uint8_t *Data, size_t Size, size_t idx) { |
33 | 28.8k | return ((uint32_t)fuzz_u16(Data, Size, idx) << 16) | (uint32_t)fuzz_u16(Data, Size, idx + 2); |
34 | 28.8k | } |
35 | | |
36 | 3.28k | static uint64_t fuzz_u64(const uint8_t *Data, size_t Size, size_t idx) { |
37 | 3.28k | return ((uint64_t)fuzz_u32(Data, Size, idx) << 32) | (uint64_t)fuzz_u32(Data, Size, idx + 4); |
38 | 3.28k | } |
39 | | |
40 | 37.1k | static bool fuzz_flag(const uint8_t *Data, size_t Size, size_t idx) { return (fuzz_byte(Data, Size, idx) & 1u) != 0; } |
41 | | |
42 | 9.84k | static void fuzz_string(const uint8_t *Data, size_t Size, size_t idx, char *out, size_t out_size) { |
43 | 9.84k | if (!out || !out_size) { |
44 | 0 | return; |
45 | 0 | } |
46 | | |
47 | 9.84k | const size_t max_len = out_size - 1; |
48 | 9.84k | const size_t len = max_len ? (size_t)(fuzz_byte(Data, Size, idx) % (max_len + 1)) : 0; |
49 | | |
50 | 268k | for (size_t i = 0; i < len; ++i) { |
51 | 258k | out[i] = (char)('A' + (fuzz_byte(Data, Size, idx + 1 + i) % 26)); |
52 | 258k | } |
53 | | |
54 | 9.84k | out[len] = '\0'; |
55 | 9.84k | } |
56 | | |
57 | 4.92k | static void fuzz_tid(const uint8_t *Data, size_t Size, size_t idx, stun_tid *tid) { |
58 | 4.92k | if (!tid) { |
59 | 0 | return; |
60 | 0 | } |
61 | | |
62 | 4.92k | memset(tid, 0, sizeof(*tid)); |
63 | 63.9k | for (size_t i = 0; i < STUN_TID_SIZE; ++i) { |
64 | 59.0k | tid->tsx_id[i] = fuzz_byte(Data, Size, idx + i); |
65 | 59.0k | } |
66 | 4.92k | } |
67 | | |
68 | 20.7k | static void fuzz_addr(const uint8_t *Data, size_t Size, size_t idx, ioa_addr *addr) { |
69 | 20.7k | if (!addr) { |
70 | 0 | return; |
71 | 0 | } |
72 | | |
73 | 20.7k | memset(addr, 0, sizeof(*addr)); |
74 | | |
75 | 20.7k | if (fuzz_flag(Data, Size, idx)) { |
76 | 8.26k | addr->s6.sin6_family = AF_INET6; |
77 | 8.26k | addr->s6.sin6_port = htons(fuzz_u16(Data, Size, idx + 1)); |
78 | 140k | for (size_t i = 0; i < 16; ++i) { |
79 | 132k | addr->s6.sin6_addr.s6_addr[i] = fuzz_byte(Data, Size, idx + 3 + i); |
80 | 132k | } |
81 | 8.26k | if (!memcmp(addr->s6.sin6_addr.s6_addr, "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0", 16)) { |
82 | 43 | addr->s6.sin6_addr.s6_addr[15] = 1; |
83 | 43 | } |
84 | 12.4k | } else { |
85 | 12.4k | addr->s4.sin_family = AF_INET; |
86 | 12.4k | addr->s4.sin_port = htons(fuzz_u16(Data, Size, idx + 1)); |
87 | 12.4k | addr->s4.sin_addr.s_addr = htonl(fuzz_u32(Data, Size, idx + 3) | 1u); |
88 | 12.4k | } |
89 | 20.7k | } |
90 | | |
91 | 41.0k | static void inspect_buffer_message(stun_buffer *msg, uint16_t addr_attr_type, const ioa_addr *default_addr) { |
92 | 41.0k | if (!msg) { |
93 | 0 | return; |
94 | 0 | } |
95 | | |
96 | 41.0k | (void)stun_get_command_message_len(msg); |
97 | 41.0k | (void)stun_is_command_message(msg); |
98 | 41.0k | (void)stun_is_request(msg); |
99 | 41.0k | (void)stun_is_response(msg); |
100 | 41.0k | (void)stun_is_success_response(msg); |
101 | 41.0k | (void)stun_is_binding_response(msg); |
102 | 41.0k | (void)stun_get_method(msg); |
103 | 41.0k | (void)stun_get_msg_type(msg); |
104 | | |
105 | 41.0k | { |
106 | 41.0k | int err_code = 0; |
107 | 41.0k | uint8_t err_msg[256] = {0}; |
108 | 41.0k | (void)stun_is_error_response(msg, &err_code, err_msg, sizeof(err_msg)); |
109 | 41.0k | } |
110 | | |
111 | 41.0k | { |
112 | 41.0k | ioa_addr parsed = {0}; |
113 | 41.0k | (void)stun_attr_get_first_addr(msg, addr_attr_type, &parsed, default_addr); |
114 | 41.0k | } |
115 | | |
116 | 41.0k | { |
117 | 41.0k | stun_attr_ref attr = stun_attr_get_first(msg); |
118 | 112k | while (attr) { |
119 | 71.7k | (void)stun_attr_get_type(attr); |
120 | 71.7k | (void)stun_attr_get_len(attr); |
121 | 71.7k | if (stun_attr_is_addr(attr)) { |
122 | 23.5k | ioa_addr parsed = {0}; |
123 | 23.5k | (void)stun_attr_get_addr(msg, attr, &parsed, default_addr); |
124 | 23.5k | } |
125 | 71.7k | attr = stun_attr_get_next(msg, attr); |
126 | 71.7k | } |
127 | 41.0k | } |
128 | | |
129 | 41.0k | (void)stun_attr_get_first_channel_number(msg); |
130 | 41.0k | } |
131 | | |
132 | 34.4k | static void inspect_raw_message(const uint8_t *buf, size_t len, uint16_t addr_attr_type, const ioa_addr *default_addr) { |
133 | 34.4k | if (!buf || !len) { |
134 | 0 | return; |
135 | 0 | } |
136 | | |
137 | 34.4k | (void)stun_is_command_message_str((uint8_t *)buf, len); |
138 | 34.4k | (void)stun_is_request_str(buf, len); |
139 | 34.4k | (void)stun_is_response_str(buf, len); |
140 | 34.4k | (void)stun_is_success_response_str(buf, len); |
141 | 34.4k | (void)stun_is_binding_response_str(buf, len); |
142 | 34.4k | (void)stun_get_method_str(buf, len); |
143 | 34.4k | (void)stun_get_msg_type_str(buf, len); |
144 | | |
145 | 34.4k | { |
146 | 34.4k | int err_code = 0; |
147 | 34.4k | uint8_t err_msg[256] = {0}; |
148 | 34.4k | (void)stun_is_error_response_str(buf, len, &err_code, err_msg, sizeof(err_msg)); |
149 | 34.4k | } |
150 | | |
151 | 34.4k | { |
152 | 34.4k | ioa_addr parsed = {0}; |
153 | 34.4k | (void)stun_attr_get_first_addr_str(buf, len, addr_attr_type, &parsed, default_addr); |
154 | 34.4k | } |
155 | | |
156 | 34.4k | { |
157 | 34.4k | stun_attr_ref attr = stun_attr_get_first_str(buf, len); |
158 | 91.1k | while (attr) { |
159 | 56.6k | (void)stun_attr_get_type(attr); |
160 | 56.6k | (void)stun_attr_get_len(attr); |
161 | 56.6k | if (stun_attr_is_addr(attr)) { |
162 | 26.5k | ioa_addr parsed = {0}; |
163 | 26.5k | (void)stun_attr_get_addr_str(buf, len, attr, &parsed, default_addr); |
164 | 26.5k | } |
165 | 56.6k | attr = stun_attr_get_next_str(buf, len, attr); |
166 | 56.6k | } |
167 | 34.4k | } |
168 | | |
169 | 34.4k | (void)stun_attr_get_first_channel_number_str(buf, len); |
170 | 34.4k | } |
171 | | |
172 | | /* ------------------------------------------------------------------ */ |
173 | | /* Raw-input coverage for stun_attr_get_first_addr. */ |
174 | | /* */ |
175 | | /* The inspect_buffer_message() path only sees messages produced by */ |
176 | | /* the project's own serializers, which are always well-formed. This */ |
177 | | /* harness feeds arbitrary fuzzer input through the stun_buffer */ |
178 | | /* wrapper (not just the _str variant) for every address attribute */ |
179 | | /* type, with both NULL and a fuzzed default_addr fallback. */ |
180 | | /* ------------------------------------------------------------------ */ |
181 | | static const uint16_t kFirstAddrAttrs[] = { |
182 | | STUN_ATTRIBUTE_MAPPED_ADDRESS, STUN_ATTRIBUTE_XOR_MAPPED_ADDRESS, OLD_STUN_ATTRIBUTE_XOR_MAPPED_ADDRESS, |
183 | | STUN_ATTRIBUTE_XOR_PEER_ADDRESS, STUN_ATTRIBUTE_XOR_RELAYED_ADDRESS, STUN_ATTRIBUTE_ALTERNATE_SERVER, |
184 | | STUN_ATTRIBUTE_RESPONSE_ORIGIN, STUN_ATTRIBUTE_OTHER_ADDRESS, |
185 | | }; |
186 | | |
187 | 1.77k | static void harness_attr_get_first_addr(const uint8_t *Data, size_t Size) { |
188 | 1.77k | if (Size < STUN_HEADER_LENGTH || Size > 5120) { |
189 | 722 | return; |
190 | 722 | } |
191 | | |
192 | 1.05k | stun_buffer msg; |
193 | 1.05k | msg.len = Size; |
194 | 1.05k | memcpy(msg.buf, Data, Size); |
195 | | |
196 | 1.05k | ioa_addr default_addr = {0}; |
197 | 1.05k | fuzz_addr(Data, Size, 0, &default_addr); |
198 | | |
199 | 1.05k | const size_t num_attrs = sizeof(kFirstAddrAttrs) / sizeof(kFirstAddrAttrs[0]); |
200 | 9.45k | for (size_t i = 0; i < num_attrs; ++i) { |
201 | 8.40k | ioa_addr parsed = {0}; |
202 | 8.40k | (void)stun_attr_get_first_addr(&msg, kFirstAddrAttrs[i], &parsed, NULL); |
203 | | |
204 | 8.40k | memset(&parsed, 0, sizeof(parsed)); |
205 | 8.40k | (void)stun_attr_get_first_addr(&msg, kFirstAddrAttrs[i], &parsed, &default_addr); |
206 | 8.40k | } |
207 | 1.05k | } |
208 | | |
209 | | /* ------------------------------------------------------------------ */ |
210 | | /* stun_buffer-based client message parsing (original FuzzStunClient). */ |
211 | | /* ------------------------------------------------------------------ */ |
212 | 1.77k | static void harness_stun_client(const uint8_t *Data, size_t Size) { |
213 | 1.77k | if (Size < 10 || Size > 5120) { |
214 | 581 | return; |
215 | 581 | } |
216 | | |
217 | 1.19k | stun_buffer buf; |
218 | 1.19k | buf.len = Size; |
219 | 1.19k | memcpy(buf.buf, Data, buf.len); |
220 | | |
221 | 1.19k | if (!stun_is_command_message(&buf)) { |
222 | 1.04k | return; |
223 | 1.04k | } |
224 | | |
225 | 149 | (void)stun_get_method_str(buf.buf, buf.len); |
226 | 149 | (void)stun_get_msg_type_str(buf.buf, buf.len); |
227 | | |
228 | 149 | if (stun_is_response(&buf) && stun_is_success_response(&buf) && stun_is_binding_response(&buf)) { |
229 | 9 | return; |
230 | 9 | } |
231 | | |
232 | 140 | stun_is_indication_str(buf.buf, buf.len); |
233 | | |
234 | 140 | int err_code = 0; |
235 | 140 | uint8_t err_msg[256] = {0}; |
236 | 140 | stun_is_error_response_str(buf.buf, buf.len, &err_code, err_msg, sizeof(err_msg)); |
237 | 140 | } |
238 | | |
239 | | /* ------------------------------------------------------------------ */ |
240 | | /* ChannelData / TCP framing (FuzzChannelData). */ |
241 | | /* ------------------------------------------------------------------ */ |
242 | 1.77k | static void harness_channel_data(const uint8_t *Data, size_t Size) { |
243 | 1.77k | if (Size < 4 || Size > 8192) { |
244 | 351 | return; |
245 | 351 | } |
246 | | |
247 | 1.42k | uint8_t buf[8192] = {0}; |
248 | 1.42k | memcpy(buf, Data, Size); |
249 | | |
250 | 1.42k | size_t app_len_tcp = 0; |
251 | 1.42k | size_t app_len_udp = 0; |
252 | | |
253 | 1.42k | int mlen_tcp = stun_get_message_len_str(buf, Size, 1, &app_len_tcp); |
254 | 1.42k | int mlen_udp = stun_get_message_len_str(buf, Size, 0, &app_len_udp); |
255 | | |
256 | 1.42k | if (mlen_tcp > 0) { |
257 | 549 | if (app_len_tcp > Size) { |
258 | 0 | __builtin_trap(); |
259 | 0 | } |
260 | 549 | if ((size_t)mlen_tcp > Size) { |
261 | 0 | __builtin_trap(); |
262 | 0 | } |
263 | 549 | if ((size_t)mlen_tcp < app_len_tcp) { |
264 | 0 | __builtin_trap(); |
265 | 0 | } |
266 | 549 | } |
267 | | |
268 | 1.42k | if (mlen_udp > 0) { |
269 | 565 | if (app_len_udp > Size) { |
270 | 0 | __builtin_trap(); |
271 | 0 | } |
272 | 565 | if ((size_t)mlen_udp > Size) { |
273 | 0 | __builtin_trap(); |
274 | 0 | } |
275 | 565 | } |
276 | | |
277 | 1.42k | size_t blen_tcp = Size; |
278 | 1.42k | uint16_t chn_tcp = 0; |
279 | 1.42k | bool is_chan_tcp = stun_is_channel_message_str(buf, &blen_tcp, &chn_tcp, true); |
280 | | |
281 | 1.42k | size_t blen_udp = Size; |
282 | 1.42k | uint16_t chn_udp = 0; |
283 | 1.42k | bool is_chan_udp = stun_is_channel_message_str(buf, &blen_udp, &chn_udp, false); |
284 | | |
285 | 1.42k | if (is_chan_tcp && (blen_tcp < 4 || blen_tcp > Size)) { |
286 | 0 | __builtin_trap(); |
287 | 0 | } |
288 | 1.42k | if (is_chan_udp && (blen_udp < 4 || blen_udp > Size)) { |
289 | 0 | __builtin_trap(); |
290 | 0 | } |
291 | 1.42k | } |
292 | | |
293 | | /* ------------------------------------------------------------------ */ |
294 | | /* STUN address encode/decode (FuzzStunAddrCodec). */ |
295 | | /* ------------------------------------------------------------------ */ |
296 | 1.77k | static void harness_addr_codec(const uint8_t *Data, size_t Size) { |
297 | 1.77k | if (Size < 2 || Size > 64) { |
298 | 575 | return; |
299 | 575 | } |
300 | | |
301 | 1.19k | uint8_t tid[STUN_TID_SIZE] = {0}; |
302 | 1.19k | size_t tid_bytes = Size > (STUN_TID_SIZE + 2) ? STUN_TID_SIZE : (Size > 2 ? Size - 2 : 0); |
303 | 1.19k | memcpy(tid, Data, tid_bytes); |
304 | 1.19k | const uint8_t *payload = Data + tid_bytes; |
305 | 1.19k | int payload_len = (int)(Size - tid_bytes); |
306 | | |
307 | 1.19k | ioa_addr addr = {0}; |
308 | | |
309 | | /* XOR decode + round-trip */ |
310 | 1.19k | if (stun_addr_decode(&addr, payload, payload_len, 1, STUN_MAGIC_COOKIE, tid) == 0) { |
311 | 10 | uint8_t enc_buf[32] = {0}; |
312 | 10 | int enc_len = 0; |
313 | 10 | if (stun_addr_encode(&addr, enc_buf, &enc_len, 1, STUN_MAGIC_COOKIE, tid) == 0) { |
314 | 10 | ioa_addr addr2 = {0}; |
315 | 10 | stun_addr_decode(&addr2, enc_buf, enc_len, 1, STUN_MAGIC_COOKIE, tid); |
316 | 10 | } |
317 | 10 | } |
318 | | |
319 | | /* Plain decode + round-trip */ |
320 | 1.19k | memset(&addr, 0, sizeof(addr)); |
321 | 1.19k | if (stun_addr_decode(&addr, payload, payload_len, 0, 0, tid) == 0) { |
322 | 10 | uint8_t enc_buf[32] = {0}; |
323 | 10 | int enc_len = 0; |
324 | 10 | if (stun_addr_encode(&addr, enc_buf, &enc_len, 0, 0, tid) == 0) { |
325 | 10 | ioa_addr addr2 = {0}; |
326 | 10 | stun_addr_decode(&addr2, enc_buf, enc_len, 0, 0, tid); |
327 | 10 | } |
328 | 10 | } |
329 | | |
330 | | /* Alternate magic cookie (old STUN) */ |
331 | 1.19k | memset(&addr, 0, sizeof(addr)); |
332 | 1.19k | uint32_t alt_cookie = 0; |
333 | 1.19k | if (Size >= 4) { |
334 | 985 | memcpy(&alt_cookie, Data, 4); |
335 | 985 | } |
336 | 1.19k | (void)stun_addr_decode(&addr, payload, payload_len, 1, alt_cookie, tid); |
337 | 1.19k | } |
338 | | |
339 | | /* ------------------------------------------------------------------ */ |
340 | | /* Message builders / wrappers / round-trip parsing. */ |
341 | | /* ------------------------------------------------------------------ */ |
342 | 1.77k | static void harness_message_builders(const uint8_t *Data, size_t Size) { |
343 | 1.77k | if (!Size || Size > 4096) { |
344 | 132 | return; |
345 | 132 | } |
346 | | |
347 | 1.64k | static const uint16_t kMethods[] = { |
348 | 1.64k | STUN_METHOD_ALLOCATE, STUN_METHOD_BINDING, STUN_METHOD_CHANNEL_BIND, STUN_METHOD_REFRESH, STUN_METHOD_CONNECT, |
349 | 1.64k | }; |
350 | 1.64k | static const uint16_t kErrorCodes[] = { |
351 | 1.64k | 300, 400, 401, 403, 420, 437, 438, 440, 441, 442, 443, 446, 447, 486, 487, 500, 508, 699, |
352 | 1.64k | }; |
353 | | |
354 | 1.64k | stun_tid tid = {0}; |
355 | 1.64k | ioa_addr relay1 = {0}; |
356 | 1.64k | ioa_addr relay2 = {0}; |
357 | 1.64k | ioa_addr reflexive = {0}; |
358 | 1.64k | ioa_addr peer = {0}; |
359 | 1.64k | ioa_addr default_addr = {0}; |
360 | 1.64k | char reason[96] = {0}; |
361 | 1.64k | char mobile_id[96] = {0}; |
362 | 1.64k | uint8_t raw[MAX_STUN_MESSAGE_SIZE] = {0}; |
363 | | |
364 | 1.64k | fuzz_tid(Data, Size, 0, &tid); |
365 | 1.64k | fuzz_addr(Data, Size, 16, &relay1); |
366 | 1.64k | fuzz_addr(Data, Size, 40, &relay2); |
367 | 1.64k | fuzz_addr(Data, Size, 64, &reflexive); |
368 | 1.64k | fuzz_addr(Data, Size, 88, &peer); |
369 | 1.64k | fuzz_addr(Data, Size, 112, &default_addr); |
370 | 1.64k | fuzz_string(Data, Size, 136, reason, sizeof(reason)); |
371 | 1.64k | fuzz_string(Data, Size, 232, mobile_id, sizeof(mobile_id)); |
372 | | |
373 | 1.64k | const uint16_t method = kMethods[fuzz_byte(Data, Size, 328) % (sizeof(kMethods) / sizeof(kMethods[0]))]; |
374 | 1.64k | const uint16_t error_code = kErrorCodes[fuzz_byte(Data, Size, 329) % (sizeof(kErrorCodes) / sizeof(kErrorCodes[0]))]; |
375 | 1.64k | const uint32_t lifetime = fuzz_u32(Data, Size, 330); |
376 | 1.64k | const uint32_t max_lifetime = fuzz_u32(Data, Size, 334); |
377 | 1.64k | const uint64_t reservation_token = fuzz_u64(Data, Size, 338); |
378 | 1.64k | const uint16_t channel_number = fuzz_u16(Data, Size, 346); |
379 | 1.64k | const bool include_reason = fuzz_flag(Data, Size, 348); |
380 | 1.64k | const bool old_stun = fuzz_flag(Data, Size, 349); |
381 | 1.64k | const bool stun_backward_compatibility = fuzz_flag(Data, Size, 350); |
382 | 1.64k | const uint32_t old_cookie = fuzz_u32(Data, Size, 351); |
383 | | |
384 | | /* Direct wrapper coverage for stun_init_error_response(). */ |
385 | 1.64k | { |
386 | 1.64k | stun_buffer msg; |
387 | 1.64k | stun_init_buffer(&msg); |
388 | 1.64k | stun_init_error_response(method, &msg, error_code, reason[0] ? (const uint8_t *)reason : NULL, &tid, |
389 | 1.64k | include_reason); |
390 | 1.64k | inspect_buffer_message(&msg, STUN_ATTRIBUTE_MAPPED_ADDRESS, &default_addr); |
391 | 1.64k | } |
392 | | |
393 | | /* Success allocate response covers addr extraction; error allocate response |
394 | | * forces the shared error builder path. */ |
395 | 1.64k | { |
396 | 1.64k | stun_buffer msg; |
397 | 1.64k | stun_init_buffer(&msg); |
398 | 1.64k | (void)stun_set_allocate_response(&msg, &tid, &relay1, fuzz_flag(Data, Size, 355) ? &relay2 : NULL, &reflexive, |
399 | 1.64k | lifetime, max_lifetime, 0, (const uint8_t *)reason, reservation_token, mobile_id, |
400 | 1.64k | include_reason); |
401 | 1.64k | inspect_buffer_message(&msg, STUN_ATTRIBUTE_XOR_RELAYED_ADDRESS, &default_addr); |
402 | | |
403 | 1.64k | size_t raw_len = sizeof(raw); |
404 | 1.64k | (void)stun_set_allocate_response_str(raw, &raw_len, &tid, &relay1, &relay2, &reflexive, lifetime, max_lifetime, 0, |
405 | 1.64k | (const uint8_t *)reason, reservation_token, mobile_id, include_reason); |
406 | 1.64k | inspect_raw_message(raw, raw_len, STUN_ATTRIBUTE_XOR_RELAYED_ADDRESS, &default_addr); |
407 | | |
408 | 1.64k | stun_init_buffer(&msg); |
409 | 1.64k | (void)stun_set_allocate_response(&msg, &tid, NULL, NULL, NULL, lifetime, max_lifetime, error_code, |
410 | 1.64k | reason[0] ? (const uint8_t *)reason : NULL, reservation_token, mobile_id, |
411 | 1.64k | include_reason); |
412 | 1.64k | inspect_buffer_message(&msg, STUN_ATTRIBUTE_XOR_RELAYED_ADDRESS, &default_addr); |
413 | | |
414 | 1.64k | raw_len = sizeof(raw); |
415 | 1.64k | (void)stun_set_allocate_response_str(raw, &raw_len, &tid, NULL, NULL, NULL, lifetime, max_lifetime, error_code, |
416 | 1.64k | reason[0] ? (const uint8_t *)reason : NULL, reservation_token, mobile_id, |
417 | 1.64k | include_reason); |
418 | 1.64k | inspect_raw_message(raw, raw_len, STUN_ATTRIBUTE_XOR_RELAYED_ADDRESS, &default_addr); |
419 | 1.64k | } |
420 | | |
421 | 1.64k | { |
422 | 1.64k | stun_buffer msg; |
423 | 1.64k | stun_init_buffer(&msg); |
424 | 1.64k | (void)stun_set_binding_response(&msg, &tid, &reflexive, 0, (const uint8_t *)reason, include_reason); |
425 | 1.64k | inspect_buffer_message(&msg, STUN_ATTRIBUTE_XOR_MAPPED_ADDRESS, &default_addr); |
426 | | |
427 | 1.64k | size_t raw_len = sizeof(raw); |
428 | 1.64k | (void)stun_set_binding_response_str(raw, &raw_len, &tid, &reflexive, 0, (const uint8_t *)reason, old_cookie, |
429 | 1.64k | old_stun, stun_backward_compatibility, include_reason); |
430 | 1.64k | inspect_raw_message(raw, raw_len, old_stun ? STUN_ATTRIBUTE_MAPPED_ADDRESS : STUN_ATTRIBUTE_XOR_MAPPED_ADDRESS, |
431 | 1.64k | &default_addr); |
432 | | |
433 | 1.64k | stun_init_buffer(&msg); |
434 | 1.64k | (void)stun_set_binding_response(&msg, &tid, NULL, error_code, reason[0] ? (const uint8_t *)reason : NULL, |
435 | 1.64k | include_reason); |
436 | 1.64k | inspect_buffer_message(&msg, STUN_ATTRIBUTE_MAPPED_ADDRESS, &default_addr); |
437 | | |
438 | 1.64k | raw_len = sizeof(raw); |
439 | 1.64k | (void)stun_set_binding_response_str(raw, &raw_len, &tid, NULL, error_code, |
440 | 1.64k | reason[0] ? (const uint8_t *)reason : NULL, old_cookie, old_stun, |
441 | 1.64k | stun_backward_compatibility, include_reason); |
442 | 1.64k | inspect_raw_message(raw, raw_len, STUN_ATTRIBUTE_MAPPED_ADDRESS, &default_addr); |
443 | 1.64k | } |
444 | | |
445 | 1.64k | { |
446 | 1.64k | stun_buffer msg; |
447 | 1.64k | stun_init_buffer(&msg); |
448 | 1.64k | (void)stun_set_channel_bind_request(&msg, fuzz_flag(Data, Size, 356) ? &peer : NULL, channel_number); |
449 | 1.64k | inspect_buffer_message(&msg, STUN_ATTRIBUTE_XOR_PEER_ADDRESS, &default_addr); |
450 | | |
451 | 1.64k | size_t raw_len = sizeof(raw); |
452 | 1.64k | (void)stun_set_channel_bind_request_str(raw, &raw_len, fuzz_flag(Data, Size, 357) ? &peer : NULL, channel_number); |
453 | 1.64k | inspect_raw_message(raw, raw_len, STUN_ATTRIBUTE_XOR_PEER_ADDRESS, &default_addr); |
454 | | |
455 | 1.64k | stun_init_buffer(&msg); |
456 | 1.64k | stun_set_channel_bind_response(&msg, &tid, 0, (const uint8_t *)reason, include_reason); |
457 | 1.64k | inspect_buffer_message(&msg, STUN_ATTRIBUTE_XOR_PEER_ADDRESS, &default_addr); |
458 | | |
459 | 1.64k | raw_len = sizeof(raw); |
460 | 1.64k | stun_set_channel_bind_response_str(raw, &raw_len, &tid, error_code, reason[0] ? (const uint8_t *)reason : NULL, |
461 | 1.64k | include_reason); |
462 | 1.64k | inspect_raw_message(raw, raw_len, STUN_ATTRIBUTE_XOR_PEER_ADDRESS, &default_addr); |
463 | 1.64k | } |
464 | 1.64k | } |
465 | | |
466 | | /* ------------------------------------------------------------------ */ |
467 | | /* Deterministic branch coverage for the response builders. */ |
468 | | /* */ |
469 | | /* harness_message_builders randomizes include_reason/old_stun/NULL- */ |
470 | | /* vs-present selectors from single input bytes, so any one iteration */ |
471 | | /* only visits a fraction of the branches inside these builders. This */ |
472 | | /* harness hits every branch point of each listed builder on every */ |
473 | | /* iteration so coverage is not gated on libFuzzer finding the right */ |
474 | | /* bytes. Inputs (tid / addrs / strings / numeric fields) are still */ |
475 | | /* fuzz-derived to keep each call meaningfully distinct. */ |
476 | | /* ------------------------------------------------------------------ */ |
477 | 1.77k | static void harness_response_matrix(const uint8_t *Data, size_t Size) { |
478 | 1.77k | if (!Size || Size > 4096) { |
479 | 132 | return; |
480 | 132 | } |
481 | | |
482 | 1.64k | stun_tid tid = {0}; |
483 | 1.64k | ioa_addr relay1 = {0}; |
484 | 1.64k | ioa_addr relay2 = {0}; |
485 | 1.64k | ioa_addr reflexive = {0}; |
486 | 1.64k | ioa_addr peer = {0}; |
487 | 1.64k | ioa_addr default_addr = {0}; |
488 | 1.64k | char reason[96] = {0}; |
489 | 1.64k | char mobile_id[96] = {0}; |
490 | 1.64k | uint8_t raw[MAX_STUN_MESSAGE_SIZE] = {0}; |
491 | | |
492 | 1.64k | fuzz_tid(Data, Size, 0, &tid); |
493 | 1.64k | fuzz_addr(Data, Size, 16, &relay1); |
494 | 1.64k | fuzz_addr(Data, Size, 40, &relay2); |
495 | 1.64k | fuzz_addr(Data, Size, 64, &reflexive); |
496 | 1.64k | fuzz_addr(Data, Size, 88, &peer); |
497 | 1.64k | fuzz_addr(Data, Size, 112, &default_addr); |
498 | 1.64k | fuzz_string(Data, Size, 136, reason, sizeof(reason)); |
499 | 1.64k | fuzz_string(Data, Size, 232, mobile_id, sizeof(mobile_id)); |
500 | | |
501 | 1.64k | const uint32_t max_lifetime = fuzz_u32(Data, Size, 328) | 1u; |
502 | 1.64k | const uint64_t reservation_token = fuzz_u64(Data, Size, 332) | 1ull; |
503 | 1.64k | const uint16_t channel_number_valid = (uint16_t)(0x4000u + (fuzz_u16(Data, Size, 340) % (0x7FFFu - 0x4000u + 1u))); |
504 | 1.64k | const uint32_t old_cookie = fuzz_u32(Data, Size, 344); |
505 | | |
506 | | /* stun_init_error_response — cover (reason NULL vs set) × (include reason). */ |
507 | 1.64k | { |
508 | 1.64k | stun_buffer msg; |
509 | 1.64k | stun_init_buffer(&msg); |
510 | 1.64k | stun_init_error_response(STUN_METHOD_ALLOCATE, &msg, 437, NULL, &tid, false); |
511 | 1.64k | inspect_buffer_message(&msg, STUN_ATTRIBUTE_MAPPED_ADDRESS, &default_addr); |
512 | | |
513 | 1.64k | stun_init_buffer(&msg); |
514 | 1.64k | stun_init_error_response(STUN_METHOD_BINDING, &msg, 400, (const uint8_t *)reason, &tid, true); |
515 | 1.64k | inspect_buffer_message(&msg, STUN_ATTRIBUTE_MAPPED_ADDRESS, &default_addr); |
516 | 1.64k | } |
517 | | |
518 | | /* stun_set_allocate_response / _str — cover every optional-field branch and |
519 | | * the error path independently of the fuzzer selectors. */ |
520 | 1.64k | { |
521 | 1.64k | stun_buffer msg; |
522 | | |
523 | | /* Minimal success: relay1 only, no reflexive, no reservation, no mobile id, |
524 | | * lifetime 0 (triggers the <1 default branch). */ |
525 | 1.64k | stun_init_buffer(&msg); |
526 | 1.64k | (void)stun_set_allocate_response(&msg, &tid, &relay1, NULL, NULL, 0, max_lifetime, 0, NULL, 0, NULL, false); |
527 | 1.64k | inspect_buffer_message(&msg, STUN_ATTRIBUTE_XOR_RELAYED_ADDRESS, &default_addr); |
528 | | |
529 | 1.64k | size_t raw_len = sizeof(raw); |
530 | 1.64k | (void)stun_set_allocate_response_str(raw, &raw_len, &tid, &relay1, NULL, NULL, 0, max_lifetime, 0, NULL, 0, NULL, |
531 | 1.64k | false); |
532 | 1.64k | inspect_raw_message(raw, raw_len, STUN_ATTRIBUTE_XOR_RELAYED_ADDRESS, &default_addr); |
533 | | |
534 | | /* Full success: both relays + reflexive + reservation + mobile id, |
535 | | * lifetime > max (triggers clamp branch). */ |
536 | 1.64k | stun_init_buffer(&msg); |
537 | 1.64k | (void)stun_set_allocate_response(&msg, &tid, &relay1, &relay2, &reflexive, max_lifetime + 1, max_lifetime, 0, |
538 | 1.64k | (const uint8_t *)reason, reservation_token, mobile_id, true); |
539 | 1.64k | inspect_buffer_message(&msg, STUN_ATTRIBUTE_XOR_RELAYED_ADDRESS, &default_addr); |
540 | | |
541 | 1.64k | raw_len = sizeof(raw); |
542 | 1.64k | (void)stun_set_allocate_response_str(raw, &raw_len, &tid, &relay1, &relay2, &reflexive, max_lifetime + 1, |
543 | 1.64k | max_lifetime, 0, (const uint8_t *)reason, reservation_token, mobile_id, true); |
544 | 1.64k | inspect_raw_message(raw, raw_len, STUN_ATTRIBUTE_XOR_RELAYED_ADDRESS, &default_addr); |
545 | | |
546 | | /* Error path with and without a reason string. */ |
547 | 1.64k | stun_init_buffer(&msg); |
548 | 1.64k | (void)stun_set_allocate_response(&msg, &tid, NULL, NULL, NULL, 0, max_lifetime, 441, NULL, 0, NULL, false); |
549 | 1.64k | inspect_buffer_message(&msg, STUN_ATTRIBUTE_XOR_RELAYED_ADDRESS, &default_addr); |
550 | | |
551 | 1.64k | raw_len = sizeof(raw); |
552 | 1.64k | (void)stun_set_allocate_response_str(raw, &raw_len, &tid, NULL, NULL, NULL, 0, max_lifetime, 508, |
553 | 1.64k | (const uint8_t *)reason, 0, NULL, true); |
554 | 1.64k | inspect_raw_message(raw, raw_len, STUN_ATTRIBUTE_XOR_RELAYED_ADDRESS, &default_addr); |
555 | 1.64k | } |
556 | | |
557 | | /* stun_set_binding_response / _str — cover success × error × old_stun. */ |
558 | 1.64k | { |
559 | 1.64k | stun_buffer msg; |
560 | | |
561 | 1.64k | stun_init_buffer(&msg); |
562 | 1.64k | (void)stun_set_binding_response(&msg, &tid, &reflexive, 0, NULL, false); |
563 | 1.64k | inspect_buffer_message(&msg, STUN_ATTRIBUTE_XOR_MAPPED_ADDRESS, &default_addr); |
564 | | |
565 | 1.64k | stun_init_buffer(&msg); |
566 | 1.64k | (void)stun_set_binding_response(&msg, &tid, NULL, 420, (const uint8_t *)reason, true); |
567 | 1.64k | inspect_buffer_message(&msg, STUN_ATTRIBUTE_MAPPED_ADDRESS, &default_addr); |
568 | | |
569 | 1.64k | const bool matrix_old_stun[] = {false, true}; |
570 | 1.64k | const bool matrix_backcompat[] = {false, true}; |
571 | 4.92k | for (size_t o = 0; o < sizeof(matrix_old_stun) / sizeof(matrix_old_stun[0]); ++o) { |
572 | 9.84k | for (size_t b = 0; b < sizeof(matrix_backcompat) / sizeof(matrix_backcompat[0]); ++b) { |
573 | 6.56k | size_t raw_len = sizeof(raw); |
574 | 6.56k | (void)stun_set_binding_response_str(raw, &raw_len, &tid, &reflexive, 0, NULL, old_cookie, matrix_old_stun[o], |
575 | 6.56k | matrix_backcompat[b], false); |
576 | 6.56k | inspect_raw_message(raw, raw_len, |
577 | 6.56k | matrix_old_stun[o] ? STUN_ATTRIBUTE_MAPPED_ADDRESS : STUN_ATTRIBUTE_XOR_MAPPED_ADDRESS, |
578 | 6.56k | &default_addr); |
579 | | |
580 | 6.56k | raw_len = sizeof(raw); |
581 | 6.56k | (void)stun_set_binding_response_str(raw, &raw_len, &tid, NULL, 500, (const uint8_t *)reason, old_cookie, |
582 | 6.56k | matrix_old_stun[o], matrix_backcompat[b], true); |
583 | 6.56k | inspect_raw_message(raw, raw_len, STUN_ATTRIBUTE_MAPPED_ADDRESS, &default_addr); |
584 | 6.56k | } |
585 | 3.28k | } |
586 | 1.64k | } |
587 | | |
588 | | /* stun_set_channel_bind_request / _str — cover peer NULL vs set. */ |
589 | 1.64k | { |
590 | 1.64k | stun_buffer msg; |
591 | | |
592 | 1.64k | stun_init_buffer(&msg); |
593 | 1.64k | (void)stun_set_channel_bind_request(&msg, NULL, channel_number_valid); |
594 | 1.64k | inspect_buffer_message(&msg, STUN_ATTRIBUTE_XOR_PEER_ADDRESS, &default_addr); |
595 | | |
596 | 1.64k | stun_init_buffer(&msg); |
597 | 1.64k | (void)stun_set_channel_bind_request(&msg, &peer, channel_number_valid); |
598 | 1.64k | inspect_buffer_message(&msg, STUN_ATTRIBUTE_XOR_PEER_ADDRESS, &default_addr); |
599 | | |
600 | 1.64k | size_t raw_len = sizeof(raw); |
601 | 1.64k | (void)stun_set_channel_bind_request_str(raw, &raw_len, NULL, channel_number_valid); |
602 | 1.64k | inspect_raw_message(raw, raw_len, STUN_ATTRIBUTE_XOR_PEER_ADDRESS, &default_addr); |
603 | | |
604 | 1.64k | raw_len = sizeof(raw); |
605 | 1.64k | (void)stun_set_channel_bind_request_str(raw, &raw_len, &peer, channel_number_valid); |
606 | 1.64k | inspect_raw_message(raw, raw_len, STUN_ATTRIBUTE_XOR_PEER_ADDRESS, &default_addr); |
607 | 1.64k | } |
608 | | |
609 | | /* stun_set_channel_bind_response / _str — cover success vs error. */ |
610 | 1.64k | { |
611 | 1.64k | stun_buffer msg; |
612 | | |
613 | 1.64k | stun_init_buffer(&msg); |
614 | 1.64k | stun_set_channel_bind_response(&msg, &tid, 0, NULL, false); |
615 | 1.64k | inspect_buffer_message(&msg, STUN_ATTRIBUTE_XOR_PEER_ADDRESS, &default_addr); |
616 | | |
617 | 1.64k | stun_init_buffer(&msg); |
618 | 1.64k | stun_set_channel_bind_response(&msg, &tid, 438, (const uint8_t *)reason, true); |
619 | 1.64k | inspect_buffer_message(&msg, STUN_ATTRIBUTE_XOR_PEER_ADDRESS, &default_addr); |
620 | | |
621 | 1.64k | size_t raw_len = sizeof(raw); |
622 | 1.64k | stun_set_channel_bind_response_str(raw, &raw_len, &tid, 0, NULL, false); |
623 | 1.64k | inspect_raw_message(raw, raw_len, STUN_ATTRIBUTE_XOR_PEER_ADDRESS, &default_addr); |
624 | | |
625 | 1.64k | raw_len = sizeof(raw); |
626 | 1.64k | stun_set_channel_bind_response_str(raw, &raw_len, &tid, 486, (const uint8_t *)reason, true); |
627 | 1.64k | inspect_raw_message(raw, raw_len, STUN_ATTRIBUTE_XOR_PEER_ADDRESS, &default_addr); |
628 | 1.64k | } |
629 | 1.64k | } |
630 | | |
631 | | /* ------------------------------------------------------------------ */ |
632 | | /* stun_buffer.c wrapper coverage. */ |
633 | | /* */ |
634 | | /* Exercises every public wrapper in src/apps/common/stun_buffer.c */ |
635 | | /* that is not already reached by the harnesses above: */ |
636 | | /* - stun_get_size NULL/non-NULL */ |
637 | | /* - stun_init_request / _indication / _success_response */ |
638 | | /* - stun_tid_from_message, stun_tid_generate_in_message */ |
639 | | /* - stun_is_indication wrapper (gates static is_channel_msg) */ |
640 | | /* - stun_attr_add, stun_attr_add_channel_number, stun_attr_add_addr */ |
641 | | /* - stun_attr_add_even_port (zero + non-zero branches) */ |
642 | | /* - stun_attr_get_first_by_type */ |
643 | | /* - stun_set_allocate_request (rt NULL + non-NULL) */ |
644 | | /* - stun_set_binding_request, stun_prepare_binding_request */ |
645 | | /* - stun_init_channel_message + stun_is_channel_message wrappers */ |
646 | | /* */ |
647 | | /* Each call is followed by inspect_buffer_message so the resulting */ |
648 | | /* serialized message is also walked by the parser predicates. */ |
649 | | /* The tail block also pumps raw fuzzer bytes through the predicate */ |
650 | | /* wrappers to hit malformed-input branches the serializers cannot */ |
651 | | /* produce. */ |
652 | | /* ------------------------------------------------------------------ */ |
653 | 1.77k | static void harness_stun_buffer_api(const uint8_t *Data, size_t Size) { |
654 | 1.77k | if (!Size || Size > 4096) { |
655 | 132 | return; |
656 | 132 | } |
657 | | |
658 | 1.64k | static const uint16_t kMethods[] = { |
659 | 1.64k | STUN_METHOD_ALLOCATE, STUN_METHOD_BINDING, STUN_METHOD_CHANNEL_BIND, STUN_METHOD_REFRESH, STUN_METHOD_CONNECT, |
660 | 1.64k | }; |
661 | | |
662 | 1.64k | stun_tid tid = {0}; |
663 | 1.64k | ioa_addr peer = {0}; |
664 | 1.64k | ioa_addr default_addr = {0}; |
665 | 1.64k | char attr_value[64] = {0}; |
666 | 1.64k | char rt[8] = {0}; |
667 | | |
668 | 1.64k | fuzz_tid(Data, Size, 0, &tid); |
669 | 1.64k | fuzz_addr(Data, Size, 16, &peer); |
670 | 1.64k | fuzz_addr(Data, Size, 40, &default_addr); |
671 | 1.64k | fuzz_string(Data, Size, 64, attr_value, sizeof(attr_value)); |
672 | 1.64k | fuzz_string(Data, Size, 128, rt, sizeof(rt)); |
673 | | |
674 | 1.64k | const uint16_t method = kMethods[fuzz_byte(Data, Size, 200) % (sizeof(kMethods) / sizeof(kMethods[0]))]; |
675 | 1.64k | const uint32_t lifetime = fuzz_u32(Data, Size, 201); |
676 | 1.64k | const uint16_t channel_number = (uint16_t)(0x4000u + (fuzz_u16(Data, Size, 205) & 0x3FFFu)); |
677 | 1.64k | const uint8_t transport = fuzz_byte(Data, Size, 207); |
678 | 1.64k | const uint8_t even_port_value = fuzz_byte(Data, Size, 208); |
679 | 1.64k | const bool af4 = fuzz_flag(Data, Size, 209); |
680 | 1.64k | const bool af6 = fuzz_flag(Data, Size, 210); |
681 | 1.64k | const bool mobile = fuzz_flag(Data, Size, 211); |
682 | 1.64k | const bool padding = fuzz_flag(Data, Size, 212); |
683 | 1.64k | const int chan_payload_len = (int)(fuzz_u16(Data, Size, 213) % 256); |
684 | 1.64k | const int ep = (int)(int8_t)fuzz_byte(Data, Size, 215); |
685 | | |
686 | | /* NULL-guard branches. */ |
687 | 1.64k | (void)stun_get_size(NULL); |
688 | 1.64k | (void)stun_init_buffer(NULL); |
689 | 1.64k | (void)stun_get_msg_type(NULL); |
690 | 1.64k | { |
691 | 1.64k | stun_tid scratch = {0}; |
692 | 1.64k | stun_tid_generate_in_message(NULL, &scratch); |
693 | 1.64k | } |
694 | | |
695 | | /* stun_init_request — also covers stun_get_size (non-NULL), the static |
696 | | * stun_init_command helper, and stun_attr_add* / stun_attr_get_first_by_type |
697 | | * over the freshly built message. */ |
698 | 1.64k | { |
699 | 1.64k | stun_buffer msg; |
700 | 1.64k | stun_init_buffer(&msg); |
701 | 1.64k | stun_init_request(method, &msg); |
702 | | |
703 | 1.64k | stun_tid extracted = {0}; |
704 | 1.64k | stun_tid_from_message(&msg, &extracted); |
705 | 1.64k | stun_tid_generate_in_message(&msg, &extracted); |
706 | | |
707 | 1.64k | const int alen = (int)strlen(attr_value); |
708 | 1.64k | (void)stun_attr_add(&msg, STUN_ATTRIBUTE_USERNAME, attr_value, alen); |
709 | 1.64k | (void)stun_attr_add_channel_number(&msg, channel_number); |
710 | 1.64k | (void)stun_attr_add_addr(&msg, STUN_ATTRIBUTE_XOR_PEER_ADDRESS, &peer); |
711 | 1.64k | (void)stun_attr_add_even_port(&msg, even_port_value); |
712 | 1.64k | (void)stun_attr_add_even_port(&msg, 0); |
713 | | |
714 | 1.64k | (void)stun_attr_get_first_by_type(&msg, STUN_ATTRIBUTE_USERNAME); |
715 | 1.64k | (void)stun_attr_get_first_by_type(&msg, STUN_ATTRIBUTE_CHANNEL_NUMBER); |
716 | 1.64k | (void)stun_attr_get_first_by_type(&msg, STUN_ATTRIBUTE_XOR_PEER_ADDRESS); |
717 | 1.64k | (void)stun_attr_get_first_by_type(&msg, STUN_ATTRIBUTE_EVEN_PORT); |
718 | | |
719 | 1.64k | (void)stun_is_indication(&msg); |
720 | 1.64k | inspect_buffer_message(&msg, STUN_ATTRIBUTE_XOR_PEER_ADDRESS, &default_addr); |
721 | 1.64k | } |
722 | | |
723 | | /* stun_init_indication — drives the IS_STUN_INDICATION branch of |
724 | | * stun_is_indication. */ |
725 | 1.64k | { |
726 | 1.64k | stun_buffer msg; |
727 | 1.64k | stun_init_buffer(&msg); |
728 | 1.64k | stun_init_indication(method, &msg); |
729 | 1.64k | (void)stun_is_indication(&msg); |
730 | 1.64k | inspect_buffer_message(&msg, STUN_ATTRIBUTE_XOR_PEER_ADDRESS, &default_addr); |
731 | 1.64k | } |
732 | | |
733 | | /* stun_init_success_response. */ |
734 | 1.64k | { |
735 | 1.64k | stun_buffer msg; |
736 | 1.64k | stun_init_buffer(&msg); |
737 | 1.64k | stun_init_success_response(method, &msg, &tid); |
738 | 1.64k | inspect_buffer_message(&msg, STUN_ATTRIBUTE_MAPPED_ADDRESS, &default_addr); |
739 | 1.64k | } |
740 | | |
741 | | /* stun_set_allocate_request — both rt NULL and rt non-NULL paths. */ |
742 | 1.64k | { |
743 | 1.64k | stun_buffer msg; |
744 | 1.64k | stun_init_buffer(&msg); |
745 | 1.64k | (void)stun_set_allocate_request(&msg, lifetime, af4, af6, transport, mobile, rt[0] ? rt : NULL, ep); |
746 | 1.64k | inspect_buffer_message(&msg, STUN_ATTRIBUTE_XOR_RELAYED_ADDRESS, &default_addr); |
747 | | |
748 | 1.64k | stun_init_buffer(&msg); |
749 | 1.64k | (void)stun_set_allocate_request(&msg, lifetime, !af4, !af6, transport, !mobile, NULL, ep); |
750 | 1.64k | inspect_buffer_message(&msg, STUN_ATTRIBUTE_XOR_RELAYED_ADDRESS, &default_addr); |
751 | 1.64k | } |
752 | | |
753 | | /* stun_set_binding_request + stun_prepare_binding_request (both currently |
754 | | * delegate to stun_set_binding_request_str but exercise the wrappers). */ |
755 | 1.64k | { |
756 | 1.64k | stun_buffer msg; |
757 | 1.64k | stun_init_buffer(&msg); |
758 | 1.64k | stun_set_binding_request(&msg); |
759 | 1.64k | inspect_buffer_message(&msg, STUN_ATTRIBUTE_MAPPED_ADDRESS, &default_addr); |
760 | | |
761 | 1.64k | stun_init_buffer(&msg); |
762 | 1.64k | stun_prepare_binding_request(&msg); |
763 | 1.64k | inspect_buffer_message(&msg, STUN_ATTRIBUTE_MAPPED_ADDRESS, &default_addr); |
764 | 1.64k | } |
765 | | |
766 | | /* stun_init_channel_message + stun_is_channel_message wrappers. */ |
767 | 1.64k | { |
768 | 1.64k | stun_buffer msg; |
769 | 1.64k | stun_init_buffer(&msg); |
770 | 1.64k | if (stun_init_channel_message(channel_number, &msg, chan_payload_len, padding)) { |
771 | 1.64k | uint16_t parsed_chn = 0; |
772 | 1.64k | (void)stun_is_channel_message(&msg, &parsed_chn, true); |
773 | 1.64k | (void)stun_is_channel_message(&msg, &parsed_chn, false); |
774 | 1.64k | } |
775 | 1.64k | { |
776 | 1.64k | uint16_t chn = 0; |
777 | 1.64k | (void)stun_is_channel_message(NULL, &chn, false); |
778 | 1.64k | } |
779 | 1.64k | } |
780 | | |
781 | | /* Raw fuzzer bytes through the wrapper-form predicates so they see |
782 | | * malformed inputs the serializer paths above never produce. */ |
783 | 1.64k | { |
784 | 1.64k | stun_buffer msg; |
785 | 1.64k | msg.len = Size > sizeof(msg.buf) ? sizeof(msg.buf) : Size; |
786 | 1.64k | memcpy(msg.buf, Data, msg.len); |
787 | | |
788 | 1.64k | (void)stun_is_indication(&msg); |
789 | | |
790 | 1.64k | stun_tid extracted = {0}; |
791 | 1.64k | stun_tid_from_message(&msg, &extracted); |
792 | | |
793 | 1.64k | { |
794 | 1.64k | uint16_t chn = 0; |
795 | 1.64k | const size_t saved_len = msg.len; |
796 | 1.64k | (void)stun_is_channel_message(&msg, &chn, true); |
797 | 1.64k | msg.len = saved_len; |
798 | 1.64k | (void)stun_is_channel_message(&msg, &chn, false); |
799 | 1.64k | } |
800 | | |
801 | 1.64k | (void)stun_attr_get_first_by_type(&msg, STUN_ATTRIBUTE_USERNAME); |
802 | 1.64k | (void)stun_attr_get_first_by_type(&msg, STUN_ATTRIBUTE_XOR_PEER_ADDRESS); |
803 | 1.64k | (void)stun_attr_get_first_by_type(&msg, STUN_ATTRIBUTE_CHANNEL_NUMBER); |
804 | 1.64k | } |
805 | 1.64k | } |
806 | | |
807 | | /* ------------------------------------------------------------------ */ |
808 | | /* libFuzzer entry point — run every harness on each input. */ |
809 | | /* */ |
810 | | /* Note: OAuth token sub-harnesses are intentionally omitted here. */ |
811 | | /* decode_oauth_token_gcm in src/client/ns_turn_msg.c leaks the */ |
812 | | /* EVP_CIPHER_CTX on several early-return paths, which trips ASan */ |
813 | | /* under CIFuzz. Those harnesses will be re-added once the library */ |
814 | | /* leak is fixed in a separate PR. */ |
815 | | /* ------------------------------------------------------------------ */ |
816 | 3.51k | extern int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) { |
817 | 3.51k | harness_stun_client(Data, Size); |
818 | 3.51k | harness_channel_data(Data, Size); |
819 | 3.51k | harness_addr_codec(Data, Size); |
820 | 3.51k | harness_message_builders(Data, Size); |
821 | 3.51k | harness_attr_get_first_addr(Data, Size); |
822 | 3.51k | harness_response_matrix(Data, Size); |
823 | 3.51k | harness_stun_buffer_api(Data, Size); |
824 | 3.51k | return 0; |
825 | 3.51k | } |