Skip to content

Measure unconsumed HTTP line bytes at the buffer boundary - #2

Merged
casselc merged 2 commits into
mainfrom
fix/oversize-boundary-oracle
Sep 6, 2026
Merged

casselc merged 2 commits into
mainfrom
fix/oversize-boundary-oracle

Conversation

@casselc

@casselc casselc commented Sep 6, 2026

Copy link
Copy Markdown
Owner

Measure unconsumed HTTP line bytes at the buffer boundary

Summary

Accept a complete request line or header field whose wire representation,
including CRLF, exactly fills the configured read buffer. Continue to reject an
incomplete line that fills the buffer with 414 or 431.

The parser currently checks buf/limit, which describes the size of the whole
read view rather than the bytes the current parser state has not consumed. When
an exactly-full line is parsed, its terminating CRLF advances the position to
the limit and the parser enters its next state with zero remaining bytes. That
next state sees the historical full limit and incorrectly reports 431.

Both line-size predicates now check buf/remaining:

  • a parsed exact-capacity line leaves zero unconsumed bytes and may advance;
  • a partial field after already-consumed fields can be compacted and continued;
  • an incomplete line at position zero that fills the view still has
    remaining == capacity and is rejected immediately.

Boundary contract

With :read-buffer-size 1024:

  • a request line of wire length 1024 is accepted;
  • a request line of wire length 1025 is rejected with 414;
  • a header line of wire length 1024 is accepted; and
  • a header line of wire length 1025 is rejected with 431.

The deterministic controls construct those exact wire lengths. Accepted
HTTP/1.1 controls request Connection: close, so their client helper does not
mistake a valid persistent connection for a stalled response.

The Hegel property now classifies the selected request or header line rather
than the total multi-line request. It generates both URI and header cases across
the boundary, records both line and total request lengths, and keeps the +1
negative controls non-vacuous.

Red to green evidence

Published base: casselc/jolt-http@dcb3016fd2af289ce2cea23db6dc4b90d22c3f10

Test-only commit: ccb79365a5804cff388e6e2805e2c447327f9e12

On stock Jolt/Jolt-HTTP before the two predicate changes, the full suite exits
1 with exactly the two expected boundary failures:

== oversized request ==
FAIL request line at read-buffer capacity is accepted
   expected: 200
   actual:   431
ok   request line one byte over read-buffer capacity -> 414
FAIL header line at read-buffer capacity is accepted
   expected: 200
   actual:   431
ok   header line one byte over read-buffer capacity -> 431
ok   long uri -> 414
ok   long header -> 431

342 checks, 2 failures

Fix commit: ece1d5ef0709712295b64fc8fcf57c85c7438184

== oversized request ==
ok   request line at read-buffer capacity is accepted
ok   request line one byte over read-buffer capacity -> 414
ok   header line at read-buffer capacity is accepted
ok   header line one byte over read-buffer capacity -> 431
ok   long uri -> 414
ok   long header -> 431

342 checks, 0 failures

The eight real-loopback Hegel properties also pass, including 25 generated
line-boundary cases.

Transport control

An earlier timing-dependent experiment suggested that an exactly-full line
might stall at the jolt-tcp boundary. A coordinated stock-TCP control disproved
that hypothesis: after the handler consumes a full view, read interest is
re-armed and an already-queued next byte is delivered. The apparent HTTP stall
was instead the accepted-case helper waiting for EOF on a keep-alive response.
No transport change is needed by this patch.

Validation

  • published base: dcb3016fd2af289ce2cea23db6dc4b90d22c3f10
  • branch tip: ece1d5ef0709712295b64fc8fcf57c85c7438184
  • Jolt v0.8.1 / Chez Scheme 10.4.1: jolt -M:test — PASS,
    342 checks, 0 failures
  • Jolt v0.8.2 / Chez Scheme 10.4.1 focused boundary gate — PASS,
    6 checks, 0 failures
  • exact test-only stock witness — 342 checks, exactly 2 expected failures

Provenance

The oracle failure, production companion, corrected transport hypothesis, and
stock red/green evidence are tracked in
chucklehead-dev/jolt-aspect-packs#97.
The rejected transport hypothesis and its deterministic control are recorded in
chucklehead-dev/jolt-aspect-packs#98.
Those issues are provenance only; the tests and fix run on the stock published
libraries without aspect instrumentation.

Scope

The production change replaces buf/limit with buf/remaining in the request
line and header-field incomplete-input guards. The rest of the branch is
deterministic acceptance and Hegel oracle coverage. It changes no buffer size,
aggregate-header limit, TCP readiness behavior, or public API.

@casselc
casselc merged commit 1478bef into main Sep 6, 2026
4 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant