diff options
author | Serhiy Storchaka <storchaka@gmail.com> | 2021-09-11 14:44:44 (GMT) |
---|---|---|
committer | GitHub <noreply@github.com> | 2021-09-11 14:44:44 (GMT) |
commit | 97ea18ecede8bfd33d5ab2dd0e7e2aada2051111 (patch) | |
tree | 375b09e844662e59cb87d86bec7ea4c6a490f6c3 | |
parent | 5f5b7d0c654488206ac13e27d9a5dcffbd2cc0af (diff) | |
download | cpython-97ea18ecede8bfd33d5ab2dd0e7e2aada2051111.zip cpython-97ea18ecede8bfd33d5ab2dd0e7e2aada2051111.tar.gz cpython-97ea18ecede8bfd33d5ab2dd0e7e2aada2051111.tar.bz2 |
bpo-35474: Fix mimetypes.guess_all_extensions() potentially mutating list (GH-28286)
* Calling guess_all_extensions() with strict=False potentially
mutated types_map_inv.
* Mutating the result of guess_all_extensions() mutated types_map_inv.
-rw-r--r-- | Lib/mimetypes.py | 2 | ||||
-rw-r--r-- | Lib/test/test_mimetypes.py | 23 | ||||
-rw-r--r-- | Misc/NEWS.d/next/Library/2021-09-11-10-45-12.bpo-35474.tEY3SD.rst | 3 |
3 files changed, 20 insertions, 8 deletions
diff --git a/Lib/mimetypes.py b/Lib/mimetypes.py index b3d70e4..3ba9177 100644 --- a/Lib/mimetypes.py +++ b/Lib/mimetypes.py @@ -175,7 +175,7 @@ class MimeTypes: but non-standard types. """ type = type.lower() - extensions = self.types_map_inv[True].get(type, []) + extensions = list(self.types_map_inv[True].get(type, [])) if not strict: for ext in self.types_map_inv[False].get(type, []): if ext not in extensions: diff --git a/Lib/test/test_mimetypes.py b/Lib/test/test_mimetypes.py index fb9cb04..4098a22 100644 --- a/Lib/test/test_mimetypes.py +++ b/Lib/test/test_mimetypes.py @@ -113,20 +113,29 @@ class MimeTypesTestCase(unittest.TestCase): eq(self.db.guess_type(r" \"\`;b&b&c |.tar.gz"), gzip_expected) def test_guess_all_types(self): - eq = self.assertEqual - unless = self.assertTrue # First try strict. Use a set here for testing the results because if # test_urllib2 is run before test_mimetypes, global state is modified # such that the 'all' set will have more items in it. - all = set(self.db.guess_all_extensions('text/plain', strict=True)) - unless(all >= set(['.bat', '.c', '.h', '.ksh', '.pl', '.txt'])) + all = self.db.guess_all_extensions('text/plain', strict=True) + self.assertTrue(set(all) >= {'.bat', '.c', '.h', '.ksh', '.pl', '.txt'}) + self.assertEqual(len(set(all)), len(all)) # no duplicates # And now non-strict all = self.db.guess_all_extensions('image/jpg', strict=False) - all.sort() - eq(all, ['.jpg']) + self.assertEqual(all, ['.jpg']) # And now for no hits all = self.db.guess_all_extensions('image/jpg', strict=True) - eq(all, []) + self.assertEqual(all, []) + # And now for type existing in both strict and non-strict mappings. + self.db.add_type('test-type', '.strict-ext') + self.db.add_type('test-type', '.non-strict-ext', strict=False) + all = self.db.guess_all_extensions('test-type', strict=False) + self.assertEqual(all, ['.strict-ext', '.non-strict-ext']) + all = self.db.guess_all_extensions('test-type') + self.assertEqual(all, ['.strict-ext']) + # Test that changing the result list does not affect the global state + all.append('.no-such-ext') + all = self.db.guess_all_extensions('test-type') + self.assertNotIn('.no-such-ext', all) def test_encoding(self): getpreferredencoding = locale.getpreferredencoding diff --git a/Misc/NEWS.d/next/Library/2021-09-11-10-45-12.bpo-35474.tEY3SD.rst b/Misc/NEWS.d/next/Library/2021-09-11-10-45-12.bpo-35474.tEY3SD.rst new file mode 100644 index 0000000..f4dd3b9 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2021-09-11-10-45-12.bpo-35474.tEY3SD.rst @@ -0,0 +1,3 @@ +Calling :func:`mimetypes.guess_all_extensions` with ``strict=False`` no +longer affects the result of the following call with ``strict=True``. +Also, mutating the returned list no longer affects the global state. |