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.