Jens Geyer created THRIFT-6279:
----------------------------------

             Summary: Erlang: the JSON protocol cannot read a message and 
writes binary strings unquoted
                 Key: THRIFT-6279
                 URL: https://issues.apache.org/jira/browse/THRIFT-6279
             Project: Thrift
          Issue Type: Bug
          Components: Erlang - Library
            Reporter: Jens Geyer


Found while working on THRIFT-6269. {{thrift_json_protocol}} does not 
round-trip a message. The Erlang cross test covers only binary and compact, and 
{{lib/erl/test}} has no JSON test, so nothing notices. Measured on master with 
OTP 25 and 28.

h2. 1. Reading any message fails

{{convert_data(integer, I)}} calls {{list_to_integer(I)}}. That dates from 
THRIFT-1227, when the protocol used jsx. THRIFT-1357 (2014) replaced jsx with 
{{thrift_json_parser}}, whose {{format_number/1}} already returns integers. 
Since then {{list_to_integer/1}} is handed an integer.
* A message the protocol wrote itself fails to read at its version number with 
{{badarg}}.
* The integer clause of {{read(_, byte)}} has the same call.

h2. 2. A string given as a binary is written without quotes

The generator's default {{string=both}} accepts a string field as a binary, but 
{{write(_, \{string, Str\})}} writes a binary unchanged.
* Measured: the field comes out as {{"str":abc}}, which is not JSON.
* A string given as a list is quoted, but nothing in it is escaped.

h2. 3. Over a socket the read never ends

{{read_all/1}} reads until the transport returns nothing more, which a socket 
or framed transport never does: it waits for more data.

Measured with {{thrift_socket_server}} and {{thrift_client_util}} using the 
JSON protocol, both buffered and framed:
* The server process dies at its 500 ms receive timeout with a {{case_clause}} 
on {{\{error,timeout\}}}.
* The client call returns an error with {{case_clause}} on {{\{error,closed\}}}.
* The binary protocol works in the same setup.

h2. 4. One transport call per byte

{{read_all_1/2}} asks the transport for one byte at a time. This is the second 
point of THRIFT-6269, left out of PR #3867 because of 1 to 3.

h2. Suggested

* Fix 1 and 2, with round-trip tests over a memory buffer. For the list case, 
the test should include characters that need escaping.
* Make the read end with the message, not with the stream: parse incrementally, 
or read what the parser still needs.
* Then read in larger pieces, and resolve the {{\{error, 'EOF'\}}} clause in 
{{read_all_1/2}}. Its only producer, {{thrift_http_transport:read/2}}, cannot 
reach it.
* Add JSON to the Erlang entry of {{test/tests.json}} once it works.

_Drafted with AI assistance (Claude Opus 5); reviewed and filed by Jens Geyer._




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

Reply via email to