From 884afd92f5a194e326df2be8279d4ab160c7b0c9 Mon Sep 17 00:00:00 2001 From: Berker Peksag Date: Wed, 10 Dec 2014 02:50:32 +0200 Subject: Issue #21775: shutil.copytree(): fix crash when copying to VFAT An exception handler assumed that that OSError objects always have a 'winerror' attribute. That is not the case, so the exception handler itself raised AttributeError when run on Linux (and, presumably, any other non-Windows OS). Patch by Greg Ward. --- Lib/shutil.py | 2 +- Lib/test/test_shutil.py | 15 +++++++++++++++ Misc/NEWS | 6 ++++++ 3 files changed, 22 insertions(+), 1 deletion(-) diff --git a/Lib/shutil.py b/Lib/shutil.py index 22958f4..ac06ae5 100644 --- a/Lib/shutil.py +++ b/Lib/shutil.py @@ -337,7 +337,7 @@ def copytree(src, dst, symlinks=False, ignore=None, copy_function=copy2, copystat(src, dst) except OSError as why: # Copying file access times may fail on Windows - if why.winerror is None: + if getattr(why, 'winerror', None) is None: errors.append((src, dst, str(why))) if errors: raise Error(errors) diff --git a/Lib/test/test_shutil.py b/Lib/test/test_shutil.py index 3490362..9325bc7 100644 --- a/Lib/test/test_shutil.py +++ b/Lib/test/test_shutil.py @@ -1,6 +1,7 @@ # Copyright (C) 2003 Python Software Foundation import unittest +import unittest.mock import shutil import tempfile import sys @@ -758,6 +759,20 @@ class TestShutil(unittest.TestCase): self.assertEqual(os.stat(restrictive_subdir).st_mode, os.stat(restrictive_subdir_dst).st_mode) + @unittest.mock.patch('os.chmod') + def test_copytree_winerror(self, mock_patch): + # When copying to VFAT, copystat() raises OSError. On Windows, the + # exception object has a meaningful 'winerror' attribute, but not + # on other operating systems. Do not assume 'winerror' is set. + src_dir = tempfile.mkdtemp() + dst_dir = os.path.join(tempfile.mkdtemp(), 'destination') + self.addCleanup(shutil.rmtree, src_dir) + self.addCleanup(shutil.rmtree, os.path.dirname(dst_dir)) + + mock_patch.side_effect = PermissionError('ka-boom') + with self.assertRaises(shutil.Error): + shutil.copytree(src_dir, dst_dir) + @unittest.skipIf(os.name == 'nt', 'temporarily disabled on Windows') @unittest.skipUnless(hasattr(os, 'link'), 'requires os.link') def test_dont_copy_file_onto_link_to_itself(self): diff --git a/Misc/NEWS b/Misc/NEWS index 6c0c1f2..4807dc4 100644 --- a/Misc/NEWS +++ b/Misc/NEWS @@ -39,6 +39,12 @@ Core and Builtins Library ------- +- Issue #21775: shutil.copytree(): fix crash when copying to VFAT. An exception + handler assumed that that OSError objects always have a 'winerror' attribute. + That is not the case, so the exception handler itself raised AttributeError + when run on Linux (and, presumably, any other non-Windows OS). + Patch by Greg Ward. + - Issue #1218234: Fix inspect.getsource() to load updated source of reloaded module. Initial patch by Berker Peksag. -- cgit v0.12