Dmytro Shteflyuk created THRIFT-6139:
----------------------------------------

             Summary: Ruby CompactProtocol writers should reject out-of-range 
integers
                 Key: THRIFT-6139
                 URL: https://issues.apache.org/jira/browse/THRIFT-6139
             Project: Thrift
          Issue Type: Bug
          Components: Ruby - Library
            Reporter: Dmytro Shteflyuk
            Assignee: Dmytro Shteflyuk


h3. Problem

Ruby's CompactProtocol writers do not consistently enforce the widths declared 
by the Thrift type system. The pure-Ruby implementation can encode integers 
outside the signed i8, i16, i32, and i64 ranges, while the native extension may 
narrow the same values during decoding. Related protocol values such as field 
identifiers, message sequence identifiers, and collection sizes also reach the 
wire without consistent bounds checking.

This means the same encoded bytes can produce different values depending on 
whether {{thrift_native}} is loaded.

h3. Client impact

A client can supply a value that does not fit its declared Thrift type and 
receive no error while serializing it. The value may then change when decoded, 
and native and pure-Ruby clients can disagree about the result. Applications 
therefore receive delayed and environment-dependent behavior instead of an 
immediate error at the invalid write.

h3. Reproduction

Run the following as {{repro.rb}} from {{lib/rb}}:

{code:ruby}
require "thrift"

transport = Thrift::MemoryBufferTransport.new
protocol = Thrift::CompactProtocol.new(transport)
protocol.write_i16(32_768)

wire = transport.read(transport.available)
transport.reset_buffer(wire)
decoded = Thrift::CompactProtocol.new(transport).read_i16

puts "native=#{protocol.native?}"
puts "wire=#{wire.bytes.inspect}"
puts "decoded=#{decoded}"
{code}

Build the native extension, then run both implementations:

{code:bash}
bundle exec rake build_ext
ruby -Ilib -Iext repro.rb
ruby -Ilib repro.rb
{code}

Testing on master commit {{a9663bc6661a5dd1d99d629e1f269c1907592a1a}} produces:

{code}
native=true
wire=[128, 128, 4]
decoded=-32768

native=false
wire=[128, 128, 4]
decoded=32768
{code}

Both implementations accept {{32768}} even though it is outside the signed i16 
range, and they disagree when decoding the resulting bytes.

h3. Expected behavior

CompactProtocol should reject integers outside their declared signed widths 
before writing any bytes or changing protocol state. Field identifiers should 
be limited to signed i16, message sequence identifiers to signed i32, and 
collection or binary sizes to the non-negative signed i32 range. Native and 
pure-Ruby implementations should behave consistently, while valid values should 
retain their existing wire encoding.




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

Reply via email to