Jens-G opened a new pull request, #3847:
URL: https://github.com/apache/thrift/pull/3847

   `TNonblockingServer`'s `TConnection` reserved the whole declared frame the 
moment it read the four-byte length prefix: `transition()` reallocated the read 
buffer to the frame size before any payload byte had arrived, so a peer could 
make the server reserve up to `getMaxFrameSize()` bytes per connection by 
sending only a four-byte header. (The reservation is address space — a 
`std::realloc` — rather than resident memory, but it is still an unamplified 
header-to-allocation step.)
   
   This bounds the allocation by what the peer actually sends:
   
   - `transition()` reserves only enough to hold the length prefix and begin 
reading (the prefix plus about a kilobyte), not the declared frame.
   - The buffer grows toward the frame size in `SOCKET_RECV` as bytes are 
actually read — by the same doubling the up-front allocation used, now driven 
by what the peer sends, with the doubling guarded so it cannot overflow 
`uint32_t`.
   
   A frame that fully arrives ends at the same buffer size as before, so there 
is no change for legitimate traffic in the steady state, and no change at all 
for frames of a kilobyte or less. A header with no payload reserves next to 
nothing. A large frame that does arrive now pays the amortized doubling copy 
any grow-as-you-go buffer pays.
   
   The `uint32_t` overflow guard in the new `growReadBuffer` helper is a small 
addition the old inline doubling lacked (the old `newSize *= 2` would loop 
forever for a `maxFrameSize` above 2 GiB); it is included here — happy to split 
it to its own ticket if a reviewer prefers.
   
   ### Test
   
   Three cases in `TNonblockingServerTest`: a Linux-only, forked case asserts 
that a 256 MiB frame header with no body does not grow the server's `VmSize`; 
two portable cases drive multi-megabyte requests that are assembled over many 
libevent callbacks (the buffer doubling as bytes arrive) and must round-trip 
byte-for-byte, one freeing the grown buffer at connection close and one between 
frames on a live connection.
   
   ### Related
   
   This is part (4) of the nonblocking-server frame handling; part (2)+(3), 
wiring the server to `TConfiguration`, is **THRIFT-6242**. The two are 
independent (not stacked) but both touch `TNonblockingServer.{h,cpp}`, so 
whichever lands second will need a small rebase.
   
   ---
   Prepared with AI assistance (Claude Opus 4.8).
   


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]

Reply via email to