cybersecurity · beginner · ~10 min
Fuzz-harness contract: allocate, NUL-terminate, call, free.
Write the body shared by every libFuzzer harness for a string parser: take the fuzzer's raw bytes, turn them into a NUL-terminated C string, hand them to the parser, and clean up.
Implement int call_under_test_with_buffer(const unsigned char *data, int size, int (*parser)(const char *)) that:
data == NULL, parser == NULL, or size <= 0;size + 1 bytes, copies size bytes from data, and NUL-terminates;parser on the copy;data, size: the fuzzer's input bytes and length (the grader passes fixed inputs).parser: the callback to invoke on the NUL-terminated copy.Always returns 0. The observable effect is that parser is called on a valid C string copy of data (and never called on degenerate input).
data {'a','b','c'}, size 3 -> parser receives "abc" (length 3), returns 0
data NULL, size 3 -> parser not called, returns 0
data {'a','b','c'}, size 0 -> parser not called, returns 0
parser NULL -> nothing called, returns 0
size == 0, NULL data, or NULL parser: skip without calling parser.size + 1 so the NUL terminator fits.The libFuzzer entry-point signature is muscle memory. Write it once; reuse forever.
A byte buffer data with length size, and a parser callback.
Always 0; parser is called on a NUL-terminated copy unless input is degenerate.
Skip on NULL/zero input; allocate size+1; always NUL-terminate and free.
#include <stddef.h>
int call_under_test_with_buffer(const unsigned char *data, int size, int (*parser)(const char *)) { /* TODO */ (void)data; (void)size; (void)parser; return 0; }
Forgetting +1 for NUL. Leaking on the early-return path.
size == 0. NULL data. NULL parser.
O(size).
Solve this exercise in the browser editor — compile and run against the test harness, no setup required.