Coverage Report

Created: 2025-06-13 06:09

/src/uWebSockets/fuzzing/libEpollFuzzer/epoll_fuzzer.h
Line
Count
Source (jump to first uncovered line)
1
/* Welcome to libEpollFuzzer - a mock implementation of the epoll/socket syscalls */
2
3
/* Current implementation is extremely experimental and trashy, mind you */
4
5
#include <stdio.h>
6
#include <stdlib.h>
7
#include <stdint.h>
8
#include <string.h>
9
#include <stdarg.h>
10
//#include <threads.h>
11
12
#include <sys/timerfd.h>
13
#include <sys/epoll.h>
14
#include <sys/types.h>
15
#include <sys/socket.h>
16
#include <netdb.h>
17
#include <errno.h>
18
19
// todo: add connect, donät pass invalid-FD to real syscalls
20
// getaddrinfo should return inet6 somtimes and sometimes wrong family (done)
21
// accept4 should produce inet6 sometimes (done)
22
// socket syscall should fail with given invalid family (done)
23
// listen syscall should fail sometimes (done)
24
25
/* Currently read, close, fcntl are wrapped to real syscalls */
26
27
/* TODO: Our FDs should start at 1024 while actual real FDs should be reserved from 0 to 1023 and passed to actual
28
 * real syscalls so that we can co-exist with overlapping syscalls like read, open, write, close */
29
30
//#define PRINTF_DEBUG
31
32
/* The test case */
33
void test();
34
void teardown();
35
36
#ifdef __cplusplus
37
extern "C" {
38
#endif
39
40
struct file {
41
  /* Every file has a type; socket, event, timer, epoll */
42
  int type;
43
44
  /* We assume there can only be one event-loop at any given point in time,
45
   * so every file holds its own epoll_event */
46
  struct epoll_event epev;
47
48
  /* A file may be added to an epfd by linking it in a list */
49
  struct file *prev, *next;
50
};
51
52
/* If FD is less than this, it should be passed to REAL syscall.
53
 * We never produce FDs lower than this (except for -1 on error) */
54
const int RESERVED_SYSTEM_FDS = 1024;
55
56
/* Map from some collection of integers to a shared extensible struct of data */
57
const int MAX_FDS = 1000;
58
struct file *fd_to_file[MAX_FDS];
59
60
const int FD_TYPE_EPOLL = 0;
61
const int FD_TYPE_TIMER = 1;
62
const int FD_TYPE_EVENT = 2;
63
const int FD_TYPE_SOCKET = 3;
64
65
int num_fds = 0;
66
67
/* Keeping track of cunsumable data */
68
unsigned char *consumable_data;
69
int consumable_data_length;
70
71
7.19k
void set_consumable_data(const unsigned char *new_data, int new_length) {
72
7.19k
  consumable_data = (unsigned char *) new_data;
73
7.19k
  consumable_data_length = new_length;
74
7.19k
}
75
76
/* Returns non-null on error */
77
3.91M
int consume_byte(unsigned char *b) {
78
3.91M
  if (consumable_data_length) {
79
3.90M
    *b = consumable_data[0];
80
3.90M
    consumable_data++;
81
3.90M
    consumable_data_length--;
82
3.90M
    return 0;
83
3.90M
  }
84
5.05k
  return -1;
85
3.91M
}
86
87
/* Keeping track of FDs */
88
89
/* Returns -1 on error, or RESERVED_SYSTEM_FDS and above */
90
1.48M
int allocate_fd() {
91
  // this can be massively optimized by having a list of free blocks or the like
92
107M
  for (int fd = 0; fd < MAX_FDS; fd++) {
93
107M
    if (!fd_to_file[fd]) {
94
1.48M
      num_fds++;
95
1.48M
      return fd + RESERVED_SYSTEM_FDS;
96
1.48M
    }
97
107M
  }
98
198
  return -1;
99
1.48M
}
100
101
/* This one should set the actual file for this FD */
102
1.48M
void init_fd(int fd, int type, struct file *f) {
103
1.48M
  if (fd >= RESERVED_SYSTEM_FDS) {
104
1.48M
    fd_to_file[fd - RESERVED_SYSTEM_FDS] = f;
105
1.48M
    fd_to_file[fd - RESERVED_SYSTEM_FDS]->type = type;
106
1.48M
    fd_to_file[fd - RESERVED_SYSTEM_FDS]->next = NULL;
107
1.48M
    fd_to_file[fd - RESERVED_SYSTEM_FDS]->prev = NULL;
108
1.48M
  }
109
1.48M
}
110
111
20.3M
struct file *map_fd(int fd) {
112
20.3M
  if (fd >= RESERVED_SYSTEM_FDS && fd < MAX_FDS + RESERVED_SYSTEM_FDS) {
113
20.3M
    return fd_to_file[fd - RESERVED_SYSTEM_FDS];
114
20.3M
  }
115
0
  return NULL;
116
20.3M
}
117
118
/* This one should remove the FD from any pollset by calling epoll_ctl remove */
119
1.48M
int free_fd(int fd) {
120
1.48M
  if (fd >= RESERVED_SYSTEM_FDS && fd < MAX_FDS + RESERVED_SYSTEM_FDS) {
121
1.48M
    if (fd_to_file[fd - RESERVED_SYSTEM_FDS]) {
122
1.48M
      fd_to_file[fd - RESERVED_SYSTEM_FDS] = 0;
123
1.48M
      num_fds--;
124
1.48M
      return 0;
125
1.48M
    }
126
1.48M
  }
127
128
0
  return -1;
129
1.48M
}
130
131
/* The epoll syscalls */
132
133
struct epoll_file {
134
  struct file base;
135
136
  /* A doubly linked list for polls awaiting events */
137
  struct file *poll_set_head, *poll_set_tail;
138
};
139
140
/* This function is O(n) and does not consume any fuzz data, but will fail if run out of FDs */
141
7.19k
int __wrap_epoll_create1(int flags) {
142
143
  /* Todo: check that we do not allocate more than one epoll FD */
144
7.19k
  int fd = allocate_fd();
145
146
7.19k
  if (fd != -1) {
147
7.19k
    struct epoll_file *ef = (struct epoll_file *)malloc(sizeof(struct epoll_file));
148
149
    /* Init the epoll_file */
150
7.19k
    ef->poll_set_head = NULL;
151
7.19k
    ef->poll_set_tail = NULL;
152
153
7.19k
    init_fd(fd, FD_TYPE_EPOLL, (struct file *)ef);
154
7.19k
  }
155
156
#ifdef PRINTF_DEBUG
157
  printf("epoll_create1 returning epfd: %d\n", fd);
158
#endif
159
160
7.19k
  return fd;
161
7.19k
}
162
163
// this function cannot be called inside an iteration! it changes the list
164
/* This function is O(1) and does not consume any fuzz data */
165
3.54M
int __wrap_epoll_ctl(int epfd, int op, int fd, struct epoll_event *event) {
166
167
3.54M
  struct epoll_file *ef = (struct epoll_file *)map_fd(epfd);
168
3.54M
  if (!ef) {
169
0
    return -1;
170
0
  }
171
172
3.54M
  struct file *f = (struct file *)map_fd(fd);
173
3.54M
  if (!f) {
174
0
    return -1;
175
0
  }
176
177
  /* We add new polls in the head */
178
3.54M
  if (op == EPOLL_CTL_ADD) {
179
    // if there is a head already
180
1.47M
    if (ef->poll_set_head) {
181
1.47M
      ef->poll_set_head->prev = f;
182
183
      // then it will be our next
184
1.47M
      f->next = ef->poll_set_head;
185
1.47M
    } else {
186
      // if there was no head then we became the tail also
187
7.19k
      ef->poll_set_tail = f;
188
7.19k
    }
189
190
    // we are now the head in any case
191
1.47M
    ef->poll_set_head = f;
192
193
1.47M
    f->epev = *event;
194
195
2.07M
  } else if (op == EPOLL_CTL_MOD) {
196
    /* Modifying is simply changing the file itself */
197
593k
    f->epev = *event;
198
1.47M
  } else if (op == EPOLL_CTL_DEL) {
199
200
1.47M
    if (f->prev) {
201
743k
      f->prev->next = f->next;
202
743k
    } else {
203
734k
      ef->poll_set_head = f->next;
204
734k
    }
205
206
1.47M
    if (f->next) {
207
1.47M
      f->next->prev = f->prev;
208
1.47M
    } else {
209
      // tail ska vara vår.prev
210
7.19k
      ef->poll_set_tail = f->prev;
211
7.19k
    }
212
213
    // a file that is not in the list should be reset to NULL
214
1.47M
    f->prev = NULL;
215
1.47M
    f->next = NULL;
216
1.47M
  }
217
218
  /* You have to poll for errors and hangups */
219
3.54M
  f->epev.events |= EPOLLERR | EPOLLHUP;
220
221
3.54M
  return 0;
222
3.54M
}
223
224
/* This function is O(n) and consumes fuzz data and might trigger teardown callback */
225
int __wrap_epoll_wait(int epfd, struct epoll_event *events,
226
3.63M
               int maxevents, int timeout) {
227
  //printf("epoll_wait: %d\n", 0);
228
229
#ifdef PRINTF_DEBUG
230
  printf("Calling epoll_wait\n");
231
#endif
232
233
3.63M
  struct epoll_file *ef = (struct epoll_file *)map_fd(epfd);
234
3.63M
  if (!ef) {
235
0
    return -1;
236
0
  }
237
238
3.63M
  if (consumable_data_length) {
239
240
3.62M
    int ready_events = 0;
241
242
22.3M
    for (struct file *f = ef->poll_set_head; f; f = f->next) {
243
244
245
      /* Consume one fuzz byte, AND it with the event */
246
18.7M
      if (!consumable_data_length) {
247
        // break if we have no data
248
498
        break;
249
498
      }
250
251
      // here we have the main condition that drives everything
252
18.7M
      int ready_event = consumable_data[0] & f->epev.events;
253
254
      // consume the byte
255
18.7M
      consumable_data_length--;
256
18.7M
      consumable_data++;
257
258
18.7M
      if (ready_event) {
259
11.7M
        if (ready_events < maxevents) {
260
11.7M
          events[ready_events] = f->epev;
261
262
          // todo: the event should be masked by the byte, not everything it wants shold be given all the time!
263
11.7M
          events[ready_events++].events = ready_event;
264
11.7M
        } else {
265
          // we are full, break
266
0
          break;
267
0
        }
268
11.7M
      }
269
270
18.7M
    }
271
272
3.62M
    return ready_events;
273
274
3.62M
  } else {
275
276
#ifdef PRINTF_DEBUG
277
    printf("Calling teardown\n");
278
#endif
279
7.17k
    teardown();
280
281
    // after shutting down the listen socket we clear the whole list (the bug in epoll_ctl remove)
282
    // so the below loop doesn't work - we never close anything more than the listen socket!
283
284
    /* You don't really need to emit teardown, you could simply emit error on every poll */
285
286
7.17k
    int ready_events = 0;
287
288
#ifdef PRINTF_DEBUG
289
    printf("Emitting error on every remaining FD\n");
290
#endif
291
77.2k
    for (struct file *f = ef->poll_set_head; f; f = f->next) {
292
293
70.0k
      if (f->type == FD_TYPE_SOCKET) {
294
295
48.5k
        if (ready_events < maxevents) {
296
48.5k
          events[ready_events] = f->epev;
297
298
          // todo: the event should be masked by the byte, not everything it wants shold be given all the time!
299
48.5k
          events[ready_events++].events = EPOLLERR | EPOLLHUP;
300
48.5k
        } else {
301
          // we are full, break
302
0
          break;
303
0
        }
304
305
48.5k
      }
306
70.0k
    }
307
308
#ifdef PRINTF_DEBUG
309
    printf("Ready events: %d\n", ready_events);
310
#endif
311
312
7.17k
    return ready_events;
313
7.17k
  }
314
3.63M
}
315
316
/* The socket syscalls */
317
318
struct socket_file {
319
  struct file base;
320
321
  /* We store socket addresses created in accept4 */
322
  union {
323
    struct sockaddr_in6 in6;
324
    struct sockaddr_in in;
325
  } addr;
326
327
  /* The size of sockaddr_in6 or sockaddr_in as a whole */
328
  socklen_t len;
329
};
330
331
extern int __real_read(int fd, void *buf, size_t count);
332
8.18M
int __wrap_read(int fd, void *buf, size_t count) {
333
334
8.18M
  if (fd < RESERVED_SYSTEM_FDS) {
335
0
    return __real_read(fd, buf, count);
336
0
  }
337
338
#ifdef PRINTF_DEBUG
339
  printf("Wrapped read\n");
340
#endif
341
342
  /* Let's try and clear the buffer first */
343
  //memset(buf, 0, count);
344
345
8.18M
  struct file *f = map_fd(fd);
346
8.18M
  if (!f) {
347
0
    return -1;
348
0
  }
349
350
8.18M
  errno = 0;
351
352
8.18M
  if (f->type == FD_TYPE_SOCKET) {
353
354
597k
    if (!consumable_data_length) {
355
3.62k
      errno = EWOULDBLOCK;
356
3.62k
      return -1;
357
593k
    } else {
358
593k
      int data_available = (unsigned char) consumable_data[0];
359
593k
      consumable_data_length--;
360
593k
      consumable_data++;
361
362
593k
      if (consumable_data_length < data_available) {
363
5.80k
        data_available = consumable_data_length;
364
5.80k
      }
365
366
593k
      if (count < data_available) {
367
0
        data_available = count;
368
0
      }
369
370
593k
      memcpy(buf, consumable_data, data_available);
371
372
593k
      consumable_data_length -= data_available;
373
593k
      consumable_data += data_available;
374
375
593k
      return data_available;
376
593k
    }
377
597k
  }
378
379
7.58M
  if (f->type == FD_TYPE_EVENT) {
380
2.44M
    memset(buf, 1, 8);
381
2.44M
    return 8;
382
2.44M
  }
383
384
5.13M
  if (f->type == FD_TYPE_TIMER) {
385
5.13M
    memset(buf, 1, 8);
386
5.13M
    return 8;
387
5.13M
  }
388
389
0
  return -1;
390
5.13M
}
391
392
/* We just ignore the extra flag here */
393
597k
int __wrap_recv(int sockfd, void *buf, size_t len, int flags) {
394
597k
  return __wrap_read(sockfd, buf, len);
395
597k
}
396
397
705k
int __wrap_send(int sockfd, const void *buf, size_t len, int flags) {
398
399
705k
  if (consumable_data_length) {
400
    /* We can send len scaled by the 1 byte */
401
688k
    unsigned char scale = consumable_data[0];
402
688k
    consumable_data++;
403
688k
    consumable_data_length--;
404
405
688k
    int written = float(scale) / 255.0f * len;
406
407
688k
    if (written == 0) {
408
93.7k
      errno = EWOULDBLOCK;
409
594k
    } else {
410
594k
      errno = 0;
411
594k
    }
412
413
688k
    return written;
414
688k
  } else {
415
17.5k
    return -1;
416
17.5k
  }
417
705k
}
418
419
int __wrap_sendto(int sockfd, const void *buf, size_t len, int flags,
420
0
  const struct sockaddr *dest_addr, socklen_t addrlen) {
421
0
    return __wrap_send(sockfd, buf, len, flags);
422
0
}
423
424
7.18k
int __wrap_bind() {
425
7.18k
  return 0;
426
7.18k
}
427
428
1.47M
int __wrap_setsockopt() {
429
1.47M
  return 0;
430
1.47M
}
431
432
extern int __real_fcntl(int fd, int cmd, ... /* arg */ );
433
2.91M
int __wrap_fcntl(int fd, int cmd, ... /* arg */) {
434
2.91M
  if (fd < RESERVED_SYSTEM_FDS) {
435
2
    va_list args;
436
2
    va_start(args, cmd);
437
2
    int ret = __real_fcntl(fd, cmd, args);
438
2
    va_end(args);
439
2
    return ret;
440
2
  }
441
442
2.91M
  return 0;
443
2.91M
}
444
445
/* Addrinfo */
446
int __wrap_getaddrinfo(const char *node, const char *service,
447
                       const struct addrinfo *hints,
448
7.19k
                       struct addrinfo **res) {
449
  //printf("Wrapped getaddrinfo\n");
450
451
7.19k
  struct addrinfo default_hints = {};
452
453
7.19k
  if (!hints) {
454
0
    hints = &default_hints;
455
0
  }
456
457
7.19k
  unsigned char b;
458
7.19k
  if (consume_byte(&b)) {
459
6
    return -1;
460
6
  }
461
462
  /* This one should be thread_local */
463
7.19k
  static /*thread_local*/ struct addrinfo ai;
464
7.19k
  ai.ai_flags = hints->ai_flags;
465
7.19k
  ai.ai_socktype = hints->ai_socktype;
466
7.19k
  ai.ai_protocol = hints->ai_protocol;
467
468
7.19k
  if (b > 127) {
469
3.53k
    ai.ai_family = AF_INET;//hints->ai_family;
470
3.65k
  } else {
471
3.65k
    ai.ai_family = AF_INET6;//hints->ai_family;
472
3.65k
  }
473
474
  /* This one is for generating the wrong family (maybe invalid?) */
475
7.19k
  if (b == 0) {
476
2
    ai.ai_family = hints->ai_family;
477
2
  }
478
479
7.19k
  ai.ai_next = NULL;
480
7.19k
  ai.ai_canonname = NULL; // fel
481
482
  // these should depend on inet6 or inet */
483
7.19k
  ai.ai_addrlen = 4; // fel
484
7.19k
  ai.ai_addr = NULL; // ska peka på en sockaddr!
485
486
  // we need to return an addrinfo with family AF_INET6
487
488
7.19k
  *res = &ai;
489
7.19k
  return 0;
490
7.19k
}
491
492
7.19k
int __wrap_freeaddrinfo() {
493
7.19k
  return 0;
494
7.19k
}
495
496
/* This one should return the same address as accept4 did produce */
497
0
int __wrap_getpeername(int sockfd, struct sockaddr *addr, socklen_t *addrlen) {
498
499
0
  struct file *f = map_fd(sockfd);
500
0
  if (!f) {
501
0
    return -1;
502
0
  }
503
504
  // todo: this could fail with -1 also (consume a byte)?
505
506
0
  if (f->type == FD_TYPE_SOCKET) {
507
508
0
    struct socket_file *sf = (struct socket_file *) f;
509
510
0
    if (addr) {
511
0
      memcpy(addr, &sf->addr, sf->len);
512
0
      *addrlen = sf->len;
513
0
    }
514
515
0
    return 0;
516
0
  }
517
518
0
  return -1;
519
0
}
520
521
3.89M
int __wrap_accept4(int sockfd, struct sockaddr *addr, socklen_t *addrlen) {
522
  /* We must end with -1 since we are called in a loop */
523
524
3.89M
  unsigned char b;
525
3.89M
  if (consume_byte(&b)) {
526
5.03k
    return -1;
527
5.03k
  }
528
529
  /* This rule might change, anything below 10 is accepted */
530
3.88M
  if (b < 10) {
531
532
1.44M
    int fd = allocate_fd();
533
1.44M
    if (fd != -1) {
534
535
      /* Allocate the file */
536
1.44M
      struct socket_file *sf = (struct socket_file *) malloc(sizeof(struct socket_file));
537
538
      /* Init the file */
539
540
      /* Here we need to create a socket FD and return */
541
1.44M
      init_fd(fd, FD_TYPE_SOCKET, (struct file *)sf);
542
543
      /* We need to provide an addr */
544
545
      /* Begin by setting it to an empty in6 address */
546
1.44M
      memset(&sf->addr, 0, sizeof(struct sockaddr_in6));
547
1.44M
      sf->len = sizeof(struct sockaddr_in6);
548
1.44M
      sf->addr.in6.sin6_family = AF_INET6;
549
550
      /* Opt-in to ipv4 */
551
1.44M
      if (b < 5) {
552
1.29M
        memset(&sf->addr, 0, sizeof(struct sockaddr_in6));
553
1.29M
        sf->len = sizeof(struct sockaddr_in);
554
1.29M
        sf->addr.in.sin_family = AF_INET;
555
1.29M
      }
556
557
1.44M
      if (addr) {
558
        /* Copy from socket to addr */
559
1.44M
        memcpy(addr, &sf->addr, sf->len);
560
1.44M
      }
561
1.44M
    }
562
563
1.44M
    return fd;
564
1.44M
  }
565
566
2.43M
  return -1;
567
3.88M
}
568
569
7.18k
int __wrap_listen() {
570
  /* Listen consumes one byte and fails on -1 */
571
7.18k
  unsigned char b;
572
7.18k
  if (consume_byte(&b)) {
573
9
    return -1;
574
9
  }
575
576
7.18k
  if (b) {
577
7.17k
    return 0;
578
7.17k
  }
579
580
1
  return -1;
581
7.18k
}
582
583
/* This one is similar to accept4 and has to return a valid FD of type socket */
584
7.18k
int __wrap_socket(int domain, int type, int protocol) {
585
586
  /* Only accept valid families */
587
7.18k
  if (domain != AF_INET && domain != AF_INET6) {
588
0
    return -1;
589
0
  }
590
591
7.18k
  int fd = allocate_fd();
592
593
7.18k
  if (fd != -1) {
594
7.18k
    struct socket_file *sf = (struct socket_file *)malloc(sizeof(struct socket_file));
595
596
    /* Init the file */
597
598
7.18k
    init_fd(fd, FD_TYPE_SOCKET, (struct file *)sf);
599
7.18k
  }
600
601
#ifdef PRINTF_DEBUG
602
  printf("socket returning fd: %d\n", fd);
603
#endif
604
605
7.18k
  return fd;
606
7.18k
}
607
608
175k
int __wrap_shutdown() {
609
  //printf("Wrapped shutdown\n");
610
175k
  return 0;
611
175k
}
612
613
/* The timerfd syscalls */
614
615
struct timer_file {
616
  struct file base;
617
};
618
619
14.3k
int __wrap_timerfd_create(int clockid, int flags) {
620
621
14.3k
  int fd = allocate_fd();
622
623
14.3k
  if (fd != -1) {
624
14.3k
    struct timer_file *tf = (struct timer_file *)malloc(sizeof(struct timer_file));
625
626
    /* Init the file */
627
628
629
14.3k
    init_fd(fd, FD_TYPE_TIMER, (struct file *)tf);
630
631
14.3k
  }
632
633
#ifdef PRINTF_DEBUG
634
  printf("timerfd_create returning fd: %d\n", fd);
635
#endif
636
637
14.3k
  return fd;
638
14.3k
}
639
640
int __wrap_timerfd_settime(int fd, int flags,
641
                    const struct itimerspec *new_value,
642
14.3k
                    struct itimerspec *old_value) {
643
  //printf("timerfd_settime: %d\n", fd);
644
14.3k
  return 0;
645
14.3k
}
646
647
/* The eventfd syscalls */
648
649
struct event_file {
650
  struct file base;
651
};
652
653
7.19k
int __wrap_eventfd() {
654
655
7.19k
  int fd = allocate_fd();
656
657
7.19k
  if (fd != -1) {
658
7.19k
    struct event_file *ef = (struct event_file *)malloc(sizeof(struct event_file));
659
660
    /* Init the file */
661
662
7.19k
    init_fd(fd, FD_TYPE_EVENT, (struct file *)ef);
663
664
    //printf("eventfd: %d\n", fd);
665
7.19k
  }
666
667
#ifdef PRINTF_DEBUG
668
  printf("eventfd returning fd: %d\n", fd);
669
#endif
670
671
7.19k
  return fd;
672
7.19k
}
673
674
// timerfd_settime
675
676
/* File descriptors exist in a shared dimension, and has to know its type */
677
extern int __real_close(int fd);
678
1.48M
int __wrap_close(int fd) {
679
680
1.48M
  if (fd < RESERVED_SYSTEM_FDS) {
681
0
    return __real_close(fd);
682
0
  }
683
684
1.48M
  struct file *f = map_fd(fd);
685
686
1.48M
  if (!f) {
687
0
    return -1;
688
0
  }
689
690
1.48M
  if (f->type == FD_TYPE_EPOLL) {
691
#ifdef PRINTF_DEBUG
692
    printf("Closing epoll FD: %d\n", fd);
693
#endif
694
695
7.19k
    free(f);
696
697
7.19k
    return free_fd(fd);
698
699
1.47M
  } else if (f->type == FD_TYPE_TIMER) {
700
#ifdef PRINTF_DEBUG
701
    printf("Closing timer fd: %d\n", fd);
702
#endif
703
704
14.3k
    free(f);
705
706
14.3k
    return free_fd(fd);
707
1.46M
  } else if (f->type == FD_TYPE_EVENT) {
708
#ifdef PRINTF_DEBUG
709
    printf("Closing event fd: %d\n", fd);
710
#endif
711
712
7.19k
    free(f);
713
714
7.19k
    return free_fd(fd);
715
1.45M
  } else if (f->type == FD_TYPE_SOCKET) {
716
#ifdef PRINTF_DEBUG
717
    printf("Closing socket fd: %d\n", fd);
718
#endif
719
720
    // we should call epoll_ctl remove here
721
722
1.45M
    free(f);
723
724
1.45M
    int ret = free_fd(fd);
725
726
#ifdef PRINTF_DEBUG
727
    printf("Ret: %d\n", ret);
728
#endif
729
730
    //free(-1);
731
1.45M
    return ret;
732
1.45M
  }
733
734
0
  return -1;
735
1.48M
}
736
737
7.19k
int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
738
7.19k
  set_consumable_data(data, size);
739
740
7.19k
  test();
741
742
7.19k
  if (num_fds) {
743
0
    printf("ERROR! Cannot leave open FDs after test!\n");
744
0
  }
745
746
7.19k
  return 0;
747
7.19k
}
748
749
#ifdef __cplusplus
750
}
751
#endif