135#define FUZZ_HARNESS_NAME "fuzz_options"
139#include <sys/socket.h>
140#include <netinet/in.h>
141#include <sys/select.h>
149#if defined(__GNUC__) || defined(__clang__)
150#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
156#define MAX_SEGMENTS 48
157#define MAX_CONNECTIONS 6
159#define RESP_DRAIN_BUF 4096
160#define GEN_BUF_SIZE 4096
170#define THREAD_WAIT_MS 2
175#define PUMP_ROUNDS_LONG 10
194 unsigned int loop_mode;
202 unsigned int resp_kind;
206 unsigned int nconn_max;
211 int accept_policy_deny;
214static struct fuzz_cfg
cfg;
250 "%s: daemons=%lu (failed to start=%lu, threaded=%lu) "
251 "connections=%lu (refused=%lu, accepted from a real socket=%lu) "
252 "handler calls=%lu\n",
292#define MODE_COUNT (sizeof (mode_tbl) / sizeof (mode_tbl[0]))
301#define RAW_FLAG_MASK (~((unsigned int) MHD_USE_TLS))
317 (((unsigned int) MHD_ALLOW_SUSPEND_RESUME) \
318 & ~((unsigned int) MHD_USE_ITC))
332 if (0xC0 == (
data[2] & 0xC0))
338 flags = ((
unsigned int)
data[1])
339 | (((
unsigned int) (
data[2] & 0x3F)) << 8)
340 | (((
unsigned int)
data[15]) << 14);
349 if (0 != (
data[1] & 0x01))
351 if (0 != (
data[1] & 0x02))
353 if (0 != (
data[1] & 0x04))
355 if ( (0 != (
data[1] & 0x08)) &&
358 if (0 != (
data[1] & 0x10))
360 if (0 != (
data[1] & 0x20))
362 if (0 != (
data[1] & 0x40))
364 if (0 != (
data[1] & 0x80))
367 if (0 != (
data[2] & 0x01))
369 if (0 != (
data[2] & 0x02))
371 if (0 != (
data[2] & 0x04))
373 if (0 != (
data[2] & 0x08))
375 if (0 != (
data[2] & 0x10))
377 if (0 != (
data[2] & 0x20))
446 const char *e = getenv (
"MHD_FUZZ_QUIESCE_EPOLL_RACE");
448 val = ((
NULL != e) && (0 != atoi (e))) ? 1 : 0;
459 0 , 128, 192, 256, 384, 512, 1024, 1400,
460 1500, 2048, 4096, 8192, 32768, 64, 0, 0
464 0 , 1, 16, 64, 128, 256, 1024, 4096,
465 1500, 32768, 0, 0, 0, 0, 0, 0
469 0, 1, 2, 3, 8, 64, 1024, 100000
473 0, 1, 2, 3, 4, 8, 64, 1000
477 0, 1, 2, 5, 60, 3600, 86400,
UINT_MAX
485 0, 1024u * 1024u, 2048u * 1024u, 8192u * 1024u
505 (int) FD_SETSIZE, (
int) FD_SETSIZE, (int) FD_SETSIZE, (
int) FD_SETSIZE,
506 (int) FD_SETSIZE, (
int) FD_SETSIZE, 64, 0
511 "\x01\x23\x45\x67\x89\xab\xcd\xef\x01\x23\x45\x67\x89\xab\xcd\xef"
512 "\xfe\xdc\xba\x98\x76\x54\x32\x10\xfe\xdc\xba\x98\x76\x54\x32\x10";
519static struct sockaddr_in6 bind6;
531 bind4.sin_family = AF_INET;
532 bind4.sin_port = htons (0);
533 bind4.sin_addr.s_addr = htonl (INADDR_LOOPBACK);
535 memset (&bind6, 0,
sizeof (bind6));
536 bind6.sin6_family = AF_INET6;
537 bind6.sin6_port = htons (0);
538 bind6.sin6_addr = in6addr_loopback;
562 (void) vfprintf (stderr, fmt, ap);
578 volatile size_t sink;
582 sink = (
NULL != uri) ? strlen (uri) : 0;
616 if (!
cfg.uses_threads)
631 void **socket_context,
637 *socket_context =
NULL;
650 (void) snprintf (msg,
sizeof (msg),
651 "MHD_PANIC() reached at %s:%u: %s",
652 (
NULL != file) ? file :
"?",
654 (
NULL != reason) ? reason :
"?");
717 if ( (0 ==
cfg.suspend_mode) ||
722 if (1 ==
cfg.suspend_mode)
743 const char *upload_data,
744 size_t *upload_data_size,
752 static int req_marker;
756 volatile size_t sink = 0;
761 if (&req_marker != *req_cls)
763 *req_cls = &req_marker;
770 sink += strlen (url);
772 sink += strlen (method);
774 sink += strlen (version);
777 if (0 != *upload_data_size)
779 *upload_data_size = 0;
793 switch (
cfg.resp_kind)
840 while (0 < recv (sock, tmp,
sizeof (tmp), MSG_DONTWAIT))
865 volatile int64_t sink;
872 switch (
cfg.loop_mode)
882 if (1 ==
cfg.loop_mode)
885 (
unsigned int) FD_SETSIZE))
902 (void) select ((
int) max_fd + 1, &rs, &ws, &es, &tv);
903 if (1 ==
cfg.loop_mode)
925 if (
cfg.uses_threads)
927 for (i = 0; i < rounds; i++)
953 for (round = 0; round < 4; round++)
964 if (0 == (p.revents & POLLIN))
966 n = recv (sock, tmp,
sizeof (tmp), MSG_DONTWAIT);
980 unsigned int stall = 0;
984 while ( (off < len) &&
987 ssize_t s = send (sock,
data + off, len - off, MSG_DONTWAIT);
996 if (
cfg.uses_threads)
1011 (EAGAIN != errno) &&
1012 (EWOULDBLOCK != errno) &&
1033 struct sockaddr_in sa;
1036 if (0 != socketpair (AF_UNIX, SOCK_STREAM, 0, sv))
1038 memset (&sa, 0,
sizeof (sa));
1039 sa.sin_family = AF_INET;
1040 sa.sin_port = htons (44444);
1041 sa.sin_addr.s_addr = htonl (INADDR_LOOPBACK);
1044 (
const struct sockaddr *) &sa,
1045 (socklen_t)
sizeof (sa)))
1048 (void) close (sv[0]);
1064 (void) shutdown (*sock, SHUT_WR);
1065 if (
cfg.uses_threads)
1069 (void) close (*sock);
1078#define PICK(tbl, idx) ((tbl)[(idx) % (sizeof (tbl) / sizeof ((tbl)[0]))])
1089 opts[*nopt].
option = option;
1090 opts[*nopt].
value = value;
1111 unsigned int nopt = 0;
1112 const uint8_t mask_a =
data[3];
1113 const uint8_t mask_b =
data[4];
1114 const uint8_t mask_d =
data[14];
1124 const int misfit = (0xE0 == (
data[15] & 0xE0));
1126 if (0 != (mask_a & 0x01))
1129 if (0 != (mask_a & 0x02))
1132 if (0 != (mask_a & 0x04))
1135 if (0 != (mask_a & 0x08))
1138 if (0 != (mask_a & 0x10))
1147 if ( (0 != (mask_a & 0x20)) &&
1148 (pool_ok || misfit) )
1151 if (0 != (mask_a & 0x40))
1154 if (0 != (mask_a & 0x80))
1156 (intptr_t) (
unsigned int) (
data[11] & 0x01),
NULL);
1158 if (0 != (mask_b & 0x01))
1161 if (0 != (mask_b & 0x02))
1164 if (0 != (mask_b & 0x04))
1166 (intptr_t) (
unsigned int) ((
data[10] >> 6) & 0x03),
NULL);
1167 if (0 != (mask_b & 0x08))
1170 if (0 != (mask_b & 0x10))
1173 if (0 != (mask_b & 0x20))
1177 (intptr_t) 1,
NULL);
1178 if (0 != (mask_b & 0x40))
1181 if (0 != (mask_b & 0x80))
1183 (intptr_t) (
int) ((
data[11] >> 5) & 0x03),
NULL);
1185 if (0 != (mask_d & 0x01))
1187 (intptr_t) (
unsigned int) ((
data[9] >> 2) & 0x0F),
NULL);
1188 if (0 != (mask_d & 0x02))
1190 (intptr_t) (
unsigned int) (
data[15] & 0x7F),
NULL);
1191 if (0 != (mask_d & 0x04))
1193 (intptr_t) (uint32_t)
data[15],
NULL);
1194 if (0 != (mask_d & 0x08))
1197 if (0 != (mask_d & 0x10))
1199 (intptr_t) (
int) (
data[15] & 0x01),
NULL);
1200 if (0 != (mask_d & 0x20))
1210 if (0 != (
data[5] & 0x20))
1212 (0 != (
data[5] & 0x40))
1220 if ( (0 != (
data[5] & 0x80)) &&
1221 (
cfg.listen_sock || misfit) )
1230 if (0 != (
data[15] & 0x02))
1232 (intptr_t) (socklen_t)
sizeof (bind6), &bind6);
1238 if (0 != (
data[15] & 0x02))
1240 (intptr_t) (socklen_t)
sizeof (
bind4), &
bind4);
1249 if (0 != (mask_d & 0x40))
1254 opts[nopt].
value = 0;
1263typedef void *(*fuzz_uri_log_cb)(
void *,
const char *,
1266#define VARARG_CALLBACKS \
1267 MHD_OPTION_NOTIFY_COMPLETED, cb_completed, NULL, \
1268 MHD_OPTION_NOTIFY_CONNECTION, cb_notify, NULL, \
1269 MHD_OPTION_URI_LOG_CALLBACK, cb_uri_log, NULL
1275 const struct sockaddr *
addr,
1303 switch ((cbsel >> 3) & 0x03)
1345 const struct sockaddr *addr,
1348 volatile size_t sink;
1351 sink = (size_t) addrlen + ((
NULL != addr) ? (size_t) addr->sa_family : 0u);
1381 if ( (
NULL == di) ||
1384 port = (uint16_t) di->
port;
1389 struct sockaddr_in6 to = bind6;
1391 to.sin6_port = htons (port);
1392 s = socket (AF_INET6, SOCK_STREAM, 0);
1395 if (0 != connect (s, (
const struct sockaddr *) &to,
sizeof (to)))
1404 struct sockaddr_in to =
bind4;
1406 to.sin_port = htons (port);
1407 s = socket (AF_INET, SOCK_STREAM, 0);
1410 if (0 != connect (s, (
const struct sockaddr *) &to,
sizeof (to)))
1418 (void) setsockopt (s, SOL_SOCKET, SO_LINGER, &lg,
sizeof (lg));
1447 volatile unsigned int sink = 0;
1458 sink += (
unsigned int) di->
flags;
1464 sink += (
unsigned int) (di->
listen_fd + 1);
1467 sink += (
unsigned int) (di->
listen_fd + 1);
1486 unsigned int nseg = 0;
1487 unsigned int nconn = 1;
1503 memset (&
cfg, 0,
sizeof (
cfg));
1508 if (
cfg.listen_sock)
1519 if (
cfg.uses_threads &&
1530 cfg.loop_mode = (
unsigned int) (
data[12] & 0x03);
1531 cfg.quiesce = (0 != (
data[12] & 0x04));
1537 cfg.daemon_info = (0 != (
data[12] & 0x08));
1539 ? (int) ((
data[12] >> 4) & 0x03)
1541 if (3 ==
cfg.suspend_mode)
1542 cfg.suspend_mode = 1;
1543 cfg.nconn_max = 1u + (
unsigned int) ((
data[12] >> 6) & 0x03);
1547 cfg.resp_kind = (
unsigned int) (
data[13] & 0x03);
1548 cfg.handler_no = (0 != (
data[13] & 0x04));
1549 cfg.conn_option = (0 != (
data[13] & 0x08));
1550 cfg.accept_policy = (0 != (
data[13] & 0x10));
1551 cfg.accept_policy_deny = (0 != (
data[13] & 0x20));
1555 cfg.real_connect =
cfg.listen_sock && (0xC0 == (
data[13] & 0xC0));
1559 cbsel = (
unsigned int)
data[5];
1579 if (
cfg.uses_threads)
1587 if (
cfg.daemon_info)
1591 if (
cfg.real_connect)
1596 static const char req[] =
"GET / HTTP/1.1\r\nHost: x\r\n\r\n";
1598 (void) send (rsock, req,
sizeof (req) - 1, MSG_DONTWAIT);
1599 if (
cfg.uses_threads)
1609 while ( (pos + 2 <= size) &&
1612 unsigned int hdr = (
unsigned int)
data[pos]
1613 | ((
unsigned int)
data[pos + 1] << 8);
1614 unsigned int op = hdr >> 14;
1615 size_t slen = (size_t) (hdr & 0x3FFF);
1619 if (slen > size - pos)
1623 (nconn <
cfg.nconn_max) )
1632 if (
cfg.uses_threads)
1641 (void) shutdown (rsock, SHUT_WR);
1642 if (
cfg.uses_threads)
1646 (void) close (rsock);
1657 if (!
cfg.uses_threads)
1678 (void) close ((
int) quiesced);
1705 if (b->len + n > b->cap)
1706 n = b->cap - b->len;
1707 memcpy (b->p + b->len, s, n);
1716 sb_raw (b, s, strlen (s));
1727 (void) snprintf (tmp,
sizeof (tmp),
1728 hex ?
"%llx" :
"%llu",
1729 (
unsigned long long) v);
1735 "GET",
"POST",
"HEAD",
"PUT",
"OPTIONS",
"DELETE",
"TRACE",
"CONNECT",
1736 "PATCH",
"get",
"BREW",
""
1740 "/",
"/a",
"/a/b/c",
"*",
"http://x/a",
"/%41%42",
"/a?b=c&d",
1741 "/very/long/path/that/does/not/fit/into/a/small/connection/memory/pool",
1742 "/a?novalue",
"//",
"/.%2e/",
"/\x01"
1746 "HTTP/1.1",
"HTTP/1.0",
"HTTP/1.2",
"HTTP/0.9",
"HTTP/1",
""
1750 "Host",
"Connection",
"Accept",
"User-Agent",
"Cookie",
"Expect",
1751 "Content-Type",
"X-Fuzz",
"Upgrade",
"Accept-Encoding",
"Range",
1756 "x",
"keep-alive",
"close",
"*/*",
"a=b; c=d",
"100-continue",
1757 "text/plain",
"1",
"fuzz-protocol",
"gzip",
"bytes=0-1",
"chunked"
1784 for (i = 0; i < 24; i++)
1793 sb_str (b,
"GET /a HTTP/1.1\r\nHost: x\r\n\r\n");
1794 sb_str (b,
"GET /b HTTP/1.1\r\nHost: x\r\nConnection: close\r\n\r\n");
1815 for (i = 0; i < nhdr; i++)
1835 sb_str (b,
"Content-Length: ");
1838 for (i = 0; i < n; i++)
1846 sb_str (b,
"Transfer-Encoding: chunked\r\n\r\n");
1847 for (i = 0; i < nch; i++)
1854 for (k = 0; k < n; k++)
1862 sb_str (b,
"Expect: 100-continue\r\nContent-Length: 4\r\n\r\nabcd");
1865 sb_str (b,
"Connection: Upgrade\r\nUpgrade: fuzz-protocol\r\n\r\n");
1884 const uint8_t *body,
1891 while (off < body_len)
1907 chunk = body_len - off;
1910 if (chunk > body_len - off)
1911 chunk = body_len - off;
1914 op = (first && new_conn_first) ? 3u : (
fuzz_chance (rng, 5) ? 2u : 0u);
1915 hv = (
op << 14) | (
unsigned int) chunk;
1916 hdr[0] = (uint8_t) (hv & 0xFF);
1917 hdr[1] = (uint8_t) (hv >> 8);
1918 if (out->len + 2 + chunk > out->cap)
1921 sb_raw (out, body + off, chunk);
1965 cfg_bytes[2] &= (uint8_t) ~0xC0u;
1967 cfg_bytes[2] |= (uint8_t) 0xC0u;
1971 cfg_bytes[14] &= (uint8_t) ~0x40u;
1976 for (i = 0; i < nreq; i++)
1980 rb.cap =
sizeof (req);
2021#define C_VAL_DAUTH 9
2022#define C_VAL_DISC 10
2023#define C_VAL_SOCK 11
2029#define REQ_PLAIN "GET /a HTTP/1.1\r\nHost: x\r\n\r\n"
2030#define REQ_CLOSE "GET /a HTTP/1.1\r\nHost: x\r\nConnection: close\r\n\r\n"
2032 "POST /a HTTP/1.1\r\nHost: x\r\nContent-Length: 4\r\n\r\nabcd"
2033#define REQ_CHUNKED \
2034 "POST /a HTTP/1.1\r\nHost: x\r\nTransfer-Encoding: chunked\r\n" \
2035 "\r\n3\r\nabc\r\n0\r\n\r\n"
2039 {
"plain-external-run",
2041 {
"external-fdset2",
2042 { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x01 | 0x08, 0, 0, 0 },
2044 {
"external-run-wait",
2045 { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x02, 0, 0, 0 },
2047 {
"external-fdset-v1",
2048 { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x03, 0, 0, 0 },
2051 { 12, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
2054 { 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
2058 {
"internal-thread-select",
2059 { 18, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
2061 {
"internal-thread-poll",
2062 { 19, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
2064 {
"internal-thread-epoll",
2065 { 20, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
2067 {
"thread-per-connection",
2068 { 21, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
2070 {
"thread-per-connection-poll",
2071 { 22, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
2077 { 18, 0, 0, 0x20, 0, 0, 0, 0, 0x00, 0, 0, 0, 0, 0, 0, 0 },
2079 {
"thread-pool-epoll-stack",
2080 { 20, 0, 0, 0x20 | 0x40, 0, 0, 0, 0, 0x10 | 0x20, 0, 0, 0, 0, 0, 0, 0 },
2085 { 0, 0, 0x01, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
2087 {
"listen-socket-reuse-backlog",
2088 { 0, 0, 0x01, 0x80, 0x01, 0, 0, 0, 0, 0, 0, 0x01 | 0x06, 0, 0, 0, 0 },
2090 {
"listen-socket-sockaddr",
2091 { 0, 0, 0x01, 0, 0, 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
2093 {
"listen-socket-ipv6-dual",
2094 { 0, 0, 0x01 | 0x02 | 0x04, 0, 0, 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
2096 {
"listen-socket-quiesce",
2097 { 0, 0, 0x01, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x04 | 0x08, 0, 0, 0 },
2099 {
"listen-socket-internal-thread",
2100 { 18, 0, 0x01, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x04, 0, 0, 0 },
2110 { 0, 0, 0x01, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xC0, 0, 0 },
2112 {
"real-connect-accept-policy",
2113 { 0, 0, 0x01, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xC0 | 0x10, 0, 0 },
2115 {
"real-connect-accept-denied",
2116 { 0, 0, 0x01, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xC0 | 0x10 | 0x20, 0, 0 },
2118 {
"real-connect-internal-thread",
2119 { 18, 0, 0x01, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xC0, 0, 0 },
2121 {
"real-connect-external-epoll",
2122 { 12, 0, 0x01, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xC0, 0, 0 },
2127 { 0, 0, 0, 0x01 | 0x02, 0, 0, 0x01 | 0x10, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
2129 {
"big-pool-big-increment",
2130 { 0, 0, 0, 0x01 | 0x02, 0, 0, 0x0C | 0x60, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
2134 {
"connection-limit-one",
2135 { 0, 0, 0, 0x04, 0, 0, 0, 0x01, 0, 0, 0, 0, 0xC0, 0, 0, 0 },
2137 {
"per-ip-limit-one",
2138 { 0, 0, 0, 0x08, 0, 0, 0, 0x10, 0, 0, 0, 0, 0xC0, 0, 0, 0 },
2140 {
"connection-limit-zero",
2141 { 0, 0, 0, 0x04, 0, 0, 0, 0x00, 0, 0, 0, 0, 0, 0, 0, 0 },
2143 {
"connection-timeout",
2144 { 0, 0, 0, 0x10, 0, 0, 0, 0, 0x01, 0, 0, 0, 0, 0, 0, 0 },
2148 {
"discipline-lowest",
2149 { 0, 0, 0, 0, 0x10, 0, 0, 0, 0, 0, 0x00, 0, 0, 0, 0, 0 },
2150 "GET /a HTTP/1.1\r\n Host: x\r\n\r\n" },
2151 {
"discipline-highest-pedantic",
2152 { 0, 0x01, 0, 0, 0x10, 0, 0, 0, 0, 0, 0x05, 0, 0, 0, 0, 0 },
2154 {
"strict-for-client",
2155 { 0, 0, 0, 0, 0x08, 0, 0, 0, 0, 0, 0x00, 0, 0, 0, 0, 0 },
2157 {
"server-insanity",
2158 { 0, 0, 0, 0, 0x04, 0, 0, 0, 0, 0, 0x40, 0, 0, 0, 0, 0 },
2160 {
"bin-zero-in-uri-path",
2161 { 0, 0, 0, 0, 0x80, 0, 0, 0, 0, 0, 0, 0x20, 0, 0, 0, 0 },
2162 "GET /a%00b HTTP/1.1\r\nHost: x\r\n\r\n" },
2164 { 0, 0, 0, 0, 0x40, 0, 0, 0, 0, 0, 0, 0x00, 0x01, 0, 0, 0 },
2168 {
"notify-completed",
2169 { 0, 0, 0, 0, 0, 0x01, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
2171 {
"notify-connection",
2172 { 0, 0, 0, 0, 0, 0x02, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
2174 {
"uri-log-callback",
2175 { 0, 0, 0, 0, 0, 0x04, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
2176 "GET /a?q=%41 HTTP/1.1\r\nHost: x\r\n\r\n" },
2177 {
"external-logger",
2178 { 0, 0x40, 0, 0, 0, 0x10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
2180 {
"unescape-callback",
2181 { 0, 0, 0, 0, 0, 0x08, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
2182 "GET /%41%42?a=%43 HTTP/1.1\r\nHost: x\r\n\r\n" },
2183 {
"all-callbacks-error-log",
2184 { 0, 0x40, 0, 0, 0, 0x01 | 0x02 | 0x04 | 0x08 | 0x10,
2185 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
2190 { 0, 0, 0, 0, 0x02, 0x20, 0, 0, 0, 0x02, 0, 0, 0, 0, 0, 0 },
2192 {
"digest-random-copy",
2193 { 0, 0, 0, 0, 0x02, 0x20 | 0x40, 0, 0, 0, 0x01, 0, 0, 0, 0, 0, 0 },
2195 {
"digest-nonce-bind-and-defaults",
2196 { 0, 0, 0, 0, 0, 0x20, 0, 0, 0, 0x3C, 0, 0, 0, 0,
2197 0x01 | 0x02 | 0x04, 0x11 },
2201 {
"suspend-immediate",
2202 { 0, 0x04, 0, 0, 0, 0x01, 0, 0, 0, 0, 0, 0, 0x10, 0, 0, 0 },
2204 {
"suspend-deferred",
2205 { 0, 0x04, 0, 0, 0, 0x01, 0, 0, 0, 0, 0, 0, 0x20, 0, 0, 0 },
2207 {
"suspend-deferred-two-connections",
2208 { 0, 0x04, 0, 0, 0, 0x01, 0, 0, 0, 0, 0, 0, 0x20 | 0x40, 0, 0, 0 },
2212 {
"turbo-itc-suppress-date",
2213 { 0, 0x02 | 0x10 | 0x20, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
2216 { 0, 0x08, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
2217 "GET / HTTP/1.1\r\nHost: x\r\nConnection: Upgrade\r\n"
2218 "Upgrade: fuzz-protocol\r\n\r\n" },
2219 {
"no-thread-safety",
2220 { 0, 0, 0x10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
2222 {
"tcp-fastopen-listen",
2223 { 0, 0, 0x01 | 0x08, 0, 0, 0, 0, 0, 0, 0, 0, 0x40, 0, 0, 0x08, 0 },
2225 {
"sigpipe-handled-by-app",
2226 { 0, 0, 0, 0, 0x20, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
2228 {
"listen-socket-option-invalid-fd",
2229 { 0, 0, 0x01, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x20, 0 },
2234 {
"raw-flags-poll-and-epoll",
2235 { 0, 0x40, 0xC0 | 0x02, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
2238 {
"raw-flags-epoll-thread-per-conn",
2239 { 0, 0x04 | 0x08, 0xC0 | 0x02, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
2242 {
"invalid-option-number",
2243 { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x40, 0 },
2246 {
"thread-pool-without-threads",
2247 { 0, 0, 0, 0x20, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
2251 {
"handler-returns-no",
2252 { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x04, 0, 0 },
2254 {
"empty-and-copied-responses",
2255 { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x01 | 0x08, 0, 0 },
2258 { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x03, 0, 0 },
2262 {
"kitchen-sink-external",
2263 { 0, 0x02 | 0x04 | 0x10 | 0x20 | 0x40, 0x01,
2264 0x01 | 0x02 | 0x04 | 0x08 | 0x10 | 0x80,
2265 0x02 | 0x10 | 0x20 | 0x40 | 0x80,
2266 0x01 | 0x02 | 0x04 | 0x08 | 0x10 | 0x20,
2267 0x63, 0x45, 0x21, 0x13, 0x02, 0x0A,
2268 0x01 | 0x04 | 0x08 | 0x20, 0x08, 0x01 | 0x02 | 0x04 | 0x10, 0x33 },
2270 {
"kitchen-sink-thread-pool",
2271 { 18, 0x02 | 0x10 | 0x20 | 0x40, 0x01,
2272 0x01 | 0x04 | 0x08 | 0x10 | 0x20 | 0x40 | 0x80,
2274 0x01 | 0x02 | 0x04 | 0x08 | 0x10 | 0x20,
2275 0x03, 0x46, 0x39, 0x02, 0x00, 0x0A,
2276 0x04 | 0x08, 0x00, 0x01 | 0x08, 0x22 },
2290static const uint8_t *
2294 const struct seed_def *sd = &
seeds[idx];
2301 if (
NULL != sd->req)
2303 size_t n = strlen (sd->req);
2309 hv = (0u << 14) | (
unsigned int) n;
2310 hdr[0] = (uint8_t) (hv & 0xFF);
2311 hdr[1] = (uint8_t) (hv >> 8);
Shared, header-only fuzzing driver for the MHD in-process fuzzers.
static FUZZ_UNUSED void fuzz_ignore_sigpipe(void)
static FUZZ_UNUSED int fuzz_verbose
static FUZZ_UNUSED uint32_t fuzz_below(struct fuzz_rng *r, uint32_t n)
static FUZZ_UNUSED uint8_t fuzz_byte(struct fuzz_rng *r)
static FUZZ_UNUSED void fuzz_report_finding(const char *what)
static FUZZ_UNUSED int fuzz_chance(struct fuzz_rng *r, uint32_t n)
static void gen_request(struct fuzz_rng *rng, struct sbuf *b, unsigned int shape)
static void pending_resume_add(struct MHD_Connection *c)
static void prepare_sock_addrs(void)
static void emit_segments(struct fuzz_rng *rng, struct sbuf *out, const uint8_t *body, size_t body_len, int new_conn_first)
static void query_daemon_info(struct MHD_Daemon *d)
static unsigned long stat_conns_refused
static void suspend_maybe(struct MHD_Connection *connection)
static size_t fuzz_seed_count(void)
static const char *const gen_hdr_values[]
static void pump(struct MHD_Daemon *d, int sock, unsigned int rounds)
static void run_once(struct MHD_Daemon *d)
static void send_all(struct MHD_Daemon *d, int sock, const uint8_t *data, size_t len)
static void * uri_log_cb(void *cls, const char *uri, struct MHD_Connection *con)
static const size_t mem_increment_tbl[]
static const struct seed_def seeds[]
static unsigned long stat_conns_added
static int stats_registered
static const char *const gen_targets[]
static unsigned long stat_daemons
static unsigned int build_options(const uint8_t *data, struct MHD_OptionItem *opts, unsigned int flags)
static const unsigned int timeout_tbl[]
static void sb_raw(struct sbuf *b, const void *s, size_t n)
static const unsigned int backlog_tbl[]
static int connect_real(struct MHD_Daemon *d, unsigned int flags)
static int new_connection(struct MHD_Daemon *d, int *sock)
static void add_opt(struct MHD_OptionItem *opts, unsigned int *nopt, enum MHD_OPTION option, intptr_t value, void *ptr_value)
static enum MHD_Result apc_cb(void *cls, const struct sockaddr *addr, socklen_t addrlen)
static void sb_str(struct sbuf *b, const char *s)
static const int fd_setsize_tbl[]
static void sb_u64(struct sbuf *b, uint64_t v, int hex)
static const unsigned int per_ip_limit_tbl[]
#define FUZZ_HARNESS_NAME
static void notify_connection_cb(void *cls, struct MHD_Connection *connection, void **socket_context, enum MHD_ConnectionNotificationCode toe)
static const uint8_t * fuzz_seed_get(size_t idx, size_t *len)
static void query_feature(uint8_t sel)
void *(* fuzz_uri_log_cb)(void *, const char *, struct MHD_Connection *)
static const char *const gen_methods[]
static const unsigned int fastopen_tbl[]
static uint8_t seed_render_buf[1024]
static const char *const gen_hdr_names[]
static void logger_cb(void *cls, const char *fmt, va_list ap)
static const size_t stack_size_tbl[]
static unsigned long stat_daemons_failed
static unsigned long stat_real_conns
static struct MHD_Connection * pending_resume[MAX_CONNECTIONS]
static const unsigned int mode_tbl[]
int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size)
static int bind_addrs_ready
static const unsigned int nonce_nc_tbl[]
static void drain(int sock)
static struct sockaddr_in bind4
static size_t fuzz_generate(struct fuzz_rng *rng, uint8_t *buf, size_t cap)
static void print_stats(void)
static const unsigned int pool_size_tbl[]
static struct MHD_Daemon * start_daemon_variant(unsigned int flags, struct MHD_OptionItem *opts, unsigned int cbsel)
static void panic_cb(void *cls, const char *file, unsigned int line, const char *reason)
static struct fuzz_cfg cfg
static const unsigned int conn_limit_tbl[]
static enum MHD_Result ahc(void *cls, struct MHD_Connection *connection, const char *url, const char *method, const char *version, const char *upload_data, size_t *upload_data_size, void **req_cls)
static unsigned long stat_threaded
static unsigned long stat_handler_calls
static int uses_epoll(unsigned int flags)
static unsigned int flags_from_input(const uint8_t *data)
static void close_connection(struct MHD_Daemon *d, int *sock)
static const char digest_rnd[32]
static int pending_resume_flush(void)
static const int strict_tbl[]
static void completed_cb(void *cls, struct MHD_Connection *connection, void **req_cls, enum MHD_RequestTerminationCode toe)
static const char resp_body[]
static const int discipline_tbl[]
static const size_t mem_limit_tbl[]
static const char *const gen_versions[]
static int quiesce_epoll_race_allowed(void)
static void wait_threaded(int sock)
static size_t unescape_cb(void *cls, struct MHD_Connection *conn, char *s)
_MHD_EXTERN int MHD_get_timeout_i(struct MHD_Daemon *daemon)
_MHD_EXTERN int64_t MHD_get_timeout64s(struct MHD_Daemon *daemon)
#define MHD_run_from_select(d, r, w, e)
_MHD_EXTERN void MHD_stop_daemon(struct MHD_Daemon *daemon)
_MHD_EXTERN enum MHD_Result MHD_run(struct MHD_Daemon *daemon)
_MHD_EXTERN enum MHD_Result MHD_get_fdset2(struct MHD_Daemon *daemon, fd_set *read_fd_set, fd_set *write_fd_set, fd_set *except_fd_set, MHD_socket *max_fd, unsigned int fd_setsize)
#define MHD_get_fdset(daemon, read_fd_set, write_fd_set, except_fd_set, max_fd)
_MHD_EXTERN enum MHD_Result MHD_get_timeout(struct MHD_Daemon *daemon, MHD_UNSIGNED_LONG_LONG *timeout)
_MHD_EXTERN enum MHD_Result MHD_run_from_select2(struct MHD_Daemon *daemon, const fd_set *read_fd_set, const fd_set *write_fd_set, const fd_set *except_fd_set, unsigned int fd_setsize)
_MHD_EXTERN struct MHD_Daemon * MHD_start_daemon(unsigned int flags, uint16_t port, MHD_AcceptPolicyCallback apc, void *apc_cls, MHD_AccessHandlerCallback dh, void *dh_cls,...)
_MHD_EXTERN enum MHD_Result MHD_run_wait(struct MHD_Daemon *daemon, int32_t millisec)
#define MHD_HTTP_INTERNAL_SERVER_ERROR
#define MHD_HTTP_NO_CONTENT
#define MHD_HTTP_FORBIDDEN
_MHD_EXTERN void MHD_set_panic_func(MHD_PanicCallback cb, void *cls)
MHD_ConnectionNotificationCode
void(* MHD_RequestCompletedCallback)(void *cls, struct MHD_Connection *connection, void **req_cls, enum MHD_RequestTerminationCode toe)
void(* MHD_NotifyConnectionCallback)(void *cls, struct MHD_Connection *connection, void **socket_context, enum MHD_ConnectionNotificationCode toe)
MHD_RequestTerminationCode
@ MHD_CONNECTION_NOTIFY_STARTED
_MHD_EXTERN struct MHD_Response * MHD_create_response_from_buffer(size_t size, void *buffer, enum MHD_ResponseMemoryMode mode)
_MHD_EXTERN enum MHD_Result MHD_queue_response(struct MHD_Connection *connection, unsigned int status_code, struct MHD_Response *response)
_MHD_EXTERN void MHD_destroy_response(struct MHD_Response *response)
_MHD_EXTERN struct MHD_Response * MHD_create_response_empty(enum MHD_ResponseFlags flags)
_MHD_EXTERN struct MHD_Response * MHD_create_response_from_buffer_static(size_t size, const void *buffer)
_MHD_EXTERN enum MHD_Result MHD_add_connection(struct MHD_Daemon *daemon, MHD_socket client_socket, const struct sockaddr *addr, socklen_t addrlen)
_MHD_EXTERN enum MHD_Result MHD_is_feature_supported(enum MHD_FEATURE feature)
_MHD_EXTERN enum MHD_Result MHD_set_connection_option(struct MHD_Connection *connection, enum MHD_CONNECTION_OPTION option,...)
_MHD_EXTERN MHD_socket MHD_quiesce_daemon(struct MHD_Daemon *daemon)
_MHD_EXTERN const union MHD_DaemonInfo * MHD_get_daemon_info(struct MHD_Daemon *daemon, enum MHD_DaemonInfoType info_type,...)
_MHD_EXTERN uint32_t MHD_get_version_bin(void)
_MHD_EXTERN const char * MHD_get_version(void)
public interface to libmicrohttpd
@ MHD_OPTION_CONNECTION_MEMORY_INCREMENT
@ MHD_OPTION_DIGEST_AUTH_DEFAULT_NONCE_TIMEOUT
@ MHD_OPTION_CLIENT_DISCIPLINE_LVL
@ MHD_OPTION_SOCK_ADDR_LEN
@ MHD_OPTION_APP_FD_SETSIZE
@ MHD_OPTION_SIGPIPE_HANDLED_BY_APP
@ MHD_OPTION_UNESCAPE_CALLBACK
@ MHD_OPTION_EXTERNAL_LOGGER
@ MHD_OPTION_LISTEN_BACKLOG_SIZE
@ MHD_OPTION_LISTENING_ADDRESS_REUSE
@ MHD_OPTION_THREAD_POOL_SIZE
@ MHD_OPTION_CONNECTION_LIMIT
@ MHD_OPTION_PER_IP_CONNECTION_LIMIT
@ MHD_OPTION_DIGEST_AUTH_DEFAULT_MAX_NC
@ MHD_OPTION_TCP_FASTOPEN_QUEUE_SIZE
@ MHD_OPTION_SERVER_INSANITY
@ MHD_OPTION_LISTEN_SOCKET
@ MHD_OPTION_DIGEST_AUTH_RANDOM
@ MHD_OPTION_NONCE_NC_SIZE
@ MHD_OPTION_ALLOW_BIN_ZERO_IN_URI_PATH
@ MHD_OPTION_CONNECTION_MEMORY_LIMIT
@ MHD_OPTION_THREAD_STACK_SIZE
@ MHD_OPTION_DIGEST_AUTH_RANDOM_COPY
@ MHD_OPTION_STRICT_FOR_CLIENT
@ MHD_OPTION_DIGEST_AUTH_NONCE_BIND_TYPE
@ MHD_OPTION_CONNECTION_TIMEOUT
enum MHD_Result(* MHD_AcceptPolicyCallback)(void *cls, const struct sockaddr *addr, socklen_t addrlen)
#define MHD_UNSIGNED_LONG_LONG
_MHD_EXTERN void MHD_resume_connection(struct MHD_Connection *connection)
#define MHD_INVALID_SOCKET
@ MHD_DAEMON_INFO_BIND_PORT
@ MHD_DAEMON_INFO_EPOLL_FD
@ MHD_DAEMON_INFO_CURRENT_CONNECTIONS
@ MHD_DAEMON_INFO_LISTEN_FD
@ MHD_ALLOW_SUSPEND_RESUME
@ MHD_USE_THREAD_PER_CONNECTION
@ MHD_USE_POST_HANDSHAKE_AUTH_SUPPORT
@ MHD_USE_SUPPRESS_DATE_NO_CLOCK
@ MHD_USE_INSECURE_TLS_EARLY_DATA
@ MHD_USE_NO_LISTEN_SOCKET
@ MHD_USE_PEDANTIC_CHECKS
@ MHD_USE_INTERNAL_POLLING_THREAD
@ MHD_USE_NO_THREAD_SAFETY
_MHD_EXTERN void MHD_suspend_connection(struct MHD_Connection *connection)
@ MHD_CONNECTION_OPTION_TIMEOUT
struct sockaddr_storage * addr
MHD_AcceptPolicyCallback apc
unsigned int num_connections