2 Commits
Author SHA1 Message Date
Jens GeyerandClaude Opus 5 da18006b9e THRIFT-6193: Hold the HTTP message body to the configured maximum message size
Client: cpp

The declared content length, and the number of chunks in a chunked body, are
numbers the peer chooses, and neither was measured against anything.
readContent() writes straight into readBuffer_, so the body does not pass
through the line buffer whose growth is already bounded, and
remainingMessageSize_ is never decremented anywhere in this transport -- the
checkReadBytesAvailable() in read() therefore only ever caps a single caller
request, and the allowance it checks against never depletes.

Measured against the unmodified library, with maxMessageSize at 100 MB: a
request declaring 4294967295 and then sending 200 MB left 205 MB resident, the
declared number itself costing nothing because nothing is allocated up front.
A chunked body has no declared total at all and simply runs until the peer
stops.

readContent() now charges what it is about to read against maxMessageSize and
refuses the message once it would exceed it, with the total reset by
readHeaders() so that each message on a keep-alive connection gets its own
allowance.

Four tests. Two fail against the unmodified library, and both count the bytes
the peer was asked for rather than asking whether something threw: an
over-declared length runs the stream out and throws either way, so "did it
throw" would have passed against the defect. 262188 bytes served against a
65536 maximum for the declared case, 262708 for the chunked one. The other two
are regression guards -- a body inside the maximum still arrives, and a second
request on the same connection still gets a full allowance.

The chunked test builds its chunk sizes through an ostringstream, and a stream
follows whatever global locale is in force, so 4096 came out as "1.000" and
stopped being a chunk size. It imbues the classic locale, which is what
TToString.h does and for the same reason. The case that left a grouping locale
set for the rest of the binary is fixed separately under THRIFT-6194; the
imbue here stays as the local guarantee.

lib/cpp/README.md gains a third paragraph under Breaking Changes 0.25.0: a
deployment exchanging bodies larger than the configured maximum has to raise it.

Stacked on THRIFT-6192, which shares the file and the README section.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-05 23:50:57 +02:00
Jens GeyerandClaude Opus 5 421283a438 Bound the growth of the HTTP line buffer
Client: cpp

THttpTransport keeps the line it is reading in httpBuf_ and doubles
httpBufSize_ whenever a line does not fit. Nothing bounded the doubling, so
a peer that never sends a CRLF decided how large the buffer became, and once
httpBufSize_ reached 2 GiB the next doubling wrapped the uint32_t.

Hold the growth to TConfiguration::maxMessageSize, never below the buffer the
transport starts with so a small limit cannot make an ordinary request line
unreadable.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-03 00:13:44 +02:00