Skip to content

Commit b9f012f

Browse files
authored
Fix URI.merge/2 handling of base with trailing dots (#14341)
1 parent 822aac8 commit b9f012f

File tree

2 files changed

+110
-1
lines changed

2 files changed

+110
-1
lines changed

Diff for: lib/elixir/lib/uri.ex

+1-1
Original file line numberDiff line numberDiff line change
@@ -954,12 +954,12 @@ defmodule URI do
954954

955955
defp remove_dot_segments([], acc), do: acc
956956
defp remove_dot_segments([:/ | tail], acc), do: remove_dot_segments(tail, [:/ | acc])
957+
defp remove_dot_segments([_, :+ | tail], acc), do: remove_dot_segments(tail, acc)
957958
defp remove_dot_segments(["."], acc), do: remove_dot_segments([], ["" | acc])
958959
defp remove_dot_segments(["." | tail], acc), do: remove_dot_segments(tail, acc)
959960
defp remove_dot_segments([".." | tail], [:/]), do: remove_dot_segments(tail, [:/])
960961
defp remove_dot_segments([".."], [_ | acc]), do: remove_dot_segments([], ["" | acc])
961962
defp remove_dot_segments([".." | tail], [_ | acc]), do: remove_dot_segments(tail, acc)
962-
defp remove_dot_segments([_, :+ | tail], acc), do: remove_dot_segments(tail, acc)
963963
defp remove_dot_segments([head | tail], acc), do: remove_dot_segments(tail, [head | acc])
964964

965965
defp join_reversed_segments(segments) do

Diff for: lib/elixir/test/elixir/uri_test.exs

+109
Original file line numberDiff line numberDiff line change
@@ -520,6 +520,115 @@ defmodule URITest do
520520
end
521521
end
522522

523+
test "merge/2 (with W3C examples)" do
524+
# These examples are from the W3C JSON-LD test suite:
525+
#
526+
# https://w3c.github.io/json-ld-api/tests/toRdf-manifest#t0124
527+
# https://w3c.github.io/json-ld-api/tests/toRdf-manifest#t0125
528+
529+
base1 = "http://a/bb/ccc/."
530+
531+
rel_and_result1 = %{
532+
"g:h" => "g:h",
533+
"g" => "http://a/bb/ccc/g",
534+
"./g" => "http://a/bb/ccc/g",
535+
"g/" => "http://a/bb/ccc/g/",
536+
"/g" => "http://a/g",
537+
"//g" => "http://g",
538+
"?y" => "http://a/bb/ccc/.?y",
539+
"g?y" => "http://a/bb/ccc/g?y",
540+
"#s" => "http://a/bb/ccc/.#s",
541+
"g#s" => "http://a/bb/ccc/g#s",
542+
"g?y#s" => "http://a/bb/ccc/g?y#s",
543+
";x" => "http://a/bb/ccc/;x",
544+
"g;x" => "http://a/bb/ccc/g;x",
545+
"g;x?y#s" => "http://a/bb/ccc/g;x?y#s",
546+
"" => "http://a/bb/ccc/.",
547+
"." => "http://a/bb/ccc/",
548+
"./" => "http://a/bb/ccc/",
549+
".." => "http://a/bb/",
550+
"../" => "http://a/bb/",
551+
"../g" => "http://a/bb/g",
552+
"../.." => "http://a/",
553+
"../../" => "http://a/",
554+
"../../g" => "http://a/g",
555+
"../../../g" => "http://a/g",
556+
"../../../../g" => "http://a/g",
557+
"/./g" => "http://a/g",
558+
"/../g" => "http://a/g",
559+
"g." => "http://a/bb/ccc/g.",
560+
".g" => "http://a/bb/ccc/.g",
561+
"g.." => "http://a/bb/ccc/g..",
562+
"..g" => "http://a/bb/ccc/..g",
563+
"./../g" => "http://a/bb/g",
564+
"./g/." => "http://a/bb/ccc/g/",
565+
"g/./h" => "http://a/bb/ccc/g/h",
566+
"g/../h" => "http://a/bb/ccc/h",
567+
"g;x=1/./y" => "http://a/bb/ccc/g;x=1/y",
568+
"g;x=1/../y" => "http://a/bb/ccc/y",
569+
"g?y/./x" => "http://a/bb/ccc/g?y/./x",
570+
"g?y/../x" => "http://a/bb/ccc/g?y/../x",
571+
"g#s/./x" => "http://a/bb/ccc/g#s/./x",
572+
"g#s/../x" => "http://a/bb/ccc/g#s/../x",
573+
"http:g" => "http:g"
574+
}
575+
576+
for {rel, result} <- rel_and_result1 do
577+
assert URI.merge(base1, rel) |> URI.to_string() == result
578+
end
579+
580+
base2 = "http://a/bb/ccc/.."
581+
582+
rel_and_result2 = %{
583+
"g:h" => "g:h",
584+
"g" => "http://a/bb/ccc/g",
585+
"./g" => "http://a/bb/ccc/g",
586+
"g/" => "http://a/bb/ccc/g/",
587+
"/g" => "http://a/g",
588+
"//g" => "http://g",
589+
"?y" => "http://a/bb/ccc/..?y",
590+
"g?y" => "http://a/bb/ccc/g?y",
591+
"#s" => "http://a/bb/ccc/..#s",
592+
"g#s" => "http://a/bb/ccc/g#s",
593+
"g?y#s" => "http://a/bb/ccc/g?y#s",
594+
";x" => "http://a/bb/ccc/;x",
595+
"g;x" => "http://a/bb/ccc/g;x",
596+
"g;x?y#s" => "http://a/bb/ccc/g;x?y#s",
597+
"" => "http://a/bb/ccc/..",
598+
"." => "http://a/bb/ccc/",
599+
"./" => "http://a/bb/ccc/",
600+
".." => "http://a/bb/",
601+
"../" => "http://a/bb/",
602+
"../g" => "http://a/bb/g",
603+
"../.." => "http://a/",
604+
"../../" => "http://a/",
605+
"../../g" => "http://a/g",
606+
"../../../g" => "http://a/g",
607+
"../../../../g" => "http://a/g",
608+
"/./g" => "http://a/g",
609+
"/../g" => "http://a/g",
610+
"g." => "http://a/bb/ccc/g.",
611+
".g" => "http://a/bb/ccc/.g",
612+
"g.." => "http://a/bb/ccc/g..",
613+
"..g" => "http://a/bb/ccc/..g",
614+
"./../g" => "http://a/bb/g",
615+
"./g/." => "http://a/bb/ccc/g/",
616+
"g/./h" => "http://a/bb/ccc/g/h",
617+
"g/../h" => "http://a/bb/ccc/h",
618+
"g;x=1/./y" => "http://a/bb/ccc/g;x=1/y",
619+
"g;x=1/../y" => "http://a/bb/ccc/y",
620+
"g?y/./x" => "http://a/bb/ccc/g?y/./x",
621+
"g?y/../x" => "http://a/bb/ccc/g?y/../x",
622+
"g#s/./x" => "http://a/bb/ccc/g#s/./x",
623+
"g#s/../x" => "http://a/bb/ccc/g#s/../x",
624+
"http:g" => "http:g"
625+
}
626+
627+
for {rel, result} <- rel_and_result2 do
628+
assert URI.merge(base2, rel) |> URI.to_string() == result
629+
end
630+
end
631+
523632
test "append_query/2" do
524633
assert URI.append_query(URI.parse("http://example.com/?x=1"), "x=2").query == "x=1&x=2"
525634
assert URI.append_query(URI.parse("http://example.com/?x=1&"), "x=2").query == "x=1&x=2"

0 commit comments

Comments
 (0)