diff --git a/Lib/glob.py b/Lib/glob.py index 36d493d7a80..7279244aa9a 100644 --- a/Lib/glob.py +++ b/Lib/glob.py @@ -29,7 +29,10 @@ def iglob(pathname): for name in glob1(None, basename): yield name return - if has_magic(dirname): + # `os.path.split()` returns the argument itself as a dirname if it is a + # drive or UNC path. Prevent an infinite recursion if a drive or UNC path + # contains magic characters (i.e. r'\\?\C:'). + if dirname != pathname and has_magic(dirname): dirs = iglob(dirname) else: dirs = [dirname] diff --git a/Lib/test/test_glob.py b/Lib/test/test_glob.py index 711369e289b..0083a70e7a4 100644 --- a/Lib/test/test_glob.py +++ b/Lib/test/test_glob.py @@ -3,6 +3,7 @@ from test.support import run_unittest, TESTFN, skip_unless_symlink, can_symlink import glob import os import shutil +import sys class GlobTests(unittest.TestCase): @@ -110,6 +111,18 @@ class GlobTests(unittest.TestCase): eq(self.glob('sym1'), [self.norm('sym1')]) eq(self.glob('sym2'), [self.norm('sym2')]) + @unittest.skipUnless(sys.platform == "win32", "Win32 specific test") + def test_glob_magic_in_drive(self): + eq = self.assertSequencesEqual_noorder + eq(glob.glob('*:'), []) + eq(glob.glob(b'*:'), []) + eq(glob.glob('?:'), []) + eq(glob.glob(b'?:'), []) + eq(glob.glob('\\\\?\\c:\\'), ['\\\\?\\c:\\']) + eq(glob.glob(b'\\\\?\\c:\\'), [b'\\\\?\\c:\\']) + eq(glob.glob('\\\\*\\*\\'), []) + eq(glob.glob(b'\\\\*\\*\\'), []) + def test_main(): run_unittest(GlobTests) diff --git a/Misc/NEWS b/Misc/NEWS index c5288f76e61..73f23982b3e 100644 --- a/Misc/NEWS +++ b/Misc/NEWS @@ -179,6 +179,10 @@ Core and Builtins Library ------- +- Issue #16626: Fix infinite recursion in glob.glob() on Windows when the + pattern contains a wildcard in the drive or UNC path. Patch by Serhiy + Storchaka. + - Issue #16298: In HTTPResponse.read(), close the socket when there is no Content-Length and the incoming stream is finished. Patch by Eran Rundstein.