44#ifndef MHD_FUZZ_COMMON_H
45#define MHD_FUZZ_COMMON_H 1
60#ifndef FUZZ_HARNESS_NAME
61#define FUZZ_HARNESS_NAME "fuzz"
67#define FUZZ_UNUSED __attribute__ ((unused))
73#define FUZZ_MAX_INPUT 32768
81#ifndef FUZZ_DEFAULT_ITERATIONS
82#define FUZZ_DEFAULT_ITERATIONS 3000
88#ifndef FUZZ_DEFAULT_TIMEOUT
89#define FUZZ_DEFAULT_TIMEOUT 20
148 *x += UINT64_C (0x9E3779B97F4A7C15);
150 z = (z ^ (z >> 30)) * UINT64_C (0xBF58476D1CE4E5B9);
151 z = (z ^ (z >> 27)) * UINT64_C (0x94D049BB133111EB);
152 return z ^ (z >> 31);
163 for (i = 0; i < 4; i++)
172 return (x << k) | (x >> (64 - k));
183 const uint64_t res =
fuzz_rot64 (r->
s[1] * 5, 7) * 9;
184 const uint64_t t = r->
s[1] << 17;
274 const char *p = (
const char *) buf;
278 ssize_t w = write (
fd, p, len);
311 O_WRONLY | O_CREAT | O_TRUNC,
315 fuzz_msg (
"\n*** FUZZ: failed to write crash file ***\n");
320 fuzz_msg (
"\n*** FUZZ: reproducer written to ");
341 fuzz_msg (
"*** FUZZ: HANG detected (watchdog fired) ***\n");
346 signal (sig, SIG_DFL);
358 size_t l = strlen (what);
401 static int sigpipe_ignored;
406 (void) signal (SIGPIPE, SIG_IGN);
419 memset (&sa, 0,
sizeof (sa));
421 sigemptyset (&sa.sa_mask);
423 (void) sigaction (SIGABRT, &sa,
NULL);
424 (void) sigaction (SIGSEGV, &sa,
NULL);
425 (void) sigaction (SIGBUS, &sa,
NULL);
426 (void) sigaction (SIGILL, &sa,
NULL);
427 (void) sigaction (SIGFPE, &sa,
NULL);
428 (void) sigaction (SIGALRM, &sa,
NULL);
447 "%s/crash-%s-seed%llu-iter%llu.bin",
454 "harness=%s seed=%llu iteration=%llu source=%s",
467 0x00, 0x01, 0x07, 0x09, 0x0A, 0x0D, 0x20, 0x22, 0x25, 0x26, 0x27,
468 0x2C, 0x2D, 0x2E, 0x2F, 0x30, 0x31, 0x3A, 0x3B, 0x3D, 0x3F, 0x40,
469 0x5C, 0x7B, 0x7D, 0x7F, 0x80, 0xC0, 0xFE, 0xFF
473 "\r\n",
"\r\n\r\n",
"\n",
"%",
"%%NONCE%%",
";",
"=",
"\"",
"\\",
474 "chunked",
"Transfer-Encoding: ",
"Content-Length: ",
"algorithm=",
475 "userhash=true",
"Authorization: Digest ",
"Authorization: Basic ",
476 "boundary=",
"multipart/form-data",
"0\r\n\r\n",
"?",
"&",
509 buf[p] = (uint8_t) (buf[p] ^ (1u <<
fuzz_below (rng, 8)));
523 buf[p] = (uint8_t) (buf[p] + (
int)
fuzz_below (rng, 17) - 8);
529 size_t n = 1 +
fuzz_below (rng, (uint32_t) (len - p));
530 memmove (buf + p, buf + p + n, len - p - n);
536 size_t p =
fuzz_below (rng, (uint32_t) len + 1);
543 memmove (buf + p + n, buf + p, len - p);
544 memset (buf + p, v, n);
551 size_t n = 1 +
fuzz_below (rng, (uint32_t) (len - p));
552 size_t d =
fuzz_below (rng, (uint32_t) len + 1);
557 memmove (buf + d + n, buf + d, len - d);
558 memmove (buf + d, buf + ((p >= d) ? (p + n) : p), n);
569 size_t n = strlen (s);
570 size_t p =
fuzz_below (rng, (uint32_t) len + 1);
573 memmove (buf + p + n, buf + p, len - p);
574 memcpy (buf + p, s, n);
606 f = fopen (path,
"rb");
610 "%s: cannot open '%s': %s\n",
641 unsigned int cnt = 0;
647 "%s: cannot open corpus dir '%s': %s\n",
653 while (
NULL != (de = readdir (d)))
657 if (
'.' == de->d_name[0])
659 (void) snprintf (path,
sizeof (path),
"%s/%s", dir, de->d_name);
660 if ( (0 != stat (path, &sb)) ||
661 (! S_ISREG (sb.st_mode)) )
667 printf (
"%s: replayed %u corpus file(s) from %s\n",
677 "Usage: %s [OPTIONS] [FILE...]\n"
679 "In-process fuzzing harness '%s' for GNU libmicrohttpd.\n"
681 " --iterations=N number of generate/mutate iterations (default %d)\n"
682 " --seed=N PRNG seed; runs are fully reproducible (default 1)\n"
683 " --corpus-dir=DIR replay every regular file in DIR and exit\n"
684 " --file=PATH replay a single input and exit (crash reproduction)\n"
685 " --crash-dir=DIR where to write reproducers (default 'crashes')\n"
686 " --timeout=SEC per-iteration watchdog (default %d, 0 disables)\n"
687 " --write-corpus=DIR write the built-in seed corpus to DIR and exit\n"
688 " --skip-seeds do not replay the built-in seed corpus first\n"
689 " --verbose enable MHD's error log inside the harness\n"
690 " --help this text\n"
692 "Environment: MHD_FUZZ_ITERATIONS, MHD_FUZZ_SEED, MHD_FUZZ_TIMEOUT,\n"
693 " MHD_FUZZ_CRASH_DIR, MHD_FUZZ_VERBOSE\n"
695 "Bare FILE arguments are equivalent to --file=FILE (libFuzzer-style).\n",
707 if ( (0 != mkdir (dir, 0755)) &&
710 fprintf (stderr,
"%s: mkdir '%s': %s\n",
714 for (i = 0; i < n; i++)
721 (void) snprintf (path,
sizeof (path),
"%s/%s-%02u.bin",
723 f = fopen (path,
"wb");
726 fprintf (stderr,
"%s: fopen '%s': %s\n",
730 if (len != fwrite (s, 1, len, f))
737 printf (
"%s: wrote %u seed(s) to %s\n",
744main (
int argc,
char *
const *argv)
749 const char *corpus_dir =
NULL;
750 const char *single_file =
NULL;
751 const char *write_corpus =
NULL;
759 e = getenv (
"MHD_FUZZ_ITERATIONS");
761 iterations = strtoull (e,
NULL, 10);
762 e = getenv (
"MHD_FUZZ_SEED");
764 seed = strtoull (e,
NULL, 10);
765 e = getenv (
"MHD_FUZZ_TIMEOUT");
767 timeout = (
unsigned int) strtoul (e,
NULL, 10);
768 e = getenv (
"MHD_FUZZ_CRASH_DIR");
771 e = getenv (
"MHD_FUZZ_VERBOSE");
774 e = getenv (
"MHD_FUZZ_SKIP_SEEDS");
778 for (j = 1; j < argc; j++)
780 const char *a = argv[j];
782 if (0 == strncmp (a,
"--iterations=", 13))
783 iterations = strtoull (a + 13,
NULL, 10);
784 else if (0 == strncmp (a,
"--seed=", 7))
785 seed = strtoull (a + 7,
NULL, 10);
786 else if (0 == strncmp (a,
"--corpus-dir=", 13))
788 else if (0 == strncmp (a,
"--file=", 7))
790 else if (0 == strncmp (a,
"--crash-dir=", 12))
792 else if (0 == strncmp (a,
"--timeout=", 10))
793 timeout = (
unsigned int) strtoul (a + 10,
NULL, 10);
794 else if (0 == strncmp (a,
"--write-corpus=", 15))
795 write_corpus = a + 15;
796 else if (0 == strcmp (a,
"--skip-seeds"))
798 else if (0 == strcmp (a,
"--verbose"))
800 else if ( (0 == strcmp (a,
"--help")) ||
801 (0 == strcmp (a,
"-h")) )
806 else if (
'-' == a[0])
819 if (
NULL != write_corpus)
822 if (
NULL != single_file)
829 if (
NULL != corpus_dir)
836 printf (
"%s: seed=%llu iterations=%llu\n",
838 (
unsigned long long) seed,
839 (
unsigned long long) iterations);
842 for (i = 0; i < iterations; i++)
860 tag =
"builtin-seed";
879 tag =
"generated+mutated";
900 tag =
"seed+mutated";
904 for (k = 0; k < nmut; k++)
916 printf (
"%s: %llu iterations completed, no findings\n",
918 (
unsigned long long) iterations);
static const char * fuzz_crash_dir
static FUZZ_UNUSED int fuzz_pristine
static FUZZ_UNUSED void fuzz_dump_current(void)
static FUZZ_UNUSED uint64_t fuzz_splitmix64(uint64_t *x)
static size_t fuzz_cur_input_len
void __sanitizer_set_death_callback(void(*cb)(void)) __attribute__((weak))
static FUZZ_UNUSED void fuzz_rng_seed(struct fuzz_rng *r, uint64_t seed)
static FUZZ_UNUSED void fuzz_death_callback(void)
static void fuzz_set_current(const uint8_t *data, size_t size, const char *tag)
static int fuzz_write_corpus(const char *dir)
static FUZZ_UNUSED const uint8_t * fuzz_seed_get(size_t idx, size_t *len)
#define FUZZ_DEFAULT_TIMEOUT
#define FUZZ_HARNESS_NAME
static FUZZ_UNUSED void fuzz_ignore_sigpipe(void)
static FUZZ_UNUSED int fuzz_verbose
static size_t fuzz_mutate_once(struct fuzz_rng *rng, uint8_t *buf, size_t len, size_t cap)
static FUZZ_UNUSED uint64_t fuzz_next(struct fuzz_rng *r)
static void fuzz_usage(const char *argv0)
static FUZZ_UNUSED uint64_t fuzz_cur_iter
static FUZZ_UNUSED void fuzz_sig_handler(int sig)
static FUZZ_UNUSED uint32_t fuzz_below(struct fuzz_rng *r, uint32_t n)
static FUZZ_UNUSED int fuzz_skip_seeds
static const uint8_t * fuzz_cur_input
int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size)
static FUZZ_UNUSED void fuzz_msg(const char *s)
#define FUZZ_DEFAULT_ITERATIONS
static const char *const fuzz_interesting_str[]
static FUZZ_UNUSED size_t fuzz_seed_count(void)
static volatile sig_atomic_t fuzz_dumped
static char fuzz_crash_path[512]
static int fuzz_run_file(const char *path)
static FUZZ_UNUSED uint64_t fuzz_rot64(uint64_t x, unsigned int k)
static const uint8_t fuzz_interesting[]
static FUZZ_UNUSED uint8_t fuzz_byte(struct fuzz_rng *r)
static FUZZ_UNUSED size_t fuzz_generate(struct fuzz_rng *rng, uint8_t *buf, size_t cap)
int main(int argc, char *const *argv)
static FUZZ_UNUSED void fuzz_write_all(int fd, const void *buf, size_t len)
static FUZZ_UNUSED void fuzz_report_finding(const char *what)
static FUZZ_UNUSED int fuzz_chance(struct fuzz_rng *r, uint32_t n)
static char fuzz_crash_msg[512]
static void fuzz_install_handlers(void)
static int fuzz_run_corpus_dir(const char *dir)
static FUZZ_UNUSED uint64_t fuzz_cur_seed