diff options
author | Zackery Spytz <zspytz@gmail.com> | 2019-05-13 07:50:52 (GMT) |
---|---|---|
committer | Serhiy Storchaka <storchaka@gmail.com> | 2019-05-13 07:50:52 (GMT) |
commit | cf599f6f6f1c392d8f12936982a370d533782195 (patch) | |
tree | da53ae10a41332d3e52c38cd3603c36dcb4329cd | |
parent | d28772ab6967fea136c0707f0207673ebad66f61 (diff) | |
download | cpython-cf599f6f6f1c392d8f12936982a370d533782195.zip cpython-cf599f6f6f1c392d8f12936982a370d533782195.tar.gz cpython-cf599f6f6f1c392d8f12936982a370d533782195.tar.bz2 |
bpo-6584: Add a BadGzipFile exception to the gzip module. (GH-13022)
Co-Authored-By: Filip Gruszczyński <gruszczy@gmail.com>
Co-Authored-By: Michele Orrù <maker@tumbolandia.net>
-rw-r--r-- | Doc/library/gzip.rst | 8 | ||||
-rw-r--r-- | Doc/whatsnew/3.8.rst | 5 | ||||
-rw-r--r-- | Lib/gzip.py | 17 | ||||
-rw-r--r-- | Lib/test/test_gzip.py | 9 | ||||
-rw-r--r-- | Misc/NEWS.d/next/Library/2019-04-30-04-34-53.bpo-6584.Hzp9-P.rst | 1 |
5 files changed, 34 insertions, 6 deletions
diff --git a/Doc/library/gzip.rst b/Doc/library/gzip.rst index 8850a33..3349a94 100644 --- a/Doc/library/gzip.rst +++ b/Doc/library/gzip.rst @@ -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 diff --git a/Doc/whatsnew/3.8.rst b/Doc/whatsnew/3.8.rst index 2cfb110..684656f 100644 --- a/Doc/whatsnew/3.8.rst +++ b/Doc/whatsnew/3.8.rst @@ -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 ---------------- diff --git a/Lib/gzip.py b/Lib/gzip.py index 7c86187..2968f47 100644 --- a/Lib/gzip.py +++ b/Lib/gzip.py @@ -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 diff --git a/Lib/test/test_gzip.py b/Lib/test/test_gzip.py index 3583b47..48a36a3 100644 --- a/Lib/test/test_gzip.py +++ b/Lib/test/test_gzip.py @@ -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 index 0000000..3a09438 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2019-04-30-04-34-53.bpo-6584.Hzp9-P.rst @@ -0,0 +1 @@ +Add a :exc:`~gzip.BadGzipFile` exception to the :mod:`gzip` module. |