cybersecurity · intermediate · ~15 min · safe pentest lab
Validate the length of every attacker-controlled field against its destination capacity BEFORE copying, and deny-by-default on any malformed or oversized input, so that parsing hostile HTTP request lines can never overflow a fixed buffer.
Every HTTP server begins by parsing the request line — the very first line a client sends, of the form METHOD SP PATH SP VERSION (for example GET /index.html HTTP/1.1). This string is fully attacker-controlled: an attacker on the network chooses its length, its delimiters, and its contents. A parser that trusts the input — copying the method or path into a fixed buffer without checking whether it fits — is the classic source of stack buffer overflows and, from there, remote code execution.
In this lab the harness owns two fixed destination buffers of caps mcap and pcap. Your job is to split the request line into its method and path fields without ever writing past those caps, NUL-terminating each field. This is a pure string operation over an in-harness buffer — there is no network, no socket, and no live target.
Implement:
int parse_request_line(const char *line, char *method, size_t mcap, char *path, size_t pcap);
Parse line as exactly three space-separated fields. Copy the first field into method (NUL-terminated, at most mcap bytes including the NUL) and the second field into path (at most pcap bytes including the NUL). Return 0 on success. Return -1 — writing nothing — if the line is malformed or if either field would not fit.
NULL line, or a cap of 0 (no room even for the terminator).Given the fixed line req:
parse_request_line(req, method, mcap, path, pcap) -> 0 // method="GET", path="/index.html"
line: a C string holding an HTTP request line, or NULL. method: caller-owned buffer of capacity mcap bytes. path: caller-owned buffer of capacity pcap bytes. mcap, pcap: size_t capacities that include space for the NUL terminator.
Returns int 0 on success, having written a NUL-terminated method (<= mcap bytes total) and path (<= pcap bytes total). Returns -1 on any malformed input or any field that would not fit, writing nothing to the buffers.
C11, freestanding logic (harness supplies all includes). No dynamic allocation, no I/O, no global state. A field 'fits' only if its length plus one NUL byte is <= its cap. Treat exactly one ASCII space (0x20) as the field delimiter; the line must contain a non-empty method, a non-empty path, and a non-empty version separated by single spaces. Never read or write outside the provided buffers.
int parse_request_line(const char *line, char *method, size_t mcap,
char *path, size_t pcap) {
/* TODO: bounds-safely split "METHOD SP PATH SP VERSION".
Validate each field's length against its cap BEFORE copying,
and return -1 (writing nothing) on any malformed or oversized input.
This stub accepts nothing yet, so well-formed lines fail. */
(void)line; (void)method; (void)mcap; (void)path; (void)pcap;
return -1;
}
Using strcpy/strcat or an unchecked loop that copies until the delimiter, overflowing the buffer; checking the length AFTER copying instead of before; using > cap instead of > cap - 1 and clobbering the byte reserved for the NUL; forgetting to reject mcap==0 or pcap==0 and writing a NUL to a zero-length buffer; truncating an oversized field and returning 0 instead of rejecting it; forgetting to require the version field so 'GET /x' is wrongly accepted; dereferencing a NULL line before checking it.
NULL line pointer; mcap or pcap equal to 0 (no room for a terminator); a line with no space at all; a line with only one space (missing version field); an empty method (leading space); an empty path (two consecutive spaces); an empty version (trailing space with nothing after it); a method or path exactly one byte too long for its cap; a method or path that fits exactly (length == cap - 1).
Solve this exercise in the browser editor — compile and run against the test harness, no setup required.