[ 
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)

Reply via email to