diff options
author | Barney Gale <barney.gale@gmail.com> | 2023-01-12 19:24:57 (GMT) |
---|---|---|
committer | GitHub <noreply@github.com> | 2023-01-12 19:24:57 (GMT) |
commit | 005e69403d638f9ff8f71e59960c600016e101a4 (patch) | |
tree | e91cca78084f6b4efcf56c66162bf45f3d7c4c0e /Lib/ntpath.py | |
parent | eecd422d1ba849f0724962666ba840581217812b (diff) | |
download | cpython-005e69403d638f9ff8f71e59960c600016e101a4.zip cpython-005e69403d638f9ff8f71e59960c600016e101a4.tar.gz cpython-005e69403d638f9ff8f71e59960c600016e101a4.tar.bz2 |
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: Eryk Sun <eryksun@gmail.com>
Diffstat (limited to 'Lib/ntpath.py')
-rw-r--r-- | Lib/ntpath.py | 55 |
1 files changed, 21 insertions, 34 deletions
diff --git a/Lib/ntpath.py b/Lib/ntpath.py index 265eaa8..cd7fb58 100644 --- a/Lib/ntpath.py +++ b/Lib/ntpath.py @@ -87,16 +87,20 @@ except ImportError: def isabs(s): """Test whether a path is absolute""" s = os.fspath(s) - # Paths beginning with \\?\ are always absolute, but do not - # necessarily contain a drive. if isinstance(s, bytes): - if s.replace(b'/', b'\\').startswith(b'\\\\?\\'): - return True + sep = b'\\' + altsep = b'/' + colon_sep = b':\\' else: - if s.replace('/', '\\').startswith('\\\\?\\'): - return True - s = splitdrive(s)[1] - return len(s) > 0 and s[0] and s[0] in _get_bothseps(s) + sep = '\\' + altsep = '/' + colon_sep = ':\\' + s = s[:3].replace(altsep, sep) + # Absolute: UNC, device, and paths with a drive and root. + # LEGACY BUG: isabs("/x") should be false since the path has no drive. + if s.startswith(sep) or s.startswith(colon_sep, 1): + return True + return False # Join two (or more) paths. @@ -172,34 +176,26 @@ def splitdrive(p): sep = b'\\' altsep = b'/' colon = b':' - unc_prefix = b'\\\\?\\UNC' + unc_prefix = b'\\\\?\\UNC\\' else: sep = '\\' altsep = '/' colon = ':' - unc_prefix = '\\\\?\\UNC' + unc_prefix = '\\\\?\\UNC\\' normp = p.replace(altsep, sep) - if (normp[0:2] == sep*2) and (normp[2:3] != sep): - # is a UNC path: - # vvvvvvvvvvvvvvvvvvvv drive letter or UNC path - # \\machine\mountpoint\directory\etc\... - # directory ^^^^^^^^^^^^^^^ - if normp[:8].upper().rstrip(sep) == unc_prefix: - start = 8 - else: - start = 2 + if normp[0:2] == sep * 2: + # UNC drives, e.g. \\server\share or \\?\UNC\server\share + # Device drives, e.g. \\.\device or \\?\device + start = 8 if normp[:8].upper() == unc_prefix else 2 index = normp.find(sep, start) if index == -1: - return p[:0], p + return p, p[:0] index2 = normp.find(sep, index + 1) - # a UNC path can't have two slashes in a row - # (after the initial two) - if index2 == index + 1: - return p[:0], p if index2 == -1: - index2 = len(p) + return p, p[:0] return p[:index2], p[index2:] if normp[1:2] == colon: + # Drive-letter drives, e.g. X: return p[:2], p[2:] return p[:0], p @@ -523,20 +519,11 @@ except ImportError: altsep = b'/' curdir = b'.' pardir = b'..' - special_prefixes = (b'\\\\.\\', b'\\\\?\\') else: sep = '\\' altsep = '/' curdir = '.' pardir = '..' - special_prefixes = ('\\\\.\\', '\\\\?\\') - if path.startswith(special_prefixes): - # in the case of paths with these prefixes: - # \\.\ -> device names - # \\?\ -> literal paths - # do not do any normalization, but return the path - # unchanged apart from the call to os.fspath() - return path path = path.replace(altsep, sep) prefix, path = splitdrive(path) |