Skip to content

Commit a83fddb

Browse files
committed
Do not crash on Path.absname(c:) (#10919)
1 parent 81d04d8 commit a83fddb

File tree

2 files changed

+26
-16
lines changed

2 files changed

+26
-16
lines changed

lib/elixir/lib/path.ex

Lines changed: 16 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,7 @@ defmodule Path do
6666

6767
case type(path) do
6868
:relative ->
69-
absname_join(relative_to, path)
69+
absname_join([relative_to, path])
7070

7171
:absolute ->
7272
absname_join([path])
@@ -80,11 +80,11 @@ defmodule Path do
8080
# Absolute path on current drive
8181
defp absname_vr(["/" | rest], [volume | _], _relative), do: absname_join([volume | rest])
8282

83-
# Relative to current directory on current drive.
83+
# Relative to current directory on current drive
8484
defp absname_vr([<<x, ?:>> | rest], [<<x, _::binary>> | _], relative),
8585
do: absname(absname_join(rest), relative)
8686

87-
# Relative to current directory on another drive.
87+
# Relative to current directory on another drive
8888
defp absname_vr([<<x, ?:>> | name], _, _relative) do
8989
cwd =
9090
case :file.get_cwd([x, ?:]) do
@@ -97,25 +97,25 @@ defmodule Path do
9797

9898
@slash [?/, ?\\]
9999

100-
# Joins a list
101-
defp absname_join([name1, name2 | rest]), do: absname_join([absname_join(name1, name2) | rest])
100+
defp absname_join([]), do: ""
101+
defp absname_join(list), do: absname_join(list, major_os_type())
102102

103-
defp absname_join([name]),
104-
do: do_absname_join(IO.chardata_to_string(name), <<>>, [], major_os_type())
103+
defp absname_join([name1, name2 | rest], os_type) do
104+
joined = do_absname_join(IO.chardata_to_string(name1), relative(name2), [], os_type)
105+
absname_join([joined | rest], os_type)
106+
end
105107

106-
# Joins two paths
107-
defp absname_join(left, right),
108-
do: do_absname_join(IO.chardata_to_string(left), relative(right), [], major_os_type())
108+
defp absname_join([name], os_type) do
109+
do_absname_join(IO.chardata_to_string(name), <<>>, [], os_type)
110+
end
109111

110112
defp do_absname_join(<<uc_letter, ?:, rest::binary>>, relativename, [], :win32)
111-
when uc_letter in ?A..?Z do
112-
do_absname_join(rest, relativename, [?:, uc_letter + ?a - ?A], :win32)
113-
end
113+
when uc_letter in ?A..?Z,
114+
do: do_absname_join(rest, relativename, [?:, uc_letter + ?a - ?A], :win32)
114115

115116
defp do_absname_join(<<c1, c2, rest::binary>>, relativename, [], :win32)
116-
when c1 in @slash and c2 in @slash do
117-
do_absname_join(rest, relativename, '//', :win32)
118-
end
117+
when c1 in @slash and c2 in @slash,
118+
do: do_absname_join(rest, relativename, '//', :win32)
119119

120120
defp do_absname_join(<<?\\, rest::binary>>, relativename, result, :win32),
121121
do: do_absname_join(<<?/, rest::binary>>, relativename, result, :win32)

lib/elixir/test/elixir/path_test.exs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,16 @@ defmodule PathTest do
5050
assert Path.absname("\\\\host\\path") == "//host/path"
5151
assert Path.absname("\\/host\\path") == "//host/path"
5252
assert Path.absname("/\\host\\path") == "//host/path"
53+
54+
assert Path.absname("c:/") == "c:/"
55+
assert Path.absname("c:/host/path") == "c:/host/path"
56+
57+
cwd = File.cwd!()
58+
assert Path.absname(cwd |> String.split("/") |> hd()) == cwd
59+
60+
<<letter, _::binary>> = cwd
61+
random = Enum.random(Enum.to_list(?c..?z) -- [letter])
62+
assert Path.absname(<<random, ?:>>) == <<random, ?:, ?/>>
5363
end
5464

5565
test "relative/1" do

0 commit comments

Comments
 (0)