Jens Geyer created THRIFT-6161:
----------------------------------
Summary: Haxe TStreamTransport does not charge reads against
MaxMessageSize
Key: THRIFT-6161
URL: https://issues.apache.org/jira/browse/THRIFT-6161
Project: Thrift
Issue Type: Bug
Components: Haxe - Library
Reporter: Jens Geyer
Fix For: 0.25.0
h3. Problem
{{TStreamTransport}} does not charge reads against the message budget, so
MaxMessageSize has
no effect on a stream-backed connection however much a message reads, as long
as no single
read exceeds the limit on its own. Its {{flush()}} does not restore the
allowance either.
h3. Why this is a defect in Haxe specifically
There is no single convention across the bindings — there are three, and every
other binding
keeps to one of them:
* *cpp, c_glib* — no endpoint charges reads (only the zlib transport does);
reads are bounded by frame binding and the per-read check alone.
* *java, netstd* — stream and socket endpoints do not charge; endpoints that
know the message boundary do ({{THttpClient}} / {{THttpTransport}}, named
pipes, a memory buffer holding one message).
* *delphi* — every endpoint charges.
Haxe is the only binding that departs from its own convention. It has four
endpoint transports:
{{TSocket}} charges (three sites), {{THttpClient}} charges,
{{TFullDuplexHttpClient}} charges,
and {{TStreamTransport}} charges nothing. The binding's design intends
endpoints to charge, and
this one silently opts out.
{{doc/specs/thrift-tconfiguration.md}} describes MaxMessageSize as "a general
device to be used
with any transport or protocol", expressed as the bytes *remaining* to be read
— which only
means something if reads draw it down.
h3. Fix
Two coordinated changes, mirroring {{TSocket}}:
* {{read()}} charges what it read.
* {{flush()}} resets the allowance, at the same point {{TSocket}} does.
Both are needed. Charging without resetting would leave the budget only ever
shrinking, so a
long-lived connection would run itself out of it — which is THRIFT-6160, fixed
just before this.
h3. Tests
Two, in {{StreamTest}}, failing before and passing after. The first reads past
the limit 32 bytes
at a time, so nothing but cumulative accounting can catch it; the second checks
the allowance comes
back. Verified on neko (full suite, including the existing stream, constants
and recursion-limit
tests, all of which read through {{TStreamTransport}}); the python and php
targets cross-compile
clean.
_Drafted with AI assistance (Claude Opus 5); reviewed and filed by Jens Geyer._
--
This message was sent by Atlassian Jira
(v8.20.10#820010)