summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorZackery Spytz <zspytz@gmail.com>2019-05-13 07:50:52 (GMT)
committerSerhiy Storchaka <storchaka@gmail.com>2019-05-13 07:50:52 (GMT)
commitcf599f6f6f1c392d8f12936982a370d533782195 (patch)
treeda53ae10a41332d3e52c38cd3603c36dcb4329cd
parentd28772ab6967fea136c0707f0207673ebad66f61 (diff)
downloadcpython-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.rst8
-rw-r--r--Doc/whatsnew/3.8.rst5
-rw-r--r--Lib/gzip.py17
-rw-r--r--Lib/test/test_gzip.py9
-rw-r--r--Misc/NEWS.d/next/Library/2019-04-30-04-34-53.bpo-6584.Hzp9-P.rst1
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.