New submission from Eryk Sun <[email protected]>:
ntpath.realpath fails to resolve the non-strict path of a broken relative
symlink if the target is a rooted path. For example:
>>> os.readlink('symlink')
'\\broken\\link'
>>> os.path.realpath('symlink')
'\\broken\\link'
>>> os.path.abspath('symlink')
'C:\\Temp\\symlink'
The problem is that relative paths have to be specially handled by
ntpath._readlink_deep, but ntpath.isabs incorrectly classifies r"\broken\link"
as an absolute path. It's actually relative to the current device or drive in
the access context. Other path libraries get this right, such as
pathlib.Path.is_absolute and C++ path::is_absolute [1]. The documented behavior
of ntpath.isabs (i.e. "begins with a (back)slash after chopping off a potential
drive letter") isn't something that we can change. So ntpath._readlink_deep
needs a private implementation of isabs. For example:
def _isabs(s):
s = os.fspath(s)
seps = _get_bothseps(s)
s = s[1:2] if (s and s[0] in seps) else splitdrive(s)[1]
return bool(s) and s[0] in seps
This classifies UNC paths as absolute; rooted paths without a drive as
relative; and otherwise depends on splitdrive() to get the root path, if any.
[1]:
https://docs.microsoft.com/en-us/cpp/standard-library/path-class?view=vs-2019#is_absolute
----
Background
The target of a relative symlink gets evaluated against the hard path that's
used to access the link. A hard path contains directories and mountpoints, but
no symlinks. In particular, a rooted symlink target such as r"\spam\eggs" is
relative to the root device of the hard path that's used to access the link.
This may or may not be the device on which the link resides. It depends on how
it's accessed. For example, if the volume that contains the r"\spam\eggs" link
is accessed via its DOS device name "V:", then it resolves to r"V:\spam\eggs".
Similarly, if the r"\spam\eggs" link is accessed via r"C:\Mount\VolumeSymlink",
where "VolumeSymlink" is a directory symlink to "V:\\", then it also resolves
to r"V:\spam\eggs". On the other hand, if the r"\spam\eggs" link is accessed
via the mountpoint r"C:\Mount\VolumeMountpoint", then it resolves to
r"C:\spam\eggs".
----------
components: Library (Lib), Windows
messages: 370690
nosy: eryksun, paul.moore, steve.dower, tim.golden, zach.ware
priority: normal
severity: normal
stage: needs patch
status: open
title: ntpath.realpath fails for broken symlinks with rooted target paths
type: behavior
versions: Python 3.10, Python 3.8, Python 3.9
_______________________________________
Python tracker <[email protected]>
<https://bugs.python.org/issue40858>
_______________________________________
_______________________________________________
Python-bugs-list mailing list
Unsubscribe:
https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com