gh-96290: Support partial/invalid UNC drives in ntpath.normpath() and… · python/cpython@55a26de · GitHub
Skip to content

Commit 55a26de

Browse files
zoobabarneygaleeryksun
authored
gh-96290: Support partial/invalid UNC drives in ntpath.normpath() and splitdrive() (GH-100351)
This brings the Python implementation of `ntpath.normpath()` in line with the C implementation added in 99fcf15 Co-authored-by: Barney Gale <barney.gale@gmail.com> Co-authored-by: Eryk Sun <eryksun@gmail.com>
1 parent 7571764 commit 55a26de

4 files changed

Lines changed: 78 additions & 37 deletions

File tree

Lib/ntpath.py

Lines changed: 22 additions & 29 deletions

Lib/test/test_ntpath.py

Lines changed: 47 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -107,17 +107,50 @@ def test_splitdrive(self):
107107
tester('ntpath.splitdrive("//conky/mountpoint/foo/bar")',
108108
('//conky/mountpoint', '/foo/bar'))
109109
tester('ntpath.splitdrive("\\\\\\conky\\mountpoint\\foo\\bar")',
110-
('', '\\\\\\conky\\mountpoint\\foo\\bar'))
110+
('\\\\\\conky', '\\mountpoint\\foo\\bar'))
111111
tester('ntpath.splitdrive("///conky/mountpoint/foo/bar")',
112-
('', '///conky/mountpoint/foo/bar'))
112+
('///conky', '/mountpoint/foo/bar'))
113113
tester('ntpath.splitdrive("\\\\conky\\\\mountpoint\\foo\\bar")',
114-
('', '\\\\conky\\\\mountpoint\\foo\\bar'))
114+
('\\\\conky\\', '\\mountpoint\\foo\\bar'))
115115
tester('ntpath.splitdrive("//conky//mountpoint/foo/bar")',
116-
('', '//conky//mountpoint/foo/bar'))
116+
('//conky/', '/mountpoint/foo/bar'))
117117
# Issue #19911: UNC part containing U+0130
118118
self.assertEqual(ntpath.splitdrive('//conky/MOUNTPOİNT/foo/bar'),
119119
('//conky/MOUNTPOİNT', '/foo/bar'))
120120

121+
# gh-81790: support device namespace, including UNC drives.
122+
tester('ntpath.splitdrive("//?/c:")', ("//?/c:", ""))
123+
tester('ntpath.splitdrive("//?/c:/")', ("//?/c:", "/"))
124+
tester('ntpath.splitdrive("//?/c:/dir")', ("//?/c:", "/dir"))
125+
tester('ntpath.splitdrive("//?/UNC")', ("//?/UNC", ""))
126+
tester('ntpath.splitdrive("//?/UNC/")', ("//?/UNC/", ""))
127+
tester('ntpath.splitdrive("//?/UNC/server/")', ("//?/UNC/server/", ""))
128+
tester('ntpath.splitdrive("//?/UNC/server/share")', ("//?/UNC/server/share", ""))
129+
tester('ntpath.splitdrive("//?/UNC/server/share/dir")', ("//?/UNC/server/share", "/dir"))
130+
tester('ntpath.splitdrive("//?/VOLUME{00000000-0000-0000-0000-000000000000}/spam")',
131+
('//?/VOLUME{00000000-0000-0000-0000-000000000000}', '/spam'))
132+
tester('ntpath.splitdrive("//?/BootPartition/")', ("//?/BootPartition", "/"))
133+
134+
tester('ntpath.splitdrive("\\\\?\\c:")', ("\\\\?\\c:", ""))
135+
tester('ntpath.splitdrive("\\\\?\\c:\\")', ("\\\\?\\c:", "\\"))
136+
tester('ntpath.splitdrive("\\\\?\\c:\\dir")', ("\\\\?\\c:", "\\dir"))
137+
tester('ntpath.splitdrive("\\\\?\\UNC")', ("\\\\?\\UNC", ""))
138+
tester('ntpath.splitdrive("\\\\?\\UNC\\")', ("\\\\?\\UNC\\", ""))
139+
tester('ntpath.splitdrive("\\\\?\\UNC\\server\\")', ("\\\\?\\UNC\\server\\", ""))
140+
tester('ntpath.splitdrive("\\\\?\\UNC\\server\\share")', ("\\\\?\\UNC\\server\\share", ""))
141+
tester('ntpath.splitdrive("\\\\?\\UNC\\server\\share\\dir")',
142+
("\\\\?\\UNC\\server\\share", "\\dir"))
143+
tester('ntpath.splitdrive("\\\\?\\VOLUME{00000000-0000-0000-0000-000000000000}\\spam")',
144+
('\\\\?\\VOLUME{00000000-0000-0000-0000-000000000000}', '\\spam'))
145+
tester('ntpath.splitdrive("\\\\?\\BootPartition\\")', ("\\\\?\\BootPartition", "\\"))
146+
147+
# gh-96290: support partial/invalid UNC drives
148+
tester('ntpath.splitdrive("//")', ("//", "")) # empty server & missing share
149+
tester('ntpath.splitdrive("///")', ("///", "")) # empty server & empty share
150+
tester('ntpath.splitdrive("///y")', ("///y", "")) # empty server & non-empty share
151+
tester('ntpath.splitdrive("//x")', ("//x", "")) # non-empty server & missing share
152+
tester('ntpath.splitdrive("//x/")', ("//x/", "")) # non-empty server & empty share
153+
121154
def test_split(self):
122155
tester('ntpath.split("c:\\foo\\bar")', ('c:\\foo', 'bar'))
123156
tester('ntpath.split("\\\\conky\\mountpoint\\foo\\bar")',
@@ -136,6 +169,10 @@ def test_isabs(self):
136169
tester('ntpath.isabs("\\foo")', 1)
137170
tester('ntpath.isabs("\\foo\\bar")', 1)
138171

172+
# gh-96290: normal UNC paths and device paths without trailing backslashes
173+
tester('ntpath.isabs("\\\\conky\\mountpoint")', 1)
174+
tester('ntpath.isabs("\\\\.\\C:")', 1)
175+
139176
def test_commonprefix(self):
140177
tester('ntpath.commonprefix(["/home/swenson/spam", "/home/swen/spam"])',
141178
"/home/swen")
@@ -245,6 +282,12 @@ def test_normpath(self):
245282
tester("ntpath.normpath('//server/share/../..')", '\\\\server\\share\\')
246283
tester("ntpath.normpath('//server/share/../../')", '\\\\server\\share\\')
247284

285+
# gh-96290: don't normalize partial/invalid UNC drives as rooted paths.
286+
tester("ntpath.normpath('\\\\foo\\\\')", '\\\\foo\\\\')
287+
tester("ntpath.normpath('\\\\foo\\')", '\\\\foo\\')
288+
tester("ntpath.normpath('\\\\foo')", '\\\\foo')
289+
tester("ntpath.normpath('\\\\')", '\\\\')
290+
248291
def test_realpath_curdir(self):
249292
expected = ntpath.normpath(os.getcwd())
250293
tester("ntpath.realpath('.')", expected)

Lib/test/test_zipfile.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1468,10 +1468,10 @@ def test_extract_hackers_arcnames_windows_only(self):
14681468
(r'C:\foo\bar', 'foo/bar'),
14691469
(r'//conky/mountpoint/foo/bar', 'foo/bar'),
14701470
(r'\\conky\mountpoint\foo\bar', 'foo/bar'),
1471-
(r'///conky/mountpoint/foo/bar', 'conky/mountpoint/foo/bar'),
1472-
(r'\\\conky\mountpoint\foo\bar', 'conky/mountpoint/foo/bar'),
1473-
(r'//conky//mountpoint/foo/bar', 'conky/mountpoint/foo/bar'),
1474-
(r'\\conky\\mountpoint\foo\bar', 'conky/mountpoint/foo/bar'),
1471+
(r'///conky/mountpoint/foo/bar', 'mountpoint/foo/bar'),
1472+
(r'\\\conky\mountpoint\foo\bar', 'mountpoint/foo/bar'),
1473+
(r'//conky//mountpoint/foo/bar', 'mountpoint/foo/bar'),
1474+
(r'\\conky\\mountpoint\foo\bar', 'mountpoint/foo/bar'),
14751475
(r'//?/C:/foo/bar', 'foo/bar'),
14761476
(r'\\?\C:\foo\bar', 'foo/bar'),
14771477
(r'C:/../C:/foo/bar', 'C_/foo/bar'),
Lines changed: 5 additions & 0 deletions

0 commit comments

Comments
 (0)