libmicrohttpd

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

fuzz_request.c (99981B)


      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_request.c
     22  * @brief End-to-end in-process fuzzer for the MHD request parser.
     23  * @author Christian Grothoff
     24  *
     25  * A real `struct MHD_Daemon` is created with #MHD_USE_NO_LISTEN_SOCKET
     26  * and driven through a `socketpair()` that is handed to MHD with
     27  * #MHD_add_connection().  The daemon runs in external-polling mode, so
     28  * everything happens in the fuzzer's thread: fully deterministic, no
     29  * TCP stack, no ports, no races.
     30  *
     31  * Input format (see README):
     32  *
     33  *   byte 0   configuration: connection memory limit
     34  *   byte 1   configuration: handler behaviour bitmask
     35  *   byte 2   configuration: client discipline / insanity level
     36  *   byte 3   configuration: digest-auth parameters
     37  *   byte 4   response construction: which MHD_create_response_*()
     38  *            to use, how many response headers to add, footers,
     39  *            header-manipulation API
     40  *   byte 5   which authentication entry point to call: the v1/v2
     41  *            compatibility wrappers, the username/request-info
     42  *            queries, or the differing fail-response variants
     43  *   byte 6   event-loop mode (MHD_run() vs MHD_get_fdset*() +
     44  *            MHD_run_from_select*()) and the connection-introspection
     45  *            calls
     46  *   byte 7   suspend/resume and HTTP "Upgrade"
     47  *   byte 8   seed for the generated response header names/values
     48  *   byte 9   seed for the content-reader callback behaviour
     49  *   byte 10. a sequence of send-segments, each introduced by a
     50  *            little-endian 16 bit header  (op << 14) | length
     51  *              op 0  send the payload
     52  *              op 1  the payload is the *expected* decoded request body
     53  *                    (ground truth for the body oracle); nothing is sent
     54  *              op 2  send the payload and pump the daemon extra rounds
     55  *              op 3  close the connection, open a fresh one, send
     56  *
     57  * All ten configuration bytes are always present; an input shorter
     58  * than that is rejected outright.  The all-zero configuration is the
     59  * plainest one -- a static two byte buffer response, MHD_run() as the
     60  * event loop, no suspend, no upgrade, no extra introspection -- so
     61  * zeroing bytes 4-9 of any input reduces it to what the harness did
     62  * before those bytes existed.
     63  *
     64  * Splitting the byte stream into explicit segments matters: MHD's
     65  * parser is incremental and several past bugs only showed up for
     66  * particular split points.
     67  *
     68  * The literal ASCII token "%%NONCE%%" inside a segment is replaced,
     69  * at send time, by the most recent `nonce="..."` value seen in a
     70  * response from the daemon.  This is what allows the fuzzer to walk
     71  * through the Digest-Auth challenge/response handshake and reach the
     72  * code that is only executed for a *valid* nonce.
     73  */
     74 
     75 /* Must precede every #include: memfd_create() and MFD_CLOEXEC are only
     76    declared by <sys/mman.h> under _GNU_SOURCE, and the OSS-Fuzz build
     77    compiles this file with nothing but -DFUZZ_NO_MAIN (the library gets
     78    _GNU_SOURCE from configure, the hand-compiled harnesses do not).
     79    Without this the fd-backed response kinds silently fall back to a
     80    buffer response and MHD_create_response_from_fd*() is never reached
     81    -- a failure mode with no error message at all. */
     82 #ifndef _GNU_SOURCE
     83 #define _GNU_SOURCE 1
     84 #endif
     85 
     86 #define FUZZ_HARNESS_NAME "fuzz_request"
     87 #include "fuzz_common.h"
     88 
     89 #include <microhttpd.h>
     90 #include <sys/socket.h>
     91 #include <netinet/in.h>
     92 #include <sys/select.h>
     93 
     94 /* MHD_create_response_from_data() and MHD_create_response_from_buffer()
     95    with an explicit MHD_ResponseMemoryMode are deprecated but are still
     96    shipped API and are therefore still worth fuzzing; the deprecation
     97    warning would otherwise drown the build output. */
     98 #if defined(__GNUC__) || defined(__clang__)
     99 #pragma GCC diagnostic ignored "-Wdeprecated-declarations"
    100 #endif
    101 
    102 /* memfd_create() gives a file descriptor backed by anonymous memory,
    103    which is what makes the MHD_create_response_from_fd*() variants
    104    affordable at fuzzing rates: no filesystem is touched.  Where it is
    105    unavailable the fd-backed response kinds fall back to a buffer
    106    response (see make_response()). */
    107 #if defined(__linux__)
    108 #include <sys/mman.h>
    109 #if defined(MFD_CLOEXEC)
    110 #define FUZZ_HAVE_MEMFD 1
    111 #endif
    112 #endif
    113 
    114 #define MAX_SEGMENTS 96
    115 #define MAX_CONNECTIONS 8
    116 #define RESP_BUF_SIZE 16384
    117 #define GEN_BUF_SIZE 8192
    118 #define MAX_EXPECT_BODY 4096
    119 
    120 /** Number of entries in the response-construction table. */
    121 #define RESP_KIND_COUNT 16
    122 /** Number of authentication entry points selectable by byte 5. */
    123 #define DAUTH_VARIANT_COUNT 10
    124 /** Largest digest MHD_digest_auth_calc_userdigest() can produce. */
    125 #define MAX_DIGEST_BIN 64
    126 
    127 #define DIGEST_REALM "TestRealm"
    128 #define DIGEST_USER "user"
    129 #define DIGEST_PASS "pass"
    130 
    131 /* ------------------------------------------------------------------ */
    132 /* Per-iteration state                                                 */
    133 /* ------------------------------------------------------------------ */
    134 
    135 struct fuzz_cfg
    136 {
    137   size_t mem_limit;
    138   int discipline;
    139   unsigned int insanity;
    140   unsigned int nonce_nc_size;
    141   enum MHD_DigestAuthMultiAlgo3 algo;
    142   enum MHD_DigestAuthMultiQOP qop;
    143   int do_digest;
    144   int do_basic;
    145   int do_postproc;
    146   int do_iterate;
    147   int chunked_reply;
    148   int error_reply;
    149 
    150   /* ---- configuration bytes 4-9; all zero is the plainest setting ---- */
    151   unsigned int resp_kind;      /**< index into the response constructors */
    152   unsigned int resp_nhdr;      /**< how many response headers to add */
    153   int resp_footer;             /**< also add a response footer/trailer */
    154   int resp_hdr_api;            /**< exercise get/del/set_response_options */
    155   unsigned int dauth_variant;  /**< which digest entry point to call */
    156   unsigned int fail_variant;   /**< which *_fail_response to queue */
    157   int basic_v1;                /**< use the v1 basic-auth getter */
    158   int calc_helpers;            /**< call the userdigest/userhash helpers */
    159   unsigned int loop_mode;      /**< 0 MHD_run, 1..3 external event loop */
    160   int use_timeouts;            /**< query MHD_get_timeout*() while pumping */
    161   int conn_lookup;             /**< MHD_lookup_connection_value*() */
    162   int conn_setvalue;           /**< MHD_set_connection_value() */
    163   int conn_info;               /**< MHD_get_connection_info/daemon_info */
    164   int conn_option;             /**< MHD_set_connection_option() */
    165   int quiesce;                 /**< MHD_quiesce_daemon() before stopping */
    166   unsigned int suspend_mode;   /**< 0 none, 1 immediate, 2 deferred */
    167   int allow_upgrade;           /**< MHD_ALLOW_UPGRADE + upgrade response */
    168   unsigned int upgrade_action; /**< which MHD_upgrade_action() to issue */
    169   uint8_t hdr_seed;            /**< picks response header name/value */
    170   uint8_t crc_seed;            /**< content-reader callback behaviour */
    171 };
    172 
    173 static struct fuzz_cfg cfg;
    174 
    175 /** Most recent nonce harvested from a 401 response. */
    176 static char nonce_val[192];
    177 static size_t nonce_len;
    178 
    179 /** Ground-truth body of a generated (pristine) request, see README. */
    180 static uint8_t expect_body[MAX_EXPECT_BODY];
    181 static size_t expect_body_len;
    182 static int oracle_on;
    183 
    184 /** Statistics, printed at exit with --verbose. */
    185 static unsigned long stat_daemons;
    186 static unsigned long stat_handler_calls;
    187 static unsigned long stat_final_calls;
    188 static unsigned long stat_body_bytes;
    189 static unsigned long stat_challenges;
    190 static unsigned long stat_auth_ok;
    191 static int stats_registered;
    192 
    193 
    194 static void
    195 print_stats (void)
    196 {
    197   if (! fuzz_verbose)
    198     return;
    199   fprintf (stderr,
    200            "%s: daemons=%lu handler calls=%lu (final=%lu) body bytes=%lu "
    201            "401 challenges=%lu authenticated=%lu\n",
    202            FUZZ_HARNESS_NAME,
    203            stat_daemons, stat_handler_calls, stat_final_calls,
    204            stat_body_bytes, stat_challenges, stat_auth_ok);
    205 }
    206 
    207 
    208 /** Bytes received from the daemon during the current iteration. */
    209 static char resp_buf[RESP_BUF_SIZE];
    210 static size_t resp_len;
    211 
    212 static const size_t mem_limit_tbl[] = {
    213   0 /* MHD default */, 128, 192, 256, 320, 384, 512, 768, 1024, 1400, 1500,
    214   2048, 4096, 32768
    215 };
    216 
    217 static const int discipline_tbl[] = { -3, -2, -1, 0, 1, 2 };
    218 
    219 /**
    220  * Lower bound for MHD_OPTION_CLIENT_DISCIPLINE_LVL, -3 is the full
    221  * range.  On a tree without the patches listed in README section 6,
    222  * levels below 0 reach two stale mhd_assert()s in get_req_header();
    223  * set MHD_FUZZ_MIN_DISCIPLINE=0 there so that the rest of the state
    224  * space keeps being explored.
    225  */
    226 static int min_discipline = -3;
    227 static int min_discipline_read;
    228 
    229 /**
    230  * Restrict the generator to a single grammar shape (see enum gen_shape).
    231  * -1 (the default) means "pick a random shape every time".  Set with
    232  * MHD_FUZZ_SHAPE=<n>; handy for triage and for regression testing a
    233  * specific past bug.
    234  */
    235 static int forced_shape = -1;
    236 static int forced_shape_read;
    237 
    238 /**
    239  * Lower bound for MHD_OPTION_CONNECTION_MEMORY_LIMIT.  0 (the default)
    240  * fuzzes the full range, including the 128 byte pools that are needed
    241  * to reach the read-buffer "shift back" code.  On a tree without the
    242  * patches listed in README section 6, pools below ~500 bytes combined
    243  * with a chunked request body reach two mhd_assert()s in connection.c;
    244  * set MHD_FUZZ_MIN_MEM_LIMIT=512 there.
    245  */
    246 static size_t min_mem_limit;
    247 static int min_mem_limit_read;
    248 
    249 static const enum MHD_DigestAuthMultiAlgo3 algo_tbl[] = {
    250   MHD_DIGEST_AUTH_MULT_ALGO3_SHA256,
    251   MHD_DIGEST_AUTH_MULT_ALGO3_MD5,
    252   MHD_DIGEST_AUTH_MULT_ALGO3_SHA512_256,
    253   MHD_DIGEST_AUTH_MULT_ALGO3_SHA256
    254 };
    255 
    256 static const unsigned int nnc_tbl[] = { 4, 1, 8, 64 };
    257 
    258 /** Fixed entropy so that nonces are reproducible across runs. */
    259 static const char digest_rnd[32] =
    260   "\x01\x23\x45\x67\x89\xab\xcd\xef\x01\x23\x45\x67\x89\xab\xcd\xef"
    261   "\xfe\xdc\xba\x98\x76\x54\x32\x10\xfe\xdc\xba\x98\x76\x54\x32\x10";
    262 
    263 
    264 /* ------------------------------------------------------------------ */
    265 /* Configuration byte 4: response construction                       */
    266 /* ------------------------------------------------------------------ */
    267 
    268 /* Defined with the access handler further down; decorate_response()
    269    hands it to MHD_get_response_headers(). */
    270 static enum MHD_Result
    271 kv_iter (void *cls,
    272          enum MHD_ValueKind kind,
    273          const char *key,
    274          const char *value);
    275 
    276 /** Daemon of the current iteration; needed by MHD_get_daemon_info(). */
    277 static struct MHD_Daemon *cur_daemon;
    278 
    279 /**
    280  * Connections suspended by suspend mode 2, which the pump loop still has
    281  * to resume.  An entry is cleared by completed_cb() so that a connection
    282  * MHD has finished with is never resumed afterwards.
    283  *
    284  * This has to be a set, not a single slot: op 3 opens a fresh connection
    285  * without waiting for the previous one to finish, so several connections
    286  * can be parked at the same time.  A single slot silently loses all but
    287  * the last, and the forgotten one is still suspended when the iteration
    288  * calls MHD_stop_daemon(), which answers with
    289  * MHD_PANIC ("MHD_stop_daemon() called while we have suspended
    290  * connections") -- a harness bug that looks exactly like an MHD bug.
    291  */
    292 static struct MHD_Connection *pending_resume[MAX_CONNECTIONS];
    293 
    294 /**
    295  * Set once the iteration has stopped feeding the daemon and only wants
    296  * to drain it.  suspend_maybe() then does nothing, which is what makes
    297  * the flush loop in the teardown provably terminate: without it,
    298  * resuming a connection lets the handler run and park it again, for as
    299  * many rounds as there are pipelined requests still buffered.
    300  */
    301 static int tearing_down;
    302 
    303 
    304 /**
    305  * Record @a c as suspended.  Silently ignores the overflow case: the
    306  * array has one slot per connection the harness can open, so it cannot
    307  * overflow, and a dropped entry would only cost the resume below.
    308  */
    309 static void
    310 pending_resume_add (struct MHD_Connection *c)
    311 {
    312   unsigned int i;
    313 
    314   for (i = 0; i < MAX_CONNECTIONS; i++)
    315   {
    316     if (NULL == pending_resume[i])
    317     {
    318       pending_resume[i] = c;
    319       return;
    320     }
    321   }
    322 }
    323 
    324 
    325 /** Forget @a c without resuming it (it is gone). */
    326 static void
    327 pending_resume_drop (const struct MHD_Connection *c)
    328 {
    329   unsigned int i;
    330 
    331   for (i = 0; i < MAX_CONNECTIONS; i++)
    332     if (pending_resume[i] == c)
    333       pending_resume[i] = NULL;
    334 }
    335 
    336 
    337 /**
    338  * Resume everything still parked.
    339  *
    340  * @return non-zero if at least one connection was resumed, so that the
    341  *         caller knows the daemon needs another round to act on it
    342  */
    343 static int
    344 pending_resume_flush (void)
    345 {
    346   unsigned int i;
    347   int any = 0;
    348 
    349   for (i = 0; i < MAX_CONNECTIONS; i++)
    350   {
    351     struct MHD_Connection *c = pending_resume[i];
    352 
    353     if (NULL == c)
    354       continue;
    355     /* Clear first: MHD_resume_connection() can run the handler, which
    356        may suspend the very same connection again. */
    357     pending_resume[i] = NULL;
    358     MHD_resume_connection (c);
    359     any = 1;
    360   }
    361   return any;
    362 }
    363 
    364 
    365 /** Body used by the buffer / fd / pipe / iovec response kinds. */
    366 static const char resp_body[] = "hello world, this is the response body";
    367 #define RESP_BODY_LEN (sizeof (resp_body) - 1)
    368 
    369 /**
    370  * Response header names and values, indexed by cfg.hdr_seed.  The list
    371  * mixes ordinary headers with ones MHD has to reject or handle
    372  * specially: an empty name, a name carrying a control character, and a
    373  * value containing CRLF -- the classic response-splitting vector, which
    374  * MHD_add_response_header() is supposed to refuse.  Exercising that
    375  * validator is the point of this table.
    376  *
    377  * The message-framing headers are deliberately NOT here.  MHD generates
    378  * Content-Length and Transfer-Encoding itself from the response object,
    379  * so an application that also sets them by hand is lying to the library
    380  * about its own body: a manual "Transfer-Encoding: chunked" on, say, an
    381  * iovec response sends MHD down the chunked path for a response that
    382  * has neither a content reader nor a flat buffer, and it aborts in
    383  * try_ready_chunked_body().  That is the harness misusing the API
    384  * rather than a defect worth reporting, and leaving it in would bury
    385  * every real finding under the same false report.  MHD_RF_INSANITY_-
    386  * HEADER_CONTENT_LENGTH, set through MHD_set_response_options() in
    387  * decorate_response(), is the sanctioned way to explore that corner.
    388  */
    389 static const char *const hdr_names[] = {
    390   "X-Fuzz", "Content-Type", "Cache-Control", "Accept-Ranges",
    391   /* "\x01" is split from the rest so that the hex escape stops after
    392      one digit instead of swallowing the following "Bad". */
    393   "Connection", "Set-Cookie", "X-\x01" "Bad", "", "Trailer", "Date",
    394   "X-Fuzz", "Server", "Location", "ETag", "Vary", "Age"
    395 };
    396 
    397 static const char *const hdr_values[] = {
    398   "1", "text/plain", "no-cache", "bytes", "keep-alive", "a=b",
    399   "x\r\nInjected: yes", "", "X-Fuzz", "Thu, 01 Jan 1970 00:00:00 GMT",
    400   "\x7f", "mhd", "/", "\"tag\"", "*", "0"
    401 };
    402 
    403 #define HDR_COUNT (sizeof (hdr_names) / sizeof (hdr_names[0]))
    404 
    405 
    406 /**
    407  * State of one MHD_create_response_from_callback() response.  Allocated
    408  * per response and released through the free callback that MHD invokes
    409  * from MHD_destroy_response().
    410  */
    411 struct crc_state
    412 {
    413   uint64_t total;      /**< bytes to produce before end-of-stream */
    414   int calls;           /**< how often the reader has been called */
    415   int err_at;          /**< fail after this many calls, -1 to never fail */
    416   unsigned int pattern;
    417 };
    418 
    419 
    420 static ssize_t
    421 crc_cb (void *cls,
    422         uint64_t pos,
    423         char *buf,
    424         size_t max)
    425 {
    426   struct crc_state *st = (struct crc_state *) cls;
    427   size_t n;
    428   size_t i;
    429 
    430   st->calls++;
    431   /* Deliberately reachable: an application content reader is allowed to
    432      fail half way through a response body, and how MHD terminates the
    433      connection in that case (especially a chunked one that can no
    434      longer be framed correctly) is worth exercising. */
    435   if ( (0 <= st->err_at) &&
    436        (st->calls > st->err_at) )
    437     return MHD_CONTENT_READER_END_WITH_ERROR;
    438   if (pos >= st->total)
    439     return MHD_CONTENT_READER_END_OF_STREAM;
    440   n = (size_t) (st->total - pos);
    441   if (n > max)
    442     n = max;
    443   if (0 == n)
    444     return MHD_CONTENT_READER_END_OF_STREAM;
    445   for (i = 0; i < n; i++)
    446     buf[i] = (char) ('a' + (int) ((pos + i + st->pattern) % 26));
    447   return (ssize_t) n;
    448 }
    449 
    450 
    451 static void
    452 crc_free (void *cls)
    453 {
    454   free (cls);
    455 }
    456 
    457 
    458 /**
    459  * Handler for an upgraded ("101 Switching Protocols") connection.
    460  *
    461  * @a extra_in holds whatever the client had already pipelined behind
    462  * the request, which is attacker-controlled and therefore read here.
    463  *
    464  * The connection MUST be closed through MHD_upgrade_action(): the
    465  * socket belongs to the application from this point on and
    466  * MHD_stop_daemon() cannot complete while an upgraded connection is
    467  * still outstanding.
    468  */
    469 static void
    470 upgrade_cb (void *cls,
    471             struct MHD_Connection *connection,
    472             void *req_cls,
    473             const char *extra_in,
    474             size_t extra_in_size,
    475             MHD_socket sock,
    476             struct MHD_UpgradeResponseHandle *urh)
    477 {
    478   volatile size_t sink = 0;
    479 
    480   (void) cls;
    481   (void) connection;
    482   (void) req_cls;
    483   (void) sock;
    484   if ( (NULL != extra_in) &&
    485        (0 != extra_in_size) )
    486     sink += (size_t) (unsigned char) extra_in[extra_in_size - 1];
    487   (void) sink;
    488   if (0 != (cfg.upgrade_action & 0x01u))
    489     (void) MHD_upgrade_action (urh, MHD_UPGRADE_ACTION_CORK_ON);
    490   if (0 != (cfg.upgrade_action & 0x02u))
    491     (void) MHD_upgrade_action (urh, MHD_UPGRADE_ACTION_CORK_OFF);
    492   (void) MHD_upgrade_action (urh, MHD_UPGRADE_ACTION_CLOSE);
    493 }
    494 
    495 
    496 /**
    497  * A file descriptor holding RESP_BODY_LEN bytes, backed by anonymous
    498  * memory so that no filesystem is involved.
    499  *
    500  * @return -1 if unavailable, in which case the caller falls back to a
    501  *         buffer response
    502  */
    503 static int
    504 make_memfd (void)
    505 {
    506 #ifdef FUZZ_HAVE_MEMFD
    507   int fd;
    508 
    509   fd = memfd_create ("mhd-fuzz", MFD_CLOEXEC);
    510   if (0 > fd)
    511     return -1;
    512   if (RESP_BODY_LEN != (size_t) write (fd, resp_body, RESP_BODY_LEN))
    513   {
    514     (void) close (fd);
    515     return -1;
    516   }
    517   return fd;
    518 #else
    519   return -1;
    520 #endif
    521 }
    522 
    523 
    524 /**
    525  * The read end of a pipe holding RESP_BODY_LEN bytes.  The body is far
    526  * below the pipe capacity, so the write cannot block.
    527  */
    528 static int
    529 make_pipe_fd (void)
    530 {
    531   int pf[2];
    532 
    533   if (0 != pipe (pf))
    534     return -1;
    535   if (RESP_BODY_LEN != (size_t) write (pf[1], resp_body, RESP_BODY_LEN))
    536   {
    537     (void) close (pf[0]);
    538     (void) close (pf[1]);
    539     return -1;
    540   }
    541   (void) close (pf[1]);
    542   return pf[0];
    543 }
    544 
    545 
    546 /**
    547  * Add response headers, footers and option flags as selected by byte 4
    548  * and the header seed in byte 8.
    549  *
    550  * Footers are only meaningful for a chunked response -- MHD emits them
    551  * as trailers after the last chunk -- which is why they are worth
    552  * fuzzing together with the callback-based response kinds.
    553  */
    554 static void
    555 decorate_response (struct MHD_Response *r)
    556 {
    557   unsigned int i;
    558 
    559   for (i = 0; i < cfg.resp_nhdr; i++)
    560   {
    561     unsigned int k = (cfg.hdr_seed + i) % HDR_COUNT;
    562 
    563     (void) MHD_add_response_header (r, hdr_names[k], hdr_values[k]);
    564   }
    565   if (cfg.resp_footer)
    566   {
    567     unsigned int k = (unsigned int) (cfg.hdr_seed + 1u) % HDR_COUNT;
    568 
    569     (void) MHD_add_response_footer (r, hdr_names[k], hdr_values[k]);
    570   }
    571   if (cfg.resp_hdr_api)
    572   {
    573     unsigned int k = cfg.hdr_seed % HDR_COUNT;
    574     volatile size_t sink = 0;
    575     const char *v;
    576 
    577     v = MHD_get_response_header (r, hdr_names[k]);
    578     if (NULL != v)
    579       sink += strlen (v);
    580     (void) sink;
    581     (void) MHD_get_response_headers (r, &kv_iter, NULL);
    582     (void) MHD_del_response_header (r, hdr_names[k], hdr_values[k]);
    583     (void) MHD_set_response_options (r,
    584                                      (enum MHD_ResponseFlags)
    585                                      (((cfg.hdr_seed & 0x01) ?
    586                                        MHD_RF_HTTP_VERSION_1_0_RESPONSE : 0)
    587                                       | ((cfg.hdr_seed & 0x02) ?
    588                                          MHD_RF_SEND_KEEP_ALIVE_HEADER : 0)
    589                                       | ((cfg.hdr_seed & 0x04) ?
    590                                          MHD_RF_INSANITY_HEADER_CONTENT_LENGTH
    591                                          : 0)
    592                                       | ((cfg.hdr_seed & 0x08) ?
    593                                          MHD_RF_HEAD_ONLY_RESPONSE : 0)),
    594                                      MHD_RO_END);
    595   }
    596 }
    597 
    598 
    599 /**
    600  * Build the response body for this iteration.
    601  *
    602  * Every constructor that fails is responsible for nothing: MHD releases
    603  * neither the buffer nor the file descriptor when it returns NULL (see
    604  * MHD_create_response_from_buffer_with_free_callback_cls() and
    605  * MHD_create_response_from_pipe() in response.c), so ownership stays
    606  * here and the resource has to be released explicitly.  Getting this
    607  * backwards would produce double frees that look exactly like MHD bugs.
    608  */
    609 static struct MHD_Response *
    610 make_response (void)
    611 {
    612   struct MHD_Response *r = NULL;
    613   struct crc_state *st;
    614   void *heap;
    615   int fd;
    616 
    617   switch (cfg.resp_kind)
    618   {
    619   case 0:
    620     /* The two responses the harness used before byte 4 existed.  Bit
    621        0x20 of byte 1 (cfg.chunked_reply) selects between them and has
    622        no other effect, so keeping the pair here is what keeps that bit
    623        meaningful. */
    624     if (cfg.chunked_reply)
    625       r = MHD_create_response_from_buffer_copy (11, "hello world");
    626     else
    627       r = MHD_create_response_from_buffer_static (2, "ok");
    628     break;
    629   case 1:
    630     r = MHD_create_response_from_buffer_copy (RESP_BODY_LEN, resp_body);
    631     break;
    632   case 2:
    633     r = MHD_create_response_empty (MHD_RF_NONE);
    634     break;
    635   case 3:
    636     r = MHD_create_response_from_buffer (RESP_BODY_LEN,
    637                                          (void *) (intptr_t) resp_body,
    638                                          MHD_RESPMEM_PERSISTENT);
    639     break;
    640   case 4:
    641     heap = malloc (RESP_BODY_LEN);
    642     if (NULL == heap)
    643       return NULL;
    644     memcpy (heap, resp_body, RESP_BODY_LEN);
    645     r = MHD_create_response_from_buffer (RESP_BODY_LEN,
    646                                          heap,
    647                                          MHD_RESPMEM_MUST_FREE);
    648     if (NULL == r)
    649       free (heap);
    650     break;
    651   case 5:
    652     r = MHD_create_response_from_buffer (RESP_BODY_LEN,
    653                                          (void *) (intptr_t) resp_body,
    654                                          MHD_RESPMEM_MUST_COPY);
    655     break;
    656   case 6:
    657     heap = malloc (RESP_BODY_LEN);
    658     if (NULL == heap)
    659       return NULL;
    660     memcpy (heap, resp_body, RESP_BODY_LEN);
    661     r = MHD_create_response_from_buffer_with_free_callback (RESP_BODY_LEN,
    662                                                             heap,
    663                                                             &free);
    664     if (NULL == r)
    665       free (heap);
    666     break;
    667   case 7:
    668     r = MHD_create_response_from_data (RESP_BODY_LEN,
    669                                        (void *) (intptr_t) resp_body,
    670                                        0 /* must_free */,
    671                                        1 /* must_copy */);
    672     break;
    673   case 8:
    674     heap = malloc (RESP_BODY_LEN);
    675     if (NULL == heap)
    676       return NULL;
    677     memcpy (heap, resp_body, RESP_BODY_LEN);
    678     r = MHD_create_response_from_data (RESP_BODY_LEN,
    679                                        heap,
    680                                        1 /* must_free */,
    681                                        0 /* must_copy */);
    682     if (NULL == r)
    683       free (heap);
    684     break;
    685   case 9:
    686   case 10:
    687     st = (struct crc_state *) calloc (1, sizeof (struct crc_state));
    688     if (NULL == st)
    689       return NULL;
    690     st->total = (uint64_t) (1u + (cfg.crc_seed & 0x7Fu));
    691     st->pattern = cfg.crc_seed;
    692     /* Injecting a reader error is only interesting some of the time;
    693        otherwise the body would rarely complete. */
    694     st->err_at = (0 != (cfg.crc_seed & 0x80u))
    695                  ? (int) (1u + (cfg.crc_seed & 0x03u))
    696                  : -1;
    697     r = MHD_create_response_from_callback (
    698       (9 == cfg.resp_kind) ? st->total : MHD_SIZE_UNKNOWN,
    699       (size_t) (16u + (cfg.crc_seed & 0x3Fu)),
    700       &crc_cb,
    701       st,
    702       &crc_free);
    703     if (NULL == r)
    704       free (st);
    705     break;
    706   case 11:
    707   case 12:
    708   case 13:
    709     fd = make_memfd ();
    710     if (0 > fd)
    711     {
    712       r = MHD_create_response_from_buffer_static (2, "ok");
    713       break;
    714     }
    715     if (11 == cfg.resp_kind)
    716       r = MHD_create_response_from_fd (RESP_BODY_LEN, fd);
    717     else if (12 == cfg.resp_kind)
    718       /* Parenthesised so that the deprecated *function* is called and
    719          not the same-named macro that redirects to the 64 bit variant;
    720          reaching the v1 entry point is the whole point here. */
    721       r = (MHD_create_response_from_fd_at_offset) (
    722         RESP_BODY_LEN / 2,
    723         fd,
    724         (off_t) (RESP_BODY_LEN / 4));
    725     else
    726       r = MHD_create_response_from_fd64 ((uint64_t) RESP_BODY_LEN, fd);
    727     if (NULL == r)
    728       (void) close (fd);
    729     break;
    730   case 14:
    731     fd = make_pipe_fd ();
    732     if (0 > fd)
    733     {
    734       r = MHD_create_response_from_buffer_static (2, "ok");
    735       break;
    736     }
    737     r = MHD_create_response_from_pipe (fd);
    738     if (NULL == r)
    739       (void) close (fd);
    740     break;
    741   case 15:
    742   default:
    743     {
    744       static struct MHD_IoVec iov[3];
    745 
    746       /* Static data, so no free callback is needed; MHD copies the
    747          array itself (see the documentation of the @a iov parameter). */
    748       iov[0].iov_base = resp_body;
    749       iov[0].iov_len = RESP_BODY_LEN / 2;
    750       iov[1].iov_base = resp_body + (RESP_BODY_LEN / 2);
    751       iov[1].iov_len = RESP_BODY_LEN - (RESP_BODY_LEN / 2);
    752       iov[2].iov_base = resp_body;
    753       iov[2].iov_len = (size_t) (cfg.crc_seed % (RESP_BODY_LEN + 1));
    754       r = MHD_create_response_from_iovec (iov,
    755                                           (0 != iov[2].iov_len) ? 3u : 2u,
    756                                           NULL,
    757                                           NULL);
    758     }
    759     break;
    760   }
    761   if (NULL != r)
    762     decorate_response (r);
    763   return r;
    764 }
    765 
    766 
    767 /* ------------------------------------------------------------------ */
    768 /* Access handler                                                      */
    769 /* ------------------------------------------------------------------ */
    770 
    771 struct hstate
    772 {
    773   size_t body_off;
    774   struct MHD_PostProcessor *pp;
    775   int pp_tried;
    776 };
    777 
    778 
    779 static enum MHD_Result
    780 kv_iter (void *cls,
    781          enum MHD_ValueKind kind,
    782          const char *key,
    783          const char *value)
    784 {
    785   volatile size_t sink = 0;
    786 
    787   (void) cls;
    788   (void) kind;
    789   if (NULL != key)
    790     sink += strlen (key);
    791   if (NULL != value)
    792     sink += strlen (value);
    793   (void) sink;
    794   return MHD_YES;
    795 }
    796 
    797 
    798 /**
    799  * Length-aware counterpart of kv_iter(), for
    800  * MHD_get_connection_values_n().  Unlike the NUL-terminated iterator it
    801  * is handed explicit sizes, so it reads exactly what MHD says is there
    802  * rather than trusting a terminator.
    803  */
    804 static enum MHD_Result
    805 kv_iter_n (void *cls,
    806            enum MHD_ValueKind kind,
    807            const char *key,
    808            size_t key_size,
    809            const char *value,
    810            size_t value_size)
    811 {
    812   volatile size_t sink = 0;
    813 
    814   (void) cls;
    815   (void) kind;
    816   if ( (NULL != key) && (0 != key_size) )
    817     sink += (size_t) (unsigned char) key[key_size - 1];
    818   if ( (NULL != value) && (0 != value_size) )
    819     sink += (size_t) (unsigned char) value[value_size - 1];
    820   (void) sink;
    821   return MHD_YES;
    822 }
    823 
    824 
    825 static enum MHD_Result
    826 post_iter (void *cls,
    827            enum MHD_ValueKind kind,
    828            const char *key,
    829            const char *filename,
    830            const char *content_type,
    831            const char *transfer_encoding,
    832            const char *data,
    833            uint64_t off,
    834            size_t size)
    835 {
    836   volatile size_t sink = 0;
    837 
    838   (void) cls;
    839   (void) kind;
    840   (void) off;
    841   if (NULL != key)
    842     sink += strlen (key);
    843   if (NULL != filename)
    844     sink += strlen (filename);
    845   if (NULL != content_type)
    846     sink += strlen (content_type);
    847   if (NULL != transfer_encoding)
    848     sink += strlen (transfer_encoding);
    849   if ( (NULL != data) && (0 != size) )
    850     sink += (size_t) (unsigned char) data[size - 1];
    851   (void) sink;
    852   return MHD_YES;
    853 }
    854 
    855 
    856 /**
    857  * Check the body MHD hands to the application against the body that
    858  * the generator encoded into the request.  MHD is allowed to reject
    859  * the request at any point, but every byte that it *does* deliver must
    860  * be the next expected byte.  A mismatch means the framing layer
    861  * (Content-Length or chunked transfer coding) got out of sync, which
    862  * is exactly the class of bug that enables request smuggling.
    863  */
    864 static void
    865 oracle_check_body (struct hstate *hs,
    866                    const char *data,
    867                    size_t size)
    868 {
    869   if ( (! oracle_on) ||
    870        (0 == size) )
    871     return;
    872   if ( (hs->body_off + size > expect_body_len) ||
    873        (0 != memcmp (expect_body + hs->body_off, data, size)) )
    874     fuzz_report_finding (
    875       "request body desync: the bytes MHD delivered to the application "
    876       "differ from the body encoded in the generated request "
    877       "(chunked/Content-Length framing bug, cf. HTTP request smuggling)");
    878   hs->body_off += size;
    879 }
    880 
    881 
    882 /* ------------------------------------------------------------------ */
    883 /* Configuration byte 5: authentication entry points                 */
    884 /* ------------------------------------------------------------------ */
    885 
    886 static const enum MHD_DigestAuthAlgorithm algo1_tbl[] = {
    887   MHD_DIGEST_ALG_AUTO,
    888   MHD_DIGEST_ALG_MD5,
    889   MHD_DIGEST_ALG_SHA256,
    890   MHD_DIGEST_ALG_AUTO
    891 };
    892 
    893 static const enum MHD_DigestAuthAlgo3 algo3_tbl[] = {
    894   MHD_DIGEST_AUTH_ALGO3_MD5,
    895   MHD_DIGEST_AUTH_ALGO3_SHA256,
    896   MHD_DIGEST_AUTH_ALGO3_SHA512_256,
    897   MHD_DIGEST_AUTH_ALGO3_MD5_SESSION,
    898   MHD_DIGEST_AUTH_ALGO3_SHA256_SESSION,
    899   MHD_DIGEST_AUTH_ALGO3_SHA512_256_SESSION,
    900   MHD_DIGEST_AUTH_ALGO3_MD5,
    901   MHD_DIGEST_AUTH_ALGO3_SHA256
    902 };
    903 
    904 /** Outcome of run_digest_check(). */
    905 #define DAUTH_CHALLENGE 0
    906 #define DAUTH_PASSED    1
    907 #define DAUTH_STALE     2
    908 
    909 
    910 /**
    911  * Exercise the digest helpers that take no connection:
    912  * MHD_digest_get_hash_size(), MHD_digest_auth_calc_userdigest(),
    913  * MHD_digest_auth_calc_userhash() and
    914  * MHD_digest_auth_calc_userhash_hex().
    915  *
    916  * The output buffers are heap allocations of *exactly* the size that is
    917  * passed to MHD, and that size is deliberately varied down to zero.  A
    918  * correct implementation must reject every buffer that is too small; if
    919  * it instead writes the full digest, ASAN's redzone catches it
    920  * immediately.  This is the shape of the bug fixed in commit 5a73c1ae,
    921  * where an over-long userhash overflowed a fixed-size decode buffer.
    922  */
    923 static void
    924 call_calc_helpers (void)
    925 {
    926   enum MHD_DigestAuthAlgo3 a = algo3_tbl[cfg.hdr_seed
    927                                          % (sizeof (algo3_tbl)
    928                                             / sizeof (algo3_tbl[0]))];
    929   size_t hs;
    930   size_t claim;
    931   void *bin;
    932   char *hex;
    933 
    934   hs = MHD_digest_get_hash_size (a);
    935   if ( (0 == hs) ||
    936        (hs > MAX_DIGEST_BIN) )
    937     return;
    938   claim = hs - (size_t) (cfg.crc_seed % (unsigned int) (hs + 1u));
    939 
    940   bin = malloc (claim);
    941   if (NULL != bin)
    942   {
    943     (void) MHD_digest_auth_calc_userdigest (a,
    944                                             DIGEST_USER,
    945                                             DIGEST_REALM,
    946                                             DIGEST_PASS,
    947                                             bin,
    948                                             claim);
    949     (void) MHD_digest_auth_calc_userhash (a,
    950                                           DIGEST_USER,
    951                                           DIGEST_REALM,
    952                                           bin,
    953                                           claim);
    954     free (bin);
    955   }
    956   /* The hex form needs 2*hs+1 bytes; ask for less about half the time. */
    957   claim = (2u * hs + 1u)
    958           - (size_t) (cfg.hdr_seed % (unsigned int) (2u * hs + 2u));
    959   hex = (char *) malloc (claim);
    960   if (NULL != hex)
    961   {
    962     (void) MHD_digest_auth_calc_userhash_hex (a,
    963                                               DIGEST_USER,
    964                                               DIGEST_REALM,
    965                                               hex,
    966                                               claim);
    967     free (hex);
    968   }
    969 }
    970 
    971 
    972 /**
    973  * Run the digest-authentication entry point selected by byte 5.
    974  *
    975  * Variant 0 is MHD_digest_auth_check3(), which is the plainest one and
    976  * what the all-zero configuration selects.  Variants 1-5 are the v1/v2 compatibility
    977  * wrappers and the pre-computed-digest forms, which do their own buffer
    978  * sizing and are therefore worth driving directly.  Variants 6-8 are
    979  * the query functions, which parse the client's Authorization header
    980  * but return no verdict, so they run *in addition* to check3().
    981  *
    982  * @return one of DAUTH_CHALLENGE, DAUTH_PASSED, DAUTH_STALE
    983  */
    984 static int
    985 run_digest_check (struct MHD_Connection *connection)
    986 {
    987   unsigned int variant = cfg.dauth_variant;
    988   enum MHD_DigestAuthResult dres;
    989   uint8_t ud[MAX_DIGEST_BIN];
    990   size_t hs;
    991   int r1;
    992   volatile size_t sink = 0;
    993 
    994   switch (variant)
    995   {
    996   case 1:
    997     r1 = MHD_digest_auth_check (connection,
    998                                 DIGEST_REALM,
    999                                 DIGEST_USER,
   1000                                 DIGEST_PASS,
   1001                                 0);
   1002     if (MHD_YES == r1)
   1003       return DAUTH_PASSED;
   1004     return (MHD_INVALID_NONCE == r1) ? DAUTH_STALE : DAUTH_CHALLENGE;
   1005   case 2:
   1006     r1 = MHD_digest_auth_check2 (connection,
   1007                                  DIGEST_REALM,
   1008                                  DIGEST_USER,
   1009                                  DIGEST_PASS,
   1010                                  0,
   1011                                  algo1_tbl[cfg.hdr_seed & 0x03]);
   1012     if (MHD_YES == r1)
   1013       return DAUTH_PASSED;
   1014     return (MHD_INVALID_NONCE == r1) ? DAUTH_STALE : DAUTH_CHALLENGE;
   1015   case 3:
   1016     /* MHD_digest_auth_check_digest() is MD5-only by definition. */
   1017     if (MHD_YES != MHD_digest_auth_calc_userdigest (
   1018           MHD_DIGEST_AUTH_ALGO3_MD5,
   1019           DIGEST_USER, DIGEST_REALM, DIGEST_PASS,
   1020           ud, MHD_MD5_DIGEST_SIZE))
   1021       break;
   1022     r1 = MHD_digest_auth_check_digest (connection,
   1023                                        DIGEST_REALM,
   1024                                        DIGEST_USER,
   1025                                        ud,
   1026                                        0);
   1027     if (MHD_YES == r1)
   1028       return DAUTH_PASSED;
   1029     return (MHD_INVALID_NONCE == r1) ? DAUTH_STALE : DAUTH_CHALLENGE;
   1030   case 4:
   1031   case 5:
   1032     {
   1033       /* The pre-computed-digest entry points are stricter than the
   1034          password-based ones: the digest and the algorithm have to
   1035          agree, and naming more than one base hashing algorithm is an
   1036          MHD_PANIC("API violation") rather than an error return.  So the
   1037          algorithm is chosen first here and the digest, its length and
   1038          the algorithm argument are all derived from that one choice.
   1039 
   1040          MHD_DIGEST_ALG_AUTO is deliberately not used for variant 4:
   1041          MHD_digest_auth_check_digest2() maps it to
   1042          MULT_ALGO3_ANY_NON_SESSION, which names three base algorithms
   1043          and therefore trips that very panic.  See README section 6. */
   1044       static const enum MHD_DigestAuthAlgo3 digest_algos[] = {
   1045         MHD_DIGEST_AUTH_ALGO3_MD5,
   1046         MHD_DIGEST_AUTH_ALGO3_SHA256,
   1047         MHD_DIGEST_AUTH_ALGO3_SHA512_256,
   1048         MHD_DIGEST_AUTH_ALGO3_MD5_SESSION,
   1049         MHD_DIGEST_AUTH_ALGO3_SHA256_SESSION,
   1050         MHD_DIGEST_AUTH_ALGO3_SHA512_256_SESSION
   1051       };
   1052       enum MHD_DigestAuthAlgo3 a3;
   1053 
   1054       if (4 == variant)
   1055         /* check_digest2() only knows MD5 and SHA-256. */
   1056         a3 = (0 != (cfg.hdr_seed & 0x01))
   1057              ? MHD_DIGEST_AUTH_ALGO3_SHA256
   1058              : MHD_DIGEST_AUTH_ALGO3_MD5;
   1059       else
   1060         a3 = digest_algos[cfg.hdr_seed
   1061                           % (sizeof (digest_algos)
   1062                              / sizeof (digest_algos[0]))];
   1063       hs = MHD_digest_get_hash_size (a3);
   1064       if ( (0 == hs) ||
   1065            (hs > sizeof (ud)) ||
   1066            (MHD_YES != MHD_digest_auth_calc_userdigest (a3,
   1067                                                         DIGEST_USER,
   1068                                                         DIGEST_REALM,
   1069                                                         DIGEST_PASS,
   1070                                                         ud,
   1071                                                         hs)) )
   1072         break;
   1073       if (4 == variant)
   1074       {
   1075         r1 = MHD_digest_auth_check_digest2 (connection,
   1076                                             DIGEST_REALM,
   1077                                             DIGEST_USER,
   1078                                             ud,
   1079                                             hs,
   1080                                             0,
   1081                                             (MHD_DIGEST_AUTH_ALGO3_SHA256 == a3)
   1082                                             ? MHD_DIGEST_ALG_SHA256
   1083                                             : MHD_DIGEST_ALG_MD5);
   1084         if (MHD_YES == r1)
   1085           return DAUTH_PASSED;
   1086         return (MHD_INVALID_NONCE == r1) ? DAUTH_STALE : DAUTH_CHALLENGE;
   1087       }
   1088       dres = MHD_digest_auth_check_digest3 (connection,
   1089                                             DIGEST_REALM,
   1090                                             DIGEST_USER,
   1091                                             ud,
   1092                                             hs,
   1093                                             0,
   1094                                             0,
   1095                                             cfg.qop,
   1096                                             /* Exactly one base algorithm.
   1097                                                The MULT_ALGO3_* constants are
   1098                                                numerically identical to their
   1099                                                ALGO3_* counterparts. */
   1100                                             (enum MHD_DigestAuthMultiAlgo3) a3);
   1101       if (MHD_DAUTH_OK == dres)
   1102         return DAUTH_PASSED;
   1103       return (MHD_DAUTH_NONCE_STALE == dres) ? DAUTH_STALE : DAUTH_CHALLENGE;
   1104     }
   1105   case 6:
   1106     {
   1107       char *u = MHD_digest_auth_get_username (connection);
   1108 
   1109       if (NULL != u)
   1110       {
   1111         sink += strlen (u);
   1112         MHD_free (u);
   1113       }
   1114     }
   1115     break;
   1116   case 7:
   1117     {
   1118       struct MHD_DigestAuthUsernameInfo *ui;
   1119 
   1120       ui = MHD_digest_auth_get_username3 (connection);
   1121       if (NULL != ui)
   1122       {
   1123         if (NULL != ui->username)
   1124           sink += ui->username_len;
   1125         if (NULL != ui->userhash_hex)
   1126           sink += ui->userhash_hex_len;
   1127         MHD_free (ui);
   1128       }
   1129     }
   1130     break;
   1131   case 8:
   1132     {
   1133       struct MHD_DigestAuthInfo *ai;
   1134 
   1135       ai = MHD_digest_auth_get_request_info3 (connection);
   1136       if (NULL != ai)
   1137       {
   1138         if (NULL != ai->username)
   1139           sink += ai->username_len;
   1140         if (NULL != ai->realm)
   1141           sink += ai->realm_len;
   1142         if (NULL != ai->opaque)
   1143           sink += ai->opaque_len;
   1144         if (NULL != ai->userhash_hex)
   1145           sink += ai->userhash_hex_len;
   1146         sink += ai->cnonce_len;
   1147         sink += (size_t) ai->nc;
   1148         MHD_free (ai);
   1149       }
   1150     }
   1151     break;
   1152   default:
   1153     break;
   1154   }
   1155   (void) sink;
   1156 
   1157   /* Variant 0, the query variants and every early break end up here. */
   1158   dres = MHD_digest_auth_check3 (connection,
   1159                                  DIGEST_REALM,
   1160                                  DIGEST_USER,
   1161                                  DIGEST_PASS,
   1162                                  0 /* daemon default nonce timeout */,
   1163                                  0 /* daemon default max_nc */,
   1164                                  cfg.qop,
   1165                                  MHD_DIGEST_AUTH_MULT_ALGO3_ANY_NON_SESSION);
   1166   if (MHD_DAUTH_OK == dres)
   1167     return DAUTH_PASSED;
   1168   return (MHD_DAUTH_NONCE_STALE == dres) ? DAUTH_STALE : DAUTH_CHALLENGE;
   1169 }
   1170 
   1171 
   1172 /**
   1173  * Send the "authentication required" reply through the variant of the
   1174  * API selected by byte 5.  The v1/v2 forms take a plain response and an
   1175  * algorithm rather than the qop/algo pair of the v3 form.
   1176  */
   1177 static enum MHD_Result
   1178 queue_auth_challenge (struct MHD_Connection *connection,
   1179                       int stale)
   1180 {
   1181   struct MHD_Response *resp;
   1182   enum MHD_Result ret;
   1183 
   1184   resp = MHD_create_response_from_buffer_static (0, "");
   1185   if (NULL == resp)
   1186     return MHD_NO;
   1187   switch (cfg.fail_variant)
   1188   {
   1189   case 1:
   1190     ret = MHD_queue_auth_fail_response (connection,
   1191                                         DIGEST_REALM,
   1192                                         "0123456789abcdef",
   1193                                         resp,
   1194                                         stale ? MHD_YES : MHD_NO);
   1195     break;
   1196   case 2:
   1197     ret = MHD_queue_auth_fail_response2 (connection,
   1198                                          DIGEST_REALM,
   1199                                          "0123456789abcdef",
   1200                                          resp,
   1201                                          stale ? MHD_YES : MHD_NO,
   1202                                          algo1_tbl[cfg.hdr_seed & 0x03]);
   1203     break;
   1204   case 3:
   1205     if (0 != (cfg.hdr_seed & 0x01))
   1206       ret = MHD_queue_basic_auth_required_response3 (connection,
   1207                                                      DIGEST_REALM,
   1208                                                      (0 != (cfg.hdr_seed
   1209                                                             & 0x02))
   1210                                                      ? MHD_YES : MHD_NO,
   1211                                                      resp);
   1212     else
   1213       ret = MHD_queue_basic_auth_fail_response (connection,
   1214                                                 DIGEST_REALM,
   1215                                                 resp);
   1216     break;
   1217   case 0:
   1218   default:
   1219     ret = MHD_queue_auth_required_response3 (connection,
   1220                                              DIGEST_REALM,
   1221                                              "0123456789abcdef" /* opaque */,
   1222                                              "/",
   1223                                              resp,
   1224                                              stale ? MHD_YES : MHD_NO,
   1225                                              cfg.qop,
   1226                                              cfg.algo,
   1227                                              MHD_YES /* userhash */,
   1228                                              MHD_NO);
   1229     break;
   1230   }
   1231   MHD_destroy_response (resp);
   1232   return ret;
   1233 }
   1234 
   1235 
   1236 /* ------------------------------------------------------------------ */
   1237 /* Configuration byte 6: connection introspection                    */
   1238 /* ------------------------------------------------------------------ */
   1239 
   1240 /**
   1241  * Call the read-only connection accessors on attacker-supplied header
   1242  * data.  MHD_lookup_connection_value*() run the case-insensitive header
   1243  * matcher over whatever the client sent, which is exactly the sort of
   1244  * input the fuzzer is good at producing.
   1245  */
   1246 static void
   1247 exercise_connection_api (struct MHD_Connection *connection)
   1248 {
   1249   volatile size_t sink = 0;
   1250 
   1251   if (cfg.conn_lookup)
   1252   {
   1253     static const char *const keys[] = {
   1254       "Host", "Content-Length", "Transfer-Encoding", "Authorization",
   1255       "Cookie", "", "X-Fuzz", "connection"
   1256     };
   1257     const char *k = keys[cfg.hdr_seed % (sizeof (keys) / sizeof (keys[0]))];
   1258     const char *v;
   1259     const char *vp = NULL;
   1260     size_t vlen = 0;
   1261     const char *uri = NULL;
   1262     size_t ulen = 0;
   1263 
   1264     v = MHD_lookup_connection_value (connection, MHD_HEADER_KIND, k);
   1265     if (NULL != v)
   1266       sink += strlen (v);
   1267     if (MHD_YES == MHD_lookup_connection_value_n (connection,
   1268                                                   MHD_HEADER_KIND,
   1269                                                   k,
   1270                                                   strlen (k),
   1271                                                   &vp,
   1272                                                   &vlen))
   1273       sink += vlen;
   1274     if (MHD_YES == MHD_get_connection_URI_path_n (connection, &uri, &ulen))
   1275       sink += ulen;
   1276   }
   1277   if (cfg.conn_setvalue)
   1278     (void) MHD_set_connection_value (connection,
   1279                                      MHD_HEADER_KIND,
   1280                                      "X-Fuzz-Added",
   1281                                      "1");
   1282   if (cfg.conn_info)
   1283   {
   1284     static const enum MHD_ConnectionInfoType cinfo[] = {
   1285       MHD_CONNECTION_INFO_CLIENT_ADDRESS,
   1286       MHD_CONNECTION_INFO_DAEMON,
   1287       MHD_CONNECTION_INFO_CONNECTION_FD,
   1288       MHD_CONNECTION_INFO_SOCKET_CONTEXT,
   1289       MHD_CONNECTION_INFO_CONNECTION_SUSPENDED,
   1290       MHD_CONNECTION_INFO_CONNECTION_TIMEOUT,
   1291       MHD_CONNECTION_INFO_REQUEST_HEADER_SIZE,
   1292       MHD_CONNECTION_INFO_HTTP_STATUS
   1293     };
   1294     static const enum MHD_DaemonInfoType dinfo[] = {
   1295       MHD_DAEMON_INFO_CURRENT_CONNECTIONS,
   1296       MHD_DAEMON_INFO_FLAGS,
   1297       MHD_DAEMON_INFO_LISTEN_FD,
   1298       MHD_DAEMON_INFO_BIND_PORT
   1299     };
   1300     unsigned int i;
   1301 
   1302     for (i = 0; i < sizeof (cinfo) / sizeof (cinfo[0]); i++)
   1303       if (NULL != MHD_get_connection_info (connection, cinfo[i]))
   1304         sink++;
   1305     for (i = 0; i < sizeof (dinfo) / sizeof (dinfo[0]); i++)
   1306       if ( (NULL != cur_daemon) &&
   1307            (NULL != MHD_get_daemon_info (cur_daemon, dinfo[i])) )
   1308         sink++;
   1309   }
   1310   if (cfg.conn_option)
   1311     (void) MHD_set_connection_option (connection,
   1312                                       MHD_CONNECTION_OPTION_TIMEOUT,
   1313                                       (unsigned int) (cfg.crc_seed & 0x0F));
   1314   if (cfg.conn_info)
   1315   {
   1316     /* Constant-output accessors.  They cannot fail on attacker input,
   1317        but they are cheap and leaving them uncovered makes the coverage
   1318        report harder to read.
   1319        MHD_fini() is deliberately NOT called anywhere: it tears down
   1320        process-global library state, so a single call would break every
   1321        later iteration in the same process. */
   1322     const char *v = MHD_get_version ();
   1323 
   1324     if (NULL != v)
   1325       sink += strlen (v);
   1326     sink += (size_t) MHD_get_version_bin ();
   1327   }
   1328   (void) sink;
   1329 }
   1330 
   1331 
   1332 /**
   1333  * Suspend the connection if byte 7 asks for it.
   1334  *
   1335  * Mode 1 suspends and resumes straight away, which exercises both state
   1336  * transitions without leaving the connection parked.  Mode 2 leaves it
   1337  * suspended and records it in @e pending_resume so that the pump loop
   1338  * resumes it on its next round; completed_cb() drops the record, so a
   1339  * connection MHD has finished with is never resumed after the fact, and
   1340  * the iteration flushes the whole set before stopping the daemon.  A
   1341  * connection left suspended makes MHD_stop_daemon() MHD_PANIC().
   1342  */
   1343 static void
   1344 suspend_maybe (struct MHD_Connection *connection)
   1345 {
   1346   if ( (0 == cfg.suspend_mode) ||
   1347        tearing_down)
   1348     return;
   1349   MHD_suspend_connection (connection);
   1350   if (1 == cfg.suspend_mode)
   1351   {
   1352     MHD_resume_connection (connection);
   1353     return;
   1354   }
   1355   pending_resume_add (connection);
   1356 }
   1357 
   1358 
   1359 static enum MHD_Result
   1360 ahc (void *cls,
   1361      struct MHD_Connection *connection,
   1362      const char *url,
   1363      const char *method,
   1364      const char *version,
   1365      const char *upload_data,
   1366      size_t *upload_data_size,
   1367      void **req_cls)
   1368 {
   1369   struct hstate *hs = (struct hstate *) *req_cls;
   1370   struct MHD_Response *resp;
   1371   enum MHD_Result ret;
   1372   volatile size_t sink = 0;
   1373   const char *conn_hdr = NULL;
   1374   char conn_lc[128];
   1375 
   1376   conn_lc[0] = '\0';
   1377   (void) cls;
   1378   if (NULL == hs)
   1379   {
   1380     hs = (struct hstate *) calloc (1, sizeof (struct hstate));
   1381     if (NULL == hs)
   1382       return MHD_NO;
   1383     *req_cls = hs;
   1384     return MHD_YES;
   1385   }
   1386 
   1387   stat_handler_calls++;
   1388   /* Touch the parsed request line the way a real application would. */
   1389   if (NULL != url)
   1390     sink += strlen (url);
   1391   if (NULL != method)
   1392     sink += strlen (method);
   1393   if (NULL != version)
   1394     sink += strlen (version);
   1395   (void) sink;
   1396 
   1397   if (0 != *upload_data_size)
   1398   {
   1399     stat_body_bytes += (unsigned long) *upload_data_size;
   1400     oracle_check_body (hs, upload_data, *upload_data_size);
   1401     if (cfg.do_postproc)
   1402     {
   1403       if ( (NULL == hs->pp) &&
   1404            (! hs->pp_tried) )
   1405       {
   1406         hs->pp_tried = 1;
   1407         hs->pp = MHD_create_post_processor (connection,
   1408                                             1024,
   1409                                             &post_iter,
   1410                                             NULL);
   1411       }
   1412       if (NULL != hs->pp)
   1413         (void) MHD_post_process (hs->pp, upload_data, *upload_data_size);
   1414     }
   1415     *upload_data_size = 0;
   1416     return MHD_YES;
   1417   }
   1418 
   1419   stat_final_calls++;
   1420   if (cfg.do_iterate)
   1421   {
   1422     const enum MHD_ValueKind kinds = MHD_HEADER_KIND
   1423                                      | MHD_GET_ARGUMENT_KIND
   1424                                      | MHD_COOKIE_KIND
   1425                                      | MHD_FOOTER_KIND;
   1426 
   1427     /* Alternate between the NUL-terminated iterator and the
   1428        length-aware one, which are separate code paths in MHD. */
   1429     if (0 != (cfg.hdr_seed & 0x10))
   1430       (void) MHD_get_connection_values_n (connection, kinds, &kv_iter_n, NULL);
   1431     else
   1432       (void) MHD_get_connection_values (connection, kinds, &kv_iter, NULL);
   1433   }
   1434 
   1435   if (oracle_on &&
   1436       (hs->body_off != expect_body_len) )
   1437     fuzz_report_finding (
   1438       "request body truncated: MHD completed the request but delivered "
   1439       "fewer body bytes than the generated request contained");
   1440 
   1441   exercise_connection_api (connection);
   1442 
   1443   /* Lower-cased copy of the request's "Connection" header, used by the
   1444      upgrade check further down.  MHD's own token matcher is internal,
   1445      so a plain case-folded substring test is used here; it only has to
   1446      be good enough to keep the harness from queueing an upgrade
   1447      response on a connection that cannot be upgraded. */
   1448   if (cfg.allow_upgrade)
   1449   {
   1450     conn_hdr = MHD_lookup_connection_value (connection,
   1451                                             MHD_HEADER_KIND,
   1452                                             MHD_HTTP_HEADER_CONNECTION);
   1453     if (NULL != conn_hdr)
   1454     {
   1455       size_t i;
   1456 
   1457       for (i = 0; (i + 1 < sizeof (conn_lc)) && ('\0' != conn_hdr[i]); i++)
   1458         conn_lc[i] = (char) (( ('A' <= conn_hdr[i]) && ('Z' >= conn_hdr[i]))
   1459                              ? (conn_hdr[i] - 'A' + 'a') : conn_hdr[i]);
   1460       conn_lc[i] = '\0';
   1461     }
   1462   }
   1463 
   1464   if (cfg.do_basic)
   1465   {
   1466     if (cfg.basic_v1)
   1467     {
   1468       /* The v1 getter returns two separate malloc()ed strings and is
   1469          the one that historically had to be freed by hand. */
   1470       char *pass = NULL;
   1471       char *user;
   1472 
   1473       user = MHD_basic_auth_get_username_password (connection, &pass);
   1474       if (NULL != user)
   1475         sink += strlen (user);
   1476       if (NULL != pass)
   1477         sink += strlen (pass);
   1478       if (NULL != user)
   1479         MHD_free (user);
   1480       if (NULL != pass)
   1481         MHD_free (pass);
   1482     }
   1483     else
   1484     {
   1485       struct MHD_BasicAuthInfo *bai;
   1486 
   1487       bai = MHD_basic_auth_get_username_password3 (connection);
   1488       if (NULL != bai)
   1489       {
   1490         if (NULL != bai->username)
   1491           sink += bai->username_len;
   1492         if (NULL != bai->password)
   1493           sink += bai->password_len;
   1494         MHD_free (bai);
   1495       }
   1496     }
   1497   }
   1498 
   1499   if (cfg.calc_helpers)
   1500     call_calc_helpers ();
   1501 
   1502   if (cfg.do_digest)
   1503   {
   1504     int dres = run_digest_check (connection);
   1505 
   1506     if (DAUTH_PASSED == dres)
   1507       stat_auth_ok++;
   1508     else
   1509     {
   1510       stat_challenges++;
   1511       return queue_auth_challenge (connection, DAUTH_STALE == dres);
   1512     }
   1513   }
   1514 
   1515   /* Only answer 101 for a request that really is an upgrade request:
   1516      HTTP/1.1, an "Upgrade" header, and a "Connection" header naming the
   1517      upgrade token (RFC 9110 section 7.8).  This is the check a real
   1518      application performs, and all three inputs come off the wire, so
   1519      the path stays fully attacker-driven.
   1520 
   1521      It is deliberately NOT enough to predict whether MHD will accept
   1522      the upgrade, and it is not meant to be: MHD may have decided during
   1523      header parsing that the connection must close, and does not expose
   1524      that decision.  That used to trip
   1525      mhd_assert (NULL == r->upgrade_handler ||
   1526                  MHD_CONN_MUST_UPGRADE == c->keepalive)
   1527      in build_header_response() -- finding K7, see README section 6,
   1528      reproducer corpus/known-findings/K7-upgrade-after-must-close.bin --
   1529      and MHD_queue_response() now returns MHD_NO for it instead, which
   1530      the code below already handles.  Do not "fix" this by tightening
   1531      the condition here: the check above is what an application can
   1532      actually do, and the harness has to behave like one. */
   1533   if (cfg.allow_upgrade &&
   1534       (NULL != version) &&
   1535       (0 == strcmp (version, MHD_HTTP_VERSION_1_1)) &&
   1536       (NULL != MHD_lookup_connection_value (connection,
   1537                                             MHD_HEADER_KIND,
   1538                                             MHD_HTTP_HEADER_UPGRADE)) &&
   1539       (NULL != conn_hdr) &&
   1540       (NULL != strstr (conn_lc, "upgrade")) &&
   1541       (NULL == strstr (conn_lc, "close")))
   1542   {
   1543     resp = MHD_create_response_for_upgrade (&upgrade_cb, NULL);
   1544     if (NULL != resp)
   1545     {
   1546       /* Mandatory: MHD_create_response_for_upgrade() documents that the
   1547          upgrade headers are the application's job, and
   1548          MHD_response_execute_upgrade_() asserts that "Upgrade" is
   1549          present before it hands the socket over.  Omitting it is an
   1550          application-contract violation, not something worth fuzzing. */
   1551       (void) MHD_add_response_header (resp,
   1552                                       MHD_HTTP_HEADER_UPGRADE,
   1553                                       "fuzz-protocol");
   1554       decorate_response (resp);
   1555       ret = MHD_queue_response (connection,
   1556                                 MHD_HTTP_SWITCHING_PROTOCOLS,
   1557                                 resp);
   1558       MHD_destroy_response (resp);
   1559       return ret;
   1560     }
   1561   }
   1562 
   1563   resp = make_response ();
   1564   if (NULL == resp)
   1565     return MHD_NO;
   1566   ret = MHD_queue_response (connection,
   1567                             cfg.error_reply
   1568                             ? MHD_HTTP_FORBIDDEN : MHD_HTTP_OK,
   1569                             resp);
   1570   MHD_destroy_response (resp);
   1571   /* Only after a response was actually accepted.  Returning MHD_NO
   1572      tells MHD to terminate the connection, and terminating a connection
   1573      that this callback has just suspended trips
   1574      mhd_assert (! connection->suspended) in MHD_connection_close_().
   1575      That is the harness contradicting itself, not an MHD defect: the
   1576      two requests are mutually exclusive by construction.  (MHD_NO is
   1577      reachable here for real -- MHD_queue_response() rejects, for
   1578      instance, a response carrying MHD_RF_HEAD_ONLY_RESPONSE on a GET,
   1579      which decorate_response() can set.) */
   1580   if (MHD_YES == ret)
   1581     suspend_maybe (connection);
   1582   return ret;
   1583 }
   1584 
   1585 
   1586 static void
   1587 completed_cb (void *cls,
   1588               struct MHD_Connection *connection,
   1589               void **req_cls,
   1590               enum MHD_RequestTerminationCode toe)
   1591 {
   1592   struct hstate *hs = (struct hstate *) *req_cls;
   1593 
   1594   (void) cls;
   1595   (void) toe;
   1596   /* MHD is done with this connection, so the deferred resume of
   1597      suspend mode 2 must not fire for it any more. */
   1598   pending_resume_drop (connection);
   1599   if (NULL == hs)
   1600     return;
   1601   if (NULL != hs->pp)
   1602     (void) MHD_destroy_post_processor (hs->pp);
   1603   free (hs);
   1604   *req_cls = NULL;
   1605 }
   1606 
   1607 
   1608 static void
   1609 panic_cb (void *cls,
   1610           const char *file,
   1611           unsigned int line,
   1612           const char *reason)
   1613 {
   1614   char msg[512];
   1615 
   1616   (void) cls;
   1617   (void) snprintf (msg, sizeof (msg),
   1618                    "MHD_PANIC() reached from network input at %s:%u: %s",
   1619                    (NULL != file) ? file : "?",
   1620                    line,
   1621                    (NULL != reason) ? reason : "?");
   1622   fuzz_report_finding (msg);
   1623 }
   1624 
   1625 
   1626 /* ------------------------------------------------------------------ */
   1627 /* Driving the daemon                                                  */
   1628 /* ------------------------------------------------------------------ */
   1629 
   1630 /**
   1631  * Read whatever the daemon has produced so far and look for a fresh
   1632  * Digest-Auth nonce in it.
   1633  */
   1634 static void
   1635 drain_and_harvest (int sock)
   1636 {
   1637   for (;;)
   1638   {
   1639     ssize_t n;
   1640     char tmp[4096];
   1641 
   1642     n = recv (sock, tmp, sizeof (tmp), MSG_DONTWAIT);
   1643     if (0 >= n)
   1644       break;
   1645     if (resp_len + (size_t) n < RESP_BUF_SIZE)
   1646     {
   1647       memcpy (resp_buf + resp_len, tmp, (size_t) n);
   1648       resp_len += (size_t) n;
   1649       resp_buf[resp_len] = '\0';
   1650     }
   1651   }
   1652   if (0 != resp_len)
   1653   {
   1654     const char *p = resp_buf;
   1655 
   1656     while (NULL != (p = strstr (p, "nonce=\"")))
   1657     {
   1658       const char *s = p + 7;
   1659       const char *e = strchr (s, '"');
   1660 
   1661       p = s;
   1662       if (NULL == e)
   1663         break;
   1664       if ((size_t) (e - s) < sizeof (nonce_val))
   1665       {
   1666         memcpy (nonce_val, s, (size_t) (e - s));
   1667         nonce_len = (size_t) (e - s);
   1668         nonce_val[nonce_len] = '\0';
   1669       }
   1670     }
   1671   }
   1672 }
   1673 
   1674 
   1675 /**
   1676  * Advance the daemon by one cycle, through the event-loop API selected
   1677  * by byte 6 of the input.
   1678  *
   1679  * Mode 0 is MHD_run(), which is what the harness used before the
   1680  * extension and which does the descriptor bookkeeping internally.
   1681  * Modes 1-3 drive the daemon the way an application with its own event
   1682  * loop does: MHD_get_fdset*() to collect the descriptors, select(), then
   1683  * MHD_run_from_select*().  That is the most common production
   1684  * integration and none of it was reachable before.
   1685  *
   1686  * The select() timeout is always zero.  The harness is single threaded
   1687  * and whatever the daemon is waiting for has already been written into
   1688  * the socketpair, so blocking would only burn wall clock; select() is
   1689  * called purely to populate the ready sets.
   1690  */
   1691 static void
   1692 run_once (struct MHD_Daemon *d)
   1693 {
   1694   fd_set rs;
   1695   fd_set ws;
   1696   fd_set es;
   1697   MHD_socket max_fd = MHD_INVALID_SOCKET;
   1698   struct timeval tv;
   1699 
   1700   if (0 == cfg.loop_mode)
   1701   {
   1702     (void) MHD_run (d);
   1703     return;
   1704   }
   1705   FD_ZERO (&rs);
   1706   FD_ZERO (&ws);
   1707   FD_ZERO (&es);
   1708   if (1 == cfg.loop_mode)
   1709   {
   1710     /* Parenthesised so that the real v1 function is called:
   1711        microhttpd.h also defines MHD_get_fdset as a macro that forwards
   1712        to MHD_get_fdset2 with FD_SETSIZE, so the unparenthesised name
   1713        would never reach the v1 entry point at all.  Same trick for
   1714        MHD_run_from_select below. */
   1715     if (MHD_YES != (MHD_get_fdset) (d, &rs, &ws, &es, &max_fd))
   1716     {
   1717       (void) MHD_run (d);
   1718       return;
   1719     }
   1720   }
   1721   else
   1722   {
   1723     if (MHD_YES != MHD_get_fdset2 (d, &rs, &ws, &es, &max_fd,
   1724                                    (unsigned int) FD_SETSIZE))
   1725     {
   1726       (void) MHD_run (d);
   1727       return;
   1728     }
   1729   }
   1730   if (cfg.use_timeouts)
   1731   {
   1732     MHD_UNSIGNED_LONG_LONG tl = 0;
   1733     uint64_t t64 = 0;
   1734     volatile int64_t sink;
   1735 
   1736     (void) MHD_get_timeout (d, &tl);
   1737     (void) MHD_get_timeout64 (d, &t64);
   1738     sink = MHD_get_timeout64s (d);
   1739     sink += (int64_t) MHD_get_timeout_i (d);
   1740     (void) sink;
   1741   }
   1742   tv.tv_sec = 0;
   1743   tv.tv_usec = 0;
   1744   if (MHD_INVALID_SOCKET != max_fd)
   1745     (void) select ((int) max_fd + 1, &rs, &ws, &es, &tv);
   1746   if (1 == cfg.loop_mode)
   1747     (void) (MHD_run_from_select) (d, &rs, &ws, &es);
   1748   else
   1749     (void) MHD_run_from_select2 (d, &rs, &ws, &es, (unsigned int) FD_SETSIZE);
   1750 }
   1751 
   1752 
   1753 static void
   1754 pump (struct MHD_Daemon *d,
   1755       int sock,
   1756       unsigned int rounds)
   1757 {
   1758   unsigned int i;
   1759 
   1760   for (i = 0; i < rounds; i++)
   1761   {
   1762     /* Deferred resume of suspend mode 2.  Each slot is cleared before
   1763        its connection is resumed, which keeps this correct even if the
   1764        resume makes MHD complete (and forget) the connection, or run the
   1765        handler again so that it suspends the same one anew. */
   1766     (void) pending_resume_flush ();
   1767     run_once (d);
   1768     drain_and_harvest (sock);
   1769   }
   1770 }
   1771 
   1772 
   1773 /**
   1774  * Copy @a in to @a out, expanding every occurrence of the ASCII token
   1775  * "%%NONCE%%" to the harvested nonce.
   1776  *
   1777  * @return number of bytes written to @a out
   1778  */
   1779 static size_t
   1780 expand_nonce (const uint8_t *in,
   1781               size_t in_len,
   1782               uint8_t *out,
   1783               size_t out_cap)
   1784 {
   1785   static const char tok[] = "%%NONCE%%";
   1786   const size_t tok_len = sizeof (tok) - 1;
   1787   size_t i = 0;
   1788   size_t o = 0;
   1789 
   1790   while (i < in_len)
   1791   {
   1792     if ( (i + tok_len <= in_len) &&
   1793          (0 == memcmp (in + i, tok, tok_len)) )
   1794     {
   1795       if (o + nonce_len > out_cap)
   1796         break;
   1797       memcpy (out + o, nonce_val, nonce_len);
   1798       o += nonce_len;
   1799       i += tok_len;
   1800       continue;
   1801     }
   1802     if (o >= out_cap)
   1803       break;
   1804     out[o++] = in[i++];
   1805   }
   1806   return o;
   1807 }
   1808 
   1809 
   1810 static void
   1811 send_all (struct MHD_Daemon *d,
   1812           int sock,
   1813           const uint8_t *data,
   1814           size_t len)
   1815 {
   1816   size_t off = 0;
   1817   unsigned int stall = 0;
   1818 
   1819   while ( (off < len) &&
   1820           (stall < 64) )
   1821   {
   1822     ssize_t s = send (sock, data + off, len - off, MSG_DONTWAIT);
   1823 
   1824     if (0 < s)
   1825     {
   1826       off += (size_t) s;
   1827       stall = 0;
   1828       continue;
   1829     }
   1830     stall++;
   1831     pump (d, sock, 2);
   1832     if ( (0 > s) &&
   1833          (EAGAIN != errno) &&
   1834          (EWOULDBLOCK != errno) &&
   1835          (EINTR != errno) )
   1836       break;
   1837   }
   1838 }
   1839 
   1840 
   1841 static int
   1842 new_connection (struct MHD_Daemon *d,
   1843                 int *sock)
   1844 {
   1845   int sv[2];
   1846   struct sockaddr_in sa;
   1847 
   1848   if (0 != socketpair (AF_UNIX, SOCK_STREAM, 0, sv))
   1849     return -1;
   1850   memset (&sa, 0, sizeof (sa));
   1851   sa.sin_family = AF_INET;
   1852   sa.sin_port = htons (44444);
   1853   sa.sin_addr.s_addr = htonl (INADDR_LOOPBACK);
   1854   if (MHD_YES != MHD_add_connection (d,
   1855                                      (MHD_socket) sv[1],
   1856                                      (const struct sockaddr *) &sa,
   1857                                      (socklen_t) sizeof (sa)))
   1858   {
   1859     /* MHD has already closed sv[1] in that case */
   1860     (void) close (sv[0]);
   1861     return -1;
   1862   }
   1863   *sock = sv[0];
   1864   return 0;
   1865 }
   1866 
   1867 
   1868 static void
   1869 close_connection (struct MHD_Daemon *d,
   1870                   int *sock)
   1871 {
   1872   if (0 > *sock)
   1873     return;
   1874   (void) shutdown (*sock, SHUT_WR);
   1875   pump (d, *sock, 4);
   1876   (void) close (*sock);
   1877   *sock = -1;
   1878 }
   1879 
   1880 
   1881 /* ------------------------------------------------------------------ */
   1882 /* The fuzz target                                                     */
   1883 /* ------------------------------------------------------------------ */
   1884 
   1885 int
   1886 LLVMFuzzerTestOneInput (const uint8_t *data,
   1887                         size_t size)
   1888 {
   1889   struct MHD_Daemon *d;
   1890   struct MHD_OptionItem opts[8];
   1891   unsigned int nopt = 0;
   1892   unsigned int flags;
   1893   int sock = -1;
   1894   size_t pos;
   1895   unsigned int nseg = 0;
   1896   unsigned int nconn = 1;
   1897   static uint8_t xbuf[FUZZ_MAX_INPUT + 4096];
   1898 
   1899   /* Must happen before the first write() into the socketpair.  The
   1900      built-in driver also does this from fuzz_install_handlers(), but
   1901      that is compiled out under -DFUZZ_NO_MAIN, which is exactly the
   1902      build every external fuzzing engine uses; the call is idempotent,
   1903      so doing it from both places is harmless.  See fuzz_ignore_sigpipe()
   1904      in fuzz_common.h for why the process dies without it. */
   1905   fuzz_ignore_sigpipe ();
   1906 
   1907   /* The ten configuration bytes are mandatory.  Anything shorter has
   1908      no segment stream either, so there is nothing to fuzz. */
   1909   if (size < 10)
   1910     return 0;
   1911 
   1912   nonce_len = 0;
   1913   nonce_val[0] = '\0';
   1914   resp_len = 0;
   1915   resp_buf[0] = '\0';
   1916 
   1917   memset (&cfg, 0, sizeof (cfg));
   1918   cfg.mem_limit =
   1919     mem_limit_tbl[data[0] % (sizeof (mem_limit_tbl)
   1920                              / sizeof (mem_limit_tbl[0]))];
   1921   cfg.do_digest = (0 != (data[1] & 0x01));
   1922   cfg.do_basic = (0 != (data[1] & 0x02));
   1923   cfg.do_postproc = (0 != (data[1] & 0x04));
   1924   cfg.do_iterate = (0 != (data[1] & 0x08));
   1925   /* Bits 0x10 and 0x80 of byte 1 are unused.  0x10 used to gate the
   1926      configuration bytes 4-9 back when they were optional; it is left
   1927      free rather than reassigned so that the meaning of the corpus
   1928      files written while it was a gate does not silently change. */
   1929   cfg.chunked_reply = (0 != (data[1] & 0x20));
   1930   cfg.error_reply = (0 != (data[1] & 0x40));
   1931   if (! min_mem_limit_read)
   1932   {
   1933     const char *e = getenv ("MHD_FUZZ_MIN_MEM_LIMIT");
   1934 
   1935     min_mem_limit_read = 1;
   1936     if (NULL != e)
   1937       min_mem_limit = (size_t) strtoul (e, NULL, 10);
   1938   }
   1939   if ( (0 != cfg.mem_limit) &&
   1940        (cfg.mem_limit < min_mem_limit) )
   1941     cfg.mem_limit = min_mem_limit;
   1942   if (! min_discipline_read)
   1943   {
   1944     const char *e = getenv ("MHD_FUZZ_MIN_DISCIPLINE");
   1945 
   1946     min_discipline_read = 1;
   1947     if (NULL != e)
   1948       min_discipline = atoi (e);
   1949   }
   1950   cfg.discipline =
   1951     discipline_tbl[(data[2] & 0x0F) % (sizeof (discipline_tbl)
   1952                                        / sizeof (discipline_tbl[0]))];
   1953   if (cfg.discipline < min_discipline)
   1954     cfg.discipline = min_discipline;
   1955   cfg.insanity = (unsigned int) MHD_DSC_SANE;
   1956   cfg.algo = algo_tbl[data[3] & 0x03];
   1957   cfg.qop = (0 != (data[3] & 0x04))
   1958             ? MHD_DIGEST_AUTH_MULT_QOP_AUTH
   1959             : MHD_DIGEST_AUTH_MULT_QOP_ANY_NON_INT;
   1960   cfg.nonce_nc_size = nnc_tbl[(data[3] >> 4) & 0x03];
   1961 
   1962   cfg.resp_kind = (unsigned int) (data[4] & 0x0F);
   1963   cfg.resp_nhdr = (unsigned int) ((data[4] >> 4) & 0x03);
   1964   cfg.resp_footer = (0 != (data[4] & 0x40));
   1965   cfg.resp_hdr_api = (0 != (data[4] & 0x80));
   1966 
   1967   cfg.dauth_variant = (unsigned int) (data[5] & 0x0F) % DAUTH_VARIANT_COUNT;
   1968   cfg.fail_variant = (unsigned int) ((data[5] >> 4) & 0x03);
   1969   cfg.basic_v1 = (0 != (data[5] & 0x40));
   1970   cfg.calc_helpers = (0 != (data[5] & 0x80));
   1971 
   1972   cfg.loop_mode = (unsigned int) (data[6] & 0x03);
   1973   cfg.use_timeouts = (0 != (data[6] & 0x04));
   1974   cfg.conn_lookup = (0 != (data[6] & 0x08));
   1975   cfg.conn_setvalue = (0 != (data[6] & 0x10));
   1976   cfg.conn_info = (0 != (data[6] & 0x20));
   1977   cfg.conn_option = (0 != (data[6] & 0x40));
   1978   cfg.quiesce = (0 != (data[6] & 0x80));
   1979 
   1980   /* Only modes 0-2 exist; 3 folds onto the immediate-resume mode
   1981      rather than being a fourth, unimplemented behaviour. */
   1982   cfg.suspend_mode = (unsigned int) (data[7] & 0x03);
   1983   if (3 == cfg.suspend_mode)
   1984     cfg.suspend_mode = 1;
   1985   cfg.allow_upgrade =
   1986     (0 != (data[7] & 0x04)) &&
   1987     (MHD_YES == MHD_is_feature_supported (MHD_FEATURE_UPGRADE));
   1988   cfg.upgrade_action = (unsigned int) ((data[7] >> 3) & 0x03);
   1989 
   1990   cfg.hdr_seed = data[8];
   1991   cfg.crc_seed = data[9];
   1992 
   1993   oracle_on = 0;
   1994   expect_body_len = 0;
   1995   /* Must never carry over: the connections these pointed at belonged to
   1996      the previous iteration's daemon and are long gone. */
   1997   memset (pending_resume, 0, sizeof (pending_resume));
   1998   tearing_down = 0;
   1999 
   2000   if (0 != cfg.mem_limit)
   2001   {
   2002     opts[nopt].option = MHD_OPTION_CONNECTION_MEMORY_LIMIT;
   2003     opts[nopt].value = (intptr_t) cfg.mem_limit;
   2004     opts[nopt].ptr_value = NULL;
   2005     nopt++;
   2006   }
   2007   opts[nopt].option = MHD_OPTION_CLIENT_DISCIPLINE_LVL;
   2008   opts[nopt].value = (intptr_t) cfg.discipline;
   2009   opts[nopt].ptr_value = NULL;
   2010   nopt++;
   2011   opts[nopt].option = MHD_OPTION_SERVER_INSANITY;
   2012   opts[nopt].value = (intptr_t) cfg.insanity;
   2013   opts[nopt].ptr_value = NULL;
   2014   nopt++;
   2015   opts[nopt].option = MHD_OPTION_NONCE_NC_SIZE;
   2016   opts[nopt].value = (intptr_t) cfg.nonce_nc_size;
   2017   opts[nopt].ptr_value = NULL;
   2018   nopt++;
   2019   opts[nopt].option = MHD_OPTION_DIGEST_AUTH_RANDOM;
   2020   opts[nopt].value = (intptr_t) sizeof (digest_rnd);
   2021   opts[nopt].ptr_value = (void *) (intptr_t) digest_rnd;
   2022   nopt++;
   2023   opts[nopt].option = MHD_OPTION_END;
   2024   opts[nopt].value = 0;
   2025   opts[nopt].ptr_value = NULL;
   2026 
   2027   flags = MHD_USE_NO_LISTEN_SOCKET;
   2028   if (fuzz_verbose)
   2029     flags |= MHD_USE_ERROR_LOG;
   2030   if (0 != cfg.suspend_mode)
   2031     flags |= MHD_ALLOW_SUSPEND_RESUME;
   2032   if (cfg.allow_upgrade)
   2033     flags |= MHD_ALLOW_UPGRADE;
   2034 
   2035   MHD_set_panic_func (&panic_cb, NULL);
   2036   d = MHD_start_daemon (flags,
   2037                         0,
   2038                         NULL, NULL,
   2039                         &ahc, NULL,
   2040                         MHD_OPTION_ARRAY, opts,
   2041                         /* passed through the varargs rather than through
   2042                            the option array: storing a function pointer in
   2043                            the array's intptr_t member is not strictly
   2044                            conforming C */
   2045                         MHD_OPTION_NOTIFY_COMPLETED, &completed_cb, NULL,
   2046                         MHD_OPTION_END);
   2047   if (NULL == d)
   2048     return 0;
   2049   cur_daemon = d;
   2050   stat_daemons++;
   2051   if (! stats_registered)
   2052   {
   2053     stats_registered = 1;
   2054     (void) atexit (&print_stats);
   2055   }
   2056 
   2057   if (0 != new_connection (d, &sock))
   2058   {
   2059     MHD_stop_daemon (d);
   2060     cur_daemon = NULL;
   2061     return 0;
   2062   }
   2063 
   2064   pos = 10u;
   2065   while ( (pos + 2 <= size) &&
   2066           (nseg < MAX_SEGMENTS) )
   2067   {
   2068     unsigned int hdr = (unsigned int) data[pos]
   2069                        | ((unsigned int) data[pos + 1] << 8);
   2070     unsigned int op = hdr >> 14;
   2071     size_t slen = (size_t) (hdr & 0x3FFF);
   2072     size_t elen;
   2073 
   2074     pos += 2;
   2075     nseg++;
   2076     if (slen > size - pos)
   2077       slen = size - pos;
   2078 
   2079     if (1 == op)
   2080     {
   2081       /* Ground-truth declaration, not wire data. */
   2082       if (fuzz_pristine && (slen <= MAX_EXPECT_BODY))
   2083       {
   2084         memcpy (expect_body, data + pos, slen);
   2085         expect_body_len = slen;
   2086         oracle_on = 1;
   2087       }
   2088       pos += slen;
   2089       continue;
   2090     }
   2091     if ( (3 == op) &&
   2092          (nconn < MAX_CONNECTIONS) )
   2093     {
   2094       close_connection (d, &sock);
   2095       if (0 != new_connection (d, &sock))
   2096         break;
   2097       nconn++;
   2098     }
   2099 
   2100     elen = expand_nonce (data + pos, slen, xbuf, sizeof (xbuf));
   2101     pos += slen;
   2102     if (0 != elen)
   2103       send_all (d, sock, xbuf, elen);
   2104     pump (d, sock, (2 == op) ? 12u : 3u);
   2105     if (0 == slen)
   2106       pump (d, sock, 4);
   2107   }
   2108 
   2109   close_connection (d, &sock);
   2110   pump (d, sock, 4);
   2111   /* A connection left suspended makes MHD_stop_daemon() MHD_PANIC()
   2112      ("called while we have suspended connections"), and
   2113      MHD_resume_connection() alone is not enough: it only raises a flag,
   2114      and the connection is taken off the daemon's suspended list by
   2115      MHD_run().  So flush and run until nothing is parked any more.
   2116      tearing_down stops the handler from parking anything new, which is
   2117      what bounds this loop; the cap is only a backstop. */
   2118   tearing_down = 1;
   2119   {
   2120     unsigned int i;
   2121 
   2122     for (i = 0; i < MAX_CONNECTIONS + 2u; i++)
   2123     {
   2124       if (! pending_resume_flush ())
   2125         break;
   2126       (void) MHD_run (d);
   2127     }
   2128   }
   2129   if (cfg.quiesce)
   2130     (void) MHD_quiesce_daemon (d);
   2131   MHD_stop_daemon (d);
   2132   cur_daemon = NULL;
   2133   return 0;
   2134 }
   2135 
   2136 
   2137 /* ------------------------------------------------------------------ */
   2138 /* Structure-aware HTTP request generator                              */
   2139 /* ------------------------------------------------------------------ */
   2140 
   2141 struct sbuf
   2142 {
   2143   uint8_t *p;
   2144   size_t len;
   2145   size_t cap;
   2146 };
   2147 
   2148 
   2149 static void
   2150 sb_raw (struct sbuf *b,
   2151         const void *v,
   2152         size_t n)
   2153 {
   2154   if (b->len + n > b->cap)
   2155     n = b->cap - b->len;
   2156   memcpy (b->p + b->len, v, n);
   2157   b->len += n;
   2158 }
   2159 
   2160 
   2161 static void
   2162 sb_str (struct sbuf *b,
   2163         const char *s)
   2164 {
   2165   sb_raw (b, s, strlen (s));
   2166 }
   2167 
   2168 
   2169 static void
   2170 sb_u64 (struct sbuf *b,
   2171         uint64_t v,
   2172         int hex,
   2173         unsigned int min_digits)
   2174 {
   2175   char tmp[32];
   2176   unsigned int n = 0;
   2177 
   2178   do
   2179   {
   2180     unsigned int dig = (unsigned int) (v % (hex ? 16u : 10u));
   2181     tmp[n++] = (char) ((dig < 10) ? ('0' + dig) : ('a' + dig - 10));
   2182     v /= (hex ? 16u : 10u);
   2183   }
   2184   while ( (0 != v) && (n < sizeof (tmp)) );
   2185   while ( (n < min_digits) && (n < sizeof (tmp)) )
   2186     tmp[n++] = '0';
   2187   while (0 != n)
   2188   {
   2189     char c = tmp[--n];
   2190     sb_raw (b, &c, 1);
   2191   }
   2192 }
   2193 
   2194 
   2195 static const char *const gen_methods[] = {
   2196   "GET", "POST", "PUT", "HEAD", "DELETE", "OPTIONS", "TRACE", "PATCH",
   2197   "CONNECT", "BREW", "get", "M-SEARCH", "\tGET", "GET "
   2198 };
   2199 
   2200 static const char *const gen_versions[] = {
   2201   "HTTP/1.1", "HTTP/1.0", "HTTP/1.1", "HTTP/1.1", "HTTP/0.9", "HTTP/1.2",
   2202   "HTTP/2.0", "http/1.1", "HTTP/1.", "HTTP/11"
   2203 };
   2204 
   2205 static const char *const gen_targets[] = {
   2206   "/", "/a", "/a/b/c", "/a?x=1", "/a?x=1&y=2", "/?novalue", "/?a=1&b",
   2207   "/?a&b&c", "/%41%42", "/a%00b", "/%zz", "/a?%41=%42", "*",
   2208   "http://example.org/a", "/a?x=1&novalue", "/..%2f..%2fetc",
   2209   "/a?=", "/a?&", "/very/long/path/that/keeps/going/and/going/and/going"
   2210 };
   2211 
   2212 static const char *const gen_hdr_names[] = {
   2213   "Host", "Accept", "User-Agent", "Connection", "Cookie", "Content-Type",
   2214   "Expect", "TE", "Trailer", "X-Custom", "Referer", "Accept-Encoding",
   2215   "content-length", "transfer-encoding", "X-A-Very-Long-Header-Name-Indeed"
   2216 };
   2217 
   2218 static const char *const gen_hdr_values[] = {
   2219   "example.org", "*/*", "fuzz/1.0", "keep-alive", "close",
   2220   "a=1; b=2; c", "100-continue", "trailers", "X-Trail", "value",
   2221   "", " ", "\ttabbed", "a, b, c", "chunked", "identity, chunked"
   2222 };
   2223 
   2224 /** Deliberately includes tokens MHD does not know: bug #1 lives here. */
   2225 static const char *const gen_algos[] = {
   2226   "MD5", "SHA-256", "SHA-512-256", "MD5-sess", "SHA-256-sess",
   2227   "SHA-512-256-sess", "sha-256", "SHA256", "BOGUS", "", "\"SHA-256\"",
   2228   "MD5 ", "SHA-1", "xyzzy", "SHA-512", "\"BOGUS\"", "0"
   2229 };
   2230 
   2231 static const char *const gen_ctypes[] = {
   2232   "application/x-www-form-urlencoded",
   2233   "multipart/form-data; boundary=--abc",
   2234   "multipart/form-data; boundary=\"XY\"",
   2235   "multipart/form-data",
   2236   "text/plain"
   2237 };
   2238 
   2239 
   2240 /**
   2241  * Append a random query string, optionally ending in an argument
   2242  * without '=' (which is the shape needed for the read-buffer shift-back
   2243  * bug).
   2244  */
   2245 static void
   2246 gen_query (struct fuzz_rng *rng,
   2247            struct sbuf *b,
   2248            int force_trailing_novalue)
   2249 {
   2250   unsigned int n = fuzz_below (rng, 4);
   2251   unsigned int i;
   2252 
   2253   if ( (0 == n) && (! force_trailing_novalue) )
   2254     return;
   2255   sb_str (b, "?");
   2256   for (i = 0; i < n; i++)
   2257   {
   2258     if (0 != i)
   2259       sb_str (b, "&");
   2260     sb_str (b, "k");
   2261     sb_u64 (b, i, 0, 1);
   2262     if (! fuzz_chance (rng, 3))
   2263     {
   2264       sb_str (b, "=");
   2265       sb_str (b, fuzz_chance (rng, 4) ? "%41%42" : "v");
   2266     }
   2267   }
   2268   if (force_trailing_novalue)
   2269   {
   2270     if (0 != n)
   2271       sb_str (b, "&");
   2272     sb_str (b, "novalue");
   2273   }
   2274 }
   2275 
   2276 
   2277 static void
   2278 gen_headers (struct fuzz_rng *rng,
   2279              struct sbuf *b,
   2280              unsigned int n)
   2281 {
   2282   unsigned int i;
   2283 
   2284   for (i = 0; i < n; i++)
   2285   {
   2286     sb_str (b, gen_hdr_names[fuzz_below (rng,
   2287                                          (uint32_t) (sizeof (gen_hdr_names)
   2288                                                      / sizeof (char *)))]);
   2289     sb_str (b, fuzz_chance (rng, 8) ? " :" : ":");
   2290     if (! fuzz_chance (rng, 6))
   2291       sb_str (b, " ");
   2292     sb_str (b, gen_hdr_values[fuzz_below (rng,
   2293                                           (uint32_t) (sizeof (gen_hdr_values)
   2294                                                       / sizeof (char *)))]);
   2295     if (fuzz_chance (rng, 12))
   2296       sb_str (b, "\r\n\tfolded-continuation");
   2297     if (fuzz_chance (rng, 20))
   2298       sb_str (b, "\n");     /* bare LF */
   2299     else if (fuzz_chance (rng, 25))
   2300       sb_str (b, "\r");     /* bare CR */
   2301     else
   2302       sb_str (b, "\r\n");
   2303   }
   2304 }
   2305 
   2306 
   2307 /**
   2308  * Emit a chunked body.  When @a oracle is non-zero the body is
   2309  * strictly RFC 9112 conformant and the decoded payload is recorded in
   2310  * #expect_body, so that the harness can verify what MHD hands to the
   2311  * application.  Chunk extensions are emitted frequently on purpose.
   2312  */
   2313 static void
   2314 gen_chunked_body (struct fuzz_rng *rng,
   2315                   struct sbuf *b,
   2316                   int oracle)
   2317 {
   2318   unsigned int nchunks = 1 + fuzz_below (rng, 4);
   2319   unsigned int i;
   2320 
   2321   if (oracle)
   2322     expect_body_len = 0;
   2323   for (i = 0; i < nchunks; i++)
   2324   {
   2325     unsigned int clen = 1 + fuzz_below (rng, 24);
   2326     unsigned int j;
   2327 
   2328     sb_u64 (b, clen, 1, fuzz_chance (rng, 4) ? 4 : 1);
   2329     /* chunk extension -- the parsing of the terminating CRLF of this
   2330        very line was broken (bug #3) */
   2331     if (! fuzz_chance (rng, 2))
   2332     {
   2333       switch (fuzz_below (rng, 5))
   2334       {
   2335       case 0:
   2336         sb_str (b, ";ext");
   2337         break;
   2338       case 1:
   2339         sb_str (b, ";ext=val");
   2340         break;
   2341       case 2:
   2342         sb_str (b, ";ext=\"quoted value\"");
   2343         break;
   2344       case 3:
   2345         sb_str (b, ";a=1;b=2;c");
   2346         break;
   2347       default:
   2348         sb_str (b, ";x=\"a;b\"");
   2349         break;
   2350       }
   2351     }
   2352     sb_str (b, "\r\n");
   2353     for (j = 0; j < clen; j++)
   2354     {
   2355       char c = (char) ('A' + ((i * 7 + j) % 26));
   2356 
   2357       sb_raw (b, &c, 1);
   2358       if (oracle && (expect_body_len < MAX_EXPECT_BODY))
   2359         expect_body[expect_body_len++] = (uint8_t) c;
   2360     }
   2361     sb_str (b, "\r\n");
   2362   }
   2363   sb_str (b, "0");
   2364   if (fuzz_chance (rng, 4))
   2365     sb_str (b, ";final=\"x\"");
   2366   sb_str (b, "\r\n");
   2367   if (fuzz_chance (rng, 3))
   2368     sb_str (b, "X-Trailer: value\r\n");
   2369   sb_str (b, "\r\n");
   2370 }
   2371 
   2372 
   2373 static void
   2374 gen_digest_header (struct fuzz_rng *rng,
   2375                    struct sbuf *b,
   2376                    const char *uri,
   2377                    int use_nonce_token,
   2378                    int overlong_response,
   2379                    int prefer_valid)
   2380 {
   2381   unsigned int nresp;
   2382   unsigned int i;
   2383 
   2384   sb_str (b, "Authorization: Digest ");
   2385   sb_str (b, "username=\"");
   2386   if (fuzz_chance (rng, prefer_valid ? 20 : 6))
   2387   {
   2388     /* userhash notation: a long hex string is accepted here too */
   2389     unsigned int n = 2 * (16 + fuzz_below (rng, 48));
   2390     for (i = 0; i < n; i++)
   2391       sb_str (b, "a");
   2392   }
   2393   else
   2394     sb_str (b, DIGEST_USER);
   2395   sb_str (b, "\", ");
   2396   if (fuzz_chance (rng, prefer_valid ? 25 : 8))
   2397     sb_str (b, "userhash=true, ");
   2398   sb_str (b, "realm=\"");
   2399   sb_str (b, fuzz_chance (rng, prefer_valid ? 25 : 8)
   2400           ? "OtherRealm" : DIGEST_REALM);
   2401   sb_str (b, "\", nonce=\"");
   2402   if (use_nonce_token)
   2403     sb_str (b, "%%NONCE%%");
   2404   else
   2405   {
   2406     unsigned int n = 8 + fuzz_below (rng, 80);
   2407     for (i = 0; i < n; i++)
   2408       sb_str (b, "0");
   2409   }
   2410   sb_str (b, "\", uri=\"");
   2411   sb_str (b, uri);
   2412   sb_str (b, "\", qop=");
   2413   sb_str (b, fuzz_chance (rng, prefer_valid ? 25 : 8) ? "auth-int" : "auth");
   2414   sb_str (b, ", nc=");
   2415   sb_u64 (b, 1 + fuzz_below (rng, 3), 1, 8);
   2416   sb_str (b, ", cnonce=\"deadbeef\", algorithm=");
   2417   if (prefer_valid && (! fuzz_chance (rng, 5)))
   2418     sb_str (b, "SHA-256");   /* must match the algorithm of the challenge */
   2419   else
   2420     sb_str (b, gen_algos[fuzz_below (rng,
   2421                                      (uint32_t) (sizeof (gen_algos)
   2422                                                  / sizeof (char *)))]);
   2423   sb_str (b, ", opaque=\"0123456789abcdef\", response=\"");
   2424   if (overlong_response)
   2425     nresp = 66 + 2 * fuzz_below (rng, 32);      /* 66 .. 128 hex digits */
   2426   else
   2427     nresp = 2 * (1 + fuzz_below (rng, 66));
   2428   for (i = 0; i < nresp; i++)
   2429   {
   2430     char c = "0123456789abcdef"[fuzz_below (rng, 16)];
   2431 
   2432     sb_raw (b, &c, 1);
   2433   }
   2434   sb_str (b, "\"\r\n");
   2435 }
   2436 
   2437 
   2438 enum gen_shape
   2439 {
   2440   SHAPE_PLAIN = 0,
   2441   SHAPE_NOHDR_QARG,
   2442   SHAPE_CL_BODY,
   2443   SHAPE_CHUNKED,
   2444   SHAPE_DIGEST_SIMPLE,
   2445   SHAPE_DIGEST_REPLAY,
   2446   SHAPE_BASIC,
   2447   SHAPE_POST_FORM,
   2448   SHAPE_WEIRD,
   2449   SHAPE_COUNT
   2450 };
   2451 
   2452 
   2453 /**
   2454  * Build one HTTP request into @a b.
   2455  *
   2456  * @return non-zero if the request is exactly reproducible, i.e. the
   2457  *         #expect_body oracle may be used
   2458  */
   2459 static int
   2460 gen_one_request (struct fuzz_rng *rng,
   2461                  struct sbuf *b,
   2462                  enum gen_shape shape,
   2463                  int second_of_pair)
   2464 {
   2465   switch (shape)
   2466   {
   2467   case SHAPE_NOHDR_QARG:
   2468     /* No header lines at all + a trailing query argument without '=';
   2469        combined with a small connection memory pool this is the shape
   2470        that reaches the read-buffer "shift back" computation. */
   2471     sb_str (b, "GET /");
   2472     gen_query (rng, b, 1);
   2473     sb_str (b, " ");
   2474     sb_str (b, fuzz_chance (rng, 2) ? "HTTP/1.0" : "HTTP/1.1");
   2475     sb_str (b, "\r\n\r\n");
   2476     return 0;
   2477 
   2478   case SHAPE_CL_BODY:
   2479     {
   2480       unsigned int blen = fuzz_below (rng, 64);
   2481       unsigned int i;
   2482 
   2483       sb_str (b, "POST /a HTTP/1.1\r\nHost: x\r\nContent-Length: ");
   2484       sb_u64 (b, blen, 0, 1);
   2485       sb_str (b, "\r\n\r\n");
   2486       expect_body_len = 0;
   2487       for (i = 0; i < blen; i++)
   2488       {
   2489         char c = (char) ('a' + (i % 26));
   2490 
   2491         sb_raw (b, &c, 1);
   2492         if (expect_body_len < MAX_EXPECT_BODY)
   2493           expect_body[expect_body_len++] = (uint8_t) c;
   2494       }
   2495       return 1;
   2496     }
   2497 
   2498   case SHAPE_CHUNKED:
   2499     sb_str (b, "POST /a HTTP/1.1\r\nHost: x\r\n"
   2500             "Transfer-Encoding: chunked\r\n\r\n");
   2501     gen_chunked_body (rng, b, 1);
   2502     return 1;
   2503 
   2504   case SHAPE_DIGEST_SIMPLE:
   2505     sb_str (b, "GET /a HTTP/1.1\r\nHost: x\r\n");
   2506     gen_digest_header (rng, b, "/a", 0, fuzz_chance (rng, 2), 0);
   2507     sb_str (b, "\r\n");
   2508     return 0;
   2509 
   2510   case SHAPE_DIGEST_REPLAY:
   2511     if (! second_of_pair)
   2512       sb_str (b, "GET /a HTTP/1.1\r\nHost: x\r\n\r\n");
   2513     else
   2514     {
   2515       sb_str (b, "GET /a HTTP/1.1\r\nHost: x\r\n");
   2516       gen_digest_header (rng, b, "/a", 1, 1, 1);
   2517       sb_str (b, "\r\n");
   2518     }
   2519     return 0;
   2520 
   2521   case SHAPE_BASIC:
   2522     sb_str (b, "GET /a HTTP/1.1\r\nHost: x\r\nAuthorization: Basic ");
   2523     {
   2524       unsigned int n = fuzz_below (rng, 40);
   2525       unsigned int i;
   2526 
   2527       for (i = 0; i < n; i++)
   2528       {
   2529         char c =
   2530           "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/="
   2531           [fuzz_below (rng, 65)];
   2532 
   2533         sb_raw (b, &c, 1);
   2534       }
   2535     }
   2536     sb_str (b, "\r\n\r\n");
   2537     return 0;
   2538 
   2539   case SHAPE_POST_FORM:
   2540     {
   2541       const char *ct = gen_ctypes[fuzz_below (rng,
   2542                                               (uint32_t) (sizeof (gen_ctypes)
   2543                                                           / sizeof (char *)))];
   2544 
   2545       sb_str (b, "POST /a HTTP/1.1\r\nHost: x\r\nContent-Type: ");
   2546       sb_str (b, ct);
   2547       sb_str (b, "\r\nTransfer-Encoding: chunked\r\n\r\n");
   2548       gen_chunked_body (rng, b, 0);
   2549       return 0;
   2550     }
   2551 
   2552   case SHAPE_WEIRD:
   2553     sb_str (b, gen_methods[fuzz_below (rng,
   2554                                        (uint32_t) (sizeof (gen_methods)
   2555                                                    / sizeof (char *)))]);
   2556     sb_str (b, " ");
   2557     sb_str (b, gen_targets[fuzz_below (rng,
   2558                                        (uint32_t) (sizeof (gen_targets)
   2559                                                    / sizeof (char *)))]);
   2560     sb_str (b, " ");
   2561     sb_str (b, gen_versions[fuzz_below (rng,
   2562                                         (uint32_t) (sizeof (gen_versions)
   2563                                                     / sizeof (char *)))]);
   2564     sb_str (b, fuzz_chance (rng, 8) ? "\n" : "\r\n");
   2565     gen_headers (rng, b, fuzz_below (rng, 6));
   2566     sb_str (b, "\r\n");
   2567     return 0;
   2568 
   2569   case SHAPE_PLAIN:
   2570   case SHAPE_COUNT:
   2571   default:
   2572     sb_str (b, gen_methods[fuzz_below (rng, 3)]);
   2573     sb_str (b, " /");
   2574     gen_query (rng, b, fuzz_chance (rng, 3));
   2575     sb_str (b, " HTTP/1.1\r\n");
   2576     gen_headers (rng, b, fuzz_below (rng, 4));
   2577     sb_str (b, "\r\n");
   2578     return 0;
   2579   }
   2580 }
   2581 
   2582 
   2583 /**
   2584  * Serialise @a body into the segment format understood by
   2585  * LLVMFuzzerTestOneInput(), starting at @a out[*out_len].
   2586  */
   2587 static void
   2588 emit_segments (struct fuzz_rng *rng,
   2589                struct sbuf *out,
   2590                const uint8_t *body,
   2591                size_t body_len,
   2592                int new_conn_first)
   2593 {
   2594   size_t off = 0;
   2595   int first = 1;
   2596 
   2597   while (off < body_len)
   2598   {
   2599     size_t chunk;
   2600     unsigned int op;
   2601     uint8_t hdr[2];
   2602     unsigned int hv;
   2603 
   2604     switch (fuzz_below (rng, 6))
   2605     {
   2606     case 0:
   2607       chunk = 1;
   2608       break;
   2609     case 1:
   2610       chunk = 2 + fuzz_below (rng, 6);
   2611       break;
   2612     case 2:
   2613       chunk = 8 + fuzz_below (rng, 40);
   2614       break;
   2615     default:
   2616       chunk = body_len - off;
   2617       break;
   2618     }
   2619     if (chunk > body_len - off)
   2620       chunk = body_len - off;
   2621     if (chunk > 0x3FFF)
   2622       chunk = 0x3FFF;
   2623     op = (first && new_conn_first) ? 3u : (fuzz_chance (rng, 4) ? 2u : 0u);
   2624     hv = (op << 14) | (unsigned int) chunk;
   2625     hdr[0] = (uint8_t) (hv & 0xFF);
   2626     hdr[1] = (uint8_t) (hv >> 8);
   2627     if (out->len + 2 + chunk > out->cap)
   2628       return;
   2629     sb_raw (out, hdr, 2);
   2630     sb_raw (out, body + off, chunk);
   2631     off += chunk;
   2632     first = 0;
   2633   }
   2634 }
   2635 
   2636 
   2637 static size_t
   2638 fuzz_generate (struct fuzz_rng *rng,
   2639                uint8_t *buf,
   2640                size_t cap)
   2641 {
   2642   struct sbuf out;
   2643   uint8_t req[GEN_BUF_SIZE];
   2644   struct sbuf rb;
   2645   enum gen_shape shape;
   2646   uint8_t cfg_bytes[4];
   2647   int oracle;
   2648   unsigned int nreq;
   2649   unsigned int i;
   2650 
   2651   expect_body_len = 0;
   2652 
   2653   out.p = buf;
   2654   out.len = 0;
   2655   out.cap = cap;
   2656 
   2657   if (! forced_shape_read)
   2658   {
   2659     const char *e = getenv ("MHD_FUZZ_SHAPE");
   2660 
   2661     forced_shape_read = 1;
   2662     if (NULL != e)
   2663       forced_shape = atoi (e);
   2664   }
   2665   if (0 <= forced_shape)
   2666     shape = (enum gen_shape) (forced_shape % (int) SHAPE_COUNT);
   2667   else
   2668     shape = (enum gen_shape) fuzz_below (rng, (uint32_t) SHAPE_COUNT);
   2669 
   2670   /* --- configuration bytes --- */
   2671   cfg_bytes[0] = fuzz_byte (rng);
   2672   cfg_bytes[1] = fuzz_byte (rng);
   2673   cfg_bytes[2] = fuzz_byte (rng);
   2674   cfg_bytes[3] = fuzz_byte (rng);
   2675   switch (shape)
   2676   {
   2677   case SHAPE_NOHDR_QARG:
   2678     /* small connection memory pool: indices 1..9 of mem_limit_tbl */
   2679     cfg_bytes[0] = (uint8_t) (1 + fuzz_below (rng, 9));
   2680     break;
   2681   case SHAPE_DIGEST_SIMPLE:
   2682   case SHAPE_DIGEST_REPLAY:
   2683     cfg_bytes[0] = (uint8_t) (fuzz_chance (rng, 2) ? 0 : 12);
   2684     cfg_bytes[1] = (uint8_t) ((cfg_bytes[1] | 0x01u) & ~0x04u);
   2685     /* SHA-256 challenge: 32 byte digest -> 128 hex chars pass the
   2686        'response' length check while hash1_bin[] is only 32 bytes */
   2687     cfg_bytes[3] = (uint8_t) ((cfg_bytes[3] & 0xF0u) | 0x00u);
   2688     break;
   2689   case SHAPE_POST_FORM:
   2690     cfg_bytes[1] |= 0x04u;
   2691     break;
   2692   case SHAPE_CHUNKED:
   2693   case SHAPE_CL_BODY:
   2694     cfg_bytes[1] &= (uint8_t) ~0x04u;   /* keep the body oracle clean */
   2695     break;
   2696   default:
   2697     break;
   2698   }
   2699   cfg_bytes[1] |= 0x08u;                /* always iterate the values */
   2700   sb_raw (&out, cfg_bytes, 4);
   2701 
   2702   nreq = (SHAPE_DIGEST_REPLAY == shape) ? 2u : (1u + (fuzz_chance (rng, 6)
   2703                                                       ? 1u : 0u));
   2704   oracle = 0;
   2705   for (i = 0; i < nreq; i++)
   2706   {
   2707     rb.p = req;
   2708     rb.len = 0;
   2709     rb.cap = sizeof (req);
   2710     oracle = gen_one_request (rng, &rb, shape, (int) i);
   2711     if (oracle && (1 == nreq) && (expect_body_len <= MAX_EXPECT_BODY))
   2712     {
   2713       /* Declare the ground truth for the body oracle (op 1). */
   2714       unsigned int hv = (1u << 14) | (unsigned int) expect_body_len;
   2715       uint8_t hdr[2];
   2716 
   2717       hdr[0] = (uint8_t) (hv & 0xFF);
   2718       hdr[1] = (uint8_t) (hv >> 8);
   2719       sb_raw (&out, hdr, 2);
   2720       sb_raw (&out, expect_body, expect_body_len);
   2721     }
   2722     emit_segments (rng, &out, req, rb.len,
   2723                    (0 != i) || fuzz_chance (rng, 8));
   2724   }
   2725   (void) oracle;
   2726   return out.len;
   2727 }
   2728 
   2729 
   2730 /* ------------------------------------------------------------------ */
   2731 /* Built-in seed corpus                                                */
   2732 /* ------------------------------------------------------------------ */
   2733 
   2734 /**
   2735  * The built-in seed corpus is described symbolically and rendered into
   2736  * the wire format at run time, so that segment lengths never have to be
   2737  * spelled out by hand.
   2738  */
   2739 struct seed_part
   2740 {
   2741   unsigned int op;              /**< 0 send, 1 expected body, 3 new conn */
   2742   const char *txt;              /**< NUL terminated payload */
   2743 };
   2744 
   2745 struct seed_def
   2746 {
   2747   const char *name;
   2748   unsigned char cfg[4];
   2749   struct seed_part parts[4];
   2750   /* Configuration bytes 4-9.  Declared after @e parts so that a seed
   2751      which only cares about the wire data can leave the member out of
   2752      its brace initialiser and get the all-zero (plainest) setting. */
   2753   unsigned char ext[6];
   2754 };
   2755 
   2756 #define P_END { 0, NULL }
   2757 
   2758 static const struct seed_def seeds[] = {
   2759   /* There is deliberately no bare "GET / HTTP/1.1" seed: every seed
   2760      below opens with a request at least as simple, so a plain one adds
   2761      no coverage of its own (libFuzzer -merge=1 drops it). */
   2762   { "content-length-body", { 0x00, 0x08, 0x03, 0x00 },
   2763     { { 1, "hello" },
   2764       { 0, "POST /a HTTP/1.1\r\nHost: x\r\nContent-Length: 5\r\n\r\nhello" },
   2765       P_END, P_END } },
   2766 
   2767   /* chunk extensions: the terminating CRLF of the chunk-size line used
   2768      to be left in the stream (bug #3, commit c13f4c64) */
   2769   { "chunked-with-extensions", { 0x00, 0x08, 0x03, 0x00 },
   2770     { { 1, "ABCDE" },
   2771       { 0, "POST /a HTTP/1.1\r\nHost: x\r\nTransfer-Encoding: chunked\r\n"
   2772         "\r\n2;ext=val\r\nAB\r\n3;a=\"b;c\"\r\nCDE\r\n0\r\n\r\n" },
   2773       P_END, P_END } },
   2774 
   2775   { "chunked-split", { 0x00, 0x08, 0x03, 0x00 },
   2776     { { 1, "ABCDEF" },
   2777       { 0, "POST /a HTTP/1.1\r\nHost: x\r\nTransfer-Encoding: chunked\r\n"
   2778         "\r\n3\r\nABC\r\n3;x=\"y\"" },
   2779       { 2, "\r\nDEF\r\n0\r\n\r\n" },
   2780       P_END } },
   2781 
   2782   /* small connection memory pool + trailing query argument without '='
   2783      and no header lines at all (bug #2, commit 29eaa56b) */
   2784   { "small-pool-trailing-query-arg", { 0x06, 0x08, 0x03, 0x00 },
   2785     { { 0, "GET /?novalue HTTP/1.0\r\n\r\n" }, P_END, P_END, P_END } },
   2786 
   2787   { "small-pool-trailing-query-arg-2", { 0x03, 0x08, 0x03, 0x00 },
   2788     { { 0, "GET /?a=1&b HTTP/1.0\r\n\r\n" }, P_END, P_END, P_END } },
   2789 
   2790   /* unrecognised 'algorithm' token -> MHD_DIGEST_AUTH_ALGO3_INVALID
   2791      (bug #1, commit bd49ce93) */
   2792   { "digest-unknown-algorithm", { 0x00, 0x09, 0x03, 0x00 },
   2793     { { 0, "GET /a HTTP/1.1\r\nHost: x\r\nAuthorization: Digest "
   2794         "username=\"user\", realm=\"TestRealm\", nonce=\"0000\", "
   2795         "uri=\"/a\", algorithm=BOGUS, response=\"00\"\r\n\r\n" },
   2796       P_END, P_END, P_END } },
   2797 
   2798   /* full digest handshake: harvest the nonce from the 401 and replay it
   2799      with a 128 hex digit 'response' value (bug #4, commit 5a73c1ae) */
   2800   { "digest-overlong-response", { 0x00, 0x09, 0x03, 0x00 },
   2801     { { 0, "GET /a HTTP/1.1\r\nHost: x\r\n\r\n" },
   2802       { 3, "GET /a HTTP/1.1\r\nHost: x\r\nAuthorization: Digest "
   2803         "username=\"user\", realm=\"TestRealm\", nonce=\"%%NONCE%%\", "
   2804         "uri=\"/a\", qop=auth, nc=00000001, cnonce=\"deadbeef\", "
   2805         "algorithm=SHA-256, response=\""
   2806         "0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef"
   2807         "0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef"
   2808         "\"\r\n\r\n" },
   2809       P_END, P_END } },
   2810 
   2811   { "digest-userhash", { 0x00, 0x09, 0x03, 0x00 },
   2812     { { 0, "GET /a HTTP/1.1\r\nHost: x\r\n\r\n" },
   2813       { 3, "GET /a HTTP/1.1\r\nHost: x\r\nAuthorization: Digest "
   2814         "username=\""
   2815         "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
   2816         "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
   2817         "\", userhash=true, realm=\"TestRealm\", nonce=\"%%NONCE%%\", "
   2818         "uri=\"/a\", qop=auth, nc=00000001, cnonce=\"deadbeef\", "
   2819         "algorithm=SHA-256, response=\"0123456789abcdef\"\r\n\r\n" },
   2820       P_END, P_END } },
   2821 
   2822   { "basic-auth", { 0x00, 0x0a, 0x03, 0x00 },
   2823     { { 0, "GET /a HTTP/1.1\r\nHost: x\r\n"
   2824         "Authorization: Basic dXNlcjpwYXNz\r\n\r\n" },
   2825       P_END, P_END, P_END } },
   2826 
   2827   { "multipart-post", { 0x00, 0x0c, 0x03, 0x00 },
   2828     { { 0, "POST /a HTTP/1.1\r\nHost: x\r\n"
   2829         "Content-Type: multipart/form-data; boundary=--abc\r\n"
   2830         "Transfer-Encoding: chunked\r\n\r\n"
   2831         "52\r\n----abc\r\nContent-Disposition: form-data; name=\"k\"\r\n\r\n"
   2832         "value\r\n----abc--\r\n\r\n0\r\n\r\n" },
   2833       P_END, P_END, P_END } },
   2834 
   2835   { "urlencoded-post", { 0x00, 0x0c, 0x03, 0x00 },
   2836     { { 1, "a=1&b=%41&c" },
   2837       { 0, "POST /a HTTP/1.1\r\nHost: x\r\n"
   2838         "Content-Type: application/x-www-form-urlencoded\r\n"
   2839         "Content-Length: 11\r\n\r\na=1&b=%41&c" },
   2840       P_END, P_END } },
   2841 
   2842   { "folded-header", { 0x00, 0x08, 0x00, 0x00 },
   2843     { { 0, "GET /a HTTP/1.1\r\nHost: x\r\nX-Fold: a\r\n\tb\r\n\r\n" },
   2844       P_END, P_END, P_END } },
   2845 
   2846   { "pipelined", { 0x00, 0x08, 0x03, 0x00 },
   2847     { { 0, "GET /a HTTP/1.1\r\nHost: x\r\n\r\n"
   2848         "GET /b?q HTTP/1.1\r\nHost: x\r\n\r\n" },
   2849       P_END, P_END, P_END } },
   2850 
   2851   /* ------------- seeds driving configuration bytes 4-9 -------------
   2852      The seeds above leave those bytes zero and only exercise the
   2853      parser.  Without at least one seed per area below, the rest of the
   2854      API stays practically unreachable: libFuzzer would have to guess
   2855      six configuration bytes before anything new runs.  Each seed turns
   2856      on exactly one area so that a minimiser keeps them distinguishable.
   2857      ext[] is { response, auth, event-loop/introspection, suspend and
   2858      upgrade, header seed, content-reader seed }. */
   2859 
   2860   /* Chunked reply produced by a content-reader callback, with response
   2861      headers and a trailer -- the reply-side counterpart of the chunk
   2862      parsing that commit c13f4c64 fixed on the request side. */
   2863   { "ext-callback-chunked", { 0x00, 0x08, 0x03, 0x00 },
   2864     { { 0, "GET / HTTP/1.1\r\nHost: x\r\n\r\n" }, P_END, P_END, P_END },
   2865     { 0x0A | 0x20 | 0x40, 0x00, 0x00, 0x00, 0x01, 0x20 } },
   2866 
   2867   /* Known-length callback body, with a reader error injected part way
   2868      through (crc_seed bit 0x80). */
   2869   { "ext-callback-error", { 0x00, 0x08, 0x03, 0x00 },
   2870     { { 0, "GET / HTTP/1.1\r\nHost: x\r\n\r\n" }, P_END, P_END, P_END },
   2871     { 0x09, 0x00, 0x00, 0x00, 0x02, 0x82 } },
   2872 
   2873   { "ext-fd-response", { 0x00, 0x08, 0x03, 0x00 },
   2874     { { 0, "GET / HTTP/1.1\r\nHost: x\r\n\r\n" }, P_END, P_END, P_END },
   2875     { 0x0B, 0x00, 0x00, 0x00, 0x00, 0x10 } },
   2876 
   2877   { "ext-fd-at-offset-response", { 0x00, 0x08, 0x03, 0x00 },
   2878     { { 0, "GET / HTTP/1.1\r\nHost: x\r\n\r\n" }, P_END, P_END, P_END },
   2879     { 0x0C, 0x00, 0x00, 0x00, 0x00, 0x10 } },
   2880 
   2881   { "ext-pipe-response", { 0x00, 0x08, 0x03, 0x00 },
   2882     { { 0, "GET / HTTP/1.1\r\nHost: x\r\n\r\n" }, P_END, P_END, P_END },
   2883     { 0x0E, 0x00, 0x00, 0x00, 0x00, 0x10 } },
   2884 
   2885   { "ext-iovec-response", { 0x00, 0x08, 0x03, 0x00 },
   2886     { { 0, "GET / HTTP/1.1\r\nHost: x\r\n\r\n" }, P_END, P_END, P_END },
   2887     { 0x0F, 0x00, 0x00, 0x00, 0x00, 0x07 } },
   2888 
   2889   /* Empty response plus the header manipulation API (get/del/options). */
   2890   { "ext-empty-response-hdrapi", { 0x00, 0x08, 0x03, 0x00 },
   2891     { { 0, "GET / HTTP/1.1\r\nHost: x\r\n\r\n" }, P_END, P_END, P_END },
   2892     { 0x02 | 0x30 | 0x40 | 0x80, 0x00, 0x00, 0x00, 0x05, 0x00 } },
   2893 
   2894   /* Digest through the pre-computed-userdigest entry point. */
   2895   { "ext-digest-check-digest3", { 0x00, 0x09, 0x03, 0x00 },
   2896     { { 0, "GET / HTTP/1.1\r\nHost: x\r\n\r\n" },
   2897       { 0, "GET / HTTP/1.1\r\nHost: x\r\nAuthorization: Digest "
   2898         "username=\"user\", realm=\"TestRealm\", nonce=\"%%NONCE%%\", "
   2899         "uri=\"/\", response=\"00000000000000000000000000000000\"\r\n\r\n" },
   2900       P_END, P_END },
   2901     { 0x00, 0x05 | 0x80, 0x00, 0x00, 0x01, 0x00 } },
   2902 
   2903   /* The v1 wrappers and the request-info query. */
   2904   { "ext-digest-v1-wrappers", { 0x00, 0x09, 0x03, 0x00 },
   2905     { { 0, "GET / HTTP/1.1\r\nHost: x\r\n\r\n" }, P_END, P_END, P_END },
   2906     { 0x00, 0x01 | 0x10, 0x00, 0x00, 0x00, 0x00 } },
   2907 
   2908   { "ext-digest-request-info", { 0x00, 0x09, 0x03, 0x00 },
   2909     { { 0, "GET / HTTP/1.1\r\nHost: x\r\n\r\n" }, P_END, P_END, P_END },
   2910     { 0x00, 0x08 | 0x20, 0x00, 0x00, 0x03, 0x00 } },
   2911 
   2912   /* Application-driven event loop: MHD_get_fdset2() + select() +
   2913      MHD_run_from_select2(), with the timeout accessors. */
   2914   { "ext-external-event-loop", { 0x00, 0x08, 0x03, 0x00 },
   2915     { { 0, "GET / HTTP/1.1\r\nHost: x\r\n\r\n" }, P_END, P_END, P_END },
   2916     { 0x01, 0x00, 0x02 | 0x04, 0x00, 0x00, 0x00 } },
   2917 
   2918   /* The v1 fdset/run_from_select pair. */
   2919   { "ext-external-event-loop-v1", { 0x00, 0x08, 0x03, 0x00 },
   2920     { { 0, "GET / HTTP/1.1\r\nHost: x\r\n\r\n" }, P_END, P_END, P_END },
   2921     { 0x01, 0x00, 0x01 | 0x04, 0x00, 0x00, 0x00 } },
   2922 
   2923   /* Every connection-introspection accessor at once. */
   2924   { "ext-connection-api", { 0x00, 0x08, 0x03, 0x00 },
   2925     { { 0, "GET /path?a=1 HTTP/1.1\r\nHost: x\r\nCookie: a=b\r\n\r\n" },
   2926       P_END, P_END, P_END },
   2927     { 0x01, 0x00, 0x08 | 0x10 | 0x20 | 0x40 | 0x80, 0x00, 0x10, 0x00 } },
   2928 
   2929   /* Suspend the connection and resume it from the pump loop. */
   2930   { "ext-suspend-resume", { 0x00, 0x08, 0x03, 0x00 },
   2931     { { 0, "GET / HTTP/1.1\r\nHost: x\r\n\r\n" },
   2932       { 2, "" }, P_END, P_END },
   2933     { 0x01, 0x00, 0x00, 0x02, 0x00, 0x00 } },
   2934 
   2935   /* Two connections parked at the same time (op 3 opens the second
   2936      without waiting for the first).  The bookkeeping behind suspend
   2937      mode 2 has to be a set for this: while it was a single slot the
   2938      first connection was forgotten and stayed suspended, and
   2939      MHD_stop_daemon() answered with
   2940      MHD_PANIC ("called while we have suspended connections"). */
   2941   { "ext-suspend-two-connections", { 0x00, 0x08, 0x03, 0x00 },
   2942     { { 0, "GET /a HTTP/1.1\r\nHost: x\r\n\r\n" },
   2943       { 3, "GET /b HTTP/1.1\r\nHost: x\r\n\r\n" },
   2944       { 2, "" }, P_END },
   2945     { 0x01, 0x00, 0x00, 0x02, 0x00, 0x00 } },
   2946 
   2947   /* HTTP "Upgrade": the client asks for it and the handler answers 101
   2948      with an upgrade response, after which the socket is handed over. */
   2949   { "ext-upgrade", { 0x00, 0x08, 0x03, 0x00 },
   2950     { { 0, "GET / HTTP/1.1\r\nHost: x\r\nConnection: Upgrade\r\n"
   2951         "Upgrade: fuzz-protocol\r\n\r\n" },
   2952       { 2, "" }, P_END, P_END },
   2953     { 0x01, 0x00, 0x00, 0x04 | 0x08, 0x00, 0x00 } },
   2954 
   2955   /* The remaining response constructors.  One seed each, because the
   2956      constructor is picked by the low nibble of ext[0] and a seed that
   2957      does not name it leaves that entry point unreachable until the
   2958      fuzzer happens to mutate the nibble. */
   2959   { "ext-buffer-persistent", { 0x00, 0x08, 0x03, 0x00 },
   2960     { { 0, "GET / HTTP/1.1\r\nHost: x\r\n\r\n" }, P_END, P_END, P_END },
   2961     { 0x03, 0x00, 0x00, 0x00, 0x00, 0x00 } },
   2962 
   2963   { "ext-buffer-free-callback", { 0x00, 0x08, 0x03, 0x00 },
   2964     { { 0, "GET / HTTP/1.1\r\nHost: x\r\n\r\n" }, P_END, P_END, P_END },
   2965     { 0x06, 0x00, 0x00, 0x00, 0x00, 0x00 } },
   2966 
   2967   { "ext-from-data", { 0x00, 0x08, 0x03, 0x00 },
   2968     { { 0, "GET / HTTP/1.1\r\nHost: x\r\n\r\n" }, P_END, P_END, P_END },
   2969     { 0x07, 0x00, 0x00, 0x00, 0x00, 0x00 } },
   2970 
   2971   { "ext-fd64-response", { 0x00, 0x08, 0x03, 0x00 },
   2972     { { 0, "GET / HTTP/1.1\r\nHost: x\r\n\r\n" }, P_END, P_END, P_END },
   2973     { 0x0D, 0x00, 0x00, 0x00, 0x00, 0x00 } },
   2974 
   2975   /* The v1 basic-auth getter, which returns two separate malloc()ed
   2976      strings rather than one struct. */
   2977   { "ext-basic-auth-v1", { 0x00, 0x0a, 0x03, 0x00 },
   2978     { { 0, "GET / HTTP/1.1\r\nHost: x\r\n"
   2979         "Authorization: Basic dXNlcjpwYXNz\r\n\r\n" },
   2980       P_END, P_END, P_END },
   2981     { 0x01, 0x40, 0x00, 0x00, 0x00, 0x00 } },
   2982 
   2983   /* Answer the challenge with the basic-auth responses instead of the
   2984      digest ones (fail_variant 3). */
   2985   { "ext-basic-auth-challenge", { 0x00, 0x09, 0x03, 0x00 },
   2986     { { 0, "GET / HTTP/1.1\r\nHost: x\r\n\r\n" }, P_END, P_END, P_END },
   2987     { 0x01, 0x30, 0x00, 0x00, 0x00, 0x00 } },
   2988 
   2989   { "ext-basic-auth-challenge-utf8", { 0x00, 0x09, 0x03, 0x00 },
   2990     { { 0, "GET / HTTP/1.1\r\nHost: x\r\n\r\n" }, P_END, P_END, P_END },
   2991     { 0x01, 0x30, 0x00, 0x00, 0x03, 0x00 } },
   2992 
   2993   /* The MD5-only and algorithm-parametrised pre-computed digest
   2994      wrappers. */
   2995   { "ext-digest-check-digest-v1", { 0x00, 0x09, 0x03, 0x00 },
   2996     { { 0, "GET / HTTP/1.1\r\nHost: x\r\n\r\n" }, P_END, P_END, P_END },
   2997     { 0x01, 0x03, 0x00, 0x00, 0x00, 0x00 } },
   2998 
   2999   { "ext-digest-check-digest2", { 0x00, 0x09, 0x03, 0x00 },
   3000     { { 0, "GET / HTTP/1.1\r\nHost: x\r\n\r\n" }, P_END, P_END, P_END },
   3001     { 0x01, 0x04, 0x00, 0x00, 0x01, 0x00 } },
   3002 
   3003   /* The username queries. */
   3004   { "ext-digest-get-username-v1", { 0x00, 0x09, 0x03, 0x00 },
   3005     { { 0, "GET / HTTP/1.1\r\nHost: x\r\n"
   3006         "Authorization: Digest username=\"user\", realm=\"TestRealm\"\r\n\r\n" }
   3007       ,
   3008       P_END, P_END, P_END },
   3009     { 0x01, 0x06, 0x00, 0x00, 0x00, 0x00 } },
   3010 
   3011   { "ext-digest-get-username3", { 0x00, 0x09, 0x03, 0x00 },
   3012     { { 0, "GET / HTTP/1.1\r\nHost: x\r\n"
   3013         "Authorization: Digest userhash=true, username=\"aabb\", "
   3014         "realm=\"TestRealm\"\r\n\r\n" },
   3015       P_END, P_END, P_END },
   3016     { 0x01, 0x07, 0x00, 0x00, 0x00, 0x00 } }
   3017 };
   3018 
   3019 static uint8_t seed_render_buf[4096];
   3020 
   3021 
   3022 static size_t
   3023 fuzz_seed_count (void)
   3024 {
   3025   return sizeof (seeds) / sizeof (seeds[0]);
   3026 }
   3027 
   3028 
   3029 static const uint8_t *
   3030 fuzz_seed_get (size_t idx,
   3031                size_t *len)
   3032 {
   3033   const struct seed_def *sd = &seeds[idx];
   3034   struct sbuf b;
   3035   unsigned int i;
   3036 
   3037   b.p = seed_render_buf;
   3038   b.len = 0;
   3039   b.cap = sizeof (seed_render_buf);
   3040   sb_raw (&b, sd->cfg, 4);
   3041   sb_raw (&b, sd->ext, sizeof (sd->ext));
   3042   for (i = 0; i < sizeof (sd->parts) / sizeof (sd->parts[0]); i++)
   3043   {
   3044     size_t n;
   3045     unsigned int hv;
   3046     uint8_t hdr[2];
   3047 
   3048     if (NULL == sd->parts[i].txt)
   3049       break;
   3050     n = strlen (sd->parts[i].txt);
   3051     if (n > 0x3FFF)
   3052       n = 0x3FFF;
   3053     hv = (sd->parts[i].op << 14) | (unsigned int) n;
   3054     hdr[0] = (uint8_t) (hv & 0xFF);
   3055     hdr[1] = (uint8_t) (hv >> 8);
   3056     sb_raw (&b, hdr, 2);
   3057     sb_raw (&b, sd->parts[i].txt, n);
   3058   }
   3059   *len = b.len;
   3060   return seed_render_buf;
   3061 }