mirror of
https://github.com/python/cpython.git
synced 2026-06-05 01:10:53 +00:00
gh-133998: Fix gzip file creation when time is out of range (GH-134278)
Co-authored-by: Serhiy Storchaka <storchaka@gmail.com>
This commit is contained in:
parent
f159419ae2
commit
1daad8a163
4 changed files with 41 additions and 5 deletions
|
|
@ -108,9 +108,13 @@ The module defines the following items:
|
|||
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.
|
||||
|
||||
|
|
|
|||
10
Lib/gzip.py
10
Lib/gzip.py
|
|
@ -188,8 +188,10 @@ def __init__(self, filename=None, mode=None,
|
|||
|
||||
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.
|
||||
|
||||
"""
|
||||
|
||||
|
|
@ -295,6 +297,8 @@ def _write_gzip_header(self, compresslevel):
|
|||
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'
|
||||
|
|
@ -663,6 +667,8 @@ def compress(data, compresslevel=_COMPRESS_LEVEL_TRADEOFF, *, mtime=0):
|
|||
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)
|
||||
|
|
|
|||
|
|
@ -10,6 +10,7 @@
|
|||
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
|
||||
|
|
@ -350,6 +351,26 @@ def test_mtime(self):
|
|||
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
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,5 @@
|
|||
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``.
|
||||
Loading…
Add table
Add a link
Reference in a new issue