cybersecurity · intermediate · ~15 min · safe pentest lab

Bounds-Safe HTTP Request-Line Parser

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.

Challenge

The attack surface

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.

Your task

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.

Edge cases to reject

  • A NULL line, or a cap of 0 (no room even for the terminator).
  • A missing second space (no version field), an empty method, or an empty path (e.g. two spaces in a row).
  • A method or path longer than its buffer allows: deny, do not truncate silently.

Example

Given the fixed line req:

parse_request_line(req, method, mcap, path, pcap) -> 0   // method="GET", path="/index.html"

Input format

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.

Output format

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.

Constraints

line is raw HTTP request line; method and path receive tokens with bounds.

Starter code

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;
}

Common mistakes

Buffer overrun when path or method exceeds capacity.

Edge cases to handle

Missing second space, path exceeding capacity, empty method.

Background lessons

Solve this exercise in the browser editor — compile and run against the test harness, no setup required.