Line data Source code
1 : #if !FD_HAS_HOSTED
2 : #error "This target requires FD_HAS_HOSTED"
3 : #endif
4 :
5 : #include <assert.h>
6 : #include <stdio.h>
7 : #include <stdlib.h>
8 : #include <unistd.h>
9 : #include <arpa/inet.h>
10 : #include <netinet/in.h>
11 : #include <pthread.h>
12 : #include <poll.h>
13 : #include <errno.h>
14 :
15 : #include "../../util/fd_util.h"
16 : #include "../../util/sanitize/fd_fuzz.h"
17 : #include "fd_http_server_private.h"
18 : #include "fd_http_server.h"
19 :
20 0 : #define FD_HTTP_SERVER_GUI_MAX_CONNS 4
21 : #define FD_HTTP_SERVER_GUI_MAX_REQUEST_LEN 2048
22 0 : #define FD_HTTP_SERVER_GUI_MAX_WS_CONNS 4
23 : #define FD_HTTP_SERVER_GUI_MAX_WS_RECV_FRAME_LEN 2048
24 : #define FD_HTTP_SERVER_GUI_MAX_WS_SEND_FRAME_CNT 8192
25 : #define FD_HTTP_SERVER_GUI_OUTGOING_BUFFER_SZ (1UL<<28UL) /* 256MiB reserved for buffering GUI websockets */
26 :
27 : const fd_http_server_params_t PARAMS = {
28 : .max_connection_cnt = FD_HTTP_SERVER_GUI_MAX_CONNS,
29 : .max_ws_connection_cnt = FD_HTTP_SERVER_GUI_MAX_WS_CONNS,
30 : .max_request_len = FD_HTTP_SERVER_GUI_MAX_REQUEST_LEN,
31 : .max_ws_recv_frame_len = FD_HTTP_SERVER_GUI_MAX_WS_RECV_FRAME_LEN,
32 : .max_ws_send_frame_cnt = FD_HTTP_SERVER_GUI_MAX_WS_SEND_FRAME_CNT,
33 : .outgoing_buffer_sz = FD_HTTP_SERVER_GUI_OUTGOING_BUFFER_SZ,
34 : };
35 :
36 : struct Unstructured {
37 : uchar const *data;
38 : ulong size;
39 : ulong used;
40 : };
41 :
42 0 : uchar rand_uchar(struct Unstructured *u) {
43 0 : if (sizeof(uchar) + u->used < u->size) {
44 0 : uchar v = *(uchar *)(u->data + u->used);
45 0 : u->used += sizeof(uchar);
46 0 : return v;
47 0 : }
48 0 : return (uchar) rand();
49 0 : }
50 :
51 0 : uint rand_uint(struct Unstructured *u) {
52 0 : if (sizeof(uint) + u->used < u->size) {
53 0 : uint v = *(uint *)(u->data + u->used);
54 0 : u->used += sizeof(uint);
55 0 : return v;
56 0 : }
57 0 : return (uint) rand();
58 0 : }
59 :
60 0 : ulong rand_ulong(struct Unstructured *u) {
61 0 : if (sizeof(ulong) + u->used < u->size) {
62 0 : ulong v = *(ulong *)(u->data + u->used);
63 0 : u->used += sizeof(ulong);
64 0 : return v;
65 0 : }
66 0 : return ((ulong)rand()) << 32 | ((ulong)rand());
67 0 : }
68 :
69 0 : void rand_bytes(struct Unstructured *u, size_t len, uchar *p) {
70 0 : if (len + u->used < u->size) {
71 0 : memcpy(p, u->data + u->used, len);
72 0 : u->used += len;
73 0 : } else {
74 0 : for (ulong i = 0; i < len; ++i) {
75 0 : p[i] = (uchar) rand();
76 0 : }
77 0 : }
78 0 : }
79 :
80 : void build_http_req(struct Unstructured *u, uchar *buf, int *len, int *use_websocket);
81 : void build_ws_req(struct Unstructured *u, uchar *buf, int *len);
82 :
83 : static fd_http_server_t *http_server = NULL;
84 : uint16_t port = 0;
85 : static int clients_fd[FD_HTTP_SERVER_GUI_MAX_CONNS * 2] = {-1};
86 : static char clients_ws_fd[FD_HTTP_SERVER_GUI_MAX_CONNS * 2] = {0};
87 : static uint clients_fd_cnt = 0;
88 :
89 0 : void reset_clients_fd(void) {
90 0 : clients_fd_cnt = 0;
91 0 : for (ulong i = 0; i < FD_HTTP_SERVER_GUI_MAX_CONNS * 2; ++i) {
92 0 : clients_fd[i] = -1;
93 0 : clients_ws_fd[i] = 0;
94 0 : }
95 0 : }
96 :
97 : int
98 : LLVMFuzzerInitialize( int * argc,
99 18 : char *** argv ) {
100 : /* Set up shell without signal handlers */
101 18 : putenv( "FD_LOG_BACKTRACE=0" );
102 18 : fd_boot( argc, argv );
103 18 : atexit( fd_halt );
104 18 : fd_log_level_core_set(3); /* crash on warning log */
105 :
106 : /* Disable parsing error logging */
107 18 : fd_log_level_stderr_set(4);
108 :
109 18 : reset_clients_fd();
110 :
111 18 : return 0;
112 18 : }
113 :
114 : typedef struct {
115 : uint32_t state;
116 : } Xorshift;
117 :
118 0 : void xorshift_init(Xorshift* x, uint32_t seed) {
119 0 : x->state = seed ? seed : 1;
120 0 : }
121 :
122 0 : uint32_t xorshift_next(Xorshift* x) {
123 0 : uint32_t s = x->state;
124 0 : s ^= s << 13;
125 0 : s ^= s >> 17;
126 0 : s ^= s << 5;
127 0 : x->state = s;
128 0 : return s;
129 0 : }
130 :
131 : static Xorshift poll_rng;
132 :
133 : void
134 : fd_http_server_close( fd_http_server_t * http,
135 : ulong conn_id,
136 : int reason );
137 :
138 : void
139 : fd_http_server_ws_close( fd_http_server_t * http,
140 : ulong ws_conn_id,
141 : int reason );
142 : int
143 : fd_http_server_ws_send( fd_http_server_t * http,
144 : ulong ws_conn_id );
145 :
146 : int
147 : fd_http_server_ws_broadcast( fd_http_server_t * http );
148 :
149 : void
150 : fd_http_server_printf( fd_http_server_t * http,
151 : char const * fmt,
152 : ... );
153 :
154 : void
155 : fd_http_server_memcpy( fd_http_server_t * http,
156 : uchar const * data,
157 : ulong data_len );
158 :
159 : void
160 : fd_http_server_stage_trunc( fd_http_server_t * http,
161 : ulong len );
162 :
163 : void
164 : fd_http_server_unstage( fd_http_server_t * http );
165 :
166 : int
167 : fd_http_server_stage_body( fd_http_server_t * http,
168 : fd_http_server_response_t * response );
169 :
170 0 : void random_api_call(Xorshift *u) {
171 0 : switch(xorshift_next(u) % 4) {
172 0 : case 0:
173 0 : {
174 0 : ulong pos = xorshift_next(u) % (FD_HTTP_SERVER_GUI_MAX_WS_CONNS);
175 0 : if (http_server->pollfds[ pos + http_server->max_conns ].fd != -1)
176 0 : fd_http_server_ws_send(http_server, pos);
177 0 : }
178 0 : break;
179 0 : case 1:
180 0 : {
181 0 : fd_http_server_ws_broadcast(http_server);
182 0 : }
183 0 : break;
184 0 : case 2:
185 0 : {
186 0 : char data[128];
187 0 : uint len = xorshift_next(u) % 128;
188 0 : memset(data, 0xcc, len);
189 0 : fd_http_server_memcpy(http_server, (uchar *)data, len);
190 0 : }
191 0 : break;
192 0 : case 3:
193 0 : {
194 0 : char data[128];
195 0 : uint len = xorshift_next(u) % 128;
196 0 : memset(data, 0xcc, len);
197 0 : fd_http_server_printf(http_server, "%s", data);
198 0 : }
199 0 : break;
200 0 : }
201 0 : }
202 :
203 0 : void open_callback( ulong conn_id, int sockfd, void * ctx ) {
204 0 : (void)conn_id;
205 0 : (void)sockfd;
206 0 : (void)ctx;
207 :
208 0 : for (uint i = 0; i < xorshift_next(&poll_rng) % 3; ++i) {
209 0 : random_api_call(&poll_rng);
210 0 : }
211 0 : }
212 :
213 0 : void close_callback( ulong conn_id, int reason, void * ctx ) {
214 0 : (void)conn_id;
215 0 : (void)reason;
216 0 : (void)ctx;
217 :
218 0 : for (uint i = 0; i < xorshift_next(&poll_rng) % 3; ++i) {
219 0 : random_api_call(&poll_rng);
220 0 : }
221 0 : }
222 :
223 0 : fd_http_server_response_t request_callback( fd_http_server_request_t const * request ) {
224 0 : (void)request;
225 :
226 0 : fd_http_server_response_t resp;
227 0 : memset(&resp, 0, sizeof(fd_http_server_response_t));
228 :
229 0 : switch(xorshift_next(&poll_rng) % 7) {
230 0 : case 0:
231 0 : {
232 0 : resp.status = 200;
233 0 : resp.upgrade_websocket = xorshift_next(&poll_rng) % 2;
234 0 : }
235 0 : break;
236 0 : case 1:
237 0 : {
238 0 : resp.status = 204;
239 0 : }
240 0 : break;
241 0 : case 2:
242 0 : {
243 0 : resp.status = 400;
244 0 : }
245 0 : break;
246 0 : case 3:
247 0 : {
248 0 : resp.status = 404;
249 0 : }
250 0 : break;
251 0 : case 4:
252 0 : {
253 0 : resp.status = 405;
254 0 : }
255 0 : break;
256 0 : case 5:
257 0 : {
258 0 : resp.status = 500;
259 0 : }
260 0 : break;
261 0 : default:
262 0 : {
263 0 : resp.status = xorshift_next(&poll_rng);
264 0 : }
265 0 : break;
266 0 : }
267 :
268 0 : if (xorshift_next(&poll_rng) % 2 == 0) {
269 0 : resp.content_type = "Any content_type";
270 0 : }
271 :
272 0 : if (xorshift_next(&poll_rng) % 2 == 0) {
273 0 : resp.cache_control = "Any cache_control";
274 0 : }
275 :
276 0 : if (xorshift_next(&poll_rng) % 2 == 0) {
277 0 : resp.content_encoding = "Any content_encoding";
278 0 : }
279 :
280 0 : if (xorshift_next(&poll_rng) % 2 == 0) {
281 0 : resp.access_control_allow_origin = "Any access_control_allow_origin";
282 0 : }
283 :
284 0 : if (xorshift_next(&poll_rng) % 2 == 0) {
285 0 : resp.access_control_allow_methods = "Any access_control_allow_methods";
286 0 : }
287 :
288 0 : if (xorshift_next(&poll_rng) % 2 == 0) {
289 0 : resp.access_control_allow_headers = "Any access_control_allow_headers";
290 0 : }
291 :
292 0 : if (xorshift_next(&poll_rng) % 2 == 0) {
293 0 : resp.access_control_max_age = ((ulong)(&poll_rng) << 32) | (ulong)xorshift_next(&poll_rng);
294 0 : }
295 :
296 0 : if (xorshift_next(&poll_rng) % 2 == 0) {
297 0 : resp.static_body = (const uchar *) "resp_body";
298 0 : resp.static_body_len = 9;
299 0 : }
300 :
301 0 : if (request->headers.upgrade_websocket && (xorshift_next(&poll_rng) % 100) > 0) {
302 0 : resp.status = 200;
303 0 : resp.upgrade_websocket = 1;
304 0 : }
305 :
306 0 : for (uint i = 0; i < xorshift_next(&poll_rng) % 3; ++i) {
307 0 : random_api_call(&poll_rng);
308 0 : }
309 :
310 0 : return resp;
311 0 : }
312 :
313 0 : void ws_open_callback( ulong ws_conn_id, void * ctx ) {
314 0 : (void) ws_conn_id;
315 0 : (void) ctx;
316 :
317 0 : for (uint i = 0; i < xorshift_next(&poll_rng) % 3; ++i) {
318 0 : random_api_call(&poll_rng);
319 0 : }
320 0 : }
321 :
322 0 : void ws_close_callback( ulong ws_conn_id, int reason, void * ctx ) {
323 0 : (void) ws_conn_id;
324 0 : (void) reason;
325 0 : (void) ctx;
326 :
327 0 : for (uint i = 0; i < xorshift_next(&poll_rng) % 3; ++i) {
328 0 : random_api_call(&poll_rng);
329 0 : }
330 0 : }
331 :
332 0 : void ws_message_callback( ulong ws_conn_id, uchar const * data, ulong data_len, void * ctx ) {
333 0 : (void) ws_conn_id;
334 0 : (void) data;
335 0 : (void) data_len;
336 0 : (void) ctx;
337 :
338 0 : for (uint i = 0; i < xorshift_next(&poll_rng) % 3; ++i) {
339 0 : random_api_call(&poll_rng);
340 0 : }
341 0 : }
342 :
343 0 : void close_reset_clients_fd(fd_http_server_t * http) {
344 0 : for (ulong i = 0; i < clients_fd_cnt; ++i) {
345 0 : if (clients_fd[i] != -1) {
346 0 : close(clients_fd[i]);
347 0 : clients_fd[i] = -1;
348 0 : clients_ws_fd[i] = 0;
349 0 : }
350 0 : }
351 0 : clients_fd_cnt = 0;
352 :
353 0 : for (ulong conn_idx = 0; conn_idx < (PARAMS.max_connection_cnt + PARAMS.max_ws_connection_cnt); ++conn_idx) {
354 0 : if (http->pollfds[ conn_idx ].fd != -1) {
355 0 : close(http->pollfds[ conn_idx ].fd);
356 0 : }
357 0 : }
358 0 : }
359 :
360 0 : int *reserve_client_fd(void) {
361 0 : if (clients_fd_cnt >= (FD_HTTP_SERVER_GUI_MAX_CONNS * 2)) {
362 0 : return NULL;
363 0 : }
364 0 : return &clients_fd[clients_fd_cnt++];
365 0 : }
366 :
367 0 : int build_http_header(struct Unstructured *u, char *buf, int max_len, int *use_web_socket) {
368 0 : if (max_len <= 0) return 0;
369 :
370 0 : int used = 0;
371 :
372 0 : switch (rand_uchar(u) % 5) {
373 : // Content-type
374 0 : case 0:
375 0 : {
376 0 : const char *CONTENT_TYPES[] = {"text/plain", "text/html", "application/json", "application/xml", "application/x-www-form-urlencoded", "multipart/form-data", "application/octet-stream", "image/png", "image/jpeg", "audio/mpeg", "video/mp4", "application/pdf"};
377 0 : const char *CHARSET = "; charset=UTF-8";
378 0 : const char *content_type = CONTENT_TYPES[rand_uchar(u) % 12];
379 0 : if (rand_uchar(u) % 2 == 0) {
380 0 : used = snprintf(buf, (size_t) max_len, "Content-Type: %s\r\n", content_type);
381 0 : } else {
382 0 : used = snprintf(buf, (size_t)max_len, "Content-Type: %s%s\r\n", content_type, CHARSET);
383 0 : }
384 0 : }
385 0 : break;
386 : // Accept-encoding
387 0 : case 1:
388 0 : {
389 0 : const char *ACCEPT_ENCODINGS[] = {"gzip", "compress", "deflate", "br", "identity", "*"};
390 0 : char accept_encoding[64];
391 0 : memset(accept_encoding, 0, 64);
392 0 : char *cur_encoding_pos = &accept_encoding[0];
393 0 : int rem = 64;
394 :
395 0 : for (int i = 0; i < (1 + (rand_uchar(u) % 6)); ++i) {
396 0 : int size = snprintf(cur_encoding_pos, (size_t) rem, "%s, ", ACCEPT_ENCODINGS[rand_uchar(u) % 6]);
397 0 : cur_encoding_pos += size;
398 0 : rem -= size;
399 0 : }
400 :
401 0 : accept_encoding[strlen(accept_encoding)-2] = 0; // remove ", "
402 :
403 0 : used = snprintf(buf, (size_t)max_len, "Accept-Encoding: %s\r\n", accept_encoding);
404 0 : }
405 0 : break;
406 : // websocket
407 0 : case 2:
408 0 : {
409 0 : used = snprintf(buf, (size_t)max_len, "Upgrade: websocket\r\nSec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==\r\nSec-WebSocket-Version: 13\r\n");
410 0 : *use_web_socket = 1;
411 0 : }
412 0 : break;
413 0 : }
414 :
415 0 : if (used >= max_len) {
416 0 : buf[0] = 0;
417 0 : used = 0;
418 0 : }
419 :
420 0 : return used;
421 0 : }
422 :
423 0 : void build_http_req(struct Unstructured *u, uchar *buf, int *len, int *use_websocket) {
424 0 : int max_size = *len;
425 0 : int size = 0;
426 0 : memset((char *)buf, 0, (size_t)*len);
427 :
428 0 : const char *METHODS[] = {"GET", "POST", "OPTIONS"};
429 0 : const char *method = METHODS[rand_uchar(u) % 3];
430 0 : int is_post = strlen(method) == 4 && strcmp(method, "POST") == 0 ? 1 : 0;
431 0 : const char *uri = "/home";
432 :
433 0 : const char *version = "HTTP/1.1";
434 :
435 0 : char headers[256];
436 0 : memset(headers, 0, 256);
437 0 : uint n_headers = 0;
438 0 : char *cur_header_pos = &headers[0];
439 0 : int rem = 256;
440 0 : if (is_post) {
441 0 : int used = snprintf(cur_header_pos, (size_t) rem, "Content-Length: 4\r\n");
442 0 : if (used >= rem) return;
443 0 : cur_header_pos += used;
444 0 : rem -= used;
445 0 : n_headers++;
446 0 : }
447 :
448 0 : while (n_headers < (rand_uint(u) % 32)) {
449 0 : int used = build_http_header(u, cur_header_pos, rem, use_websocket);
450 0 : cur_header_pos += used;
451 0 : rem -= used;
452 0 : n_headers++;
453 0 : }
454 :
455 0 : size = (uchar) snprintf((char *)buf, (size_t) max_size, "%s %s %s\r\n%s\r\n", method, uri, version, headers);
456 0 : if (size >= max_size) return;
457 :
458 0 : if (is_post) {
459 0 : int _size = snprintf((char *)buf + size, (size_t) (max_size-size), "body");
460 0 : if (_size <= max_size-size) return;
461 0 : size += _size;
462 0 : }
463 :
464 0 : *len = size;
465 0 : }
466 :
467 0 : void build_ws_req(struct Unstructured *u, uchar *buf, int *len) {
468 0 : uchar *cur_pos = buf;
469 :
470 0 : const uchar OPCODES[] = {0x0, 0x1, 0x2, 0x8, 0x9, 0xA};
471 0 : uchar opcode = OPCODES[rand_uchar(u) % 6] & 0x0F;
472 0 : *cur_pos = opcode;
473 0 : if (rand_uchar(u) % 2 == 0) {
474 0 : *cur_pos |= (1 << 7);
475 0 : }
476 :
477 0 : ++cur_pos;
478 :
479 0 : uint payload_len = (uchar) rand_uint(u);
480 0 : if (opcode == 0x8 || opcode == 0x9 || opcode == 0xA || *len < 140) {
481 0 : payload_len %= 126;
482 0 : } else {
483 0 : payload_len %= 256;
484 0 : }
485 :
486 0 : if (payload_len < 126) {
487 0 : *cur_pos = (uchar) payload_len;
488 0 : } else if (rand_uchar(u) % 2 == 0) {
489 0 : *cur_pos = 126;
490 0 : } else {
491 0 : *cur_pos = 127;
492 0 : }
493 :
494 0 : int payload_len_choice = *cur_pos;
495 :
496 0 : *cur_pos |= (1 << 7);
497 :
498 0 : ++cur_pos;
499 0 : if (payload_len_choice == 126) {
500 0 : *(ushort *)cur_pos = (ushort) payload_len;
501 0 : cur_pos += sizeof(ushort);
502 0 : } else if (payload_len_choice == 127) {
503 0 : *(ulong *)cur_pos = (ulong) payload_len;
504 0 : cur_pos += sizeof(ulong);
505 0 : }
506 :
507 0 : *(ulong *)cur_pos = 0;
508 0 : cur_pos += sizeof(ulong);
509 :
510 0 : for (uint i = 0; i < payload_len; ++i) {
511 0 : cur_pos[i] = rand_uchar(u);
512 0 : }
513 :
514 0 : *len = (int) (cur_pos - buf);
515 0 : }
516 :
517 : static ulong stem_iters = 0;
518 : static int stop = 0;
519 0 : void* stem_thread(void* arg) {
520 0 : (void) arg;
521 0 : stem_iters = 0;
522 :
523 0 : while (1) {
524 0 : for (uint i = 0; i < xorshift_next(&poll_rng) % 3; ++i) {
525 0 : random_api_call(&poll_rng);
526 0 : }
527 :
528 0 : fd_http_server_poll(http_server);
529 :
530 0 : for (uint i = 0; i < xorshift_next(&poll_rng) % 3; ++i) {
531 0 : random_api_call(&poll_rng);
532 0 : }
533 :
534 0 : ++stem_iters;
535 :
536 0 : if (stop) break;
537 0 : sched_yield();
538 0 : }
539 0 : return NULL;
540 0 : }
541 :
542 : enum Action {
543 : HttpOpen = 0,
544 : Close,
545 : Send,
546 : ActionEnd,
547 : };
548 :
549 0 : void do_action(struct Unstructured *u) {
550 0 : switch(rand_uchar(u) % ActionEnd) {
551 0 : case HttpOpen:
552 0 : {
553 0 : int *client_fd = reserve_client_fd();
554 0 : if (!client_fd) return;
555 :
556 0 : struct sockaddr_in server_addr;
557 0 : *client_fd = socket(AF_INET, SOCK_STREAM, 0);
558 :
559 0 : memset(&server_addr, 0, sizeof(server_addr));
560 0 : server_addr.sin_family = AF_INET;
561 0 : server_addr.sin_port = htons(port);
562 :
563 0 : if (inet_pton(AF_INET, "127.0.0.1", &server_addr.sin_addr) != 1) {
564 0 : close(*client_fd);
565 0 : *client_fd = -1;
566 0 : clients_fd_cnt--;
567 0 : return;
568 0 : }
569 :
570 0 : struct sockaddr sa;
571 0 : memcpy(&sa, &server_addr, sizeof(struct sockaddr));
572 :
573 0 : if (connect(*client_fd, &sa, sizeof(server_addr)) < 0) {
574 0 : close(*client_fd);
575 0 : *client_fd = -1;
576 0 : clients_fd_cnt--;
577 0 : }
578 0 : }
579 0 : break;
580 0 : case Close:
581 0 : {
582 0 : if (clients_fd_cnt > 0) {
583 0 : uchar pos = rand_uchar(u) % ((uchar) clients_fd_cnt);
584 0 : if (clients_fd[pos] != -1) {
585 0 : close(clients_fd[pos]);
586 0 : clients_fd[pos] = -1;
587 0 : clients_ws_fd[pos] = 0;
588 0 : }
589 0 : }
590 0 : }
591 0 : break;
592 0 : case Send:
593 0 : {
594 0 : if (clients_fd_cnt > 0) {
595 0 : int len = 1024;
596 0 : uchar buf[1024];
597 0 : int use_websocket = 0;
598 0 : uchar pos = rand_uchar(u) % ((uchar) clients_fd_cnt);
599 :
600 0 : if (clients_fd[pos] != -1 && clients_ws_fd[pos] == 0) {
601 0 : build_http_req(u, buf, &len, &use_websocket);
602 0 : if (rand_uchar(u) % 5 == 0) {
603 0 : LLVMFuzzerMutate(buf, (ulong)len, (ulong)len);
604 0 : }
605 0 : send(clients_fd[pos], buf, (size_t)len, MSG_NOSIGNAL);
606 0 : if (use_websocket) {
607 0 : clients_ws_fd[pos] = 1;
608 0 : }
609 0 : }
610 :
611 0 : else if (clients_fd[pos] != -1 && clients_ws_fd[pos] == 1) {
612 0 : build_ws_req(u, buf, &len);
613 :
614 : // add up to 2 messages
615 0 : for (ulong i = 0; i < rand_uchar(u) % 3 && len < 1024; ++i) {
616 0 : int len2 = 1024 - len;
617 0 : build_ws_req(u, buf + len, &len2);
618 0 : len += len2;
619 0 : }
620 :
621 0 : if (rand_uchar(u) % 5 == 0) {
622 0 : LLVMFuzzerMutate(buf, (ulong)len, (ulong)len);
623 0 : }
624 :
625 0 : send(clients_fd[pos], buf, (size_t)len, MSG_NOSIGNAL);
626 0 : }
627 0 : }
628 0 : }
629 0 : break;
630 0 : }
631 0 : }
632 :
633 : int
634 : LLVMFuzzerTestOneInput( uchar const * data,
635 : ulong size ) {
636 :
637 : if (size >= sizeof(int)) {
638 : const fd_valloc_t valloc = fd_libc_alloc_virtual();
639 : struct Unstructured u = {
640 : .data = data,
641 : .size = size,
642 : .used = 0
643 : };
644 : pthread_t thread;
645 : uint32_t ip_as_int;
646 : inet_pton(AF_INET, "0.0.0.0", &ip_as_int);
647 :
648 : srand( rand_uint(&u));
649 :
650 : void *shmem = fd_valloc_malloc(valloc, fd_http_server_align(), fd_http_server_footprint( PARAMS ));
651 :
652 : fd_http_server_callbacks_t gui_callbacks = {
653 : .open = open_callback,
654 : .close = close_callback,
655 : .request = request_callback,
656 : .ws_open = ws_open_callback,
657 : .ws_close = ws_close_callback,
658 : .ws_message = ws_message_callback,
659 : };
660 :
661 : http_server = fd_http_server_join( fd_http_server_new( shmem, PARAMS, gui_callbacks, NULL ) );
662 : http_server = fd_http_server_listen( http_server, ip_as_int, 0 );
663 :
664 : struct sockaddr_in addr;
665 : socklen_t addr_len = sizeof(addr);
666 : struct sockaddr sock_addr;
667 : memset(&addr, 0, sizeof(addr));
668 : memset(&sock_addr, 0, sizeof(sock_addr));
669 : memcpy(&sock_addr, &addr, sizeof(addr));
670 :
671 : if (getsockname(http_server->socket_fd, &sock_addr, &addr_len) == -1) {
672 : printf( "bind failed (%i-%s)", errno, strerror( errno ) );
673 : abort();
674 : }
675 :
676 : port = ntohs(addr.sin_port);
677 :
678 : xorshift_init(&poll_rng, (uint32_t) rand_uint(&u));
679 :
680 : stop = 0;
681 : pthread_create(&thread, NULL, stem_thread, NULL);
682 :
683 : uchar n_actions = (uchar) rand_uchar(&u) % 32;
684 : for (uchar i = 0; i < n_actions; ++i) {
685 : do_action(&u);
686 :
687 : ulong iters = stem_iters;
688 : do { sched_yield(); } while (stem_iters < iters + 1);
689 : }
690 :
691 : stop = 1;
692 : pthread_join(thread, NULL);
693 :
694 : close_reset_clients_fd(http_server);
695 : close(fd_http_server_fd(http_server));
696 : fd_http_server_delete(fd_http_server_leave(http_server));
697 : fd_valloc_free(valloc, shmem);
698 : }
699 :
700 : return 0;
701 : }
|