]> granicus.if.org Git - python/commitdiff
bpo-6584: Add a BadGzipFile exception to the gzip module. (GH-13022)
authorZackery Spytz <zspytz@gmail.com>
Mon, 13 May 2019 07:50:52 +0000 (01:50 -0600)
committerSerhiy Storchaka <storchaka@gmail.com>
Mon, 13 May 2019 07:50:52 +0000 (10:50 +0300)
Co-Authored-By: Filip Gruszczyński <gruszczy@gmail.com>
Co-Authored-By: Michele Orrù <maker@tumbolandia.net>
Doc/library/gzip.rst
Doc/whatsnew/3.8.rst
Lib/gzip.py
Lib/test/test_gzip.py
Misc/NEWS.d/next/Library/2019-04-30-04-34-53.bpo-6584.Hzp9-P.rst [new file with mode: 0644]

index 8850a33f4abb908a0b5e6bba39ab80dc71a6ed8d..3349a94446d0ce59919146c44e7303cc1eb3c50a 100644 (file)
@@ -59,6 +59,14 @@ The module defines the following items:
    .. versionchanged:: 3.6
       Accepts a :term:`path-like object`.
 
+.. exception:: BadGzipFile
+
+   An exception raised for invalid gzip files.  It inherits :exc:`OSError`.
+   :exc:`EOFError` and :exc:`zlib.error` can also be raised for invalid gzip
+   files.
+
+   .. versionadded:: 3.8
+
 .. class:: GzipFile(filename=None, mode=None, compresslevel=9, fileobj=None, mtime=None)
 
    Constructor for the :class:`GzipFile` class, which simulates most of the
index 2cfb110b3d50ee88f5846e53a6fcf2103fe47f4e..684656fc2a58f6304e201ddcf25ac99562829bf4 100644 (file)
@@ -304,6 +304,11 @@ gzip
 Added the *mtime* parameter to :func:`gzip.compress` for reproducible output.
 (Contributed by Guo Ci Teo in :issue:`34898`.)
 
+A :exc:`~gzip.BadGzipFile` exception is now raised instead of :exc:`OSError`
+for certain types of invalid or corrupt gzip files.
+(Contributed by Filip Gruszczyński, Michele Orrù, and Zackery Spytz in
+:issue:`6584`.)
+
 
 idlelib and IDLE
 ----------------
index 7c861874198842c018bd56ceec71dd5ad75d0099..2968f475efad313511c2a5a8fcdd943fc18b328c 100644 (file)
@@ -11,7 +11,7 @@ import builtins
 import io
 import _compression
 
-__all__ = ["GzipFile", "open", "compress", "decompress"]
+__all__ = ["BadGzipFile", "GzipFile", "open", "compress", "decompress"]
 
 FTEXT, FHCRC, FEXTRA, FNAME, FCOMMENT = 1, 2, 4, 8, 16
 
@@ -112,6 +112,11 @@ class _PaddedFile:
     def seekable(self):
         return True  # Allows fast-forwarding even in unseekable streams
 
+
+class BadGzipFile(OSError):
+    """Exception raised in some cases for invalid gzip files."""
+
+
 class GzipFile(_compression.BaseStream):
     """The GzipFile class simulates most of the methods of a file object with
     the exception of the truncate() method.
@@ -413,12 +418,12 @@ class _GzipReader(_compression.DecompressReader):
             return False
 
         if magic != b'\037\213':
-            raise OSError('Not a gzipped file (%r)' % magic)
+            raise BadGzipFile('Not a gzipped file (%r)' % magic)
 
         (method, flag,
          self._last_mtime) = struct.unpack("<BBIxx", self._read_exact(8))
         if method != 8:
-            raise OSError('Unknown compression method')
+            raise BadGzipFile('Unknown compression method')
 
         if flag & FEXTRA:
             # Read & discard the extra field, if present
@@ -502,10 +507,10 @@ class _GzipReader(_compression.DecompressReader):
         # stored is the true file size mod 2**32.
         crc32, isize = struct.unpack("<II", self._read_exact(8))
         if crc32 != self._crc:
-            raise OSError("CRC check failed %s != %s" % (hex(crc32),
-                                                         hex(self._crc)))
+            raise BadGzipFile("CRC check failed %s != %s" % (hex(crc32),
+                                                             hex(self._crc)))
         elif isize != (self._stream_size & 0xffffffff):
-            raise OSError("Incorrect length of data produced")
+            raise BadGzipFile("Incorrect length of data produced")
 
         # Gzip files can be padded with zeroes and still have archives.
         # Consume all zero bytes and set the file position to the first
index 3583b47336fb9f643eed339eec9b324ca65f8b43..48a36a30913f6ad66d30cd991daa89f60df1e06f 100644 (file)
@@ -391,6 +391,15 @@ class TestGzip(BaseTest):
             d = f.read()
             self.assertEqual(d, data1 * 50, "Incorrect data in file")
 
+    def test_gzip_BadGzipFile_exception(self):
+        self.assertTrue(issubclass(gzip.BadGzipFile, OSError))
+
+    def test_bad_gzip_file(self):
+        with open(self.filename, 'wb') as file:
+            file.write(data1 * 50)
+        with gzip.GzipFile(self.filename, 'r') as file:
+            self.assertRaises(gzip.BadGzipFile, file.readlines)
+
     def test_non_seekable_file(self):
         uncompressed = data1 * 50
         buf = UnseekableIO()
diff --git a/Misc/NEWS.d/next/Library/2019-04-30-04-34-53.bpo-6584.Hzp9-P.rst b/Misc/NEWS.d/next/Library/2019-04-30-04-34-53.bpo-6584.Hzp9-P.rst
new file mode 100644 (file)
index 0000000..3a09438
--- /dev/null
@@ -0,0 +1 @@
+Add a :exc:`~gzip.BadGzipFile` exception to the :mod:`gzip` module.