romele / git-trace public
62 commits · 1 branch · 1 tag · 1 contributor (top: Romele) · first commit 3d ago · last push 12m ago
tests/fuzzdrv.c
/* * fuzzdrv — unit-level fuzz driver for git-trace's untrusted-input * parsers. Reads a blob (argv[1] or stdin) and feeds it to every * target. Build with -fsanitize=address,undefined and link against * ASan-instrumented project objects (see tests/fuzz.sh). * * Exit 0 on clean run; the sanitizers abort on any memory error. */ #include "util.h" #include "highlight.h" #include "webhook.h" #include "auth.h" #include "wcommit.h" #include <stdio.h> #include <stdlib.h> #include <string.h> static unsigned char *slurp(const char *path, size_t *out) { FILE *f = path ? fopen(path, "rb") : stdin; if (!f) return NULL; size_t cap = 65536, n = 0; unsigned char *b = malloc(cap + 1); if (!b) { fclose(f); return NULL; } size_t r; while ((r = fread(b + n, 1, cap - n, f)) > 0) { n += r; if (n == cap) break; /* 64 KiB is plenty */ } b[n] = '\0'; /* some targets want C strings */ fclose(f); *out = n; return b; } int main(int argc, char **argv) { size_t n = 0; unsigned char *blob = slurp(argc > 1 ? argv[1] : NULL, &n); if (!blob) return 2; /* form_get: treat the blob as a urlencoded body */ { char out[256]; form_get((const char *)blob, n, "csrf", out, sizeof out); form_get((const char *)blob, n, "", out, sizeof out); } /* url_decode */ { char *d = url_decode((const char *)blob, n); free(d); } /* gt_glob: first half is the pattern, second the subject */ { size_t h = n / 2; char pat[512], subj[512]; size_t pl = h > sizeof pat - 1 ? sizeof pat - 1 : h; size_t sl = (n - h) > sizeof subj - 1 ? sizeof subj - 1 : n - h; memcpy(pat, blob, pl); pat[pl] = '\0'; memcpy(subj, blob + h, sl); subj[sl] = '\0'; gt_glob(pat, subj); gt_glob(subj, pat); } /* hl_emit as C and as script */ { struct buf b; buf_init(&b); hl_emit(&b, (const char *)blob, n, "x.c"); buf_free(&b); buf_init(&b); hl_emit(&b, (const char *)blob, n, "x.sh"); buf_free(&b); } /* json_put_esc + buf_put_escaped + buf_put_urlenc */ { struct buf b; buf_init(&b); json_put_esc(&b, (const char *)blob, n); buf_free(&b); buf_init(&b); buf_put_escaped(&b, (const char *)blob, n); buf_put_urlenc(&b, (const char *)blob, 0); buf_put_urlenc(&b, (const char *)blob, 1); buf_free(&b); } /* multipart parser: first blob line is the boundary, the rest is * the body; also fuzz with the whole blob as the boundary */ { char *nl = memchr(blob, '\n', n); if (nl && nl != (char *)blob) { char bnd[240]; size_t bl = (size_t)(nl - (char *)blob); if (bl > sizeof bnd - 1) bl = sizeof bnd - 1; memcpy(bnd, blob, bl); bnd[bl] = '\0'; const char *d; size_t dl; char fn[256]; wc_mp_find((char *)blob, n, bnd, "file", &d, &dl, fn, sizeof fn); wc_mp_find((char *)blob, n, bnd, "csrf", &d, &dl, NULL, 0); wc_mp_find((char *)blob, n, bnd, "", &d, &dl, NULL, 0); wc_mp_find((char *)blob, n, (char *)blob, "x", &d, &dl, NULL, 0); } } /* basename + cdisp attr on the raw blob */ { char fn[256], hv[128]; wc_basename((const char *)blob, fn, sizeof fn); wc_mp_attr((const char *)blob, "name", hv, sizeof hv); wc_mp_attr((const char *)blob, (const char *)blob, hv, sizeof hv); } free(blob); return 0; }