From 27f32e938ff51fd5d90a29abbbabc6b81d156f33 Mon Sep 17 00:00:00 2001 From: Anthony Sottile Date: Mon, 15 Jan 2018 13:39:04 -0800 Subject: [PATCH] bpo-32539: Fix OSError for os.listdir() for extended-length paths on Windows (#5169) See https://msdn.microsoft.com/en-us/library/windows/desktop/aa365247(v=vs.85).aspx?f=255&MSPPError=-2147217396#maxpath Paths that begin with `\\?\` are "extended-length paths". --- Lib/test/test_os.py | 50 +++++++++++++++++++ .../2018-01-12-09-20-22.bpo-32539.D7AbdE.rst | 2 + Modules/posixmodule.c | 2 +- 3 files changed, 53 insertions(+), 1 deletion(-) create mode 100644 Misc/NEWS.d/next/Library/2018-01-12-09-20-22.bpo-32539.D7AbdE.rst diff --git a/Lib/test/test_os.py b/Lib/test/test_os.py index aca03fdabb..84e20e0c01 100644 --- a/Lib/test/test_os.py +++ b/Lib/test/test_os.py @@ -900,6 +900,56 @@ class Win32KillTests(unittest.TestCase): self._kill_with_event(signal.CTRL_BREAK_EVENT, "CTRL_BREAK_EVENT") +@unittest.skipUnless(sys.platform == "win32", "Win32 specific tests") +class Win32ListdirTests(unittest.TestCase): + """Test listdir on Windows.""" + + def setUp(self): + self.created_paths = [] + for i in range(2): + dir_name = 'SUB%d' % i + dir_path = os.path.join(support.TESTFN, dir_name) + file_name = 'FILE%d' % i + file_path = os.path.join(support.TESTFN, file_name) + os.makedirs(dir_path) + with open(file_path, 'w') as f: + f.write("I'm %s and proud of it. Blame test_os.\n" % file_path) + self.created_paths.extend([dir_name, file_name]) + self.created_paths.sort() + + def tearDown(self): + shutil.rmtree(support.TESTFN) + + def test_listdir_no_extended_path(self): + """Test when the path is not an "extended" path.""" + # unicode + fs_encoding = sys.getfilesystemencoding() + self.assertEqual( + sorted(os.listdir(support.TESTFN.decode(fs_encoding))), + [path.decode(fs_encoding) for path in self.created_paths]) + + # bytes + self.assertEqual( + sorted(os.listdir(os.fsencode(support.TESTFN))), + self.created_paths) + + def test_listdir_extended_path(self): + """Test when the path starts with '\\\\?\\'.""" + # See: http://msdn.microsoft.com/en-us/library/windows/desktop/aa365247(v=vs.85).aspx#maxpath + # unicode + fs_encoding = sys.getfilesystemencoding() + path = u'\\\\?\\' + os.path.abspath(support.TESTFN.decode(fs_encoding)) + self.assertEqual( + sorted(os.listdir(path)), + [path.decode(fs_encoding) for path in self.created_paths]) + + # bytes + path = b'\\\\?\\' + os.path.abspath(support.TESTFN) + self.assertEqual( + sorted(os.listdir(path)), + self.created_paths) + + class SpawnTests(unittest.TestCase): def _test_invalid_env(self, spawn): args = [sys.executable, '-c', 'pass'] diff --git a/Misc/NEWS.d/next/Library/2018-01-12-09-20-22.bpo-32539.D7AbdE.rst b/Misc/NEWS.d/next/Library/2018-01-12-09-20-22.bpo-32539.D7AbdE.rst new file mode 100644 index 0000000000..cc24a6b953 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2018-01-12-09-20-22.bpo-32539.D7AbdE.rst @@ -0,0 +1,2 @@ +Fix ``OSError`` for ``os.listdir`` with deep paths (starting with ``\\?\``) on +windows. Patch by Anthony Sottile. diff --git a/Modules/posixmodule.c b/Modules/posixmodule.c index c9886d514b..cecbb45fb4 100644 --- a/Modules/posixmodule.c +++ b/Modules/posixmodule.c @@ -2385,7 +2385,7 @@ posix_listdir(PyObject *self, PyObject *args) if (len > 0) { char ch = namebuf[len-1]; if (ch != SEP && ch != ALTSEP && ch != ':') - namebuf[len++] = '/'; + namebuf[len++] = SEP; strcpy(namebuf + len, "*.*"); } -- 2.50.1