[
https://issues.apache.org/jira/browse/THRIFT-6132?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel
]
Dmytro Shteflyuk resolved THRIFT-6132.
--------------------------------------
Fix Version/s: 0.25.0
Resolution: Fixed
> Ruby HeaderTransport retains stale metadata after legacy frames
> ---------------------------------------------------------------
>
> Key: THRIFT-6132
> URL: https://issues.apache.org/jira/browse/THRIFT-6132
> Project: Thrift
> Issue Type: Bug
> Components: Ruby - Library
> Reporter: Dmytro Shteflyuk
> Assignee: Dmytro Shteflyuk
> Priority: Major
> Fix For: 0.25.0
>
> Time Spent: 20m
> Remaining Estimate: 0h
>
> h3. Problem
> {{HeaderTransport}} exposes key-value metadata from the most recently parsed
> Header frame through {{get_headers}}. When the same connection subsequently
> receives a framed or unframed Binary or Compact message, the transport does
> not clear that metadata because the reset currently occurs only while parsing
> another Header frame.
> As a result, metadata from an earlier Header message remains visible while
> processing a later legacy message that did not carry any headers. The same
> stale state can remain visible when parsing the following frame fails before
> Header metadata is reset.
> h3. Client impact
> Applications that use Header metadata for logging, tracing, routing, or
> request context can associate values from an earlier request with a later
> request on the same connection. The stale values remain visible until another
> valid Header frame replaces them.
> This affects HeaderTransport's supported protocol auto-detection paths for
> framed and unframed Binary and Compact messages.
> h3. Reproduction
> The following reproduction constructs a Header frame containing a request ID
> followed by a framed Binary message with no Header metadata:
> {code:ruby}
> require "thrift"
> def header_frame(payload, headers)
> buffer = Thrift::MemoryBufferTransport.new
> writer = Thrift::HeaderTransport.new(buffer)
> headers.each { |key, value| writer.set_header(key, value) }
> writer.write(payload)
> writer.flush
> buffer.read(buffer.available)
> end
> binary = [
> Thrift::BinaryProtocol::VERSION_1 | Thrift::MessageTypes::CALL
> ].pack("N")
> bytes = header_frame("A", "request-id" => "first")
> bytes << [binary.bytesize].pack("N")
> bytes << binary
> transport = Thrift::HeaderTransport.new(
> Thrift::MemoryBufferTransport.new(bytes)
> )
> transport.read(1)
> puts "after Header: #{transport.get_headers.inspect}"
> transport.reset_protocol
> transport.read(4)
> puts "after framed Binary: #{transport.get_headers.inspect}"
> {code}
> Run from {{lib/rb}} with:
> {code:bash}
> bundle exec ruby -Ilib reproduction.rb
> {code}
> Testing on master commit {{f69c2078b7c11c09aa4f8b8879d8b41342145461}}
> produces:
> {code}
> after Header: {"request-id" => "first"}
> after framed Binary: {"request-id" => "first"}
> {code}
> h3. Expected behavior
> Header metadata should be reset when parsing begins for every new frame,
> before protocol detection or validation. Legacy Binary and Compact messages
> should expose an empty header map, malformed following frames should not
> leave metadata from the previous message visible, and a later valid Header
> frame should expose only its own metadata.
--
This message was sent by Atlassian Jira
(v8.20.10#820010)