Jens Geyer created THRIFT-6299:
----------------------------------
Summary: C++: TQIODeviceTransport::readAll returns a short count
when a read fails after partial progress
Key: THRIFT-6299
URL: https://issues.apache.org/jira/browse/THRIFT-6299
Project: Thrift
Issue Type: Bug
Components: C++ - Library
Reporter: Jens Geyer
{{TQIODeviceTransport::readAll}}
({{lib/cpp/src/thrift/qt/TQIODeviceTransport.cpp:61}}) is the read-exactly
entry point, but it does not always read exactly. When the inner {{read()}}
throws after some bytes have already been delivered, it swallows the exception
and returns the number of bytes delivered so far:
{code:cpp}
uint32_t TQIODeviceTransport::readAll(uint8_t* buf, uint32_t len) {
uint32_t requestLen = len;
while (len) {
uint32_t readSize;
try {
readSize = read(buf, len);
} catch (...) {
if (len != requestLen) {
// something read already
return requestLen - len;
}
// error but nothing read yet
throw;
}
...
{code}
Callers of {{readAll}} are entitled to assume that the buffer holds {{len}}
bytes on return. {{TBinaryProtocol}} is one of them: {{readI32}} and friends
decode the buffer without consulting the return value, so a short return is
decoded as though it were complete. The other C++ {{readAll}} implementations
do not behave this way — {{TVirtualTransport}}, {{TBufferBase}} and
{{TFileTransport}} each loop until {{len}} or throw.
The Qt transports are client-side; {{lib/cpp/src/thrift/qt}} ships no server.
So this needs a peer that answers a request and then breaks the connection
mid-reply.
h2. Suggested
Let the exception out. A caller that wants the partial count can use {{read}},
which is the API that is allowed to return less than asked for. If the swallow
has to stay for compatibility, the untouched tail should at least be zeroed, so
that a short return cannot be decoded as complete data.
A test can drive this through a {{QBuffer}} whose backing device is closed
part-way through a {{readAll}}.
_Drafted with AI assistance (Claude Opus 5); reviewed and filed by Jens Geyer._
--
This message was sent by Atlassian Jira
(v8.20.10#820010)