You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
[ntpath] realpath fails for broken symlinks with rooted target paths #85035
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. The documented behavior of ntpath.isabs isn't something that we can change (i.e. "begins with a (back)slash after chopping off a potential drive letter"). So ntpath._readlink_deep needs a private implementation of isabs. For example:
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.
Background
The target of a relative symlink gets evaluated against the solid path that's used to access the link. A solid path contains directories and mountpoints, but no symlinks. In particular, a rooted target such as r"\spam\eggs" is relative to the root device of the solid 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 symlink is accessed via its DOS device name "V:", then it resolves to r"V:\spam\eggs". Similarly, if the symlink 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 symlink is accessed via the mount point r"C:\Mount\VolumeMountpoint", then it resolves to r"C:\spam\eggs".
changed the title [-]ntpath.realpath fails for broken symlinks with rooted target paths[/-][+][ntpath] realpath fails for broken symlinks with rooted target paths[/+]on Aug 8, 2022
Fixed in 3.13 by GH-113829, which made ntpath.isabs() return False for a rooted path without a drive, so _readlink_deep() now joins such target with the location of the link.
Activity
eryksun commentedon Jun 3, 2020
ntpath.realpathfails 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, butntpath.isabsincorrectly classifiesr"\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 aspathlib.Path.is_absoluteand C++path::is_absolute. The documented behavior ofntpath.isabsisn't something that we can change (i.e. "begins with a (back)slash after chopping off a potential drive letter"). Sontpath._readlink_deepneeds a private implementation ofisabs. For example: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.Background
The target of a relative symlink gets evaluated against the solid path that's used to access the link. A solid path contains directories and mountpoints, but no symlinks. In particular, a rooted target such as
r"\spam\eggs"is relative to the root device of the solid 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 symlink is accessed via its DOS device name "V:", then it resolves tor"V:\spam\eggs". Similarly, if the symlink is accessed viar"C:\Mount\VolumeSymlink", where "VolumeSymlink" is a directory symlink to"V:\\\\", then it also resolves tor"V:\spam\eggs". On the other hand, if the symlink is accessed via the mount pointr"C:\Mount\VolumeMountpoint", then it resolves tor"C:\spam\eggs".[-]ntpath.realpath fails for broken symlinks with rooted target paths[/-][+][ntpath] realpath fails for broken symlinks with rooted target paths[/+]serhiy-storchaka commentedon Aug 8, 2026
Fixed in 3.13 by GH-113829, which made
ntpath.isabs()returnFalsefor a rooted path without a drive, so_readlink_deep()now joins such target with the location of the link.@eryksun, is this the result you expected, and can the issue be closed?