Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
31 changes: 31 additions & 0 deletions Lib/test/test_zipfile/test_core.py
Original file line number Diff line number Diff line change
Expand Up @@ -4020,6 +4020,37 @@ def test_write_without_source_date_epoch(self):
zip_info = zf.getinfo("test_no_source_date_epoch.txt")
self.assertTimestampAlmostEqual(time.localtime(), zip_info.date_time, tolerance=2)

def test_writestr_strict_timestamps_false_with_pre1980_source_date_epoch(self):
# gh-152445: writestr() with strict_timestamps=False should clamp
# SOURCE_DATE_EPOCH before 1980 to 1980-01-01, not raise.
with os_helper.EnvironmentVarGuard() as env:
env['SOURCE_DATE_EPOCH'] = '0' # 1970-01-01
with zipfile.ZipFile(TESTFN, 'w', strict_timestamps=False) as zf:
zf.writestr('test.txt', 'Hello World')
with zipfile.ZipFile(TESTFN, 'r') as zf:
info = zf.getinfo('test.txt')
self.assertEqual(info.date_time[:3], (1980, 1, 1))

def test_writestr_strict_timestamps_false_with_post2107_source_date_epoch(self):
# gh-152445: writestr() with strict_timestamps=False should clamp
# SOURCE_DATE_EPOCH after 2107 to 2107-12-31, not raise.
with os_helper.EnvironmentVarGuard() as env:
env['SOURCE_DATE_EPOCH'] = '4354819200' # 2108-01-01
with zipfile.ZipFile(TESTFN, 'w', strict_timestamps=False) as zf:
zf.writestr('test.txt', 'Hello World')
with zipfile.ZipFile(TESTFN, 'r') as zf:
info = zf.getinfo('test.txt')
self.assertEqual(info.date_time[:3], (2107, 12, 31))

def test_writestr_strict_timestamps_true_raises_for_pre1980_source_date_epoch(self):
# gh-152445: writestr() with strict_timestamps=True (default) should
# still raise when SOURCE_DATE_EPOCH is before 1980.
with os_helper.EnvironmentVarGuard() as env:
env['SOURCE_DATE_EPOCH'] = '0' # 1970-01-01
with zipfile.ZipFile(TESTFN, 'w') as zf:
with self.assertRaises((struct.error, ValueError)):
zf.writestr('test.txt', 'Hello World')

def assertTimestampAlmostEqual(self, time1, time2, tolerance):
import datetime
dt1 = datetime.datetime(*time1[:6])
Expand Down
8 changes: 8 additions & 0 deletions Lib/zipfile/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -683,6 +683,14 @@ def _for_archive(self, archive):
else:
self.date_time = time.localtime(time.time())[:6]

# gh-152445: Clamp date_time when strict_timestamps=False,
# mirroring the behaviour of ZipInfo.from_file().
if not archive._strict_timestamps:
if self.date_time[0] < 1980:
self.date_time = (1980, 1, 1, 0, 0, 0)
elif self.date_time[0] > 2107:
self.date_time = (2107, 12, 31, 23, 59, 59)

self.compress_type = archive.compression
self.compress_level = archive.compresslevel
if self.filename.endswith('/'): # pragma: no cover
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Fix :func:`zipfile.ZipFile.writestr` ignoring ``strict_timestamps=False`` when ``SOURCE_DATE_EPOCH`` is set to a date before 1980 or after 2107.
Loading