libmicrohttpd

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

fuzz_eventloop.c (61619B)


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