-
-
Notifications
You must be signed in to change notification settings - Fork 32.4k
Description
Bug report
Bug description:
Note that
_readlink_deep()
does nothing to ensure that the result is a final, normalized pathname. It just tries to keep reading symlinks until the target isn't a symlink or access/reading fails in a manner that's allowed. If it succeeds, the resulting pathname may include any number of symlinks, mount points, and short names._getfinalpathname_nonstrict()
should instead pass both the pathname and theseen
set into_readlink_deep()
. If it succeeds, then add the resulting pathname to the set, and continue the loop to try to get a final, normalized pathname.Originally posted by @eryksun in #110298 (comment)
I was able to reproduce this issue. Run the following code block with Administrator privileges in Windows:
mkdir C:\testdir
mkdir C:\testdir\real
echo 1 > C:\testdir\real\file.txt
icacls C:\testdir\real\file.txt /deny *S-1-5-32-545:(S)
mklink /d C:\testdir\symlink1 C:\testdir\real
mklink /d C:\testdir\symlink2 C:\testdir\symlink1
mklink C:\testdir\symlink2\filelink.txt C:\testdir\symlink1\file.txt
python -c "import ntpath; print(ntpath.realpath('C:\\testdir\\symlink2\\filelink.txt'))"
REM Cleanup
icacls C:\testdir\real\file.txt /grant *S-1-5-32-545:(S)
rmdir C:\testdir /s /q
Expected output:
C:\testdir\real\file.txt
Actual output:
C:\testdir\symlink1\file.txt
This happens because _getfinalpathname_nonstrict()
returns the result of _readlink_deep()
if the return value is different from the input.
Lines 680 to 686 in 92ca90b
try: | |
# The OS could not resolve this path fully, so we attempt | |
# to follow the link ourselves. If we succeed, join the tail | |
# and return. | |
new_path = _readlink_deep(path) | |
if new_path != path: | |
return join(new_path, tail) if tail else new_path |
However, because _readlink_deep()
does not ensure that it's result is a final, normalized pathname, ntpath.realpath()
result is not ensured to be a final, normalized pathname.
I'll try to come up with a patch. @eryksun, if you have any further discussions or comments on how this should be fixed, please let me know in the comments.
CPython versions tested on:
CPython main branch
Operating systems tested on:
Windows