gh-126780: Fix ntpath.normpath() for drive-relative paths (GH-126801)

This commit is contained in:
Nice Zombies 2024-11-21 15:43:36 +01:00 committed by GitHub
parent 0c5556fcb7
commit 60ec854bc2
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
4 changed files with 34 additions and 25 deletions

View file

@ -347,13 +347,18 @@ class TestNtpath(NtpathTestCase):
tester("ntpath.normpath('..')", r'..') tester("ntpath.normpath('..')", r'..')
tester("ntpath.normpath('.')", r'.') tester("ntpath.normpath('.')", r'.')
tester("ntpath.normpath('c:.')", 'c:')
tester("ntpath.normpath('')", r'.') tester("ntpath.normpath('')", r'.')
tester("ntpath.normpath('/')", '\\') tester("ntpath.normpath('/')", '\\')
tester("ntpath.normpath('c:/')", 'c:\\') tester("ntpath.normpath('c:/')", 'c:\\')
tester("ntpath.normpath('/../.././..')", '\\') tester("ntpath.normpath('/../.././..')", '\\')
tester("ntpath.normpath('c:/../../..')", 'c:\\') tester("ntpath.normpath('c:/../../..')", 'c:\\')
tester("ntpath.normpath('/./a/b')", r'\a\b')
tester("ntpath.normpath('c:/./a/b')", r'c:\a\b')
tester("ntpath.normpath('../.././..')", r'..\..\..') tester("ntpath.normpath('../.././..')", r'..\..\..')
tester("ntpath.normpath('K:../.././..')", r'K:..\..\..') tester("ntpath.normpath('K:../.././..')", r'K:..\..\..')
tester("ntpath.normpath('./a/b')", r'a\b')
tester("ntpath.normpath('c:./a/b')", r'c:a\b')
tester("ntpath.normpath('C:////a/b')", r'C:\a\b') tester("ntpath.normpath('C:////a/b')", r'C:\a\b')
tester("ntpath.normpath('//machine/share//a/b')", r'\\machine\share\a\b') tester("ntpath.normpath('//machine/share//a/b')", r'\\machine\share\a\b')

View file

@ -379,6 +379,7 @@ class PosixPathTest(unittest.TestCase):
("/.", "/"), ("/.", "/"),
("/./", "/"), ("/./", "/"),
("/.//.", "/"), ("/.//.", "/"),
("/./foo/bar", "/foo/bar"),
("/foo", "/foo"), ("/foo", "/foo"),
("/foo/bar", "/foo/bar"), ("/foo/bar", "/foo/bar"),
("//", "//"), ("//", "//"),
@ -388,6 +389,7 @@ class PosixPathTest(unittest.TestCase):
("///..//./foo/.//bar", "/foo/bar"), ("///..//./foo/.//bar", "/foo/bar"),
(".", "."), (".", "."),
(".//.", "."), (".//.", "."),
("./foo/bar", "foo/bar"),
("..", ".."), ("..", ".."),
("../", ".."), ("../", ".."),
("../foo", "../foo"), ("../foo", "../foo"),

View file

@ -0,0 +1 @@
Fix :func:`os.path.normpath` for drive-relative paths on Windows.

View file

@ -2506,16 +2506,6 @@ _Py_normpath_and_size(wchar_t *path, Py_ssize_t size, Py_ssize_t *normsize)
#endif #endif
#define SEP_OR_END(x) (IS_SEP(x) || IS_END(x)) #define SEP_OR_END(x) (IS_SEP(x) || IS_END(x))
if (p1[0] == L'.' && IS_SEP(&p1[1])) {
// Skip leading '.\'
path = &path[2];
while (IS_SEP(path)) {
path++;
}
p1 = p2 = minP2 = path;
lastC = SEP;
}
else {
Py_ssize_t drvsize, rootsize; Py_ssize_t drvsize, rootsize;
_Py_skiproot(path, size, &drvsize, &rootsize); _Py_skiproot(path, size, &drvsize, &rootsize);
if (drvsize || rootsize) { if (drvsize || rootsize) {
@ -2538,6 +2528,17 @@ _Py_normpath_and_size(wchar_t *path, Py_ssize_t size, Py_ssize_t *normsize)
} }
#endif #endif
} }
if (p1[0] == L'.' && SEP_OR_END(&p1[1])) {
// Skip leading '.\'
lastC = *++p1;
#ifdef ALTSEP
if (lastC == ALTSEP) {
lastC = SEP;
}
#endif
while (IS_SEP(p1)) {
p1++;
}
} }
/* if pEnd is specified, check that. Else, check for null terminator */ /* if pEnd is specified, check that. Else, check for null terminator */