Skip to content

Commit bb0a1d1

Browse files
committed
gh-152445: fix zipfile.writestr() ignoring strict_timestamps when SOURCE_DATE_EPOCH is set
1 parent 87ac0bc commit bb0a1d1

2 files changed

Lines changed: 39 additions & 0 deletions

File tree

Lib/test/test_zipfile/test_core.py

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4019,6 +4019,37 @@ def test_write_without_source_date_epoch(self):
40194019
with zipfile.ZipFile(TESTFN, "r") as zf:
40204020
zip_info = zf.getinfo("test_no_source_date_epoch.txt")
40214021
self.assertTimestampAlmostEqual(time.localtime(), zip_info.date_time, tolerance=2)
4022+
4023+
def test_writestr_strict_timestamps_false_with_pre1980_source_date_epoch(self):
4024+
# gh-152445: writestr() with strict_timestamps=False should clamp
4025+
# SOURCE_DATE_EPOCH before 1980 to 1980-01-01, not raise.
4026+
with os_helper.EnvironmentVarGuard() as env:
4027+
env['SOURCE_DATE_EPOCH'] = '0' # 1970-01-01
4028+
with zipfile.ZipFile(TESTFN, 'w', strict_timestamps=False) as zf:
4029+
zf.writestr('test.txt', 'Hello World')
4030+
with zipfile.ZipFile(TESTFN, 'r') as zf:
4031+
info = zf.getinfo('test.txt')
4032+
self.assertEqual(info.date_time[:3], (1980, 1, 1))
4033+
4034+
def test_writestr_strict_timestamps_false_with_post2107_source_date_epoch(self):
4035+
# gh-152445: writestr() with strict_timestamps=False should clamp
4036+
# SOURCE_DATE_EPOCH after 2107 to 2107-12-31, not raise.
4037+
with os_helper.EnvironmentVarGuard() as env:
4038+
env['SOURCE_DATE_EPOCH'] = '4354819200' # 2108-01-01
4039+
with zipfile.ZipFile(TESTFN, 'w', strict_timestamps=False) as zf:
4040+
zf.writestr('test.txt', 'Hello World')
4041+
with zipfile.ZipFile(TESTFN, 'r') as zf:
4042+
info = zf.getinfo('test.txt')
4043+
self.assertEqual(info.date_time[:3], (2107, 12, 31))
4044+
4045+
def test_writestr_strict_timestamps_true_raises_for_pre1980_source_date_epoch(self):
4046+
# gh-152445: writestr() with strict_timestamps=True (default) should
4047+
# still raise when SOURCE_DATE_EPOCH is before 1980.
4048+
with os_helper.EnvironmentVarGuard() as env:
4049+
env['SOURCE_DATE_EPOCH'] = '0' # 1970-01-01
4050+
with zipfile.ZipFile(TESTFN, 'w') as zf:
4051+
with self.assertRaises((struct.error, ValueError)):
4052+
zf.writestr('test.txt', 'Hello World')
40224053

40234054
def assertTimestampAlmostEqual(self, time1, time2, tolerance):
40244055
import datetime

Lib/zipfile/__init__.py

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -683,6 +683,14 @@ def _for_archive(self, archive):
683683
else:
684684
self.date_time = time.localtime(time.time())[:6]
685685

686+
# gh-152445: Clamp date_time when strict_timestamps=False,
687+
# mirroring the behaviour of ZipInfo.from_file().
688+
if not archive._strict_timestamps:
689+
if self.date_time[0] < 1980:
690+
self.date_time = (1980, 1, 1, 0, 0, 0)
691+
elif self.date_time[0] > 2107:
692+
self.date_time = (2107, 12, 31, 23, 59, 59)
693+
686694
self.compress_type = archive.compression
687695
self.compress_level = archive.compresslevel
688696
if self.filename.endswith('/'): # pragma: no cover

0 commit comments

Comments
 (0)