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)

Reply via email to