]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
gh-126780: Fix `ntpath.normpath()` for drive-relative paths (GH-126801)
authorNice Zombies <nineteendo19d0@gmail.com>
Thu, 21 Nov 2024 14:43:36 +0000 (15:43 +0100)
committerGitHub <noreply@github.com>
Thu, 21 Nov 2024 14:43:36 +0000 (14:43 +0000)
Lib/test/test_ntpath.py
Lib/test/test_posixpath.py
Misc/NEWS.d/next/Library/2024-11-13-19-15-18.gh-issue-126780.ZZqJvI.rst [new file with mode: 0644]
Python/fileutils.c

index 4f59184dfcfdc7009967a62193c258314e4e38de..6715071af8c7522a1576c92164a4ba38d8eff487 100644 (file)
@@ -347,13 +347,18 @@ class TestNtpath(NtpathTestCase):
 
         tester("ntpath.normpath('..')", r'..')
         tester("ntpath.normpath('.')", r'.')
+        tester("ntpath.normpath('c:.')", 'c:')
         tester("ntpath.normpath('')", r'.')
         tester("ntpath.normpath('/')", '\\')
         tester("ntpath.normpath('c:/')", 'c:\\')
         tester("ntpath.normpath('/../.././..')", '\\')
         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('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('//machine/share//a/b')", r'\\machine\share\a\b')
 
index b39255ebc79ac196b1dc543ef7c750e446b51921..43e4fbc610e5f72f0fc24eafe86f7e8967aec5f7 100644 (file)
@@ -379,6 +379,7 @@ class PosixPathTest(unittest.TestCase):
         ("/.", "/"),
         ("/./", "/"),
         ("/.//.", "/"),
+        ("/./foo/bar", "/foo/bar"),
         ("/foo", "/foo"),
         ("/foo/bar", "/foo/bar"),
         ("//", "//"),
@@ -388,6 +389,7 @@ class PosixPathTest(unittest.TestCase):
         ("///..//./foo/.//bar", "/foo/bar"),
         (".", "."),
         (".//.", "."),
+        ("./foo/bar", "foo/bar"),
         ("..", ".."),
         ("../", ".."),
         ("../foo", "../foo"),
diff --git a/Misc/NEWS.d/next/Library/2024-11-13-19-15-18.gh-issue-126780.ZZqJvI.rst b/Misc/NEWS.d/next/Library/2024-11-13-19-15-18.gh-issue-126780.ZZqJvI.rst
new file mode 100644 (file)
index 0000000..93d45ca
--- /dev/null
@@ -0,0 +1 @@
+Fix :func:`os.path.normpath` for drive-relative paths on Windows.
index c9ae1b3f54e1675da32582cfc46136fec6f87c8e..9529b14d377c609472c3f69135a3bd37b3d30209 100644 (file)
@@ -2506,37 +2506,38 @@ _Py_normpath_and_size(wchar_t *path, Py_ssize_t size, Py_ssize_t *normsize)
 #endif
 #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_skiproot(path, size, &drvsize, &rootsize);
-        if (drvsize || rootsize) {
-            // Skip past root and update minP2
-            p1 = &path[drvsize + rootsize];
+    Py_ssize_t drvsize, rootsize;
+    _Py_skiproot(path, size, &drvsize, &rootsize);
+    if (drvsize || rootsize) {
+        // Skip past root and update minP2
+        p1 = &path[drvsize + rootsize];
 #ifndef ALTSEP
-            p2 = p1;
+        p2 = p1;
 #else
-            for (; p2 < p1; ++p2) {
-                if (*p2 == ALTSEP) {
-                    *p2 = SEP;
-                }
+        for (; p2 < p1; ++p2) {
+            if (*p2 == ALTSEP) {
+                *p2 = SEP;
             }
+        }
 #endif
-            minP2 = p2 - 1;
-            lastC = *minP2;
+        minP2 = p2 - 1;
+        lastC = *minP2;
 #ifdef MS_WINDOWS
-            if (lastC != SEP) {
-                minP2++;
-            }
+        if (lastC != SEP) {
+            minP2++;
+        }
+#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++;
         }
     }