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
os.path.realpath() on Windows misresolves a broken symlink reached through a directory symlink #160506
On Windows, os.path.realpath() returns the wrong path for a broken relative symlink when the path used to reach it goes through a symlink to a directory. ntpath._readlink_deep() joins the link target to dirname() of the path as given, so a .. in the target removes the directory link's name instead of going up from the directory that contains the link. The join dates from bpo-38453 (GH-16967).
tarfile's data and tar extraction filters use this result to decide where a member will be written. Whoever supplies the archive can make extractall() create a new file outside the destination directory, in a directory that already exists, when the extracting process is able to create symlinks.
# Windows, with permission to create symlinksimportosos.makedirs(r"C:\work\out")
os.symlink(".", r"C:\work\out\alias", target_is_directory=True)
os.symlink(r"..\outside\new.txt", r"C:\work\out\link")
print(os.path.realpath(r"C:\work\out\link"))
print(os.path.realpath(r"C:\work\out\alias\link"))
Both names are the same link, so both lines should be C:\work\outside\new.txt; the second is C:\work\out\outside\new.txt. Opening either name for writing creates C:\work\outside\new.txt.
An archive with the members alias -> ., alias/link -> ../outside/new.txt and a regular file alias/link is extracted by extractall(r"C:\work\out", filter="data") without error and the file's content ends up in C:\work\outside\new.txt. The same archive with the regular file named link raises OutsideDestinationError.
I have not run this on Windows. The output above comes from running the Windows branch of Lib/ntpath.py and Lib/tarfile.py from main on Linux over stand-ins for the nt functions, and from reading the code. test_realpath_broken_symlinks in test_ntpath already asserts the textual join (broken2, broken3). gh-88102, gh-85035 and gh-110495 are related realpath() issues but do not cover this case.
Activity