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)