gh-142155: Fix infinite recursion in shutil.copytree on Windows junctions #142156
+52
−5
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Summary
This PR fixes a critical crash (WinError 206 / WinError 1921) in
shutil.copytreeon Windows when encountering directory junctions that point to a parent directory (recursive cycles).The Problem
On Windows,
shutil.copytreecontains specific logic to force traversal into Directory Junctions by treating them as standard directories (is_symlinkis forced toFalse).However, unlike
os.walkorshutil.rmtree(after recent fixes),copytreelacked a cycle detection mechanism for these traversed junctions. This caused infinite recursion until the path exceeded the OS limit, resulting in an unhandledOSError(Crash) rather than a PythonRecursionError.The Fix
I implemented cycle detection using file system identity (
st_dev,st_ino), similar to how deepcopy handles recursion:_seenset parameter tocopytreeand its helper_copytree.(st.st_dev, st.st_ino)is already in_seen.shutil.Error("Infinite recursion detected")immediately, preventing the crash.Verification
test_copytree_recursive_junctiontoLib/test/test_shutil.py.WinError 206crash.shutil.Error: Infinite recursion detected.