@@ -250,6 +250,49 @@ class StdioTransportTest < ActiveSupport::TestCase
250250 end
251251 end
252252
253+ test "open serves a frame holding an invalid byte in a value and keeps reading" do
254+ frames = "{\" jsonrpc\" :\" 2.0\" ,\" id\" :1,\" method\" :\" ping\" ,\" params\" :{\" x\" :\" \xFF \" }}\n " \
255+ "{\" jsonrpc\" :\" 2.0\" ,\" id\" :2,\" method\" :\" ping\" }\n "
256+ input = StringIO . new ( frames . dup . force_encoding ( Encoding ::UTF_8 ) )
257+ output = StringIO . new
258+ original_stdin = $stdin
259+ original_stdout = $stdout
260+
261+ begin
262+ $stdin = input
263+ $stdout = output
264+ @transport . open
265+
266+ responses = output . string . lines . map { |line | JSON . parse ( line , symbolize_names : true ) }
267+ assert_equal ( { jsonrpc : "2.0" , id : 1 , result : { } } , responses [ 0 ] )
268+ assert_equal ( { jsonrpc : "2.0" , id : 2 , result : { } } , responses [ 1 ] )
269+ ensure
270+ $stdin = original_stdin
271+ $stdout = original_stdout
272+ end
273+ end
274+
275+ test "open answers a frame starting with an invalid byte with -32700 and keeps reading" do
276+ frames = "\xFF []\n {\" jsonrpc\" :\" 2.0\" ,\" id\" :2,\" method\" :\" ping\" }\n "
277+ input = StringIO . new ( frames . dup . force_encoding ( Encoding ::UTF_8 ) )
278+ output = StringIO . new
279+ original_stdin = $stdin
280+ original_stdout = $stdout
281+
282+ begin
283+ $stdin = input
284+ $stdout = output
285+ @transport . open
286+
287+ responses = output . string . lines . map { |line | JSON . parse ( line , symbolize_names : true ) }
288+ assert_equal ( JsonRpcHandler ::ErrorCode ::PARSE_ERROR , responses [ 0 ] [ :error ] [ :code ] )
289+ assert_equal ( { jsonrpc : "2.0" , id : 2 , result : { } } , responses [ 1 ] )
290+ ensure
291+ $stdin = original_stdin
292+ $stdout = original_stdout
293+ end
294+ end
295+
253296 test "handles invalid JSON requests" do
254297 invalid_json = "invalid json"
255298 output = StringIO . new
@@ -319,6 +362,35 @@ class StdioTransportTest < ActiveSupport::TestCase
319362 end
320363 end
321364
365+ test "send_request reads a client reply holding an invalid byte in a value" do
366+ reader , writer = IO . pipe
367+ output = StringIO . new
368+ original_stdin = $stdin
369+ original_stdout = $stdout
370+
371+ begin
372+ $stdin = reader
373+ $stdout = output
374+ @transport . instance_variable_set ( :@open , true )
375+
376+ Thread . new do
377+ sleep ( 0.05 ) # Wait for request to be written to `StringIO`.
378+ request = JSON . parse ( output . string . lines . first , symbolize_names : true )
379+ writer . write ( "{\" jsonrpc\" :\" 2.0\" ,\" id\" :\" #{ request [ :id ] } \" ,\" result\" :{\" x\" :\" \xFF \" }}\n " . b )
380+ writer . flush
381+ end
382+
383+ result = @transport . send_request ( "test/method" )
384+
385+ assert_equal ( "\xFF " . b , result [ :x ] . b )
386+ ensure
387+ $stdin = original_stdin
388+ $stdout = original_stdout
389+ writer . close
390+ reader . close
391+ end
392+ end
393+
322394 test "send_request raises on error response from client" do
323395 reader , writer = IO . pipe
324396 output = StringIO . new
0 commit comments