is no compression. The default is ``9``.
The optional *mtime* argument is the timestamp requested by gzip. The time
- is in Unix format, i.e., seconds since 00:00:00 UTC, January 1, 1970.
- If *mtime* is omitted or ``None``, the current time is used. Use *mtime* = 0
- to generate a compressed stream that does not depend on creation time.
+ is in Unix format, i.e., seconds since 00:00:00 UTC, January 1, 1970. Set
+ *mtime* to ``0`` to generate a compressed stream that does not depend on
+ creation time. If *mtime* is omitted or ``None``, the current time is used;
+ however, if the current time is outside the range 00:00:00 UTC, January 1,
+ 1970 through 06:28:15 UTC, February 7, 2106, or explicitly passed *mtime*
+ argument is outside the range ``0`` to ``2**32-1``, then the value ``0``
+ is used instead.
See below for the :attr:`mtime` attribute that is set when decompressing.
The optional mtime argument is the timestamp requested by gzip. The time
is in Unix format, i.e., seconds since 00:00:00 UTC, January 1, 1970.
- If mtime is omitted or None, the current time is used. Use mtime = 0
- to generate a compressed stream that does not depend on creation time.
+ Set mtime to 0 to generate a compressed stream that does not depend on
+ creation time. If mtime is omitted or None, the current time is used.
+ If the resulting mtime is outside the range 0 to 2**32-1, then the
+ value 0 is used instead.
"""
mtime = self._write_mtime
if mtime is None:
mtime = time.time()
+ if not 0 <= mtime < 2**32:
+ mtime = 0
write32u(self.fileobj, int(mtime))
if compresslevel == _COMPRESS_LEVEL_BEST:
xfl = b'\002'
gzip_data = zlib.compress(data, level=compresslevel, wbits=31)
if mtime is None:
mtime = time.time()
+ if not 0 <= mtime < 2**32:
+ mtime = 0
# Reuse gzip header created by zlib, replace mtime and OS byte for
# consistency.
header = struct.pack("<4sLBB", gzip_data, int(mtime), gzip_data[8], 255)
import sys
import unittest
from subprocess import PIPE, Popen
+from unittest import mock
from test.support import catch_unraisable_exception
from test.support import force_not_colorized_test_class, import_helper
from test.support import os_helper
self.assertEqual(dataRead, data1)
self.assertEqual(fRead.mtime, mtime)
+ def test_mtime_out_of_range(self):
+ for mtime in (-1, 2**32):
+ with gzip.GzipFile(self.filename, 'w', mtime=mtime) as fWrite:
+ fWrite.write(data1)
+ with gzip.GzipFile(self.filename) as fRead:
+ fRead.read(1)
+ self.assertEqual(fRead.mtime, 0)
+ datac = gzip.compress(data1, mtime=mtime)
+ with gzip.GzipFile(fileobj=io.BytesIO(datac)) as fRead:
+ fRead.read(1)
+ self.assertEqual(fRead.mtime, 0)
+
+ for mtime in (-1, 2**32):
+ with mock.patch('time.time', return_value=float(mtime)):
+ with gzip.GzipFile(self.filename, 'w') as fWrite:
+ fWrite.write(data1)
+ with gzip.GzipFile(self.filename) as fRead:
+ fRead.read(1)
+ self.assertEqual(fRead.mtime, 0)
+
def test_metadata(self):
mtime = 123456789
--- /dev/null
+Fix :exc:`struct.error` exception when creating a file with
+:class:`gzip.GzipFile` or compressing data with :func:`gzip.compress`
+if the system time is outside the range 00:00:00 UTC, January 1, 1970
+through 06:28:15 UTC, February 7, 2106, or explicitly passed *mtime*
+argument is outside the range ``0`` to ``2**32-1``.