libmicrohttpd

HTTP/1.x server C library (MHD 1.x, stable)
Log | Files | Refs | Submodules | README | LICENSE

fuzz_eventloop.c (64816B)


      1 /*
      2   This file is part of libmicrohttpd
      3   Copyright (C) 2026 Christian Grothoff
      4 
      5   This library is free software; you can redistribute it and/or
      6   modify it under the terms of the GNU Lesser General Public
      7   License as published by the Free Software Foundation; either
      8   version 2.1 of the License, or (at your option) any later version.
      9 
     10   This library is distributed in the hope that it will be useful,
     11   but WITHOUT ANY WARRANTY; without even the implied warranty of
     12   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
     13   Lesser General Public License for more details.
     14 
     15   You should have received a copy of the GNU Lesser General Public
     16   License along with this library.
     17   If not, see <http://www.gnu.org/licenses/>.
     18 */
     19 
     20 /**
     21  * @file fuzz/fuzz_eventloop.c
     22  * @brief In-process fuzzer for MHD's external event loop and for the
     23  *        scheduling of the connection life cycle.
     24  * @author Christian Grothoff
     25  *
     26  * fuzz_request.c already touches these entry points, but only as a side
     27  * channel: it picks one event-loop mode per iteration and then always
     28  * pumps in the same rhythm.  The bugs this harness is after are in the
     29  * *scheduling* -- what MHD does when the application polls at adversarial
     30  * times, ignores the timeout it was given, calls MHD_run_from_select()
     31  * with descriptor sets that do not match what MHD asked for, or
     32  * suspends/resumes connections across those calls.
     33  *
     34  * The input is therefore not an HTTP request but a *schedule*: a short
     35  * configuration block followed by a program of one-byte opcodes that is
     36  * interpreted against a live `struct MHD_Daemon` with up to
     37  * #MAX_CONNS socketpair connections.  Request bytes enter the program
     38  * through two of those opcodes (a fragment table and a raw literal), so
     39  * the parser is still driven, just not fuzzed.
     40  *
     41  * Input format
     42  * ------------
     43  *
     44  *   byte 0   daemon configuration
     45  *              bits 0-1  MHD_OPTION_CONNECTION_TIMEOUT selector,
     46  *                        index into {1, 2, 0, 1} seconds
     47  *              bit  2    give the daemon a real listening socket (port 0)
     48  *                        instead of MHD_USE_NO_LISTEN_SOCKET, so that
     49  *                        MHD_quiesce_daemon() has something to do and the
     50  *                        listen FD shows up in the descriptor sets
     51  *              bit  3    pass MHD_OPTION_APP_FD_SETSIZE
     52  *              bits 4-5  MHD_OPTION_CONNECTION_MEMORY_LIMIT selector,
     53  *                        index into {default, 256, 1024, 4096}
     54  *              bit  6    MHD_OPTION_CONNECTION_LIMIT = 2, so that
     55  *                        MHD_add_connection() starts failing
     56  *              bit  7    shrink SO_SNDBUF/SO_RCVBUF of the socketpair, so
     57  *                        that responses do not fit and connections stay
     58  *                        blocked on write
     59  *   byte 1   access-handler behaviour
     60  *              bits 0-1  response kind: 0 small static buffer,
     61  *                        1 chunked callback (MHD_SIZE_UNKNOWN),
     62  *                        2 large (128 KiB) static buffer, 3 empty
     63  *              bit  2    answer 500 instead of 200
     64  *              bit  3    suspend in the handler and leave it parked
     65  *              bit  4    suspend and resume immediately in the handler
     66  *              bit  5    call MHD_set_connection_option() from the handler
     67  *              bit  6    call MHD_get_connection_info() from the handler
     68  *              bit  7    drain the client side after every run
     69  *   byte 2   event-loop defaults
     70  *              bits 0-2  default MHD_get_fdset*() variant
     71  *              bits 3-4  default run entry point
     72  *              bit  5    honour the timeout MHD returns
     73  *              bit  6    query the timeouts after every run
     74  *              bit  7    MHD_quiesce_daemon() before stopping
     75  *   byte 3   schedule knobs
     76  *              bits 0-1  number of connections opened up front (1-4)
     77  *              bit  2    run the timeout oracle after every operation
     78  *              bit  3    allow a real-time wait for a connection timeout
     79  *                        to expire (globally budgeted, see below)
     80  *              bit  4    queue one more connection at the very end and
     81  *                        stop the daemon without running the loop again,
     82  *                        so that MHD has to dispose of a connection it
     83  *                        never started (see queue_unprocessed_conn())
     84  *              bits 5-7  unused
     85  *   byte 4   artificial-clock step base
     86  *   byte 5.  the operation program.  Each operation is one byte,
     87  *            `(opcode << 4) | argument`; see enum op below.  OP_SEND_RAW
     88  *            is the only one with an operand: a length byte followed by
     89  *            that many payload bytes.
     90  *
     91  * An input shorter than five bytes is rejected: the configuration block
     92  * is mandatory and an input that short carries no program either.
     93  *
     94  * Oracles
     95  * -------
     96  *
     97  * Beyond ASAN/UBSAN and the MHD_set_panic_func() tripwire (any
     98  * MHD_PANIC() reached this way is a finding, including the
     99  * "MHD_stop_daemon() called while we have suspended connections" one
    100  * that answers the "the daemon must always be stoppable" requirement):
    101  *
    102  *  a) the four timeout accessors must agree.  MHD_get_timeout(),
    103  *     MHD_get_timeout64(), MHD_get_timeout64s() and MHD_get_timeout_i()
    104  *     read the same state, so either all of them report a timeout or
    105  *     none of them does.  Their values are read in sequence, so the
    106  *     clock may advance between two of them and the value may only
    107  *     *decrease*; connection_get_wait() has a documented 100 ms floor
    108  *     for the "exact match" case, hence the 100 ms slack.
    109  *
    110  *  b) a reported timeout must never exceed the largest connection
    111  *     timeout in effect.  MHD only ever derives it from
    112  *     `last_activity + connection_timeout_ms`, so a larger value would
    113  *     mean the deadline is somewhere the application cannot reach.
    114  *
    115  *  c) MHD must never ask the application to wait forever while it has a
    116  *     live, not-suspended connection with a non-zero timeout: that is
    117  *     precisely the "timeout in the past" situation, i.e. a connection
    118  *     that can never be reaped.  Live connections are tracked through
    119  *     MHD_OPTION_NOTIFY_CONNECTION, which brackets exactly the interval
    120  *     in which MHD owns the connection object.
    121  *
    122  *     Both inputs of (b) and (c) -- whether a connection is suspended and
    123  *     what its timeout is -- are read back from MHD rather than modelled,
    124  *     because both diverge from what the application asked for:
    125  *     MHD_set_connection_option() silently does nothing while a
    126  *     connection is suspended.  A harness that models them ends up
    127  *     reporting findings against its own model.
    128  *
    129  *  d) MHD_get_fdset*() must not set a descriptor at or above the
    130  *     FD_SETSIZE limit it was given, `*max_fd` must be at least as large
    131  *     as every descriptor that was added, and `*max_fd` itself must be
    132  *     one of them.
    133  *
    134  *  e) after MHD_quiesce_daemon() the listening socket must be gone from
    135  *     the descriptor sets.
    136  *
    137  * Two contract rules the harness has to respect (violating either makes
    138  * MHD abort on a schedule that is perfectly legal, so the harness would
    139  * only be finding its own bugs):
    140  *
    141  *  * a connection is only suspended when the access handler is about to
    142  *    return MHD_YES.  MHD_NO asks MHD to terminate the connection, and
    143  *    terminating one that the same callback just suspended trips
    144  *    mhd_assert (! connection->suspended) in MHD_connection_close_();
    145  *
    146  *  * every suspended connection is resumed before MHD_stop_daemon().
    147  *    Several connections can be parked at once, so this is a set
    148  *    (@e lives[i].susp), not a single slot, and @e tearing_down stops
    149  *    the handler from parking anything new while the set is drained.
    150  *
    151  * MHD_suspend_connection() is additionally only called when MHD does not
    152  * already consider the connection suspended, *unless* a resume of it is
    153  * still pending -- that is the one case internal_suspend_connection_()
    154  * handles itself (it cancels the resume), and the harness mirrors the
    155  * resulting state.  Calling it on an already-suspended connection would
    156  * unlink it from a list it is not on.
    157  *
    158  * One more trap: with MHD_USE_ITC -- which MHD_ALLOW_SUSPEND_RESUME
    159  * implies, so this harness always has it -- MHD_add_connection() only
    160  * *queues* the socket, and the `struct MHD_Connection` is created later,
    161  * from inside a run.  There is therefore no moment at which the
    162  * application could pair its own socket up with the connection object,
    163  * and the registry of live connections has to be built purely from
    164  * MHD_OPTION_NOTIFY_CONNECTION.  This is why the client sockets
    165  * (@e csock) and the connections (@e lives) are two separate arrays.
    166  *
    167  * Note on MHD_get_timeout_expiration(): no such function exists in the
    168  * MHD 1.x API.  The four accessors above are the complete family; the
    169  * absolute-deadline form is a MHD 2.x addition.
    170  */
    171 
    172 #define FUZZ_HARNESS_NAME "fuzz_eventloop"
    173 #include "fuzz_common.h"
    174 
    175 #include <microhttpd.h>
    176 #include <sys/socket.h>
    177 #include <netinet/in.h>
    178 #include <sys/select.h>
    179 #include <limits.h>
    180 
    181 /** Largest number of connections a single iteration may have open. */
    182 #define MAX_CONNS 8
    183 
    184 /** Upper bound on the number of operations interpreted per iteration. */
    185 #define MAX_OPS 400
    186 
    187 /** Size of the "large response" body. */
    188 #define BIG_BODY_LEN 131072
    189 
    190 /** Bytes read back from the daemon are counted, never inspected. */
    191 #define DRAIN_BUF 4096
    192 
    193 
    194 /* ------------------------------------------------------------------ */
    195 /* Per-iteration configuration                                         */
    196 /* ------------------------------------------------------------------ */
    197 
    198 struct el_cfg
    199 {
    200   unsigned int timeout_s;      /**< MHD_OPTION_CONNECTION_TIMEOUT */
    201   int listen_sock;             /**< real listening socket wanted */
    202   int app_fd_setsize;          /**< pass MHD_OPTION_APP_FD_SETSIZE */
    203   size_t mem_limit;            /**< MHD_OPTION_CONNECTION_MEMORY_LIMIT */
    204   int conn_limit;              /**< MHD_OPTION_CONNECTION_LIMIT = 2 */
    205   int small_sockbuf;           /**< shrink the socketpair buffers */
    206 
    207   unsigned int resp_kind;      /**< which response the handler queues */
    208   int error_reply;             /**< answer 500 instead of 200 */
    209   int susp_park;               /**< handler suspends and leaves it parked */
    210   int susp_now;                /**< handler suspends and resumes at once */
    211   int hnd_connopt;             /**< handler calls set_connection_option */
    212   int hnd_info;                /**< handler calls get_connection_info */
    213   int auto_drain;              /**< drain the client sockets after a run */
    214 
    215   unsigned int fdset_var;      /**< default MHD_get_fdset*() variant */
    216   unsigned int run_var;        /**< default run entry point */
    217   int honour_timeout;          /**< act on the timeout MHD returns */
    218   int timeout_every_run;       /**< query the timeouts after every run */
    219   int quiesce_end;             /**< quiesce before stopping */
    220 
    221   unsigned int nconn_up_front; /**< connections opened before the program */
    222   int check_always;            /**< run the timeout oracle after every op */
    223   int allow_real_wait;         /**< may burn real time on a timeout expiry */
    224   int stop_with_queued;        /**< stop with a connection still queued */
    225   uint8_t clock_seed;          /**< artificial-clock step base */
    226 };
    227 
    228 static struct el_cfg cfg;
    229 
    230 /** Connection memory limits selectable by byte 0. */
    231 static const size_t mem_limit_tbl[] = { 0, 256, 1024, 4096 };
    232 
    233 /** Connection timeouts (seconds) selectable by byte 0. */
    234 static const unsigned int timeout_tbl[] = { 1, 2, 0, 1 };
    235 
    236 /**
    237  * FD_SETSIZE values handed to MHD_get_fdset2()/MHD_run_from_select2().
    238  *
    239  * All of them are <= FD_SETSIZE on purpose.  Passing a *larger* value
    240  * than the `fd_set` objects actually hold would let MHD write past them,
    241  * which is the application lying about its own buffers rather than
    242  * anything MHD could defend against; the interesting direction is the
    243  * smaller one, where MHD has to refuse descriptors that do not fit.
    244  */
    245 static const unsigned int setsize_tbl[] = {
    246   (unsigned int) FD_SETSIZE,
    247   (unsigned int) FD_SETSIZE,
    248   (unsigned int) FD_SETSIZE / 2,
    249   64, 16, 4, 1, (unsigned int) FD_SETSIZE
    250 };
    251 
    252 
    253 /* ------------------------------------------------------------------ */
    254 /* Per-iteration state                                                 */
    255 /* ------------------------------------------------------------------ */
    256 
    257 /**
    258  * The client end of one socketpair.  Deliberately *not* tied to a
    259  * `struct MHD_Connection`: with MHD_USE_ITC (which
    260  * MHD_ALLOW_SUSPEND_RESUME implies) MHD_add_connection() only queues the
    261  * socket and the connection object is created later, from inside a run.
    262  * There is therefore no moment at which the harness could pair the two
    263  * up, and trying to would silently mistrack every connection.
    264  */
    265 static int csock[MAX_CONNS];
    266 static unsigned int nconns;
    267 static unsigned int cur_conn;
    268 
    269 /**
    270  * A connection MHD currently owns.
    271  *
    272  * The registry is maintained purely from MHD_OPTION_NOTIFY_CONNECTION,
    273  * which brackets exactly the interval in which the object exists: after
    274  * MHD_CONNECTION_NOTIFY_CLOSED nothing may reference it any more, in
    275  * particular not a deferred resume and not the "is there a live
    276  * connection" oracle.
    277  */
    278 struct live_conn
    279 {
    280   struct MHD_Connection *mc;   /**< NULL if the slot is free */
    281   int susp;                    /**< suspended by us, not resumed yet */
    282 };
    283 
    284 /** A few more slots than connections, so the registry cannot overflow. */
    285 #define MAX_LIVE (MAX_CONNS + 4)
    286 
    287 static struct live_conn lives[MAX_LIVE];
    288 
    289 /** Daemon of the current iteration. */
    290 static struct MHD_Daemon *cur_daemon;
    291 
    292 /**
    293  * Set once the iteration only wants to drain the daemon.  The handler
    294  * then stops parking connections, which is what makes the flush loop in
    295  * the teardown terminate.
    296  */
    297 static int tearing_down;
    298 
    299 /** Listening socket returned by MHD_quiesce_daemon(), ours to close. */
    300 static MHD_socket quiesced_fd = MHD_INVALID_SOCKET;
    301 
    302 /** Artificial clock; only the harness's own scheduling depends on it. */
    303 static uint64_t clk_ms;
    304 static uint64_t deadline_ms;
    305 static int deadline_valid;
    306 
    307 /** Descriptor sets collected by the last OP_FDSET. */
    308 static fd_set g_rs;
    309 static fd_set g_ws;
    310 static fd_set g_es;
    311 static MHD_socket g_max_fd = MHD_INVALID_SOCKET;
    312 static unsigned int g_setsize = (unsigned int) FD_SETSIZE;
    313 static int g_have_sets;
    314 
    315 /** The large response body, filled once. */
    316 static char big_body[BIG_BODY_LEN];
    317 static int big_body_ready;
    318 
    319 /**
    320  * Budget for iterations that are allowed to wait in real time for a
    321  * connection timeout to expire.  MHD_OPTION_CONNECTION_TIMEOUT has a
    322  * resolution of one second, so the expiry path cannot be reached without
    323  * actually burning about that much wall clock; the budget keeps the
    324  * whole run in the "couple of seconds" range while still exercising it.
    325  * Override with MHD_FUZZ_EXPIRY_BUDGET.
    326  */
    327 static int expiry_budget = 2;
    328 static int expiry_budget_read;
    329 
    330 /** Statistics, printed at exit with --verbose. */
    331 static unsigned long stat_daemons;
    332 static unsigned long stat_handler_calls;
    333 static unsigned long stat_fdset_v1;
    334 static unsigned long stat_fdset_v2;
    335 static unsigned long stat_rfs_v1;
    336 static unsigned long stat_rfs_v2;
    337 static unsigned long stat_run;
    338 static unsigned long stat_run_wait;
    339 static unsigned long stat_timeouts;
    340 static unsigned long stat_quiesce;
    341 static unsigned long stat_suspend;
    342 static unsigned long stat_resume;
    343 static unsigned long stat_expiry_waits;
    344 static unsigned long stat_queued_at_stop;
    345 static int stats_registered;
    346 
    347 
    348 static void
    349 print_stats (void)
    350 {
    351   if (! fuzz_verbose)
    352     return;
    353   fprintf (stderr,
    354            "%s: daemons=%lu handler=%lu get_fdset=%lu get_fdset2=%lu "
    355            "run_from_select=%lu run_from_select2=%lu run=%lu run_wait=%lu "
    356            "timeout queries=%lu quiesce=%lu suspend=%lu resume=%lu "
    357            "expiry waits=%lu queued at stop=%lu\n",
    358            FUZZ_HARNESS_NAME,
    359            stat_daemons, stat_handler_calls, stat_fdset_v1, stat_fdset_v2,
    360            stat_rfs_v1, stat_rfs_v2, stat_run, stat_run_wait,
    361            stat_timeouts, stat_quiesce, stat_suspend, stat_resume,
    362            stat_expiry_waits, stat_queued_at_stop);
    363 }
    364 
    365 
    366 /* ------------------------------------------------------------------ */
    367 /* Callbacks                                                           */
    368 /* ------------------------------------------------------------------ */
    369 
    370 static void
    371 panic_cb (void *cls,
    372           const char *file,
    373           unsigned int line,
    374           const char *reason)
    375 {
    376   char msg[512];
    377 
    378   (void) cls;
    379   (void) snprintf (msg, sizeof (msg),
    380                    "MHD_PANIC() reached from an event-loop schedule "
    381                    "at %s:%u: %s",
    382                    (NULL != file) ? file : "?",
    383                    line,
    384                    (NULL != reason) ? reason : "?");
    385   fuzz_report_finding (msg);
    386 }
    387 
    388 
    389 /**
    390  * Find the registry slot of @a c, or -1.
    391  */
    392 static int
    393 slot_of (const struct MHD_Connection *c)
    394 {
    395   unsigned int i;
    396 
    397   for (i = 0; i < MAX_LIVE; i++)
    398     if ( (NULL != lives[i].mc) &&
    399          (lives[i].mc == c) )
    400       return (int) i;
    401   return -1;
    402 }
    403 
    404 
    405 static void
    406 notify_conn_cb (void *cls,
    407                 struct MHD_Connection *connection,
    408                 void **socket_context,
    409                 enum MHD_ConnectionNotificationCode toe)
    410 {
    411   unsigned int i;
    412   int idx;
    413 
    414   (void) cls;
    415   (void) socket_context;
    416   if (MHD_CONNECTION_NOTIFY_STARTED == toe)
    417   {
    418     for (i = 0; i < MAX_LIVE; i++)
    419     {
    420       if (NULL != lives[i].mc)
    421         continue;
    422       lives[i].mc = connection;
    423       lives[i].susp = 0;
    424       return;
    425     }
    426     return;
    427   }
    428   /* MHD_CONNECTION_NOTIFY_CLOSED: the object is about to be freed. */
    429   idx = slot_of (connection);
    430   if (0 <= idx)
    431   {
    432     lives[idx].mc = NULL;
    433     lives[idx].susp = 0;
    434   }
    435 }
    436 
    437 
    438 /* ------------------------------------------------------------------ */
    439 /* Suspend / resume bookkeeping                                        */
    440 /* ------------------------------------------------------------------ */
    441 
    442 /**
    443  * Ask MHD whether it considers slot @a i suspended.
    444  */
    445 static int
    446 mhd_thinks_suspended (unsigned int i)
    447 {
    448   const union MHD_ConnectionInfo *ci;
    449 
    450   if (NULL == lives[i].mc)
    451     return 0;
    452   ci = MHD_get_connection_info (lives[i].mc,
    453                                 MHD_CONNECTION_INFO_CONNECTION_SUSPENDED);
    454   if (NULL == ci)
    455     return 0;
    456   return (MHD_YES == ci->suspended);
    457 }
    458 
    459 
    460 /**
    461  * Suspend slot @a i, if that is legal right now.
    462  *
    463  * MHD_suspend_connection() unlinks the connection from the timeout and
    464  * connection lists, so calling it on a connection MHD already has on the
    465  * suspended list corrupts those lists.  The one exception is a
    466  * connection with a resume still pending: internal_suspend_connection_()
    467  * detects that itself and merely cancels the resume, leaving the
    468  * connection suspended -- which is why @e susp is set in both branches.
    469  */
    470 static void
    471 do_suspend (unsigned int i)
    472 {
    473   int mhd_susp;
    474 
    475   if ( (i >= MAX_LIVE) ||
    476        (NULL == lives[i].mc) )
    477     return;
    478   mhd_susp = mhd_thinks_suspended (i);
    479   if (mhd_susp && lives[i].susp)
    480     return;                     /* really suspended already */
    481   MHD_suspend_connection (lives[i].mc);
    482   lives[i].susp = 1;
    483   stat_suspend++;
    484 }
    485 
    486 
    487 static void
    488 do_resume (unsigned int i)
    489 {
    490   if ( (i >= MAX_LIVE) ||
    491        (NULL == lives[i].mc) ||
    492        (! lives[i].susp) )
    493     return;
    494   /* Clear first: MHD_resume_connection() may end up running the handler
    495      later, which is allowed to suspend the very same connection again. */
    496   lives[i].susp = 0;
    497   MHD_resume_connection (lives[i].mc);
    498   stat_resume++;
    499 }
    500 
    501 
    502 /**
    503  * Resume everything still parked.
    504  *
    505  * @return non-zero if at least one connection was resumed, so that the
    506  *         caller knows the daemon needs another round to act on it
    507  */
    508 static int
    509 resume_all (void)
    510 {
    511   unsigned int i;
    512   int any = 0;
    513 
    514   for (i = 0; i < MAX_LIVE; i++)
    515   {
    516     if ( (NULL == lives[i].mc) ||
    517          (! lives[i].susp) )
    518       continue;
    519     lives[i].susp = 0;
    520     MHD_resume_connection (lives[i].mc);
    521     stat_resume++;
    522     any = 1;
    523   }
    524   return any;
    525 }
    526 
    527 
    528 /**
    529  * Summarise the connections MHD currently owns.
    530  *
    531  * Both properties are read back from MHD rather than modelled: a
    532  * connection leaves the timeout lists exactly when MHD sets
    533  * `connection->suspended`, and its timeout is exactly what
    534  * MHD_set_connection_option() left there -- which is *not* what the
    535  * application passed if the connection happened to be suspended at the
    536  * time.  Modelling either of them means the oracle eventually fires on
    537  * the model rather than on MHD.
    538  *
    539  * @param[out] max_ms largest timeout, in milliseconds, of the
    540  *        connections that are in a timeout list right now
    541  * @return non-zero if at least one such connection exists, i.e. if MHD
    542  *         must report a timeout
    543  */
    544 static int
    545 scan_live_timeouts (uint64_t *max_ms)
    546 {
    547   unsigned int i;
    548   int any = 0;
    549 
    550   *max_ms = 0;
    551   for (i = 0; i < MAX_LIVE; i++)
    552   {
    553     const union MHD_ConnectionInfo *ci;
    554     uint64_t ms;
    555 
    556     if (NULL == lives[i].mc)
    557       continue;
    558     ci = MHD_get_connection_info (lives[i].mc,
    559                                   MHD_CONNECTION_INFO_CONNECTION_SUSPENDED);
    560     if ( (NULL != ci) &&
    561          (MHD_YES == ci->suspended) )
    562       continue;                 /* not in any timeout list */
    563     ci = MHD_get_connection_info (lives[i].mc,
    564                                   MHD_CONNECTION_INFO_CONNECTION_TIMEOUT);
    565     if (NULL == ci)
    566       continue;
    567     ms = ((uint64_t) ci->connection_timeout) * 1000;
    568     if (0 == ms)
    569       continue;                 /* in a list, but exempt from timeouts */
    570     any = 1;
    571     if (ms > *max_ms)
    572       *max_ms = ms;
    573   }
    574   return any;
    575 }
    576 
    577 
    578 /* ------------------------------------------------------------------ */
    579 /* The access handler                                                  */
    580 /* ------------------------------------------------------------------ */
    581 
    582 struct crc_state
    583 {
    584   uint64_t total;
    585   unsigned int pattern;
    586 };
    587 
    588 
    589 static ssize_t
    590 crc_cb (void *cls,
    591         uint64_t pos,
    592         char *buf,
    593         size_t max)
    594 {
    595   struct crc_state *st = (struct crc_state *) cls;
    596   size_t n;
    597   size_t i;
    598 
    599   if (pos >= st->total)
    600     return MHD_CONTENT_READER_END_OF_STREAM;
    601   n = (size_t) (st->total - pos);
    602   if (n > max)
    603     n = max;
    604   if (0 == n)
    605     return MHD_CONTENT_READER_END_OF_STREAM;
    606   for (i = 0; i < n; i++)
    607     buf[i] = (char) ('a' + (int) ((pos + i + st->pattern) % 26));
    608   return (ssize_t) n;
    609 }
    610 
    611 
    612 static void
    613 crc_free (void *cls)
    614 {
    615   free (cls);
    616 }
    617 
    618 
    619 static struct MHD_Response *
    620 make_response (void)
    621 {
    622   struct crc_state *st;
    623   struct MHD_Response *r;
    624 
    625   switch (cfg.resp_kind)
    626   {
    627   case 1:
    628     st = (struct crc_state *) calloc (1, sizeof (struct crc_state));
    629     if (NULL == st)
    630       return NULL;
    631     st->total = 700;
    632     st->pattern = cfg.clock_seed;
    633     r = MHD_create_response_from_callback (MHD_SIZE_UNKNOWN,
    634                                            128,
    635                                            &crc_cb,
    636                                            st,
    637                                            &crc_free);
    638     if (NULL == r)
    639       free (st);
    640     return r;
    641   case 2:
    642     /* Large enough not to fit into the socket buffers, so that the
    643        connection stays blocked on write and MHD has to schedule it
    644        through the write descriptor set over several rounds. */
    645     return MHD_create_response_from_buffer_static (BIG_BODY_LEN, big_body);
    646   case 3:
    647     return MHD_create_response_empty (MHD_RF_NONE);
    648   default:
    649     return MHD_create_response_from_buffer_static (2, "ok");
    650   }
    651 }
    652 
    653 
    654 static enum MHD_Result
    655 ahc (void *cls,
    656      struct MHD_Connection *connection,
    657      const char *url,
    658      const char *method,
    659      const char *version,
    660      const char *upload_data,
    661      size_t *upload_data_size,
    662      void **req_cls)
    663 {
    664   struct MHD_Response *resp;
    665   enum MHD_Result ret;
    666   int idx;
    667 
    668   (void) cls;
    669   (void) url;
    670   (void) method;
    671   (void) version;
    672   (void) upload_data;
    673   if (NULL == *req_cls)
    674   {
    675     *req_cls = (void *) (intptr_t) 1;
    676     return MHD_YES;
    677   }
    678   stat_handler_calls++;
    679   if (0 != *upload_data_size)
    680   {
    681     *upload_data_size = 0;
    682     return MHD_YES;
    683   }
    684 
    685   idx = slot_of (connection);
    686   if (cfg.hnd_connopt)
    687   {
    688     /* Moves the connection between the "normal" and the "manual" timeout
    689        list, i.e. changes which connection MHD_get_timeout*() reports. */
    690     unsigned int nt = (0 == cfg.timeout_s) ? 1u : (cfg.timeout_s + 1u);
    691 
    692     (void) MHD_set_connection_option (connection,
    693                                       MHD_CONNECTION_OPTION_TIMEOUT,
    694                                       nt);
    695   }
    696   if (cfg.hnd_info)
    697   {
    698     volatile size_t sink = 0;
    699     const union MHD_ConnectionInfo *ci;
    700 
    701     ci = MHD_get_connection_info (connection,
    702                                   MHD_CONNECTION_INFO_CONNECTION_FD);
    703     if (NULL != ci)
    704       sink += (size_t) (ci->connect_fd + 1);
    705     ci = MHD_get_connection_info (connection,
    706                                   MHD_CONNECTION_INFO_CONNECTION_TIMEOUT);
    707     if (NULL != ci)
    708       sink += (size_t) ci->connection_timeout;
    709     (void) sink;
    710   }
    711 
    712   resp = make_response ();
    713   if (NULL == resp)
    714     return MHD_NO;
    715   ret = MHD_queue_response (connection,
    716                             cfg.error_reply
    717                             ? MHD_HTTP_INTERNAL_SERVER_ERROR : MHD_HTTP_OK,
    718                             resp);
    719   MHD_destroy_response (resp);
    720   if (MHD_YES != ret)
    721     return ret;
    722   /* Only once the response was accepted: returning MHD_NO tells MHD to
    723      terminate the connection, and terminating one that this very callback
    724      suspended trips mhd_assert (! connection->suspended) in
    725      MHD_connection_close_(). */
    726   if (tearing_down ||
    727       (0 > idx))
    728     return ret;
    729   if (cfg.susp_now)
    730   {
    731     MHD_suspend_connection (connection);
    732     MHD_resume_connection (connection);
    733     stat_suspend++;
    734     stat_resume++;
    735   }
    736   else if (cfg.susp_park &&
    737            (! lives[idx].susp))
    738   {
    739     MHD_suspend_connection (connection);
    740     lives[idx].susp = 1;
    741     stat_suspend++;
    742   }
    743   return ret;
    744 }
    745 
    746 
    747 /* ------------------------------------------------------------------ */
    748 /* Oracles                                                             */
    749 /* ------------------------------------------------------------------ */
    750 
    751 /**
    752  * Query all four timeout accessors and cross-check them.
    753  *
    754  * The values are read one after the other, so the monotonic clock may
    755  * advance in between and a later reading may be *smaller*.  It may never
    756  * be larger, except for the 100 ms floor connection_get_wait() falls back
    757  * to when the elapsed time exactly matches the timeout.
    758  */
    759 static void
    760 check_timeouts (struct MHD_Daemon *d)
    761 {
    762   MHD_UNSIGNED_LONG_LONG tl = 0;
    763   uint64_t t64 = 0;
    764   int64_t t64s;
    765   int ti;
    766   enum MHD_Result r1;
    767   enum MHD_Result r2;
    768   int have[4];
    769   uint64_t val[4];
    770   unsigned int k;
    771   uint64_t max_ms;
    772   int any_timed;
    773   char msg[256];
    774 
    775   stat_timeouts++;
    776   r1 = MHD_get_timeout (d, &tl);
    777   r2 = MHD_get_timeout64 (d, &t64);
    778   t64s = MHD_get_timeout64s (d);
    779   ti = MHD_get_timeout_i (d);
    780 
    781   have[0] = (MHD_YES == r1);
    782   have[1] = (MHD_YES == r2);
    783   have[2] = (0 <= t64s);
    784   have[3] = (0 <= ti);
    785   val[0] = (uint64_t) tl;
    786   val[1] = t64;
    787   val[2] = (uint64_t) (t64s < 0 ? 0 : t64s);
    788   val[3] = (uint64_t) (ti < 0 ? 0 : ti);
    789 
    790   for (k = 1; k < 4; k++)
    791     if (have[k] != have[0])
    792       fuzz_report_finding (
    793         "MHD_get_timeout*(): the four accessors disagree about whether "
    794         "a timeout is in effect");
    795 
    796   any_timed = scan_live_timeouts (&max_ms);
    797   if (! have[0])
    798   {
    799     /* An indefinite wait while a live, not-suspended connection has a
    800        non-zero timeout means that connection can never be reaped: its
    801        deadline is already unreachable for the application. */
    802     if (any_timed)
    803       fuzz_report_finding (
    804         "MHD_get_timeout*() reported no timeout although the daemon has a "
    805         "live, not suspended connection with a non-zero timeout");
    806     deadline_valid = 0;
    807     return;
    808   }
    809 
    810   for (k = 0; k < 4; k++)
    811   {
    812     if (val[k] <= max_ms)
    813       continue;
    814     (void) snprintf (msg, sizeof (msg),
    815                      "MHD_get_timeout*() [accessor %u] returned %llu ms, "
    816                      "larger than the largest connection timeout in effect "
    817                      "(%llu ms)",
    818                      k,
    819                      (unsigned long long) val[k],
    820                      (unsigned long long) max_ms);
    821     fuzz_report_finding (msg);
    822   }
    823   for (k = 1; k < 4; k++)
    824     if ( (val[k] > val[k - 1]) &&
    825          (val[k] > 100) )
    826       fuzz_report_finding (
    827         "MHD_get_timeout*(): a later accessor reported a larger timeout "
    828         "than an earlier one, although the deadline cannot have moved");
    829 
    830   deadline_ms = clk_ms + val[1];
    831   deadline_valid = 1;
    832 }
    833 
    834 
    835 /**
    836  * Check the descriptor sets that the last MHD_get_fdset*() produced.
    837  *
    838  * @param setsize the FD_SETSIZE limit that was passed to MHD
    839  * @param max_fd the reported maximum, #MHD_INVALID_SOCKET if none
    840  * @param had_max whether a @a max_fd pointer was passed at all
    841  * @param with_es whether an except set was passed
    842  */
    843 static void
    844 check_fdsets (unsigned int setsize,
    845               MHD_socket max_fd,
    846               int had_max,
    847               int with_es)
    848 {
    849   int f;
    850   int hi = -1;
    851   int max_seen = 0;
    852 
    853   for (f = 0; f < (int) FD_SETSIZE; f++)
    854   {
    855     int in_set = FD_ISSET (f, &g_rs) || FD_ISSET (f, &g_ws);
    856 
    857     if (with_es && FD_ISSET (f, &g_es))
    858       in_set = 1;
    859     if (! in_set)
    860       continue;
    861     if ((unsigned int) f >= setsize)
    862       fuzz_report_finding (
    863         "MHD_get_fdset*() added a descriptor at or above the FD_SETSIZE "
    864         "limit it was given");
    865     if (f > hi)
    866       hi = f;
    867     if ( (had_max) &&
    868          (MHD_INVALID_SOCKET != max_fd) &&
    869          (f == (int) max_fd) )
    870       max_seen = 1;
    871   }
    872   if (! had_max)
    873     return;
    874   if (0 > hi)
    875   {
    876     if (MHD_INVALID_SOCKET != max_fd)
    877       fuzz_report_finding (
    878         "MHD_get_fdset*() set max_fd although it added no descriptor");
    879     return;
    880   }
    881   if (MHD_INVALID_SOCKET == max_fd)
    882     fuzz_report_finding (
    883       "MHD_get_fdset*() added descriptors but left max_fd unset");
    884   if (hi > (int) max_fd)
    885     fuzz_report_finding (
    886       "MHD_get_fdset*() added a descriptor larger than the max_fd it "
    887       "reported");
    888   if ((unsigned int) max_fd >= setsize)
    889     fuzz_report_finding (
    890       "MHD_get_fdset*() reported a max_fd at or above the FD_SETSIZE "
    891       "limit it was given");
    892   if (! max_seen)
    893     fuzz_report_finding (
    894       "MHD_get_fdset*() reported a max_fd that is not in any of the sets");
    895 }
    896 
    897 
    898 /* ------------------------------------------------------------------ */
    899 /* Event-loop primitives                                               */
    900 /* ------------------------------------------------------------------ */
    901 
    902 /**
    903  * Collect the descriptor sets.
    904  *
    905  * Variant 0 goes through the *real* v1 entry point.  microhttpd.h also
    906  * defines MHD_get_fdset as a macro forwarding to MHD_get_fdset2 with
    907  * FD_SETSIZE, so the name has to be parenthesised or the v1 function is
    908  * never reached at all.  Same trick for MHD_run_from_select below.
    909  */
    910 static void
    911 op_fdset (struct MHD_Daemon *d,
    912           unsigned int var)
    913 {
    914   MHD_socket max_fd = MHD_INVALID_SOCKET;
    915   unsigned int setsize = (unsigned int) FD_SETSIZE;
    916   int had_max = 1;
    917   int with_es = 1;
    918 
    919   FD_ZERO (&g_rs);
    920   FD_ZERO (&g_ws);
    921   FD_ZERO (&g_es);
    922   switch (var % 5)
    923   {
    924   case 0:
    925     stat_fdset_v1++;
    926     (void) (MHD_get_fdset) (d, &g_rs, &g_ws, &g_es, &max_fd);
    927     break;
    928   case 1:
    929     stat_fdset_v2++;
    930     (void) MHD_get_fdset2 (d, &g_rs, &g_ws, &g_es, &max_fd,
    931                            (unsigned int) FD_SETSIZE);
    932     break;
    933   case 2:
    934     stat_fdset_v2++;
    935     setsize = setsize_tbl[(var + cfg.clock_seed)
    936                           % (sizeof (setsize_tbl)
    937                              / sizeof (setsize_tbl[0]))];
    938     (void) MHD_get_fdset2 (d, &g_rs, &g_ws, &g_es, &max_fd, setsize);
    939     break;
    940   case 3:
    941     /* max_fd is documented as optional */
    942     stat_fdset_v2++;
    943     had_max = 0;
    944     (void) MHD_get_fdset2 (d, &g_rs, &g_ws, &g_es, NULL,
    945                            (unsigned int) FD_SETSIZE);
    946     break;
    947   default:
    948     /* no except set: deprecated, but shipped API */
    949     stat_fdset_v2++;
    950     with_es = 0;
    951     (void) MHD_get_fdset2 (d, &g_rs, &g_ws, NULL, &max_fd,
    952                            (unsigned int) FD_SETSIZE);
    953     break;
    954   }
    955   check_fdsets (setsize, max_fd, had_max, with_es);
    956   g_max_fd = max_fd;
    957   g_setsize = setsize;
    958   g_have_sets = 1;
    959   if ( (MHD_INVALID_SOCKET != quiesced_fd) &&
    960        ((unsigned int) quiesced_fd < (unsigned int) FD_SETSIZE) &&
    961        FD_ISSET (quiesced_fd, &g_rs) )
    962     fuzz_report_finding (
    963       "MHD_get_fdset*() still watches the listening socket after "
    964       "MHD_quiesce_daemon() handed it back to the application");
    965 }
    966 
    967 
    968 /**
    969  * select() on the sets collected last, with a zero timeout.
    970  *
    971  * The harness is single threaded and everything MHD could be waiting for
    972  * has already been written into the socketpairs, so blocking would only
    973  * burn wall clock; select() is called purely to fill in the readiness.
    974  */
    975 static void
    976 op_poll (void)
    977 {
    978   struct timeval tv;
    979 
    980   if ( (! g_have_sets) ||
    981        (MHD_INVALID_SOCKET == g_max_fd) )
    982     return;
    983   tv.tv_sec = 0;
    984   tv.tv_usec = 0;
    985   (void) select ((int) g_max_fd + 1, &g_rs, &g_ws, &g_es, &tv);
    986 }
    987 
    988 
    989 /**
    990  * Drain whatever the daemon has produced on slot @a i, so that a large
    991  * response can make progress.
    992  */
    993 static void
    994 drain_conn (unsigned int i)
    995 {
    996   char tmp[DRAIN_BUF];
    997 
    998   if ( (i >= MAX_CONNS) ||
    999        (0 > csock[i]) )
   1000     return;
   1001   for (;;)
   1002   {
   1003     ssize_t n = recv (csock[i], tmp, sizeof (tmp), MSG_DONTWAIT);
   1004 
   1005     if (0 >= n)
   1006       break;
   1007   }
   1008 }
   1009 
   1010 
   1011 static void
   1012 drain_all (void)
   1013 {
   1014   unsigned int i;
   1015 
   1016   for (i = 0; i < MAX_CONNS; i++)
   1017     drain_conn (i);
   1018 }
   1019 
   1020 
   1021 /**
   1022  * Advance the daemon once.
   1023  *
   1024  * @param d the daemon
   1025  * @param var which entry point to use
   1026  * @param flavour which descriptor sets to hand over:
   1027  *        0 the ones MHD asked for, 1 all-zero, 2 all-ones,
   1028  *        3 only the read set as collected
   1029  */
   1030 static void
   1031 op_run (struct MHD_Daemon *d,
   1032         unsigned int var,
   1033         unsigned int flavour)
   1034 {
   1035   fd_set rs;
   1036   fd_set ws;
   1037   fd_set es;
   1038 
   1039   switch (flavour % 4)
   1040   {
   1041   case 1:
   1042     FD_ZERO (&rs);
   1043     FD_ZERO (&ws);
   1044     FD_ZERO (&es);
   1045     break;
   1046   case 2:
   1047     /* Every descriptor number reported ready.  MHD only tests the bits of
   1048        the sockets it owns, so this is an application that lies about
   1049        readiness, not an invalid descriptor. */
   1050     memset (&rs, 0xFF, sizeof (rs));
   1051     memset (&ws, 0xFF, sizeof (ws));
   1052     memset (&es, 0xFF, sizeof (es));
   1053     break;
   1054   case 3:
   1055     rs = g_rs;
   1056     FD_ZERO (&ws);
   1057     FD_ZERO (&es);
   1058     break;
   1059   default:
   1060     rs = g_rs;
   1061     ws = g_ws;
   1062     es = g_es;
   1063     break;
   1064   }
   1065   switch (var % 4)
   1066   {
   1067   case 0:
   1068     stat_rfs_v1++;
   1069     (void) (MHD_run_from_select) (d, &rs, &ws, &es);
   1070     break;
   1071   case 1:
   1072     stat_rfs_v2++;
   1073     (void) MHD_run_from_select2 (d, &rs, &ws, &es,
   1074                                  (g_setsize > (unsigned int) FD_SETSIZE)
   1075                                  ? (unsigned int) FD_SETSIZE : g_setsize);
   1076     break;
   1077   case 2:
   1078     stat_run++;
   1079     (void) MHD_run (d);
   1080     break;
   1081   default:
   1082     stat_run_wait++;
   1083     (void) MHD_run_wait (d, 0);
   1084     break;
   1085   }
   1086   deadline_valid = 0;
   1087   if (cfg.auto_drain)
   1088     drain_all ();
   1089   if (cfg.timeout_every_run)
   1090     check_timeouts (d);
   1091 }
   1092 
   1093 
   1094 /* ------------------------------------------------------------------ */
   1095 /* Connections                                                         */
   1096 /* ------------------------------------------------------------------ */
   1097 
   1098 static int
   1099 new_connection (struct MHD_Daemon *d)
   1100 {
   1101   int sv[2];
   1102   struct sockaddr_in sa;
   1103   unsigned int idx;
   1104 
   1105   if (nconns >= MAX_CONNS)
   1106     return -1;
   1107   idx = nconns;
   1108   if (0 != socketpair (AF_UNIX, SOCK_STREAM, 0, sv))
   1109     return -1;
   1110   if (cfg.small_sockbuf)
   1111   {
   1112     int bs = 2048;
   1113 
   1114     (void) setsockopt (sv[0], SOL_SOCKET, SO_RCVBUF, &bs, sizeof (bs));
   1115     (void) setsockopt (sv[1], SOL_SOCKET, SO_SNDBUF, &bs, sizeof (bs));
   1116   }
   1117   memset (&sa, 0, sizeof (sa));
   1118   sa.sin_family = AF_INET;
   1119   sa.sin_port = htons (44444);
   1120   sa.sin_addr.s_addr = htonl (INADDR_LOOPBACK);
   1121   csock[idx] = sv[0];
   1122   if (MHD_YES != MHD_add_connection (d,
   1123                                      (MHD_socket) sv[1],
   1124                                      (const struct sockaddr *) &sa,
   1125                                      (socklen_t) sizeof (sa)))
   1126   {
   1127     /* MHD has already closed sv[1] in that case. */
   1128     (void) close (sv[0]);
   1129     csock[idx] = -1;
   1130     return -1;
   1131   }
   1132   nconns++;
   1133   cur_conn = idx;
   1134   return (int) idx;
   1135 }
   1136 
   1137 
   1138 /**
   1139  * Hand the daemon one more connection and do not run the loop again.
   1140  *
   1141  * MHD_add_connection() on a thread-safe daemon does not build the
   1142  * `struct MHD_Connection` right away; it puts the socket on
   1143  * `daemon->new_connections_head` and leaves the rest to the next run.
   1144  * Stopping the daemon before that run is the only way to reach
   1145  * new_connection_close_() in daemon.c, which is where MHD disposes of a
   1146  * connection it accepted but never started.  The ordinary teardown below
   1147  * always calls MHD_run() once more, which is why 1.6 billion executions
   1148  * left that function at zero coverage.
   1149  *
   1150  * The socket pair is deliberately kept out of the harness's own
   1151  * connection table: nothing is ever sent on it, no notify callback fires
   1152  * for it, and by this point the teardown has already closed every
   1153  * tracked slot.  Our end is returned so that the caller can close it
   1154  * after MHD_stop_daemon().
   1155  *
   1156  * @param d the daemon, about to be stopped
   1157  * @return our end of the socket pair, or -1 if nothing was queued
   1158  */
   1159 static int
   1160 queue_unprocessed_conn (struct MHD_Daemon *d)
   1161 {
   1162   int sv[2];
   1163   struct sockaddr_in sa;
   1164 
   1165   if (0 != socketpair (AF_UNIX, SOCK_STREAM, 0, sv))
   1166     return -1;
   1167   memset (&sa, 0, sizeof (sa));
   1168   sa.sin_family = AF_INET;
   1169   sa.sin_port = htons (44444);
   1170   sa.sin_addr.s_addr = htonl (INADDR_LOOPBACK);
   1171   if (MHD_YES != MHD_add_connection (d,
   1172                                      (MHD_socket) sv[1],
   1173                                      (const struct sockaddr *) &sa,
   1174                                      (socklen_t) sizeof (sa)))
   1175   {
   1176     /* MHD has closed sv[1] already. */
   1177     (void) close (sv[0]);
   1178     return -1;
   1179   }
   1180   stat_queued_at_stop++;
   1181   return sv[0];
   1182 }
   1183 
   1184 
   1185 /**
   1186  * Drop our end of connection @a i.
   1187  *
   1188  * @param graceful non-zero to shut the write side down first (an orderly
   1189  *        client close), zero to just close (an abrupt one, which MHD sees
   1190  *        as a reset)
   1191  */
   1192 static void
   1193 close_conn (unsigned int i,
   1194             int graceful)
   1195 {
   1196   if ( (i >= MAX_CONNS) ||
   1197        (0 > csock[i]) )
   1198     return;
   1199   if (graceful)
   1200     (void) shutdown (csock[i], SHUT_WR);
   1201   (void) close (csock[i]);
   1202   csock[i] = -1;
   1203 }
   1204 
   1205 
   1206 static void
   1207 send_bytes (unsigned int i,
   1208             const void *buf,
   1209             size_t len)
   1210 {
   1211   const char *p = (const char *) buf;
   1212   size_t off = 0;
   1213   unsigned int tries = 0;
   1214 
   1215   if ( (i >= MAX_CONNS) ||
   1216        (0 > csock[i]) ||
   1217        (0 == len) )
   1218     return;
   1219   while ( (off < len) &&
   1220           (tries < 4) )
   1221   {
   1222     ssize_t s = send (csock[i], p + off, len - off, MSG_DONTWAIT);
   1223 
   1224     if (0 < s)
   1225     {
   1226       off += (size_t) s;
   1227       continue;
   1228     }
   1229     tries++;
   1230     /* The peer's receive buffer is full because MHD has not run yet, or
   1231        MHD is gone.  One round is enough to tell the two apart; the rest
   1232        of the fragment is simply dropped, which is a split point like any
   1233        other. */
   1234     if (NULL != cur_daemon)
   1235       (void) MHD_run (cur_daemon);
   1236     if ( (0 > s) &&
   1237          (EAGAIN != errno) &&
   1238          (EWOULDBLOCK != errno) &&
   1239          (EINTR != errno) )
   1240       break;
   1241   }
   1242 }
   1243 
   1244 
   1245 /**
   1246  * Request fragments.  Whole requests, halves of requests and pipelines,
   1247  * so that a schedule can leave a connection in any parser state while it
   1248  * plays with the event loop.
   1249  */
   1250 static const char *const frag_tbl[16] = {
   1251   "GET / HTTP/1.1\r\nHost: x\r\n\r\n",
   1252   "GET /a HTTP/1.1\r\nHost: x\r\n",
   1253   "\r\n",
   1254   "POST /p HTTP/1.1\r\nHost: x\r\nContent-Length: 10\r\n\r\n",
   1255   "0123456789",
   1256   "POST /c HTTP/1.1\r\nHost: x\r\nTransfer-Encoding: chunked\r\n\r\n",
   1257   "5\r\nabcde\r\n",
   1258   "0\r\n\r\n",
   1259   "GET / HTTP/1.1\r\nHost: x\r\nConnection: close\r\n\r\n",
   1260   "GET / HTTP/1.0\r\n\r\n",
   1261   "HEAD / HTTP/1.1\r\nHost: x\r\n\r\n",
   1262   "GET / HTTP/1.1\r\nHost: x\r\n\r\nGET /2 HTTP/1.1\r\nHost: x\r\n\r\n",
   1263   "G",
   1264   "ET / HTTP/1.1\r\n",
   1265   "Host: x\r\n\r\n",
   1266   "\r\n\r\n"
   1267 };
   1268 
   1269 
   1270 /* ------------------------------------------------------------------ */
   1271 /* The operation program                                               */
   1272 /* ------------------------------------------------------------------ */
   1273 
   1274 enum op
   1275 {
   1276   OP_SEND_FRAG = 0,
   1277   OP_SEND_RAW = 1,
   1278   OP_FDSET = 2,
   1279   OP_RUN = 3,
   1280   OP_TIMEOUT = 4,
   1281   OP_CLOCK = 5,
   1282   OP_SUSPEND = 6,
   1283   OP_RESUME = 7,
   1284   OP_NEWCONN = 8,
   1285   OP_CLOSECONN = 9,
   1286   OP_SWITCH = 10,
   1287   OP_QUIESCE = 11,
   1288   OP_DRAIN = 12,
   1289   OP_CONNOPT = 13,
   1290   OP_INFO = 14,
   1291   OP_POLL = 15
   1292 };
   1293 
   1294 
   1295 /**
   1296  * Wait in real time until the connection timeout of the current daemon
   1297  * has certainly expired, so that the expiry path is actually reached.
   1298  *
   1299  * MHD_OPTION_CONNECTION_TIMEOUT has a resolution of one second, so this
   1300  * costs about that much wall clock and is therefore globally budgeted.
   1301  */
   1302 static void
   1303 wait_for_expiry (struct MHD_Daemon *d)
   1304 {
   1305   struct timeval tv;
   1306 
   1307   if ( (! cfg.allow_real_wait) ||
   1308        (1 != cfg.timeout_s) ||
   1309        (0 >= expiry_budget) )
   1310     return;
   1311   expiry_budget--;
   1312   stat_expiry_waits++;
   1313   tv.tv_sec = 1;
   1314   tv.tv_usec = 50000;
   1315   (void) select (0, NULL, NULL, NULL, &tv);
   1316   clk_ms += 1050;
   1317   /* Everything parked has to come back first, or the expiry cannot be
   1318      observed for it at all. */
   1319   (void) resume_all ();
   1320   (void) MHD_run (d);
   1321   (void) MHD_run (d);
   1322 }
   1323 
   1324 
   1325 static void
   1326 op_quiesce (struct MHD_Daemon *d)
   1327 {
   1328   MHD_socket ls;
   1329 
   1330   stat_quiesce++;
   1331   ls = MHD_quiesce_daemon (d);
   1332   if (MHD_INVALID_SOCKET == ls)
   1333     return;
   1334   if (MHD_INVALID_SOCKET != quiesced_fd)
   1335   {
   1336     /* MHD_quiesce_daemon() is documented to hand the socket over once
   1337        and to answer MHD_INVALID_SOCKET afterwards. */
   1338     (void) close (ls);
   1339     fuzz_report_finding (
   1340       "MHD_quiesce_daemon() handed out the listening socket twice");
   1341     return;
   1342   }
   1343   quiesced_fd = ls;
   1344 }
   1345 
   1346 
   1347 static void
   1348 op_info (struct MHD_Daemon *d,
   1349          unsigned int arg)
   1350 {
   1351   const union MHD_DaemonInfo *di;
   1352   const union MHD_ConnectionInfo *ci;
   1353   volatile size_t sink = 0;
   1354   unsigned int i = arg % MAX_LIVE;
   1355 
   1356   di = MHD_get_daemon_info (d, MHD_DAEMON_INFO_CURRENT_CONNECTIONS);
   1357   if (NULL != di)
   1358     sink += (size_t) di->num_connections;
   1359   di = MHD_get_daemon_info (d, MHD_DAEMON_INFO_FLAGS);
   1360   if (NULL != di)
   1361     sink += (size_t) di->flags;
   1362   if (NULL != lives[i].mc)
   1363   {
   1364     ci = MHD_get_connection_info (lives[i].mc,
   1365                                   MHD_CONNECTION_INFO_CONNECTION_SUSPENDED);
   1366     if (NULL != ci)
   1367       sink += (size_t) ci->suspended;
   1368     ci = MHD_get_connection_info (lives[i].mc,
   1369                                   MHD_CONNECTION_INFO_DAEMON);
   1370     if (NULL != ci)
   1371       sink += (NULL != ci->daemon) ? 1u : 0u;
   1372   }
   1373   (void) sink;
   1374 }
   1375 
   1376 
   1377 static void
   1378 op_connopt (unsigned int i,
   1379             unsigned int val)
   1380 {
   1381   if ( (i >= MAX_LIVE) ||
   1382        (NULL == lives[i].mc) )
   1383     return;
   1384   /* Note that MHD skips the whole update while connection->suspended is
   1385      set, so this is not necessarily the timeout the connection ends up
   1386      with -- which is why the oracle reads it back instead. */
   1387   (void) MHD_set_connection_option (lives[i].mc,
   1388                                     MHD_CONNECTION_OPTION_TIMEOUT,
   1389                                     val);
   1390 }
   1391 
   1392 
   1393 /* ------------------------------------------------------------------ */
   1394 /* The fuzz target                                                     */
   1395 /* ------------------------------------------------------------------ */
   1396 
   1397 int
   1398 LLVMFuzzerTestOneInput (const uint8_t *data,
   1399                         size_t size)
   1400 {
   1401   struct MHD_Daemon *d;
   1402   struct MHD_OptionItem opts[8];
   1403   unsigned int nopt = 0;
   1404   unsigned int flags;
   1405   size_t pos;
   1406   unsigned int nops = 0;
   1407   unsigned int i;
   1408   int queued_fd = -1;          /**< see queue_unprocessed_conn() */
   1409 
   1410   /* Must happen before the first write() into a socketpair.  The built-in
   1411      driver also does this, but that code is compiled out under
   1412      -DFUZZ_NO_MAIN, which is exactly the build every external fuzzing
   1413      engine uses; the call is idempotent.  See fuzz_ignore_sigpipe() in
   1414      fuzz_common.h for why the process dies without it. */
   1415   fuzz_ignore_sigpipe ();
   1416 
   1417   if (size < 5)
   1418     return 0;
   1419 
   1420   if (! big_body_ready)
   1421   {
   1422     big_body_ready = 1;
   1423     for (i = 0; i < BIG_BODY_LEN; i++)
   1424       big_body[i] = (char) ('a' + (i % 26));
   1425   }
   1426   if (! expiry_budget_read)
   1427   {
   1428     const char *e = getenv ("MHD_FUZZ_EXPIRY_BUDGET");
   1429 
   1430     expiry_budget_read = 1;
   1431     if (NULL != e)
   1432       expiry_budget = atoi (e);
   1433   }
   1434 
   1435   memset (&cfg, 0, sizeof (cfg));
   1436   /* Must never carry over: everything these point at belonged to the
   1437      previous iteration's daemon and is long gone. */
   1438   memset (lives, 0, sizeof (lives));
   1439   for (i = 0; i < MAX_CONNS; i++)
   1440     csock[i] = -1;
   1441   nconns = 0;
   1442   cur_conn = 0;
   1443   tearing_down = 0;
   1444   quiesced_fd = MHD_INVALID_SOCKET;
   1445   clk_ms = 0;
   1446   deadline_ms = 0;
   1447   deadline_valid = 0;
   1448   g_have_sets = 0;
   1449   g_max_fd = MHD_INVALID_SOCKET;
   1450   g_setsize = (unsigned int) FD_SETSIZE;
   1451 
   1452   cfg.timeout_s = timeout_tbl[data[0] & 0x03];
   1453   cfg.listen_sock = (0 != (data[0] & 0x04));
   1454   cfg.app_fd_setsize = (0 != (data[0] & 0x08));
   1455   cfg.mem_limit = mem_limit_tbl[(data[0] >> 4) & 0x03];
   1456   cfg.conn_limit = (0 != (data[0] & 0x40));
   1457   cfg.small_sockbuf = (0 != (data[0] & 0x80));
   1458 
   1459   cfg.resp_kind = (unsigned int) (data[1] & 0x03);
   1460   cfg.error_reply = (0 != (data[1] & 0x04));
   1461   cfg.susp_park = (0 != (data[1] & 0x08));
   1462   cfg.susp_now = (0 != (data[1] & 0x10));
   1463   cfg.hnd_connopt = (0 != (data[1] & 0x20));
   1464   cfg.hnd_info = (0 != (data[1] & 0x40));
   1465   cfg.auto_drain = (0 != (data[1] & 0x80));
   1466 
   1467   cfg.fdset_var = (unsigned int) (data[2] & 0x07);
   1468   cfg.run_var = (unsigned int) ((data[2] >> 3) & 0x03);
   1469   cfg.honour_timeout = (0 != (data[2] & 0x20));
   1470   cfg.timeout_every_run = (0 != (data[2] & 0x40));
   1471   cfg.quiesce_end = (0 != (data[2] & 0x80));
   1472 
   1473   cfg.nconn_up_front = 1u + (unsigned int) (data[3] & 0x03);
   1474   cfg.check_always = (0 != (data[3] & 0x04));
   1475   cfg.allow_real_wait = (0 != (data[3] & 0x08));
   1476   cfg.stop_with_queued = (0 != (data[3] & 0x10));
   1477   cfg.clock_seed = data[4];
   1478 
   1479   if (0 != cfg.mem_limit)
   1480   {
   1481     opts[nopt].option = MHD_OPTION_CONNECTION_MEMORY_LIMIT;
   1482     opts[nopt].value = (intptr_t) cfg.mem_limit;
   1483     opts[nopt].ptr_value = NULL;
   1484     nopt++;
   1485   }
   1486   opts[nopt].option = MHD_OPTION_CONNECTION_TIMEOUT;
   1487   opts[nopt].value = (intptr_t) cfg.timeout_s;
   1488   opts[nopt].ptr_value = NULL;
   1489   nopt++;
   1490   if (cfg.conn_limit)
   1491   {
   1492     opts[nopt].option = MHD_OPTION_CONNECTION_LIMIT;
   1493     opts[nopt].value = (intptr_t) 2;
   1494     opts[nopt].ptr_value = NULL;
   1495     nopt++;
   1496   }
   1497   if (cfg.app_fd_setsize)
   1498   {
   1499     opts[nopt].option = MHD_OPTION_APP_FD_SETSIZE;
   1500     opts[nopt].value = (intptr_t) FD_SETSIZE;
   1501     opts[nopt].ptr_value = NULL;
   1502     nopt++;
   1503   }
   1504   opts[nopt].option = MHD_OPTION_END;
   1505   opts[nopt].value = 0;
   1506   opts[nopt].ptr_value = NULL;
   1507 
   1508   /* MHD_ALLOW_SUSPEND_RESUME is always on: it is what this harness is
   1509      about, and it implies MHD_USE_ITC, whose descriptor is one more thing
   1510      MHD_get_fdset*() has to report correctly. */
   1511   flags = MHD_ALLOW_SUSPEND_RESUME;
   1512   if (! cfg.listen_sock)
   1513     flags |= MHD_USE_NO_LISTEN_SOCKET;
   1514   if (fuzz_verbose)
   1515     flags |= MHD_USE_ERROR_LOG;
   1516 
   1517   MHD_set_panic_func (&panic_cb, NULL);
   1518   d = MHD_start_daemon (flags,
   1519                         0,
   1520                         NULL, NULL,
   1521                         &ahc, NULL,
   1522                         MHD_OPTION_ARRAY, opts,
   1523                         /* through the varargs rather than the option
   1524                            array: storing a function pointer in the
   1525                            array's intptr_t member is not strictly
   1526                            conforming C */
   1527                         MHD_OPTION_NOTIFY_CONNECTION, &notify_conn_cb, NULL,
   1528                         MHD_OPTION_END);
   1529   if ( (NULL == d) &&
   1530        cfg.listen_sock)
   1531   {
   1532     /* No networking available: fall back to the socketpair-only daemon
   1533        rather than losing the whole iteration. */
   1534     cfg.listen_sock = 0;
   1535     flags |= MHD_USE_NO_LISTEN_SOCKET;
   1536     d = MHD_start_daemon (flags,
   1537                           0,
   1538                           NULL, NULL,
   1539                           &ahc, NULL,
   1540                           MHD_OPTION_ARRAY, opts,
   1541                           MHD_OPTION_NOTIFY_CONNECTION, &notify_conn_cb, NULL,
   1542                           MHD_OPTION_END);
   1543   }
   1544   if (NULL == d)
   1545     return 0;
   1546   cur_daemon = d;
   1547   stat_daemons++;
   1548   if (! stats_registered)
   1549   {
   1550     stats_registered = 1;
   1551     (void) atexit (&print_stats);
   1552   }
   1553 
   1554   for (i = 0; i < cfg.nconn_up_front; i++)
   1555     if (0 > new_connection (d))
   1556       break;
   1557 
   1558   pos = 5;
   1559   while ( (pos < size) &&
   1560           (nops < MAX_OPS) )
   1561   {
   1562     const unsigned int b = data[pos++];
   1563     const unsigned int opc = b >> 4;
   1564     const unsigned int arg = b & 0x0F;
   1565 
   1566     nops++;
   1567     switch (opc)
   1568     {
   1569     case OP_SEND_FRAG:
   1570       {
   1571         const char *f = frag_tbl[arg];
   1572 
   1573         send_bytes (cur_conn, f, strlen (f));
   1574         break;
   1575       }
   1576     case OP_SEND_RAW:
   1577       {
   1578         size_t l;
   1579 
   1580         if (pos >= size)
   1581           break;
   1582         l = data[pos++];
   1583         if (l > size - pos)
   1584           l = size - pos;
   1585         send_bytes (cur_conn, data + pos, l);
   1586         pos += l;
   1587         break;
   1588       }
   1589     case OP_FDSET:
   1590       op_fdset (d, (0 != (arg & 0x08)) ? cfg.fdset_var : arg);
   1591       break;
   1592     case OP_RUN:
   1593       op_run (d, arg & 0x03, (arg >> 2) & 0x03);
   1594       break;
   1595     case OP_TIMEOUT:
   1596       check_timeouts (d);
   1597       if ( (cfg.honour_timeout) &&
   1598            (deadline_valid) &&
   1599            (deadline_ms <= clk_ms) )
   1600         op_run (d, cfg.run_var, 0);
   1601       break;
   1602     case OP_CLOCK:
   1603       if (15 == arg)
   1604         wait_for_expiry (d);
   1605       else
   1606       {
   1607         clk_ms += (uint64_t) (1u + arg) * (uint64_t) (1u + cfg.clock_seed % 64u)
   1608         ;
   1609         if ( (cfg.honour_timeout) &&
   1610              (deadline_valid) &&
   1611              (deadline_ms <= clk_ms) )
   1612           op_run (d, cfg.run_var, 0);
   1613       }
   1614       break;
   1615     case OP_SUSPEND:
   1616       do_suspend (arg % MAX_LIVE);
   1617       break;
   1618     case OP_RESUME:
   1619       do_resume (arg % MAX_LIVE);
   1620       break;
   1621     case OP_NEWCONN:
   1622       (void) new_connection (d);
   1623       break;
   1624     case OP_CLOSECONN:
   1625       close_conn ((0 != (arg & 0x08)) ? cur_conn : (arg % MAX_CONNS),
   1626                   (0 != (arg & 0x04)));
   1627       break;
   1628     case OP_SWITCH:
   1629       if ( (arg % MAX_CONNS) < nconns)
   1630         cur_conn = arg % MAX_CONNS;
   1631       break;
   1632     case OP_QUIESCE:
   1633       op_quiesce (d);
   1634       break;
   1635     case OP_DRAIN:
   1636       if (0 != (arg & 0x08))
   1637         drain_all ();
   1638       else
   1639         drain_conn (arg % MAX_CONNS);
   1640       break;
   1641     case OP_CONNOPT:
   1642       op_connopt (arg % MAX_LIVE, (arg >> 3) & 0x01);
   1643       break;
   1644     case OP_INFO:
   1645       op_info (d, arg);
   1646       break;
   1647     default:
   1648       op_poll ();
   1649       break;
   1650     }
   1651     if (cfg.check_always)
   1652       check_timeouts (d);
   1653   }
   1654 
   1655   /* ---- teardown ---- */
   1656   tearing_down = 1;
   1657   queued_fd = -1;
   1658   for (i = 0; i < MAX_CONNS; i++)
   1659     close_conn (i, 1);
   1660   /* A connection left suspended makes MHD_stop_daemon() MHD_PANIC()
   1661      ("called while we have suspended connections"), and
   1662      MHD_resume_connection() alone is not enough: it only raises a flag,
   1663      and the connection leaves the suspended list in MHD_run().  So flush
   1664      and run until nothing is parked any more.  tearing_down keeps the
   1665      handler from parking anything new, which is what bounds this loop;
   1666      the cap is only a backstop. */
   1667   for (i = 0; i < MAX_CONNS + 2u; i++)
   1668   {
   1669     if (! resume_all ())
   1670       break;
   1671     (void) MHD_run (d);
   1672   }
   1673   (void) MHD_run (d);
   1674   if (cfg.quiesce_end)
   1675     op_quiesce (d);
   1676   /* Last, so that no run can drain the list again. */
   1677   if (cfg.stop_with_queued)
   1678     queued_fd = queue_unprocessed_conn (d);
   1679   MHD_stop_daemon (d);
   1680   cur_daemon = NULL;
   1681   if (0 <= queued_fd)
   1682   {
   1683     (void) close (queued_fd);
   1684     queued_fd = -1;
   1685   }
   1686   if (MHD_INVALID_SOCKET != quiesced_fd)
   1687   {
   1688     (void) close (quiesced_fd);
   1689     quiesced_fd = MHD_INVALID_SOCKET;
   1690   }
   1691   for (i = 0; i < MAX_CONNS; i++)
   1692     close_conn (i, 0);
   1693   memset (lives, 0, sizeof (lives));
   1694   return 0;
   1695 }
   1696 
   1697 
   1698 /* ------------------------------------------------------------------ */
   1699 /* Structure-aware schedule generator                                  */
   1700 /* ------------------------------------------------------------------ */
   1701 
   1702 struct sbuf
   1703 {
   1704   uint8_t *p;
   1705   size_t len;
   1706   size_t cap;
   1707 };
   1708 
   1709 
   1710 static void
   1711 sb_byte (struct sbuf *b,
   1712          uint8_t v)
   1713 {
   1714   if (b->len < b->cap)
   1715     b->p[b->len++] = v;
   1716 }
   1717 
   1718 
   1719 static void
   1720 sb_op (struct sbuf *b,
   1721        unsigned int opc,
   1722        unsigned int arg)
   1723 {
   1724   sb_byte (b, (uint8_t) ((opc << 4) | (arg & 0x0F)));
   1725 }
   1726 
   1727 
   1728 /**
   1729  * Fragment indices, weighted towards the ones that complete a request:
   1730  * a schedule that never reaches the access handler exercises very little
   1731  * of the connection life cycle.
   1732  */
   1733 static const unsigned char gen_frag_bias[] = {
   1734   0, 0, 0, 3, 4, 5, 6, 7, 8, 9, 10, 11, 11, 1, 2, 12, 13, 14, 15
   1735 };
   1736 
   1737 
   1738 static unsigned int
   1739 gen_frag (struct fuzz_rng *rng)
   1740 {
   1741   if (fuzz_chance (rng, 4))
   1742     return fuzz_below (rng, 16);
   1743   return gen_frag_bias[fuzz_below (rng,
   1744                                    (uint32_t) sizeof (gen_frag_bias))];
   1745 }
   1746 
   1747 
   1748 /**
   1749  * Emit "collect the descriptors, poll, run" -- the shape a real external
   1750  * event loop has -- with a randomly chosen variant of each step.
   1751  */
   1752 static void
   1753 gen_loop_round (struct fuzz_rng *rng,
   1754                 struct sbuf *b)
   1755 {
   1756   unsigned int v;
   1757   unsigned int fl;
   1758 
   1759   if (! fuzz_chance (rng, 5))
   1760     sb_op (b, OP_FDSET, fuzz_below (rng, 16));
   1761   if (! fuzz_chance (rng, 3))
   1762     sb_op (b, OP_POLL, 0);
   1763   if (fuzz_chance (rng, 3))
   1764     sb_op (b, OP_TIMEOUT, fuzz_below (rng, 16));
   1765   v = fuzz_below (rng, 4);
   1766   /* Half the runs use the descriptor sets MHD actually asked for, so
   1767      that requests make progress; the other half are the adversarial
   1768      ones (all-zero, all-ones, read set only). */
   1769   fl = fuzz_chance (rng, 2) ? 0u : fuzz_below (rng, 4);
   1770   sb_op (b, OP_RUN, v | (fl << 2));
   1771 }
   1772 
   1773 
   1774 static size_t
   1775 fuzz_generate (struct fuzz_rng *rng,
   1776                uint8_t *buf,
   1777                size_t cap)
   1778 {
   1779   struct sbuf b;
   1780   unsigned int nrounds;
   1781   unsigned int i;
   1782   unsigned int r;
   1783 
   1784   b.p = buf;
   1785   b.len = 0;
   1786   b.cap = cap;
   1787 
   1788   /* --- configuration block --- */
   1789   sb_byte (&b, fuzz_byte (rng));
   1790   sb_byte (&b, fuzz_byte (rng));
   1791   sb_byte (&b, fuzz_byte (rng));
   1792   sb_byte (&b, fuzz_byte (rng));
   1793   sb_byte (&b, fuzz_byte (rng));
   1794 
   1795   nrounds = 3u + fuzz_below (rng, 40);
   1796   for (i = 0; i < nrounds; i++)
   1797   {
   1798     switch (fuzz_below (rng, 24))
   1799     {
   1800     case 0:
   1801     case 1:
   1802     case 2:
   1803     case 3:
   1804     case 4:
   1805     case 5:
   1806       /* feed the current connection */
   1807       sb_op (&b, OP_SEND_FRAG, gen_frag (rng));
   1808       gen_loop_round (rng, &b);
   1809       break;
   1810     case 6:
   1811       /* raw literal, so that a mutator has somewhere to put bytes */
   1812       {
   1813         unsigned int n = fuzz_below (rng, 24);
   1814         unsigned int k;
   1815 
   1816         sb_op (&b, OP_SEND_RAW, 0);
   1817         sb_byte (&b, (uint8_t) n);
   1818         for (k = 0; k < n; k++)
   1819           sb_byte (&b, fuzz_byte (rng));
   1820         break;
   1821       }
   1822     case 7:
   1823     case 8:
   1824       gen_loop_round (rng, &b);
   1825       break;
   1826     case 9:
   1827       r = fuzz_below (rng, 16);
   1828       sb_op (&b, OP_SUSPEND, r);
   1829       break;
   1830     case 10:
   1831       r = fuzz_below (rng, 16);
   1832       sb_op (&b, OP_RESUME, r);
   1833       break;
   1834     case 11:
   1835       sb_op (&b, OP_NEWCONN, 0);
   1836       sb_op (&b, OP_SEND_FRAG, gen_frag (rng));
   1837       break;
   1838     case 12:
   1839       r = fuzz_below (rng, 16);
   1840       sb_op (&b, OP_CLOSECONN, r);
   1841       break;
   1842     case 13:
   1843       r = fuzz_below (rng, 16);
   1844       sb_op (&b, OP_SWITCH, r);
   1845       break;
   1846     case 14:
   1847       sb_op (&b, OP_QUIESCE, 0);
   1848       break;
   1849     case 15:
   1850       r = fuzz_below (rng, 16);
   1851       sb_op (&b, OP_DRAIN, r);
   1852       break;
   1853     case 16:
   1854       r = fuzz_below (rng, 16);
   1855       sb_op (&b, OP_CONNOPT, r);
   1856       break;
   1857     case 17:
   1858       r = fuzz_below (rng, 16);
   1859       sb_op (&b, OP_INFO, r);
   1860       break;
   1861     case 18:
   1862       r = fuzz_below (rng, 16);
   1863       sb_op (&b, OP_TIMEOUT, r);
   1864       break;
   1865     case 19:
   1866       /* an artificial clock jump, occasionally the real one that lets a
   1867          connection time out */
   1868       r = fuzz_chance (rng, 40) ? 15u : fuzz_below (rng, 15);
   1869       sb_op (&b, OP_CLOCK, r);
   1870       break;
   1871     case 20:
   1872       /* a run without ever asking MHD what it wanted */
   1873       r = fuzz_below (rng, 16);
   1874       sb_op (&b, OP_RUN, r);
   1875       break;
   1876     case 21:
   1877       sb_op (&b, OP_POLL, 0);
   1878       break;
   1879     default:
   1880       sb_op (&b, OP_SEND_FRAG, gen_frag (rng));
   1881       break;
   1882     }
   1883   }
   1884   /* Make sure most schedules end with the daemon actually run, so that
   1885      the interesting states are reached rather than only set up. */
   1886   gen_loop_round (rng, &b);
   1887   return b.len;
   1888 }
   1889 
   1890 
   1891 /* ------------------------------------------------------------------ */
   1892 /* Built-in seed corpus                                                */
   1893 /* ------------------------------------------------------------------ */
   1894 
   1895 /**
   1896  * A seed is the five configuration bytes plus a literal operation
   1897  * program.  Programs are short on purpose: each one is meant to pin down
   1898  * one entry point or one life-cycle transition, and libFuzzer's -merge
   1899  * keeps the shortest input reaching a given edge.
   1900  */
   1901 struct seed_def
   1902 {
   1903   const char *name;
   1904   unsigned char cfg[5];
   1905   unsigned char ops[24];
   1906   unsigned char nops;
   1907 };
   1908 
   1909 #define OPB(o,a) (unsigned char) (((o) << 4) | (a))
   1910 
   1911 static const struct seed_def seeds[] = {
   1912   /* MHD_get_fdset() (the real v1 entry point) + select() +
   1913      MHD_run_from_select() (also v1) */
   1914   { "fdset-v1-run-from-select-v1", { 0x00, 0x80, 0x00, 0x00, 0x00 },
   1915     { OPB (OP_SEND_FRAG, 0), OPB (OP_FDSET, 0), OPB (OP_POLL, 0),
   1916       OPB (OP_RUN, 0), OPB (OP_TIMEOUT, 0), OPB (OP_FDSET, 0),
   1917       OPB (OP_POLL, 0), OPB (OP_RUN, 0) }, 8 },
   1918 
   1919   /* MHD_get_fdset2() + MHD_run_from_select2() */
   1920   { "fdset2-run-from-select2", { 0x00, 0x80, 0x09, 0x00, 0x00 },
   1921     { OPB (OP_SEND_FRAG, 0), OPB (OP_FDSET, 1), OPB (OP_POLL, 0),
   1922       OPB (OP_RUN, 1), OPB (OP_TIMEOUT, 0), OPB (OP_FDSET, 1),
   1923       OPB (OP_POLL, 0), OPB (OP_RUN, 1) }, 8 },
   1924 
   1925   /* a small FD_SETSIZE limit, which MHD has to refuse descriptors for */
   1926   { "fdset2-small-setsize", { 0x00, 0x80, 0x02, 0x00, 0x04 },
   1927     { OPB (OP_SEND_FRAG, 0), OPB (OP_FDSET, 2), OPB (OP_RUN, 1),
   1928       OPB (OP_FDSET, 2), OPB (OP_TIMEOUT, 0), OPB (OP_RUN, 1) }, 6 },
   1929 
   1930   /* max_fd == NULL and except_fd_set == NULL, both documented shapes */
   1931   { "fdset2-null-args", { 0x00, 0x80, 0x00, 0x00, 0x00 },
   1932     { OPB (OP_SEND_FRAG, 0), OPB (OP_FDSET, 3), OPB (OP_RUN, 1),
   1933       OPB (OP_FDSET, 4), OPB (OP_RUN, 1), OPB (OP_TIMEOUT, 0) }, 6 },
   1934 
   1935   /* MHD_run() and MHD_run_wait() */
   1936   { "run-and-run-wait", { 0x00, 0x80, 0x10, 0x00, 0x00 },
   1937     { OPB (OP_SEND_FRAG, 0), OPB (OP_RUN, 2), OPB (OP_RUN, 3),
   1938       OPB (OP_TIMEOUT, 0), OPB (OP_RUN, 2) }, 5 },
   1939 
   1940   /* descriptor sets MHD never asked for: all-zero and all-ones */
   1941   { "run-from-select-bogus-sets", { 0x00, 0x80, 0x00, 0x00, 0x00 },
   1942     { OPB (OP_SEND_FRAG, 0), OPB (OP_RUN, 0x04), OPB (OP_RUN, 0x08),
   1943       OPB (OP_RUN, 0x05), OPB (OP_RUN, 0x09), OPB (OP_TIMEOUT, 0),
   1944       OPB (OP_RUN, 0x0C) }, 7 },
   1945 
   1946   /* stale sets: collect, close the connection, then run with them */
   1947   { "run-from-select-stale-sets", { 0x00, 0x80, 0x00, 0x00, 0x00 },
   1948     { OPB (OP_SEND_FRAG, 1), OPB (OP_FDSET, 1), OPB (OP_CLOSECONN, 0),
   1949       OPB (OP_RUN, 0), OPB (OP_RUN, 1), OPB (OP_TIMEOUT, 0) }, 6 },
   1950 
   1951   /* suspend from the pump loop, across a full fdset/poll/run round */
   1952   { "suspend-across-loop", { 0x00, 0x80, 0x00, 0x00, 0x00 },
   1953     { OPB (OP_SEND_FRAG, 1), OPB (OP_RUN, 2), OPB (OP_SUSPEND, 0),
   1954       OPB (OP_FDSET, 1), OPB (OP_TIMEOUT, 0), OPB (OP_POLL, 0),
   1955       OPB (OP_RUN, 1), OPB (OP_RESUME, 0), OPB (OP_RUN, 2) }, 9 },
   1956 
   1957   /* the handler parks the connection; several are parked at once */
   1958   { "handler-parks-two-connections", { 0x00, 0x88, 0x00, 0x00, 0x00 },
   1959     { OPB (OP_SEND_FRAG, 0), OPB (OP_RUN, 2), OPB (OP_NEWCONN, 0),
   1960       OPB (OP_SEND_FRAG, 0), OPB (OP_RUN, 2), OPB (OP_TIMEOUT, 0),
   1961       OPB (OP_RESUME, 0), OPB (OP_RUN, 2) }, 8 },
   1962 
   1963   /* suspend while a resume is still pending (cancels the resume) */
   1964   { "suspend-cancels-pending-resume", { 0x00, 0x80, 0x00, 0x00, 0x00 },
   1965     { OPB (OP_SEND_FRAG, 1), OPB (OP_RUN, 2), OPB (OP_SUSPEND, 0),
   1966       OPB (OP_RESUME, 0), OPB (OP_SUSPEND, 0), OPB (OP_TIMEOUT, 0),
   1967       OPB (OP_RESUME, 0), OPB (OP_RUN, 2) }, 8 },
   1968 
   1969   /* quiesce a daemon that really has a listening socket, then check that
   1970      it is gone from the descriptor sets */
   1971   { "quiesce-listening-daemon", { 0x04, 0x80, 0x00, 0x00, 0x00 },
   1972     { OPB (OP_SEND_FRAG, 0), OPB (OP_FDSET, 1), OPB (OP_RUN, 1),
   1973       OPB (OP_QUIESCE, 0), OPB (OP_FDSET, 1), OPB (OP_TIMEOUT, 0),
   1974       OPB (OP_RUN, 1), OPB (OP_QUIESCE, 0) }, 8 },
   1975 
   1976   /* a large response on a small socket buffer: the connection stays
   1977      blocked on write over many rounds */
   1978   { "blocked-write-scheduling", { 0x80, 0x02, 0x00, 0x00, 0x00 },
   1979     { OPB (OP_SEND_FRAG, 0), OPB (OP_FDSET, 1), OPB (OP_POLL, 0),
   1980       OPB (OP_RUN, 1), OPB (OP_FDSET, 1), OPB (OP_POLL, 0),
   1981       OPB (OP_RUN, 1), OPB (OP_DRAIN, 8), OPB (OP_FDSET, 1),
   1982       OPB (OP_RUN, 1), OPB (OP_TIMEOUT, 0) }, 11 },
   1983 
   1984   /* a real connection-timeout expiry */
   1985   { "connection-timeout-expiry", { 0x00, 0x80, 0x00, 0x08, 0x00 },
   1986     { OPB (OP_SEND_FRAG, 1), OPB (OP_RUN, 2), OPB (OP_TIMEOUT, 0),
   1987       OPB (OP_CLOCK, 15), OPB (OP_TIMEOUT, 0), OPB (OP_RUN, 2) }, 6 },
   1988 
   1989   /* per-connection timeouts, which move the connection to the "manual"
   1990      timeout list that MHD_get_timeout*() has to scan separately */
   1991   { "manual-timeout-list", { 0x00, 0x80, 0x00, 0x03, 0x00 },
   1992     { OPB (OP_SEND_FRAG, 1), OPB (OP_CONNOPT, 8), OPB (OP_TIMEOUT, 0),
   1993       OPB (OP_CONNOPT, 1), OPB (OP_TIMEOUT, 0), OPB (OP_RUN, 2),
   1994       OPB (OP_TIMEOUT, 0) }, 7 },
   1995 
   1996   /* pipelined requests plus a chunked upload, driven one run at a time */
   1997   { "pipelined-and-chunked", { 0x00, 0x81, 0x00, 0x00, 0x00 },
   1998     { OPB (OP_SEND_FRAG, 11), OPB (OP_RUN, 2), OPB (OP_SEND_FRAG, 5),
   1999       OPB (OP_RUN, 2), OPB (OP_SEND_FRAG, 6), OPB (OP_RUN, 2),
   2000       OPB (OP_SEND_FRAG, 7), OPB (OP_RUN, 2), OPB (OP_TIMEOUT, 0) }, 9 },
   2001 
   2002   /* never poll, never ask for descriptors, only run from empty sets */
   2003   { "never-poll", { 0x00, 0x80, 0x00, 0x00, 0x00 },
   2004     { OPB (OP_SEND_FRAG, 0), OPB (OP_RUN, 0x04), OPB (OP_RUN, 0x04),
   2005       OPB (OP_RUN, 0x04), OPB (OP_RUN, 0x04), OPB (OP_TIMEOUT, 0) }, 6 },
   2006 
   2007   /* abrupt close in the middle of a request, with the descriptor sets
   2008      collected before it */
   2009   { "abrupt-close-mid-request", { 0x00, 0x80, 0x00, 0x00, 0x00 },
   2010     { OPB (OP_SEND_FRAG, 3), OPB (OP_FDSET, 1), OPB (OP_CLOSECONN, 0),
   2011       OPB (OP_RUN, 1), OPB (OP_TIMEOUT, 0), OPB (OP_RUN, 2) }, 6 },
   2012 
   2013   /* connection limit of two, so that MHD_add_connection() starts to fail */
   2014   { "connection-limit", { 0x40, 0x80, 0x00, 0x03, 0x00 },
   2015     { OPB (OP_NEWCONN, 0), OPB (OP_NEWCONN, 0), OPB (OP_SEND_FRAG, 0),
   2016       OPB (OP_RUN, 2), OPB (OP_TIMEOUT, 0) }, 5 },
   2017 
   2018   /* no connection timeout at all: MHD_get_timeout*() must report that an
   2019      indefinite wait is fine */
   2020   { "no-timeout-configured", { 0x02, 0x80, 0x00, 0x04, 0x00 },
   2021     { OPB (OP_SEND_FRAG, 1), OPB (OP_TIMEOUT, 0), OPB (OP_RUN, 2),
   2022       OPB (OP_TIMEOUT, 0), OPB (OP_SEND_FRAG, 2), OPB (OP_RUN, 2) }, 6 },
   2023 
   2024   /* byte 3 bit 4: after the program has run and everything has been torn
   2025      down, hand MHD one more connection and stop it without another run,
   2026      so that it has to dispose of a connection it never started.  That is
   2027      new_connection_close_() in daemon.c, which nothing else reaches. */
   2028   { "stop-with-queued-connection", { 0x00, 0x80, 0x00, 0x10, 0x00 },
   2029     { OPB (OP_SEND_FRAG, 0), OPB (OP_RUN, 2), OPB (OP_TIMEOUT, 0) }, 3 },
   2030 
   2031   /* the same after MHD_quiesce_daemon() on a daemon that really has a
   2032      listening socket, which is the other order the two can happen in */
   2033   { "stop-with-queued-after-quiesce", { 0x04, 0x80, 0x80, 0x10, 0x00 },
   2034     { OPB (OP_SEND_FRAG, 0), OPB (OP_RUN, 2) }, 2 }
   2035 };
   2036 
   2037 static uint8_t seed_render_buf[64];
   2038 
   2039 
   2040 static size_t
   2041 fuzz_seed_count (void)
   2042 {
   2043   return sizeof (seeds) / sizeof (seeds[0]);
   2044 }
   2045 
   2046 
   2047 static const uint8_t *
   2048 fuzz_seed_get (size_t idx,
   2049                size_t *len)
   2050 {
   2051   const struct seed_def *sd = &seeds[idx];
   2052   size_t n = sd->nops;
   2053 
   2054   if (n > sizeof (sd->ops))
   2055     n = sizeof (sd->ops);
   2056   if (n + sizeof (sd->cfg) > sizeof (seed_render_buf))
   2057     n = sizeof (seed_render_buf) - sizeof (sd->cfg);
   2058   memcpy (seed_render_buf, sd->cfg, sizeof (sd->cfg));
   2059   memcpy (seed_render_buf + sizeof (sd->cfg), sd->ops, n);
   2060   *len = sizeof (sd->cfg) + n;
   2061   return seed_render_buf;
   2062 }