/src/curl_fuzzer/curl_fuzzer.cc
Line | Count | Source (jump to first uncovered line) |
1 | | /*************************************************************************** |
2 | | * _ _ ____ _ |
3 | | * Project ___| | | | _ \| | |
4 | | * / __| | | | |_) | | |
5 | | * | (__| |_| | _ <| |___ |
6 | | * \___|\___/|_| \_\_____| |
7 | | * |
8 | | * Copyright (C) 2017 - 2022, Max Dymond, <cmeister2@gmail.com>, et al. |
9 | | * |
10 | | * This software is licensed as described in the file COPYING, which |
11 | | * you should have received as part of this distribution. The terms |
12 | | * are also available at https://curl.se/docs/copyright.html. |
13 | | * |
14 | | * You may opt to use, copy, modify, merge, publish, distribute and/or sell |
15 | | * copies of the Software, and permit persons to whom the Software is |
16 | | * furnished to do so, under the terms of the COPYING file. |
17 | | * |
18 | | * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY |
19 | | * KIND, either express or implied. |
20 | | * |
21 | | ***************************************************************************/ |
22 | | |
23 | | #include <stdlib.h> |
24 | | #include <signal.h> |
25 | | #include <string.h> |
26 | | #include <unistd.h> |
27 | | #include <curl/curl.h> |
28 | | #include "curl_fuzzer.h" |
29 | | |
30 | | /** |
31 | | * Fuzzing entry point. This function is passed a buffer containing a test |
32 | | * case. This test case should drive the CURL API into making a request. |
33 | | */ |
34 | | extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) |
35 | 1.15k | { |
36 | 1.15k | int rc = 0; |
37 | 1.15k | int tlv_rc; |
38 | 1.15k | FUZZ_DATA fuzz; |
39 | 1.15k | TLV tlv; |
40 | | |
41 | | /* Ignore SIGPIPE errors. We'll handle the errors ourselves. */ |
42 | 1.15k | signal(SIGPIPE, SIG_IGN); |
43 | | |
44 | | /* Have to set all fields to zero before getting to the terminate function */ |
45 | 1.15k | memset(&fuzz, 0, sizeof(FUZZ_DATA)); |
46 | | |
47 | 1.15k | if(size < sizeof(TLV_RAW)) { |
48 | | /* Not enough data for a single TLV - don't continue */ |
49 | 4 | goto EXIT_LABEL; |
50 | 4 | } |
51 | | |
52 | | /* Try to initialize the fuzz data */ |
53 | 1.15k | FTRY(fuzz_initialize_fuzz_data(&fuzz, data, size)); |
54 | | |
55 | 1.15k | for(tlv_rc = fuzz_get_first_tlv(&fuzz, &tlv); |
56 | 73.8k | tlv_rc == 0; |
57 | 73.0k | tlv_rc = fuzz_get_next_tlv(&fuzz, &tlv)) { |
58 | | |
59 | | /* Have the TLV in hand. Parse the TLV. */ |
60 | 73.0k | rc = fuzz_parse_tlv(&fuzz, &tlv); |
61 | | |
62 | 73.0k | if(rc != 0) { |
63 | | /* Failed to parse the TLV. Can't continue. */ |
64 | 374 | goto EXIT_LABEL; |
65 | 374 | } |
66 | 73.0k | } |
67 | | |
68 | 778 | if(tlv_rc != TLV_RC_NO_MORE_TLVS) { |
69 | | /* A TLV call failed. Can't continue. */ |
70 | 87 | goto EXIT_LABEL; |
71 | 87 | } |
72 | | |
73 | | /* Set up the standard easy options. */ |
74 | 691 | FTRY(fuzz_set_easy_options(&fuzz)); |
75 | | |
76 | | /** |
77 | | * Add in more curl options that have been accumulated over possibly |
78 | | * multiple TLVs. |
79 | | */ |
80 | 0 | if(fuzz.header_list != NULL) { |
81 | 0 | curl_easy_setopt(fuzz.easy, CURLOPT_HTTPHEADER, fuzz.header_list); |
82 | 0 | } |
83 | |
|
84 | 0 | if(fuzz.mail_recipients_list != NULL) { |
85 | 0 | curl_easy_setopt(fuzz.easy, CURLOPT_MAIL_RCPT, fuzz.mail_recipients_list); |
86 | 0 | } |
87 | |
|
88 | 0 | if(fuzz.mime != NULL) { |
89 | 0 | curl_easy_setopt(fuzz.easy, CURLOPT_MIMEPOST, fuzz.mime); |
90 | 0 | } |
91 | |
|
92 | 0 | if (fuzz.httppost != NULL) { |
93 | 0 | curl_easy_setopt(fuzz.easy, CURLOPT_HTTPPOST, fuzz.httppost); |
94 | 0 | } |
95 | | |
96 | | /* Run the transfer. */ |
97 | 0 | fuzz_handle_transfer(&fuzz); |
98 | |
|
99 | 1.15k | EXIT_LABEL: |
100 | | |
101 | 1.15k | fuzz_terminate_fuzz_data(&fuzz); |
102 | | |
103 | | /* This function must always return 0. Non-zero codes are reserved. */ |
104 | 1.15k | return 0; |
105 | 0 | } |
106 | | |
107 | | /** |
108 | | * Utility function to convert 4 bytes to a u32 predictably. |
109 | | */ |
110 | | uint32_t to_u32(const uint8_t b[4]) |
111 | 113k | { |
112 | 113k | uint32_t u; |
113 | 113k | u = (b[0] << 24) + (b[1] << 16) + (b[2] << 8) + b[3]; |
114 | 113k | return u; |
115 | 113k | } |
116 | | |
117 | | /** |
118 | | * Utility function to convert 2 bytes to a u16 predictably. |
119 | | */ |
120 | | uint16_t to_u16(const uint8_t b[2]) |
121 | 112k | { |
122 | 112k | uint16_t u; |
123 | 112k | u = (b[0] << 8) + b[1]; |
124 | 112k | return u; |
125 | 112k | } |
126 | | |
127 | | /** |
128 | | * Initialize the local fuzz data structure. |
129 | | */ |
130 | | int fuzz_initialize_fuzz_data(FUZZ_DATA *fuzz, |
131 | | const uint8_t *data, |
132 | | size_t data_len) |
133 | 1.15k | { |
134 | 1.15k | int rc = 0; |
135 | 1.15k | int ii; |
136 | | |
137 | | /* Initialize the fuzz data. */ |
138 | 1.15k | memset(fuzz, 0, sizeof(FUZZ_DATA)); |
139 | | |
140 | | /* Create an easy handle. This will have all of the settings configured on |
141 | | it. */ |
142 | 1.15k | fuzz->easy = curl_easy_init(); |
143 | 1.15k | FCHECK(fuzz->easy != NULL); |
144 | | |
145 | | /* Set up the state parser */ |
146 | 1.15k | fuzz->state.data = data; |
147 | 1.15k | fuzz->state.data_len = data_len; |
148 | | |
149 | | /* Set up the state of the server sockets. */ |
150 | 3.45k | for(ii = 0; ii < FUZZ_NUM_CONNECTIONS; ii++) { |
151 | 2.30k | fuzz->sockman[ii].index = ii; |
152 | 2.30k | fuzz->sockman[ii].fd_state = FUZZ_SOCK_CLOSED; |
153 | 2.30k | } |
154 | | |
155 | | /* Check for verbose mode. */ |
156 | 1.15k | fuzz->verbose = (getenv("FUZZ_VERBOSE") != NULL); |
157 | | |
158 | 1.15k | FCHECK(setenv("CURL_HSTS_HTTP", "1", 0) == 0); |
159 | 1.15k | FCHECK(setenv("CURL_ALTSVC_HTTP", "1", 0) == 0); |
160 | | |
161 | 1.15k | EXIT_LABEL: |
162 | | |
163 | 1.15k | return rc; |
164 | 1.15k | } |
165 | | |
166 | | /** |
167 | | * Set standard options on the curl easy. |
168 | | */ |
169 | | int fuzz_set_easy_options(FUZZ_DATA *fuzz) |
170 | 691 | { |
171 | 691 | int rc = 0; |
172 | 691 | unsigned long allowed_protocols; |
173 | | |
174 | | /* Set some standard options on the CURL easy handle. We need to override the |
175 | | socket function so that we create our own sockets to present to CURL. */ |
176 | 691 | FTRY(curl_easy_setopt(fuzz->easy, |
177 | 691 | CURLOPT_OPENSOCKETFUNCTION, |
178 | 691 | fuzz_open_socket)); |
179 | 691 | FTRY(curl_easy_setopt(fuzz->easy, CURLOPT_OPENSOCKETDATA, fuzz)); |
180 | | |
181 | | /* In case something tries to set a socket option, intercept this. */ |
182 | 691 | FTRY(curl_easy_setopt(fuzz->easy, |
183 | 691 | CURLOPT_SOCKOPTFUNCTION, |
184 | 691 | fuzz_sockopt_callback)); |
185 | | |
186 | | /* Set the standard read function callback. */ |
187 | 691 | FTRY(curl_easy_setopt(fuzz->easy, |
188 | 691 | CURLOPT_READFUNCTION, |
189 | 691 | fuzz_read_callback)); |
190 | 691 | FTRY(curl_easy_setopt(fuzz->easy, CURLOPT_READDATA, fuzz)); |
191 | | |
192 | | /* Set the standard write function callback. */ |
193 | 691 | FTRY(curl_easy_setopt(fuzz->easy, |
194 | 691 | CURLOPT_WRITEFUNCTION, |
195 | 691 | fuzz_write_callback)); |
196 | 691 | FTRY(curl_easy_setopt(fuzz->easy, CURLOPT_WRITEDATA, fuzz)); |
197 | | |
198 | | /* Set the writable cookie jar path so cookies are tested. */ |
199 | 691 | FTRY(curl_easy_setopt(fuzz->easy, CURLOPT_COOKIEJAR, FUZZ_COOKIE_JAR_PATH)); |
200 | | |
201 | | /* Set the RO cookie file path so cookies are tested. */ |
202 | 691 | FTRY(curl_easy_setopt(fuzz->easy, CURLOPT_COOKIEFILE, FUZZ_RO_COOKIE_FILE_PATH)); |
203 | | |
204 | | /* Set altsvc header cache filepath so that it can be fuzzed. */ |
205 | 691 | FTRY(curl_easy_setopt(fuzz->easy, CURLOPT_ALTSVC, FUZZ_ALT_SVC_HEADER_CACHE_PATH)); |
206 | | |
207 | | /* Set the hsts header cache filepath so that it can be fuzzed. */ |
208 | 691 | FTRY(curl_easy_setopt(fuzz->easy, CURLOPT_HSTS, FUZZ_HSTS_HEADER_CACHE_PATH)); |
209 | | |
210 | | /* Set the Certificate Revocation List file path so it can be fuzzed */ |
211 | 0 | FTRY(curl_easy_setopt(fuzz->easy, CURLOPT_CRLFILE, FUZZ_CRL_FILE_PATH)); |
212 | | |
213 | | /* Set the .netrc file path so it can be fuzzed */ |
214 | 0 | FTRY(curl_easy_setopt(fuzz->easy, CURLOPT_NETRC_FILE, FUZZ_NETRC_FILE_PATH)); |
215 | | |
216 | | /* Time out requests quickly. */ |
217 | 0 | FTRY(curl_easy_setopt(fuzz->easy, CURLOPT_TIMEOUT_MS, 200L)); |
218 | 0 | FTRY(curl_easy_setopt(fuzz->easy, CURLOPT_SERVER_RESPONSE_TIMEOUT, 1L)); |
219 | | |
220 | | /* Can enable verbose mode by having the environment variable FUZZ_VERBOSE. */ |
221 | 0 | if(fuzz->verbose) { |
222 | 0 | FTRY(curl_easy_setopt(fuzz->easy, CURLOPT_VERBOSE, 1L)); |
223 | 0 | } |
224 | | |
225 | | /* Force resolution of all addresses to a specific IP address. */ |
226 | 0 | fuzz->connect_to_list = curl_slist_append(NULL, "::127.0.1.127:"); |
227 | 0 | FTRY(curl_easy_setopt(fuzz->easy, CURLOPT_CONNECT_TO, fuzz->connect_to_list)); |
228 | | |
229 | | /* Limit the protocols in use by this fuzzer. */ |
230 | 0 | FTRY(fuzz_set_allowed_protocols(fuzz)); |
231 | |
|
232 | 691 | EXIT_LABEL: |
233 | | |
234 | 691 | return rc; |
235 | 0 | } |
236 | | |
237 | | /** |
238 | | * Terminate the fuzz data structure, including freeing any allocated memory. |
239 | | */ |
240 | | void fuzz_terminate_fuzz_data(FUZZ_DATA *fuzz) |
241 | 1.15k | { |
242 | 1.15k | int ii; |
243 | | |
244 | 1.15k | fuzz_free((void **)&fuzz->postfields); |
245 | | |
246 | 3.46k | for(ii = 0; ii < FUZZ_NUM_CONNECTIONS; ii++) { |
247 | 2.31k | if(fuzz->sockman[ii].fd_state != FUZZ_SOCK_CLOSED) { |
248 | 0 | close(fuzz->sockman[ii].fd); |
249 | 0 | fuzz->sockman[ii].fd_state = FUZZ_SOCK_CLOSED; |
250 | 0 | } |
251 | 2.31k | } |
252 | | |
253 | 1.15k | if(fuzz->connect_to_list != NULL) { |
254 | 0 | curl_slist_free_all(fuzz->connect_to_list); |
255 | 0 | fuzz->connect_to_list = NULL; |
256 | 0 | } |
257 | | |
258 | 1.15k | if(fuzz->header_list != NULL) { |
259 | 52 | curl_slist_free_all(fuzz->header_list); |
260 | 52 | fuzz->header_list = NULL; |
261 | 52 | } |
262 | | |
263 | 1.15k | if(fuzz->mail_recipients_list != NULL) { |
264 | 41 | curl_slist_free_all(fuzz->mail_recipients_list); |
265 | 41 | fuzz->mail_recipients_list = NULL; |
266 | 41 | } |
267 | | |
268 | 1.15k | if(fuzz->mime != NULL) { |
269 | 170 | curl_mime_free(fuzz->mime); |
270 | 170 | fuzz->mime = NULL; |
271 | 170 | } |
272 | | |
273 | 1.15k | if(fuzz->easy != NULL) { |
274 | 1.15k | curl_easy_cleanup(fuzz->easy); |
275 | 1.15k | fuzz->easy = NULL; |
276 | 1.15k | } |
277 | | |
278 | | /* When you have passed the struct curl_httppost pointer to curl_easy_setopt |
279 | | * (using the CURLOPT_HTTPPOST option), you must not free the list until after |
280 | | * you have called curl_easy_cleanup for the curl handle. |
281 | | * https://curl.se/libcurl/c/curl_formadd.html */ |
282 | 1.15k | if (fuzz->httppost != NULL) { |
283 | 31 | curl_formfree(fuzz->httppost); |
284 | 31 | fuzz->httppost = NULL; |
285 | 31 | } |
286 | | |
287 | | // free after httppost and last_post_part. |
288 | 1.15k | if (fuzz->post_body != NULL) { |
289 | 31 | fuzz_free((void **)&fuzz->post_body); |
290 | 31 | } |
291 | 1.15k | } |
292 | | |
293 | | /** |
294 | | * If a pointer has been allocated, free that pointer. |
295 | | */ |
296 | | void fuzz_free(void **ptr) |
297 | 108k | { |
298 | 108k | if(*ptr != NULL) { |
299 | 59.6k | free(*ptr); |
300 | 59.6k | *ptr = NULL; |
301 | 59.6k | } |
302 | 108k | } |
303 | | |
304 | | /** |
305 | | * Function for handling the fuzz transfer, including sending responses to |
306 | | * requests. |
307 | | */ |
308 | | int fuzz_handle_transfer(FUZZ_DATA *fuzz) |
309 | 0 | { |
310 | 0 | int rc = 0; |
311 | 0 | CURLM *multi_handle; |
312 | 0 | int still_running; /* keep number of running handles */ |
313 | 0 | CURLMsg *msg; /* for picking up messages with the transfer status */ |
314 | 0 | int msgs_left; /* how many messages are left */ |
315 | 0 | int double_timeout = 0; |
316 | 0 | fd_set fdread; |
317 | 0 | fd_set fdwrite; |
318 | 0 | fd_set fdexcep; |
319 | 0 | struct timeval timeout; |
320 | 0 | int select_rc; |
321 | 0 | CURLMcode mc; |
322 | 0 | int maxfd = -1; |
323 | 0 | long curl_timeo = -1; |
324 | 0 | int ii; |
325 | 0 | FUZZ_SOCKET_MANAGER *sman[FUZZ_NUM_CONNECTIONS]; |
326 | |
|
327 | 0 | for(ii = 0; ii < FUZZ_NUM_CONNECTIONS; ii++) { |
328 | 0 | sman[ii] = &fuzz->sockman[ii]; |
329 | | |
330 | | /* Set up the starting index for responses. */ |
331 | 0 | sman[ii]->response_index = 1; |
332 | 0 | } |
333 | | |
334 | | /* init a multi stack */ |
335 | 0 | multi_handle = curl_multi_init(); |
336 | | |
337 | | /* add the individual transfers */ |
338 | 0 | curl_multi_add_handle(multi_handle, fuzz->easy); |
339 | | |
340 | | /* Do an initial process. This might end the transfer immediately. */ |
341 | 0 | curl_multi_perform(multi_handle, &still_running); |
342 | 0 | FV_PRINTF(fuzz, |
343 | 0 | "FUZZ: Initial perform; still running? %d \n", |
344 | 0 | still_running); |
345 | |
|
346 | 0 | while(still_running) { |
347 | | /* Reset the sets of file descriptors. */ |
348 | 0 | FD_ZERO(&fdread); |
349 | 0 | FD_ZERO(&fdwrite); |
350 | 0 | FD_ZERO(&fdexcep); |
351 | | |
352 | | /* Set a timeout of 10ms. This is lower than recommended by the multi guide |
353 | | but we're not going to any remote servers, so everything should complete |
354 | | very quickly. */ |
355 | 0 | timeout.tv_sec = 0; |
356 | 0 | timeout.tv_usec = 10000; |
357 | | |
358 | | /* get file descriptors from the transfers */ |
359 | 0 | mc = curl_multi_fdset(multi_handle, &fdread, &fdwrite, &fdexcep, &maxfd); |
360 | 0 | if(mc != CURLM_OK) { |
361 | 0 | fprintf(stderr, "curl_multi_fdset() failed, code %d.\n", mc); |
362 | 0 | rc = -1; |
363 | 0 | break; |
364 | 0 | } |
365 | | |
366 | 0 | for(ii = 0; ii < FUZZ_NUM_CONNECTIONS; ii++) { |
367 | | /* Add the socket FD into the readable set if connected. */ |
368 | 0 | if(sman[ii]->fd_state == FUZZ_SOCK_OPEN) { |
369 | 0 | FD_SET(sman[ii]->fd, &fdread); |
370 | | |
371 | | /* Work out the maximum FD between the cURL file descriptors and the |
372 | | server FD. */ |
373 | 0 | maxfd = FUZZ_MAX(sman[ii]->fd, maxfd); |
374 | 0 | } |
375 | 0 | } |
376 | | |
377 | | /* Work out what file descriptors need work. */ |
378 | 0 | rc = fuzz_select(maxfd + 1, &fdread, &fdwrite, &fdexcep, &timeout); |
379 | |
|
380 | 0 | if(rc == -1) { |
381 | | /* Had an issue while selecting a file descriptor. Let's just exit. */ |
382 | 0 | FV_PRINTF(fuzz, "FUZZ: select failed, exiting \n"); |
383 | 0 | break; |
384 | 0 | } |
385 | 0 | else if(rc == 0) { |
386 | 0 | FV_PRINTF(fuzz, |
387 | 0 | "FUZZ: Timed out; double timeout? %d \n", |
388 | 0 | double_timeout); |
389 | | |
390 | | /* Timed out. */ |
391 | 0 | if(double_timeout == 1) { |
392 | | /* We don't expect multiple timeouts in a row. If there are double |
393 | | timeouts then exit. */ |
394 | 0 | break; |
395 | 0 | } |
396 | 0 | else { |
397 | | /* Set the timeout flag for the next time we select(). */ |
398 | 0 | double_timeout = 1; |
399 | 0 | } |
400 | 0 | } |
401 | 0 | else { |
402 | | /* There's an active file descriptor. Reset the timeout flag. */ |
403 | 0 | double_timeout = 0; |
404 | 0 | } |
405 | | |
406 | | /* Check to see if a server file descriptor is readable. If it is, |
407 | | then send the next response from the fuzzing data. */ |
408 | 0 | for(ii = 0; ii < FUZZ_NUM_CONNECTIONS; ii++) { |
409 | 0 | if(sman[ii]->fd_state == FUZZ_SOCK_OPEN && |
410 | 0 | FD_ISSET(sman[ii]->fd, &fdread)) { |
411 | 0 | rc = fuzz_send_next_response(fuzz, sman[ii]); |
412 | 0 | if(rc != 0) { |
413 | | /* Failed to send a response. Break out here. */ |
414 | 0 | break; |
415 | 0 | } |
416 | 0 | } |
417 | 0 | } |
418 | |
|
419 | 0 | curl_multi_perform(multi_handle, &still_running); |
420 | 0 | } |
421 | | |
422 | | /* Remove the easy handle from the multi stack. */ |
423 | 0 | curl_multi_remove_handle(multi_handle, fuzz->easy); |
424 | | |
425 | | /* Clean up the multi handle - the top level function will handle the easy |
426 | | handle. */ |
427 | 0 | curl_multi_cleanup(multi_handle); |
428 | |
|
429 | 0 | return(rc); |
430 | 0 | } |
431 | | |
432 | | /** |
433 | | * Sends the next fuzzing response to the server file descriptor. |
434 | | */ |
435 | | int fuzz_send_next_response(FUZZ_DATA *fuzz, FUZZ_SOCKET_MANAGER *sman) |
436 | 0 | { |
437 | 0 | int rc = 0; |
438 | 0 | ssize_t ret_in; |
439 | 0 | ssize_t ret_out; |
440 | 0 | char buffer[8192]; |
441 | 0 | const uint8_t *data; |
442 | 0 | size_t data_len; |
443 | | |
444 | | /* Need to read all data sent by the client so the file descriptor becomes |
445 | | unreadable. Because the file descriptor is non-blocking we won't just |
446 | | hang here. */ |
447 | 0 | do { |
448 | 0 | ret_in = read(sman->fd, buffer, sizeof(buffer)); |
449 | 0 | if(fuzz->verbose && ret_in > 0) { |
450 | 0 | printf("FUZZ[%d]: Received %zu bytes \n==>\n", sman->index, ret_in); |
451 | 0 | fwrite(buffer, ret_in, 1, stdout); |
452 | 0 | printf("\n<==\n"); |
453 | 0 | } |
454 | 0 | } while (ret_in > 0); |
455 | | |
456 | | /* Now send a response to the request that the client just made. */ |
457 | 0 | FV_PRINTF(fuzz, |
458 | 0 | "FUZZ[%d]: Sending next response: %d \n", |
459 | 0 | sman->index, |
460 | 0 | sman->response_index); |
461 | 0 | data = sman->responses[sman->response_index].data; |
462 | 0 | data_len = sman->responses[sman->response_index].data_len; |
463 | |
|
464 | 0 | if(data != NULL) { |
465 | 0 | if(write(sman->fd, data, data_len) != (ssize_t)data_len) { |
466 | | /* Failed to write the data back to the client. Prevent any further |
467 | | testing. */ |
468 | 0 | rc = -1; |
469 | 0 | } |
470 | 0 | } |
471 | | |
472 | | /* Work out if there are any more responses. If not, then shut down the |
473 | | server. */ |
474 | 0 | sman->response_index++; |
475 | |
|
476 | 0 | if(sman->response_index >= TLV_MAX_NUM_RESPONSES || |
477 | 0 | sman->responses[sman->response_index].data == NULL) { |
478 | 0 | FV_PRINTF(fuzz, |
479 | 0 | "FUZZ[%d]: Shutting down server socket: %d \n", |
480 | 0 | sman->index, |
481 | 0 | sman->fd); |
482 | 0 | shutdown(sman->fd, SHUT_WR); |
483 | 0 | sman->fd_state = FUZZ_SOCK_SHUTDOWN; |
484 | 0 | } |
485 | |
|
486 | 0 | return(rc); |
487 | 0 | } |
488 | | |
489 | | /** |
490 | | * Wrapper for select() so profiling can track it. |
491 | | */ |
492 | | int fuzz_select(int nfds, |
493 | | fd_set *readfds, |
494 | | fd_set *writefds, |
495 | | fd_set *exceptfds, |
496 | 0 | struct timeval *timeout) { |
497 | 0 | return select(nfds, readfds, writefds, exceptfds, timeout); |
498 | 0 | } |
499 | | |
500 | | /** |
501 | | * Set allowed protocols based on the compile options. |
502 | | * |
503 | | * Note that it can only use ONE of the FUZZ_PROTOCOLS_* defines.a |
504 | | */ |
505 | | int fuzz_set_allowed_protocols(FUZZ_DATA *fuzz) |
506 | 0 | { |
507 | 0 | int rc = 0; |
508 | 0 | const char *allowed_protocols = ""; |
509 | |
|
510 | | #ifdef FUZZ_PROTOCOLS_ALL |
511 | | /* Do not allow telnet currently as it accepts input from stdin. */ |
512 | | allowed_protocols = |
513 | | "dict,file,ftp,ftps,gopher,gophers,http,https,imap,imaps," |
514 | | "ldap,ldaps,mqtt,pop3,pop3s,rtmp,rtmpe,rtmps,rtmpt,rtmpte,rtmpts," |
515 | | "rtsp,scp,sftp,smb,smbs,smtp,smtps,tftp"; |
516 | | #endif |
517 | | #ifdef FUZZ_PROTOCOLS_DICT |
518 | | allowed_protocols = "dict"; |
519 | | #endif |
520 | | #ifdef FUZZ_PROTOCOLS_FILE |
521 | | allowed_protocols = "file"; |
522 | | #endif |
523 | | #ifdef FUZZ_PROTOCOLS_FTP |
524 | | allowed_protocols = "ftp,ftps"; |
525 | | #endif |
526 | | #ifdef FUZZ_PROTOCOLS_GOPHER |
527 | | allowed_protocols = "gopher,gophers"; |
528 | | #endif |
529 | | #ifdef FUZZ_PROTOCOLS_HTTP |
530 | | allowed_protocols = "http"; |
531 | | #endif |
532 | | #ifdef FUZZ_PROTOCOLS_HTTPS |
533 | | allowed_protocols = "https"; |
534 | | #endif |
535 | | #ifdef FUZZ_PROTOCOLS_IMAP |
536 | | allowed_protocols = "imap,imaps"; |
537 | | #endif |
538 | | #ifdef FUZZ_PROTOCOLS_LDAP |
539 | | allowed_protocols = "ldap,ldaps"; |
540 | | #endif |
541 | | #ifdef FUZZ_PROTOCOLS_MQTT |
542 | | allowed_protocols = "mqtt"; |
543 | | #endif |
544 | | #ifdef FUZZ_PROTOCOLS_POP3 |
545 | | allowed_protocols = "pop3,pop3s"; |
546 | | #endif |
547 | | #ifdef FUZZ_PROTOCOLS_RTMP |
548 | | allowed_protocols = "rtmp,rtmpe,rtmps,rtmpt,rtmpte,rtmpts"; |
549 | | #endif |
550 | | #ifdef FUZZ_PROTOCOLS_RTSP |
551 | | allowed_protocols = "rtsp"; |
552 | | #endif |
553 | | #ifdef FUZZ_PROTOCOLS_SCP |
554 | | allowed_protocols = "scp"; |
555 | | #endif |
556 | | #ifdef FUZZ_PROTOCOLS_SFTP |
557 | | allowed_protocols = "sftp"; |
558 | | #endif |
559 | | #ifdef FUZZ_PROTOCOLS_SMB |
560 | | allowed_protocols = "smb,smbs"; |
561 | | #endif |
562 | 0 | #ifdef FUZZ_PROTOCOLS_SMTP |
563 | 0 | allowed_protocols = "smtp,smtps"; |
564 | 0 | #endif |
565 | | #ifdef FUZZ_PROTOCOLS_TFTP |
566 | | allowed_protocols = "tftp"; |
567 | | #endif |
568 | | #ifdef FUZZ_PROTOCOLS_WS |
569 | | allowed_protocols = "ws,wss"; |
570 | | #endif |
571 | |
|
572 | 0 | FTRY(curl_easy_setopt(fuzz->easy, CURLOPT_PROTOCOLS_STR, allowed_protocols)); |
573 | |
|
574 | 0 | EXIT_LABEL: |
575 | |
|
576 | 0 | return rc; |
577 | 0 | } |