diff options
author | neonene <53406459+neonene@users.noreply.github.com> | 2022-01-06 19:13:10 (GMT) |
---|---|---|
committer | GitHub <noreply@github.com> | 2022-01-06 19:13:10 (GMT) |
commit | 9c5fa9c97c5c5336e60e4ae7a2e6e3f67acedfc7 (patch) | |
tree | 97d9ab902046a3af10a6f44e9ad993d6e31c154a /Python/fileutils.c | |
parent | 9925e70e4811841556747a77acd89c1a70bf344a (diff) | |
download | cpython-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.c | 25 |
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) { |