cybersecurity · intermediate · ~25 min

Unfold an HTTP/1.1 continuation header

Careful protocol parsing with strict line discipline.

Challenge

Implement int unfold_header(const char *input, char *out, size_t cap) that takes a possibly-folded header line group and unfolds it into a single line.

Input format:

  • Lines are separated by \r\n.
  • The first line is the primary header (e.g. X-Foo: bar).
  • Subsequent lines that begin with a space or tab are continuation lines — concatenate them onto the primary line, replacing the \r\n + leading whitespace with a single space.

The function:

  • Stops at the first non-continuation line OR end of input.
  • Writes the unfolded result to out, NUL-terminated, capped at cap-1.
  • Returns the number of input lines consumed (>= 1), or 0 on failure (insufficient cap, empty input).

Examples

"X-Foo: bar\r\n other\r\n"
   -> consumes 2 lines, out = "X-Foo: bar other"

"Content-Type: text/html\r\nHost: x\r\n"
   -> consumes 1 line, out = "Content-Type: text/html"

"X-Long: one\r\n\ttwo\r\n  three\r\nNext: 1\r\n"
   -> consumes 3 lines, out = "X-Long: one two three"

Why this matters

A bug where the proxy joins the lines differently from the back-end is a request-smuggling primitive: the proxy sees one request, the back-end sees two.

Why this matters

HTTP/1.1 'header folding' lets a header value span multiple lines using a continuation line that begins with whitespace. RFC 7230 has since deprecated this — but parsers still encounter it, and mishandling it is a known request-smuggling vector. Writing a careful unfold helps you understand why proxies are so paranoid.

Input format

Buffer with CRLF-separated lines.

Output format

Unfolded single line + line count consumed.

Constraints

Cap-aware. No allocations.

Starter code

#include <stddef.h>
int unfold_header(const char *input, char *out, size_t cap) { /* TODO */ return 0; }

Common mistakes

Joining lines with \r\n left in. Treating LF without preceding CR as end of line — strict HTTP wants CRLF only. Forgetting the leading-WS rule for continuations.

Edge cases to handle

Header with no continuation; empty input; continuation lines with only whitespace; cap too small.

Complexity

O(strlen(input)).

Background lessons

Up next

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