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

   Wrapping a transport in `TFramedTransport` or `TFastFramedTransport` 
overwrote the maximum frame size it was configured with, even when no maximum 
had been asked for:
   
   ```java
   public TFramedTransport(TTransport transport) throws TTransportException {
     this(transport, TConfiguration.DEFAULT_MAX_FRAME_SIZE);
   }
   
   public TFramedTransport(TTransport transport, int maxLength) throws 
TTransportException {
     TConfiguration _configuration = ... transport.getConfiguration();
     _configuration.setMaxFrameSize(maxLength);
   ```
   
   So
   
   ```java
   socket.getConfiguration().setMaxFrameSize(1024);
   TTransport framed = new TFramedTransport(socket);
   ```
   
   left the socket configured for `16384000`.
   
   Two things went wrong at once. A maximum the operator set was replaced by 
the library default; and the object written into belongs to the transport 
underneath, so anything else sharing that `TConfiguration` changed with it. A 
layered transport has no configuration of its own to write into — 
`TLayeredTransport.getConfiguration()` delegates to the inner transport by 
design.
   
   `TFastFramedTransport(underlying)` and `TFastFramedTransport(underlying, 
initialBufferCapacity)` did the same, as did `TFramedTransport.Factory()` and 
`TFastFramedTransport.Factory()` / `Factory(initialCapacity)` — so a server 
configured with `new TFramedTransport.Factory()` raised the limit on **every 
connection it accepted**.
   
   ### The change
   
   A constructor or factory that was not given a maximum now passes back the 
one the transport already carries, so wrapping changes nothing. Given one 
explicitly, the behaviour is unchanged: it is applied, as the argument's 
javadoc promises.
   
   ### The rest of the tree
   
   Go solved this for its own deprecated constructors, and the reason is 
written into its `TConfiguration`:
   
   > `noPropagation` — *"Used internally by deprecated constructors, to avoid 
overriding underlying TTransport/TProtocol's cfg by accidental propagations."*
   
   C++ (`TFramedTransport` copies `configuration_->getMaxFrameSize()` into its 
own `maxFrameSize_`), netstd, Delphi and Haxe all read the configured maximum 
and never write it. Java was the only binding where wrapping wrote it.
   
   ### Tests
   
   Four in `TestTFramedTransport`, inherited by `TestTFastFramedTransport`, so 
both classes are covered:
   
   - wrapping keeps a lowered maximum,
   - the factory keeps it,
   - an explicit maximum is still applied,
   - and — the point of the other three — a frame declaring 2048 bytes is still 
refused by a transport configured for 1024 after being wrapped.
   
   Three of the four fail on each class beforehand (`expected: <1024> but was: 
<16384000>`, and *"Expected TTransportException to be thrown, but nothing was 
thrown"*). The explicit-maximum one is a regression guard and passes either way.
   
   Full `gradle test spotlessCheck`: BUILD SUCCESSFUL.
   
   🤖 Generated with [Claude Code](https://claude.com/claude-code)
   


-- 
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