]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
gh-130655: Add a test for corrupt `.mo` files in `gettext` (#131911)
authorTomas R. <tomas.roun8@gmail.com>
Fri, 4 Apr 2025 13:26:59 +0000 (15:26 +0200)
committerGitHub <noreply@github.com>
Fri, 4 Apr 2025 13:26:59 +0000 (13:26 +0000)
Lib/test/test_gettext.py

index 87a77aab19336ec48b835280523728137d96c6e0..d2f18f1dfede77db8856fd46dae28ea67b4b8724 100644 (file)
@@ -88,6 +88,32 @@ IHNiZSBsYmhlIENsZ3ViYSBjZWJ0ZW56ZiBvbCBjZWJpdnF2YXQgbmEgdmFncmVzbnByIGdiIGd1
 ciBUQUgKdHJnZ3JrZyB6cmZmbnRyIHBuZ255YnQgeXZvZW5lbC4AYmFjb24Ad2luayB3aW5rAA==
 '''
 
+# Corrupt .mo file
+# Generated from
+#
+# msgid "foo"
+# msgstr "bar"
+#
+# with msgfmt --no-hash
+#
+# The translation offset is changed to 0xFFFFFFFF,
+# making it larger than the file size, which should
+# raise an error when parsing.
+GNU_MO_DATA_CORRUPT = base64.b64encode(bytes([
+    0xDE, 0x12, 0x04, 0x95,  # Magic
+    0x00, 0x00, 0x00, 0x00,  # Version
+    0x01, 0x00, 0x00, 0x00,  # Message count
+    0x1C, 0x00, 0x00, 0x00,  # Message offset
+    0x24, 0x00, 0x00, 0x00,  # Translation offset
+    0x00, 0x00, 0x00, 0x00,  # Hash table size
+    0x2C, 0x00, 0x00, 0x00,  # Hash table offset
+    0x03, 0x00, 0x00, 0x00,  # 1st message length
+    0x2C, 0x00, 0x00, 0x00,  # 1st message offset
+    0x03, 0x00, 0x00, 0x00,  # 1st trans length
+    0xFF, 0xFF, 0xFF, 0xFF,  # 1st trans offset (Modified to make it invalid)
+    0x66, 0x6F, 0x6F, 0x00,  # Message data
+    0x62, 0x61, 0x72, 0x00,  # Message data
+]))
 
 UMO_DATA = b'''\
 3hIElQAAAAADAAAAHAAAADQAAAAAAAAAAAAAAAAAAABMAAAABAAAAE0AAAAQAAAAUgAAAA8BAABj
@@ -115,6 +141,7 @@ MOFILE = os.path.join(LOCALEDIR, 'gettext.mo')
 MOFILE_BAD_MAGIC_NUMBER = os.path.join(LOCALEDIR, 'gettext_bad_magic_number.mo')
 MOFILE_BAD_MAJOR_VERSION = os.path.join(LOCALEDIR, 'gettext_bad_major_version.mo')
 MOFILE_BAD_MINOR_VERSION = os.path.join(LOCALEDIR, 'gettext_bad_minor_version.mo')
+MOFILE_CORRUPT = os.path.join(LOCALEDIR, 'gettext_corrupt.mo')
 UMOFILE = os.path.join(LOCALEDIR, 'ugettext.mo')
 MMOFILE = os.path.join(LOCALEDIR, 'metadata.mo')
 
@@ -139,6 +166,8 @@ class GettextBaseTest(unittest.TestCase):
             fp.write(base64.decodebytes(GNU_MO_DATA_BAD_MAJOR_VERSION))
         with open(MOFILE_BAD_MINOR_VERSION, 'wb') as fp:
             fp.write(base64.decodebytes(GNU_MO_DATA_BAD_MINOR_VERSION))
+        with open(MOFILE_CORRUPT, 'wb') as fp:
+            fp.write(base64.decodebytes(GNU_MO_DATA_CORRUPT))
         with open(UMOFILE, 'wb') as fp:
             fp.write(base64.decodebytes(UMO_DATA))
         with open(MMOFILE, 'wb') as fp:
@@ -254,6 +283,16 @@ class GettextTestCase2(GettextBaseTest):
             # Check that no error is thrown with a bad minor version number
             gettext.GNUTranslations(fp)
 
+    def test_corrupt_file(self):
+        with open(MOFILE_CORRUPT, 'rb') as fp:
+            with self.assertRaises(OSError) as cm:
+                gettext.GNUTranslations(fp)
+
+            exception = cm.exception
+            self.assertEqual(exception.errno, 0)
+            self.assertEqual(exception.strerror, "File is corrupt")
+            self.assertEqual(exception.filename, MOFILE_CORRUPT)
+
     def test_some_translations(self):
         eq = self.assertEqual
         # test some translations