From 630df37116b1c5b381984c547ef9d23792ceb464 Mon Sep 17 00:00:00 2001 From: Barney Gale Date: Wed, 10 Apr 2024 18:17:18 +0100 Subject: GH-117546: Fix symlink resolution in `os.path.realpath('loop/../link')` (#117568) Continue resolving symlink targets after encountering a symlink loop, which matches coreutils `realpath` behaviour. --- Doc/library/os.path.rst | 5 ++--- Lib/posixpath.py | 15 ++------------- Lib/test/test_posixpath.py | 2 +- .../2024-04-05-13-38-53.gh-issue-117546.lWjhHE.rst | 2 ++ 4 files changed, 7 insertions(+), 17 deletions(-) create mode 100644 Misc/NEWS.d/next/Library/2024-04-05-13-38-53.gh-issue-117546.lWjhHE.rst diff --git a/Doc/library/os.path.rst b/Doc/library/os.path.rst index fcf4b6d..ebeb3bb 100644 --- a/Doc/library/os.path.rst +++ b/Doc/library/os.path.rst @@ -409,9 +409,8 @@ the :mod:`glob` module.) style names such as ``C:\\PROGRA~1`` to ``C:\\Program Files``. If a path doesn't exist or a symlink loop is encountered, and *strict* is - ``True``, :exc:`OSError` is raised. If *strict* is ``False``, the path is - resolved as far as possible and any remainder is appended without checking - whether it exists. + ``True``, :exc:`OSError` is raised. If *strict* is ``False`` these errors + are ignored, and so the result might be missing or otherwise inaccessible. .. note:: This function emulates the operating system's procedure for making a path diff --git a/Lib/posixpath.py b/Lib/posixpath.py index 79e6558..8fd49cd 100644 --- a/Lib/posixpath.py +++ b/Lib/posixpath.py @@ -431,11 +431,6 @@ symbolic links encountered in the path.""" # the same links. seen = {} - # Whether we're calling lstat() and readlink() to resolve symlinks. If we - # encounter an OSError for a symlink loop in non-strict mode, this is - # switched off. - querying = True - while rest: name = rest.pop() if name is None: @@ -453,9 +448,6 @@ symbolic links encountered in the path.""" newpath = path + name else: newpath = path + sep + name - if not querying: - path = newpath - continue try: st = os.lstat(newpath) if not stat.S_ISLNK(st.st_mode): @@ -477,11 +469,8 @@ symbolic links encountered in the path.""" if strict: # Raise OSError(errno.ELOOP) os.stat(newpath) - else: - # Return already resolved part + rest of the path unchanged. - path = newpath - querying = False - continue + path = newpath + continue seen[newpath] = None # not resolved symlink target = os.readlink(newpath) if target.startswith(sep): diff --git a/Lib/test/test_posixpath.py b/Lib/test/test_posixpath.py index ff78410..248fe2c 100644 --- a/Lib/test/test_posixpath.py +++ b/Lib/test/test_posixpath.py @@ -484,7 +484,7 @@ class PosixPathTest(unittest.TestCase): self.assertEqual(realpath(ABSTFN+"1/../x"), dirname(ABSTFN) + "/x") os.symlink(ABSTFN+"x", ABSTFN+"y") self.assertEqual(realpath(ABSTFN+"1/../" + basename(ABSTFN) + "y"), - ABSTFN + "y") + ABSTFN + "x") self.assertEqual(realpath(ABSTFN+"1/../" + basename(ABSTFN) + "1"), ABSTFN + "1") diff --git a/Misc/NEWS.d/next/Library/2024-04-05-13-38-53.gh-issue-117546.lWjhHE.rst b/Misc/NEWS.d/next/Library/2024-04-05-13-38-53.gh-issue-117546.lWjhHE.rst new file mode 100644 index 0000000..9762991 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2024-04-05-13-38-53.gh-issue-117546.lWjhHE.rst @@ -0,0 +1,2 @@ +Fix issue where :func:`os.path.realpath` stopped resolving symlinks after +encountering a symlink loop on POSIX. -- cgit v0.12