Skip to content

Commit 870a2f7

Browse files
committed
crash early on unvalid utf
1 parent 1e7a52c commit 870a2f7

File tree

1 file changed

+23
-12
lines changed

1 file changed

+23
-12
lines changed

apps/language_server/lib/language_server/source_file.ex

Lines changed: 23 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -3,12 +3,14 @@ defmodule ElixirLS.LanguageServer.SourceFile do
33

44
defstruct [:text, :version, dirty?: false]
55

6+
@endings ["\r\n", "\r", "\n"]
7+
68
def lines(%__MODULE__{text: text}) do
79
lines(text)
810
end
911

1012
def lines(text) when is_binary(text) do
11-
String.split(text, ["\r\n", "\r", "\n"])
13+
String.split(text, @endings)
1214
end
1315

1416
@doc """
@@ -20,17 +22,18 @@ defmodule ElixirLS.LanguageServer.SourceFile do
2022
do_lines_with_endings(text, "")
2123
end
2224

23-
def do_lines_with_endings("", line) do
25+
def do_lines_with_endings("", line) when is_binary(line) do
2426
[{line, nil}]
2527
end
2628

27-
for line_ending <- ["\r\n", "\r", "\n"] do
28-
def do_lines_with_endings(<<unquote(line_ending), rest::binary>>, line) do
29+
for line_ending <- @endings do
30+
def do_lines_with_endings(<<unquote(line_ending), rest::binary>>, line)
31+
when is_binary(line) do
2932
[{line, unquote(line_ending)} | do_lines_with_endings(rest, "")]
3033
end
3134
end
3235

33-
def do_lines_with_endings(<<char::utf8, rest::binary>>, line) do
36+
def do_lines_with_endings(<<char::utf8, rest::binary>>, line) when is_binary(line) do
3437
do_lines_with_endings(rest, line <> <<char::utf8>>)
3538
end
3639

@@ -177,13 +180,15 @@ defmodule ElixirLS.LanguageServer.SourceFile do
177180

178181
def line_length_utf16(line) do
179182
line
180-
|> :unicode.characters_to_binary(:utf8, :utf16)
183+
|> characters_to_binary!(:utf8, :utf16)
181184
|> byte_size()
182185
|> div(2)
183186
end
184187

185-
defp prepend_line(line, nil, acc), do: [line | acc]
186-
defp prepend_line(line, ending, acc), do: [[line, ending] | acc]
188+
defp prepend_line(line, nil, acc) when is_binary(line), do: [line | acc]
189+
190+
defp prepend_line(line, ending, acc) when is_binary(line) and ending in @endings,
191+
do: [[line, ending] | acc]
187192

188193
def apply_edit(text, range(start_line, start_character, end_line, end_character), new_text) do
189194
lines_with_idx =
@@ -201,13 +206,13 @@ defmodule ElixirLS.LanguageServer.SourceFile do
201206
# LSP contentChanges positions are based on UTF-16 string representation
202207
# https://microsoft.github.io/language-server-protocol/specification#textDocuments
203208
beginning_utf8 =
204-
:unicode.characters_to_binary(line, :utf8, :utf16)
209+
characters_to_binary!(line, :utf8, :utf16)
205210
|> (&binary_part(
206211
&1,
207212
0,
208213
min(start_character * 2, byte_size(&1))
209214
)).()
210-
|> :unicode.characters_to_binary(:utf16, :utf8)
215+
|> characters_to_binary!(:utf16, :utf8)
211216

212217
[beginning_utf8 | acc]
213218

@@ -228,13 +233,13 @@ defmodule ElixirLS.LanguageServer.SourceFile do
228233
# LSP contentChanges positions are based on UTF-16 string representation
229234
# https://microsoft.github.io/language-server-protocol/specification#textDocuments
230235
ending_utf8 =
231-
:unicode.characters_to_binary(line, :utf8, :utf16)
236+
characters_to_binary!(line, :utf8, :utf16)
232237
|> (&binary_part(
233238
&1,
234239
min(end_character * 2, byte_size(&1)),
235240
max(byte_size(&1) - end_character * 2, 0)
236241
)).()
237-
|> :unicode.characters_to_binary(:utf16, :utf8)
242+
|> characters_to_binary!(:utf16, :utf8)
238243

239244
prepend_line(ending_utf8, ending, acc)
240245

@@ -246,6 +251,12 @@ defmodule ElixirLS.LanguageServer.SourceFile do
246251
IO.iodata_to_binary(Enum.reverse(acc))
247252
end
248253

254+
defp characters_to_binary!(binary, from, to) do
255+
case :unicode.characters_to_binary(binary, from, to) do
256+
result when is_binary(result) -> result
257+
end
258+
end
259+
249260
def module_line(module) do
250261
# TODO: Don't call into here directly
251262
case ElixirSense.Core.Normalized.Code.get_docs(module, :moduledoc) do

0 commit comments

Comments
 (0)