From ede7ba390d1833de8b9290f1a343ccf6c01d43e0 Mon Sep 17 00:00:00 2001 From: harjoth Date: Sat, 20 Jun 2026 20:26:16 -0700 Subject: [PATCH 1/2] gh-133998: Clamp out-of-range mtime in tarfile streaming gzip writes tarfile.open(..., "w|gz", mtime=...) packed mtime into the gzip header's 32-bit field with no range check, so a value < 0 or >= 2**32 raised struct.error. Mirror the merged gzip fix: substitute 0 for out-of-range values and coerce to int (RFC 1952), so floats and out-of-range system clocks behave the same as in gzip and the non-streaming "w:gz" path (which already delegates to GzipFile and was unaffected). --- Lib/tarfile.py | 8 +++- Lib/test/test_tarfile.py | 38 +++++++++++++++++++ ...-06-20-20-24-03.gh-issue-133998.nkqhMz.rst | 4 ++ 3 files changed, 48 insertions(+), 2 deletions(-) create mode 100644 Misc/NEWS.d/next/Library/2026-06-20-20-24-03.gh-issue-133998.nkqhMz.rst diff --git a/Lib/tarfile.py b/Lib/tarfile.py index a293a0492472749..61909017120d290 100644 --- a/Lib/tarfile.py +++ b/Lib/tarfile.py @@ -427,8 +427,12 @@ def _init_write_gz(self, compresslevel, mtime): self.zlib.DEF_MEM_LEVEL, 0) if mtime is None: - mtime = int(time.time()) - timestamp = struct.pack(" Date: Mon, 5 Oct 2026 14:53:31 +0200 Subject: [PATCH 2/2] Update Lib/test/test_tarfile.py --- Lib/test/test_tarfile.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Lib/test/test_tarfile.py b/Lib/test/test_tarfile.py index ac74b8b20b07a86..91a6bf227a08da6 100644 --- a/Lib/test/test_tarfile.py +++ b/Lib/test/test_tarfile.py @@ -1888,13 +1888,13 @@ def test_create_with_mtime(self): def test_create_with_mtime_out_of_range(self): # gh-133998: an mtime outside the gzip header's 32-bit range is # stored as 0 rather than raising struct.error. + self.addCleanup(os_helper.unlink, tmpname) for mtime in (-1, 2**32): with self.subTest(mtime=mtime): tarfile.open(tmpname, self.mode, mtime=mtime).close() with self.open(tmpname, 'r') as fobj: fobj.read() self.assertEqual(fobj.mtime, 0) - os_helper.unlink(tmpname) def test_create_with_mtime_at_boundary(self): # gh-133998: the largest in-range mtime is preserved, not clamped.