diff --git a/src/absinthe_parser.yrl b/src/absinthe_parser.yrl index 7d1f1fb95a..68d8844c56 100644 --- a/src/absinthe_parser.yrl +++ b/src/absinthe_parser.yrl @@ -361,36 +361,7 @@ put_description(Node, Description) -> % String extract_quoted_string_token({_Token, _Loc, Value}) -> - unicode:characters_to_binary(process_string(lists:sublist(Value, 2, length(Value) - 2))). - -process_string(Escaped) -> - process_string(Escaped, []). - -process_string([], Acc) -> - lists:reverse(Acc); -process_string([$\\, $" | T], Acc) -> - process_string(T, [$" | Acc]); -process_string([$\\, $\\ | T], Acc) -> - process_string(T, [$\\ | Acc]); -process_string([$\\, $/ | T], Acc) -> - process_string(T, [$/ | Acc]); -process_string([$\\, $b | T], Acc) -> - process_string(T, [$\b | Acc]); -process_string([$\\, $f | T], Acc) -> - process_string(T, [$\f | Acc]); -process_string([$\\, $n | T], Acc) -> - process_string(T, [$\n | Acc]); -process_string([$\\, $r | T], Acc) -> - process_string(T, [$\r | Acc]); -process_string([$\\, $t | T], Acc) -> - process_string(T, [$\t | Acc]); -process_string([$\\, $u, A, B, C, D | T], Acc) -> - process_string(T, [hexlist_to_utf8_binary([A, B, C, D]) | Acc]); -process_string([H | T], Acc) -> - process_string(T, [H | Acc]). - -hexlist_to_utf8_binary(HexList) -> - unicode:characters_to_binary([httpd_util:hexlist_to_integer(HexList)]). + unicode:characters_to_binary(lists:sublist(Value, 2, length(Value) - 2)). % Block String diff --git a/test/absinthe/integration/execution/escape_sequence_test.exs b/test/absinthe/integration/execution/escape_sequence_test.exs new file mode 100644 index 0000000000..bdff9c5221 --- /dev/null +++ b/test/absinthe/integration/execution/escape_sequence_test.exs @@ -0,0 +1,72 @@ +defmodule Absinthe.Phase.Document.Execution.EscapeSequenceTest do + use Absinthe.Case, async: true + + defmodule Schema do + use Absinthe.Schema + + query do + field :echo, :string do + arg :value, :string + + resolve(fn %{value: input_string}, _ -> + {:ok, input_string} + end) + end + end + end + + test "one slash" do + assert Absinthe.run( + ~S""" + { + echo(value: "\FOO") + } + """, + Schema + ) == {:ok, %{data: %{"echo" => ~S"\FOO"}}} + end + + test "two slashes" do + assert Absinthe.run( + ~S""" + { + echo(value: "\\FOO") + } + """, + Schema + ) == {:ok, %{data: %{"echo" => ~S"\FOO"}}} + end + + test "four slashes" do + assert Absinthe.run( + ~S""" + { + echo(value: "\\\\FOO") + } + """, + Schema + ) == {:ok, %{data: %{"echo" => ~S"\\FOO"}}} + end + + test "eight slashes" do + assert Absinthe.run( + ~S""" + { + echo(value: "\\\\\\\\FOO") + } + """, + Schema + ) == {:ok, %{data: %{"echo" => ~S"\\\\FOO"}}} + end + + test "literal slash n" do + assert Absinthe.run( + ~S""" + { + echo(value: "\\nFOO") + } + """, + Schema + ) == {:ok, %{data: %{"echo" => ~S"\nFOO"}}} + end +end diff --git a/test/absinthe/lexer_test.exs b/test/absinthe/lexer_test.exs index a38f72f32b..5d8eabf2ac 100644 --- a/test/absinthe/lexer_test.exs +++ b/test/absinthe/lexer_test.exs @@ -27,6 +27,28 @@ defmodule Absinthe.LexerTest do Absinthe.Lexer.tokenize(@query) end + @query ~S""" + { + { foo(bar: "\\\\FOO") } + } + """ + test "multiple escaped slashes" do + assert Absinthe.Lexer.tokenize(@query) == + {:ok, + [ + {:"{", {1, 1}}, + {:"{", {2, 3}}, + {:name, {2, 5}, 'foo'}, + {:"(", {2, 8}}, + {:name, {2, 9}, 'bar'}, + {:":", {2, 12}}, + {:string_value, {2, 14}, ~S("\\FOO") |> String.to_char_list()}, + {:")", {2, 23}}, + {:"}", {2, 25}}, + {:"}", {3, 1}} + ]} + end + @query """ { foo(bar: \"""