Dmytro Shteflyuk created THRIFT-6147:
----------------------------------------

             Summary: Ruby Serializer should finalize buffered protocol 
transports
                 Key: THRIFT-6147
                 URL: https://issues.apache.org/jira/browse/THRIFT-6147
             Project: Thrift
          Issue Type: Bug
          Components: Ruby - Library
            Reporter: Dmytro Shteflyuk
            Assignee: Dmytro Shteflyuk


h3. Problem

{{Thrift::Serializer#serialize}} writes a value through its protocol and then 
immediately reads the serializer's backing memory buffer. It does not flush the 
transport selected by the protocol factory first.

This works for protocols that write directly to {{MemoryBufferTransport}}, 
whose {{flush}} is a no-op. It does not work when the protocol factory 
introduces a buffering or framing transport. {{HeaderTransport}} and 
{{FramedTransport}} retain the encoded bytes until they are flushed, so the 
serializer returns an empty string instead of the completed wire representation.

h3. Client impact

Ruby callers using {{HeaderProtocolFactory}} receive an empty serialized 
payload without an exception. The same behavior affects custom protocol 
factories that compose a protocol with {{FramedTransport}}. A caller can 
therefore store or send an empty payload while believing serialization 
succeeded.

h3. Reproduction

Save the following as {{reproduce_serializer.rb}}:

{code:ruby}
require "thrift"

class FramedBinaryProtocolFactory
  def get_protocol(transport)
    Thrift::BinaryProtocol.new(Thrift::FramedTransport.new(transport))
  end
end

value = Thrift::ApplicationException.new(
  Thrift::ApplicationException::UNKNOWN,
  "example"
)

header = Thrift::Serializer.new(
  Thrift::HeaderProtocolFactory.new
).serialize(value)

framed = Thrift::Serializer.new(
  FramedBinaryProtocolFactory.new
).serialize(value)

puts "header_bytes=#{header.bytesize}"
puts "framed_bytes=#{framed.bytesize}"
{code}

Run it from {{lib/rb}}:

{code:bash}
bundle exec ruby -Ilib reproduce_serializer.rb
{code}

Testing on master commit {{c2def39207a73394420088da9b4b105571dd9036}} produces:

{code}
header_bytes=0
framed_bytes=0
{code}

h3. Expected behavior

{{Serializer}} should flush the transport exposed by the selected protocol 
before reading its backing memory buffer. This finalizes Header, Framed, and 
other conforming buffered transport output, while preserving existing behavior 
for direct memory protocols because {{MemoryBufferTransport#flush}} is a no-op.

The returned payload should contain the complete wire representation and be 
readable by the corresponding protocol stack.




--
This message was sent by Atlassian Jira
(v8.20.10#820010)

Reply via email to