From 2640774fb43ca174aabdfb079ce4f81029894de9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Valim?= Date: Sat, 17 Apr 2021 21:53:36 +0200 Subject: [PATCH] Do not crash on Path.absname(c:) --- lib/elixir/lib/path.ex | 32 ++++++++++++++-------------- lib/elixir/test/elixir/path_test.exs | 10 +++++++++ 2 files changed, 26 insertions(+), 16 deletions(-) diff --git a/lib/elixir/lib/path.ex b/lib/elixir/lib/path.ex index 885eced193a..fb1742a37ad 100644 --- a/lib/elixir/lib/path.ex +++ b/lib/elixir/lib/path.ex @@ -67,7 +67,7 @@ defmodule Path do case type(path) do :relative -> - absname_join(relative_to, path) + absname_join([relative_to, path]) :absolute -> absname_join([path]) @@ -81,11 +81,11 @@ defmodule Path do # Absolute path on current drive defp absname_vr(["/" | rest], [volume | _], _relative), do: absname_join([volume | rest]) - # Relative to current directory on current drive. + # Relative to current directory on current drive defp absname_vr([<> | rest], [<> | _], relative), do: absname(absname_join(rest), relative) - # Relative to current directory on another drive. + # Relative to current directory on another drive defp absname_vr([<> | name], _, _relative) do cwd = case :file.get_cwd([x, ?:]) do @@ -98,25 +98,25 @@ defmodule Path do @slash [?/, ?\\] - # Joins a list - defp absname_join([name1, name2 | rest]), do: absname_join([absname_join(name1, name2) | rest]) + defp absname_join([]), do: "" + defp absname_join(list), do: absname_join(list, major_os_type()) - defp absname_join([name]), - do: do_absname_join(IO.chardata_to_string(name), <<>>, [], major_os_type()) + defp absname_join([name1, name2 | rest], os_type) do + joined = do_absname_join(IO.chardata_to_string(name1), relative(name2), [], os_type) + absname_join([joined | rest], os_type) + end - # Joins two paths - defp absname_join(left, right), - do: do_absname_join(IO.chardata_to_string(left), relative(right), [], major_os_type()) + defp absname_join([name], os_type) do + do_absname_join(IO.chardata_to_string(name), <<>>, [], os_type) + end defp do_absname_join(<>, relativename, [], :win32) - when uc_letter in ?A..?Z do - do_absname_join(rest, relativename, [?:, uc_letter + ?a - ?A], :win32) - end + when uc_letter in ?A..?Z, + do: do_absname_join(rest, relativename, [?:, uc_letter + ?a - ?A], :win32) defp do_absname_join(<>, relativename, [], :win32) - when c1 in @slash and c2 in @slash do - do_absname_join(rest, relativename, '//', :win32) - end + when c1 in @slash and c2 in @slash, + do: do_absname_join(rest, relativename, '//', :win32) defp do_absname_join(<>, relativename, result, :win32), do: do_absname_join(<>, relativename, result, :win32) diff --git a/lib/elixir/test/elixir/path_test.exs b/lib/elixir/test/elixir/path_test.exs index a51057db2f4..44aa5770759 100644 --- a/lib/elixir/test/elixir/path_test.exs +++ b/lib/elixir/test/elixir/path_test.exs @@ -50,6 +50,16 @@ defmodule PathTest do assert Path.absname("\\\\host\\path") == "//host/path" assert Path.absname("\\/host\\path") == "//host/path" assert Path.absname("/\\host\\path") == "//host/path" + + assert Path.absname("c:/") == "c:/" + assert Path.absname("c:/host/path") == "c:/host/path" + + cwd = File.cwd!() + assert Path.absname(cwd |> String.split("/") |> hd()) == cwd + + <> = cwd + random = Enum.random(Enum.to_list(?c..?z) -- [letter]) + assert Path.absname(<>) == <> end test "relative/1" do