]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
posixpath.realpath() now detects loops from symlinks and returns the longest
authorBrett Cannon <bcannon@gmail.com>
Sat, 10 Jul 2004 22:58:32 +0000 (22:58 +0000)
committerBrett Cannon <bcannon@gmail.com>
Sat, 10 Jul 2004 22:58:32 +0000 (22:58 +0000)
path before recursion.

Lib/posixpath.py
Misc/NEWS

index 1d225ae7d3cdae3c412618ed2c256dd9c082c824..5ee25843f714ce8e4cdd179646d65dee9ee3400f 100644 (file)
@@ -408,13 +408,37 @@ symbolic links encountered in the path."""
     bits = ['/'] + filename.split('/')[1:]
     for i in range(2, len(bits)+1):
         component = join(*bits[0:i])
-        if islink(component):
-            resolved = os.readlink(component)
-            (dir, file) = split(component)
-            resolved = normpath(join(dir, resolved))
-            newpath = join(*([resolved] + bits[i:]))
-            return realpath(newpath)
+        # Resolve symbolic links.
+       if islink(component):
+            resolved = _resolve_link(component)
+            if resolved is None:
+                # Infinite loop -- return original component + rest of the path
+                return join(*([component] + bits[i:]))
+            else:
+                newpath = join(*([resolved] + bits[i:]))
+                return realpath(newpath)
 
     return filename
 
+
+def _resolve_link(path):
+    """Internal helper function.  Takes a path and follows symlinks
+    until we either arrive at something that isn't a symlink, or 
+    encounter a path we've seen before (meaning that there's a loop).
+    """
+    paths_seen = []
+    while islink(path):
+       if path in paths_seen:
+            # Already seen this path, so we must have a symlink loop
+            return None
+       paths_seen.append(path)
+        # Resolve where the link points to
+       resolved = os.readlink(path)
+        if not abspath(resolved):
+            dir = dirname(path)
+            path = normpath(join(dir, resolved))
+        else:
+            path = normpath(resolved)
+    return path
+
 supports_unicode_filenames = False
index 46050d7cb80077592198b3e5b7d7c46ee5093c23..4ac67d4be5e5ed91e27c4fffaa22d4f5d5070ab1 100644 (file)
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -40,6 +40,9 @@ Extension modules
 Library
 -------
 
+- Bug #930024: posixpath.realpath() now detects loops from symlinks and returns
+  the longest path before the loop begins.
+
 - Bug #980327/Patch #988607: ntpath now compresses extra slashes between the
   drive letter and the rest of the path properly.  Also removed ambiguity from
   UNC paths.  Thanks Paul Moore.