Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions lib/ruby_lsp/base_server.rb
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,8 @@ def start
)
end
end
rescue URI::Error
# A client can send a document URI with a scheme Ruby's URI parser rejects, so we don't want to fail
rescue Store::NonExistingDocumentError
# If we receive a request for a file that no longer exists, we don't want to fail
end
Expand Down
30 changes: 30 additions & 0 deletions test/server_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -1749,6 +1749,36 @@ def test_unrecognized_request_returns_method_not_found
assert_equal("Method not found: #{non_existent_method}", error.message)
end

def test_does_not_crash_when_a_document_uri_cannot_be_parsed
# A document URI with a scheme Ruby's URI parser rejects must not crash the server
body = {
id: 1,
method: "textDocument/hover",
params: {
textDocument: { uri: "_diff_view:/path/to/file.rb" },
position: { line: 0, character: 0 },
},
}.to_json
server = RubyLsp::Server.new(
test_mode: true,
reader: StringIO.new("Content-Length: #{body.bytesize}\r\n\r\n#{body}"),
writer: StringIO.new,
)

error = nil #: StandardError?
capture_subprocess_io do
server.start
rescue StandardError => e
error = e
end

assert_nil(error, "server crashed on an unparseable document URI: #{error&.message}")
# The request still gets an error response instead of hanging
assert_instance_of(RubyLsp::Error, server.pop_response)
ensure
server&.run_shutdown
end

private

def run_initialize_server_with_setup_error(error)
Expand Down
Loading