summaryrefslogtreecommitdiffstats
path: root/Python/fileutils.c
diff options
context:
space:
mode:
authorneonene <53406459+neonene@users.noreply.github.com>2022-01-06 19:13:10 (GMT)
committerGitHub <noreply@github.com>2022-01-06 19:13:10 (GMT)
commit9c5fa9c97c5c5336e60e4ae7a2e6e3f67acedfc7 (patch)
tree97d9ab902046a3af10a6f44e9ad993d6e31c154a /Python/fileutils.c
parent9925e70e4811841556747a77acd89c1a70bf344a (diff)
downloadcpython-9c5fa9c97c5c5336e60e4ae7a2e6e3f67acedfc7.zip
cpython-9c5fa9c97c5c5336e60e4ae7a2e6e3f67acedfc7.tar.gz
cpython-9c5fa9c97c5c5336e60e4ae7a2e6e3f67acedfc7.tar.bz2
bpo-46208: Fix normalization of relative paths in _Py_normpath()/os.path.normpath (GH-30362)
Diffstat (limited to 'Python/fileutils.c')
-rw-r--r--Python/fileutils.c25
1 files changed, 16 insertions, 9 deletions
diff --git a/Python/fileutils.c b/Python/fileutils.c
index cae6b75..d570be5 100644
--- a/Python/fileutils.c
+++ b/Python/fileutils.c
@@ -2218,11 +2218,11 @@ _Py_normpath(wchar_t *path, Py_ssize_t size)
if (!path[0] || size == 0) {
return path;
}
- wchar_t lastC = L'\0';
- wchar_t *p1 = path;
wchar_t *pEnd = size >= 0 ? &path[size] : NULL;
- wchar_t *p2 = path;
- wchar_t *minP2 = path;
+ wchar_t *p1 = path; // sequentially scanned address in the path
+ wchar_t *p2 = path; // destination of a scanned character to be ljusted
+ wchar_t *minP2 = path; // the beginning of the destination range
+ wchar_t lastC = L'\0'; // the last ljusted character, p2[-1] in most cases
#define IS_END(x) (pEnd ? (x) == pEnd : !*(x))
#ifdef ALTSEP
@@ -2264,14 +2264,18 @@ _Py_normpath(wchar_t *path, Py_ssize_t size)
*p2++ = lastC = *p1;
}
}
- minP2 = p2;
+ if (sepCount) {
+ minP2 = p2; // Invalid path
+ } else {
+ minP2 = p2 - 1; // Absolute path has SEP at minP2
+ }
}
#else
// Skip past two leading SEPs
else if (IS_SEP(&p1[0]) && IS_SEP(&p1[1]) && !IS_SEP(&p1[2])) {
*p2++ = *p1++;
*p2++ = *p1++;
- minP2 = p2;
+ minP2 = p2 - 1; // Absolute path has SEP at minP2
lastC = SEP;
}
#endif /* MS_WINDOWS */
@@ -2292,8 +2296,11 @@ _Py_normpath(wchar_t *path, Py_ssize_t size)
wchar_t *p3 = p2;
while (p3 != minP2 && *--p3 == SEP) { }
while (p3 != minP2 && *(p3 - 1) != SEP) { --p3; }
- if (p3[0] == L'.' && p3[1] == L'.' && IS_SEP(&p3[2])) {
- // Previous segment is also ../, so append instead
+ if (p2 == minP2
+ || (p3[0] == L'.' && p3[1] == L'.' && IS_SEP(&p3[2])))
+ {
+ // Previous segment is also ../, so append instead.
+ // Relative path does not absorb ../ at minP2 as well.
*p2++ = L'.';
*p2++ = L'.';
lastC = L'.';
@@ -2314,7 +2321,7 @@ _Py_normpath(wchar_t *path, Py_ssize_t size)
}
} else {
*p2++ = lastC = c;
- }
+ }
}
*p2 = L'\0';
if (p2 != minP2) {