You are viewing a plain text version of this content. The canonical link for it is here.
Posted to notifications@thrift.apache.org by "Dmytro Shteflyuk (Jira)" <ji...@apache.org> on 2026/08/12 19:22:00 UTC

[jira] [Created] (THRIFT-6147) Ruby Serializer should finalize buffered protocol transports

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)