diff --git a/Lib/posixpath.py b/Lib/posixpath.py index e4f155e41a3221..5abaaf46d43989 100644 --- a/Lib/posixpath.py +++ b/Lib/posixpath.py @@ -524,8 +524,19 @@ def relpath(path, start=None): start = os.fspath(start) try: - start_list = [x for x in abspath(start).split(sep) if x] - path_list = [x for x in abspath(path).split(sep) if x] + start_abs = abspath(normpath(start)) + path_abs = abspath(normpath(path)) + + _, start_root, start_rest = splitroot(start_abs) + _, path_root, path_rest = splitroot(path_abs) + + if start_root != path_root: + raise ValueError( + f"Path is on root {path_root!r}, start on root {start_root!r}" + ) + + start_list = [x for x in start_rest.split(sep) if x] + path_list = [x for x in path_rest.split(sep) if x] # Work out how much of the filepath is shared by start and path. i = len(commonprefix([start_list, path_list])) @@ -533,7 +544,7 @@ def relpath(path, start=None): if not rel_list: return curdir return join(*rel_list) - except (TypeError, AttributeError, BytesWarning, DeprecationWarning): + except (TypeError, ValueError, AttributeError, BytesWarning, DeprecationWarning): genericpath._check_arg_types('relpath', path, start) raise diff --git a/Lib/test/test_posixpath.py b/Lib/test/test_posixpath.py index 9be4640f970aef..f5e88edc7de97c 100644 --- a/Lib/test/test_posixpath.py +++ b/Lib/test/test_posixpath.py @@ -652,6 +652,12 @@ def test_relpath(self): self.assertEqual(posixpath.relpath("/", "/"), '.') self.assertEqual(posixpath.relpath("/a", "/a"), '.') self.assertEqual(posixpath.relpath("/a/b", "/a/b"), '.') + self.assertRaises(ValueError, posixpath.relpath, "/foo/bar", "//foo") + self.assertRaises(ValueError, posixpath.relpath, "//foo/bar", "/foo") + self.assertRaises(ValueError, posixpath.relpath, "//foo/bar", "///foo") + self.assertEqual(posixpath.relpath("//foo/bar", "//foo"), "bar") + self.assertEqual(posixpath.relpath("///foo/bar", "/foo"), "bar") + self.assertEqual(posixpath.relpath("/foo/bar/baz", "///foo"), "bar/baz") finally: os.getcwd = real_getcwd diff --git a/Misc/NEWS.d/next/Library/2023-04-24-15-23-49.gh-issue-92737.ZK2sK3.rst b/Misc/NEWS.d/next/Library/2023-04-24-15-23-49.gh-issue-92737.ZK2sK3.rst new file mode 100644 index 00000000000000..b64b8457e21bcc --- /dev/null +++ b/Misc/NEWS.d/next/Library/2023-04-24-15-23-49.gh-issue-92737.ZK2sK3.rst @@ -0,0 +1,2 @@ +Fixed posixpath.relpath to not assume '//' is equivalent to '/'. Patch by +Adam Chhina.