Dmytro Shteflyuk created THRIFT-6122:
----------------------------------------

             Summary: Ruby JSONProtocol mishandles Unicode strings and 
surrogate pairs
                 Key: THRIFT-6122
                 URL: https://issues.apache.org/jira/browse/THRIFT-6122
             Project: Thrift
          Issue Type: Bug
          Components: Ruby - Library
            Reporter: Dmytro Shteflyuk
            Assignee: Dmytro Shteflyuk


h3. Problem

The Ruby JSON protocol does not consistently apply JSON's UTF-8 string rules.

When reading a supplementary Unicode character represented as a UTF-16 
surrogate pair, such as {{\uD83D\uDE00}}, the protocol converts the high 
surrogate independently. Ruby rejects that standalone surrogate with 
{{RangeError}} before the low surrogate can be combined.

When writing, the protocol emits bytes from the supplied Ruby string without 
first normalizing declared character encodings to UTF-8. A valid string in an 
encoding such as ISO-8859-1 can therefore produce a JSON payload containing 
non-UTF-8 bytes.

h3. Client impact

Ruby clients and servers cannot read valid JSON payloads that use 
surrogate-pair escapes for characters outside the Basic Multilingual Plane. 
They can also emit JSON string values that other JSON implementations reject or 
misinterpret because the wire payload is not valid UTF-8.

h3. Reproduction

With a {{Thrift::JsonProtocol}} backed by {{Thrift::MemoryBufferTransport}}:

{code:ruby}
reader = Thrift::JsonProtocol.new(
  Thrift::MemoryBufferTransport.new('"\\uD83D\\uDE00"')
)
reader.read_string
# RangeError: invalid codepoint 0xD83D in UTF-8

value = +"caf\xE9"
value.force_encoding(Encoding::ISO_8859_1)

transport = Thrift::MemoryBufferTransport.new
writer = Thrift::JsonProtocol.new(transport)
writer.write_string(value)

transport.read(transport.available).bytes
# [34, 99, 97, 102, 233, 34]
{code}

The second payload contains byte {{0xE9}} directly rather than its UTF-8 
representation {{0xC3 0xA9}}.

h3. Expected behavior

The reader should combine a valid high/low UTF-16 surrogate pair into one 
Unicode scalar value and reject malformed escapes or unpaired surrogates with a 
typed {{ProtocolException}}.

The writer should preserve valid UTF-8 strings, transcode strings with a 
declared source encoding to UTF-8, reject invalid byte sequences before 
emitting partial JSON, and avoid mutating the caller's string.




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

Reply via email to