Skip to content

blackbull.fault_injection.catalogue.h1_client

blackbull.fault_injection.catalogue.h1_client

Named HTTP/1.1 client-side misbehaviour cases.

The last of the grid's four catalogues. Cells B, C and D shipped named sets (9, 4 and 11 cases); this cell had none — it was reachable only through the atheris and Hypothesis harnesses, which generate inputs rather than name them. That is a real difference in kind: a generated input tells you that something broke, a named case tells you which known mistake you are testing against, and only the second can be cited in a bug report or parametrized over by a downstream user.

Every case is raw bytes, because on this side the fault is the bytes. A typed SendRequest step would be built from the same encoder the production client uses, and could not emit a fault that encoder has — the same reasoning that keeps the two fault servers off the production send path.

The cases are drawn from RFC 9112's framing rules and the request- smuggling literature, so the names line up with what a reader is likely to be defending against.

absent_host()

No Host header. RFC 9112 §3.2 makes this a 400.

bare_lf_terminators()

Bare LF instead of CRLF (RFC 9112 §2.2 makes recognising it a MAY).

Implementations legitimately differ, which is exactly why it belongs in a catalogue: the case is here to make the difference visible, not to assert one answer.

body_shorter_than_declared()

Declares 100 bytes of body and sends 5, then stops.

chunk_size_not_hex()

A chunk size that is not hexadecimal (RFC 9112 §7.1).

content_length_and_transfer_encoding()

Both framing headers at once — RFC 9112 §6.1 says reject.

The classic CL.TE / TE.CL desync: whichever one the recipient honours determines where it thinks the body ends.

duplicate_transfer_encoding()

Two Transfer-Encoding headers, the second not chunked.

head_never_ends()

Headers that never reach the terminating CRLFCRLF.

negative_content_length()

Content-Length: -1 — not a valid length.

nul_in_header_value()

A NUL byte in a field value — not a valid field-vchar.

obs_fold_header()

An obs-fold continuation line (RFC 9112 §5.2 deprecates it).

oversized_method_token()

A 2 KiB method token — a head-budget case, not a parse case.

space_before_header_colon()

Foo : bar — RFC 9112 §5.1 requires rejecting, not trimming.

Trimming is the defect: a proxy that trims and an origin that rejects see different header sets.

trickled_head()

The request head one byte at a time — the slowloris primitive.

Nothing here is malformed; the fault is the rate, which is why the server's answer comes from its header deadline rather than its parser.

two_content_lengths()

Two Content-Length headers that disagree (RFC 9112 §6.3).

The smuggling primitive: a recipient that picks one and a recipient that picks the other disagree about where the next request starts.