Dmytro Shteflyuk created THRIFT-6121:
----------------------------------------

             Summary: Ruby HeaderProtocol emits unparseable errors for unknown 
protocol IDs
                 Key: THRIFT-6121
                 URL: https://issues.apache.org/jira/browse/THRIFT-6121
             Project: Thrift
          Issue Type: Bug
          Components: Ruby - Library
            Reporter: Dmytro Shteflyuk
            Assignee: Dmytro Shteflyuk


h3. Problem

When Ruby HeaderProtocol reads an otherwise valid Header frame containing an 
unknown subprotocol ID, it raises a ProtocolException and attempts to return an 
INVALID_PROTOCOL ApplicationException. The response Header frame still 
advertises the unknown, peer-supplied subprotocol ID, however, so the receiver 
cannot select a Binary or Compact decoder to read the error. The response also 
replaces the incoming Header sequence ID with zero.

h3. Client impact

A client cannot decode the typed application error and instead fails again 
while selecting a protocol for the response. Replacing the sequence ID also 
prevents the response from being correlated with the request that caused it. 
The useful "Unknown protocol ID" diagnostic is therefore trapped inside a 
response that a normal HeaderProtocol reader cannot consume.

h3. Reproduction

Save the following as {{/tmp/header_unknown_protocol.rb}}:

{code:language=ruby}
require "thrift"

# Header frame with sequence ID 77 and unknown subprotocol ID 16.
frame = [14, 0x0fff, 0, 77, 1].pack("NnnNn")
frame << "\x10\x00\x00\x00".b

buffer = Thrift::MemoryBufferTransport.new(frame)
protocol = Thrift::HeaderProtocol.new(buffer)

begin
  protocol.read_message_begin
rescue Thrift::ProtocolException
end

response = buffer.read(buffer.available)
puts "response_protocol_id=#{response.getbyte(14)} " \
     "response_sequence_id=#{response.byteslice(8, 4).unpack1("N")} " \
     "bytes=#{response.bytesize}"

reader = Thrift::HeaderProtocol.new(
  Thrift::MemoryBufferTransport.new(response)
)
reader.read_message_begin
{code}

Run it from {{lib/rb}}:

{code:bash}
bundle exec ruby -Ilib /tmp/header_unknown_protocol.rb
{code}

The response retains protocol ID 16, loses sequence ID 77, and cannot be parsed:

{code}
response_protocol_id=16 response_sequence_id=0 bytes=50
Thrift::ProtocolException: Unknown protocol ID: 16
{code}

h3. Expected behavior

The error response should use the HeaderProtocol instance's configured, 
supported default subprotocol and preserve the parsed Header sequence ID. A 
fresh HeaderProtocol reader should be able to decode an EXCEPTION message 
containing an INVALID_PROTOCOL ApplicationException with the original 
diagnostic. If a malformed header cannot be parsed far enough to obtain safe 
response metadata, handling it must not recursively emit another unparseable 
response.




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

Reply via email to