]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
bpo-35474: Fix mimetypes.guess_all_extensions() potentially mutating list (GH-28286...
authorMiss Islington (bot) <31488909+miss-islington@users.noreply.github.com>
Mon, 13 Sep 2021 17:24:08 +0000 (10:24 -0700)
committerGitHub <noreply@github.com>
Mon, 13 Sep 2021 17:24:08 +0000 (19:24 +0200)
* Calling guess_all_extensions() with strict=False potentially
  mutated types_map_inv.
* Mutating the result of guess_all_extensions() mutated types_map_inv.
(cherry picked from commit 97ea18ecede8bfd33d5ab2dd0e7e2aada2051111)

Co-authored-by: Serhiy Storchaka <storchaka@gmail.com>
Lib/mimetypes.py
Lib/test/test_mimetypes.py
Misc/NEWS.d/next/Library/2021-09-11-10-45-12.bpo-35474.tEY3SD.rst [new file with mode: 0644]

index 92c2a470e9789df5ab41be97a14a562f6aff2398..d36e1664cdcc8267b93a834a9e3b9b81456adf19 100644 (file)
@@ -169,7 +169,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:
index 683d393fdb4913978a9e1ff92ac9cb5937d6baab..5d0615e99b4e4a32bd866f199da41b70a87b3cac 100644 (file)
@@ -107,20 +107,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 (file)
index 0000000..f4dd3b9
--- /dev/null
@@ -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.