/* fuzz_lite — dependency-free mutational fuzzer. Seeds from the fixture corpus, * applies random mutations, and feeds both parsers. Run under -fsanitize= * address,undefined so any out-of-bounds / UB aborts. Not a replacement for * libFuzzer coverage-guidance, but it exercises the hostile-input paths hard. * * usage: fuzz_lite [seedfile ...] */ #include "naut/bencode.h" #include "naut/metainfo.h" #include #include #include static void run_one(int meta, const uint8_t *p, size_t n) { if (meta) { naut_metainfo mi; if (naut_metainfo_parse(p, n, &mi) == NAUT_OK) naut_metainfo_free(&mi); } else { naut_bc_doc *d = NULL; if (naut_bc_parse(p, n, &d) == NAUT_OK) { (void)naut_bc_dict_get(naut_bc_root(d), "info"); naut_bc_free(d); } } } int main(int argc, char **argv) { if (argc < 3) { fprintf(stderr, "usage: %s [seed..]\n", argv[0]); return 2; } int meta = strcmp(argv[1], "metainfo") == 0; long iters = atol(argv[2]); /* load seeds */ uint8_t *seed[16]; size_t seedlen[16]; int nseed = 0; for (int i = 3; i < argc && nseed < 16; i++) { FILE *f = fopen(argv[i], "rb"); if (!f) continue; fseek(f, 0, SEEK_END); long sz = ftell(f); fseek(f, 0, SEEK_SET); seed[nseed] = malloc(sz ? sz : 1); if (fread(seed[nseed], 1, sz, f) == (size_t)sz) { seedlen[nseed] = sz; nseed++; } fclose(f); } srand(1234); size_t cap = 1 << 20; uint8_t *buf = malloc(cap); for (long it = 0; it < iters; it++) { size_t n; if (nseed && (rand() & 3)) { /* mutate a seed */ int s = rand() % nseed; n = seedlen[s]; if (n > cap) n = cap; memcpy(buf, seed[s], n); int muts = 1 + rand() % 16; for (int m = 0; m < muts && n; m++) { int op = rand() % 3; if (op == 0) buf[rand() % n] ^= (uint8_t)(1 << (rand() & 7)); /* bit flip */ else if (op == 1) buf[rand() % n] = (uint8_t)rand(); /* byte set */ else n = rand() % (n + 1); /* truncate */ } } else { /* pure random */ n = rand() % 4096; for (size_t i = 0; i < n; i++) buf[i] = (uint8_t)rand(); } run_one(meta, buf, n); } printf("fuzz_lite %s: %ld iterations clean\n", argv[1], iters); free(buf); for (int i = 0; i < nseed; i++) free(seed[i]); return 0; }