Skip to content

Commit 43210be

Browse files
committed
Report an error if the target overwrites a source file
1 parent 39aebcb commit 43210be

File tree

2 files changed

+31
-1
lines changed

2 files changed

+31
-1
lines changed

Lib/test/test_zipapp.py

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -91,7 +91,7 @@ def skip_pyc_files(path):
9191

9292
def test_create_archive_self_insertion(self):
9393
# When creating an archive, we shouldn't
94-
# include the archive in the lis of files to add.
94+
# include the archive in the list of files to add.
9595
source = self.tmpdir
9696
(source / '__main__.py').touch()
9797
(source / 'test.py').touch()
@@ -103,6 +103,16 @@ def test_create_archive_self_insertion(self):
103103
self.assertIn('__main__.py', z.namelist())
104104
self.assertIn('test.py', z.namelist())
105105

106+
def test_target_overwrites_source_file(self):
107+
# The target cannot be one of the files to add.
108+
source = self.tmpdir
109+
(source / '__main__.py').touch()
110+
target = source / 'target.pyz'
111+
target.touch()
112+
113+
with self.assertRaises(zipapp.ZipAppError):
114+
zipapp.create_archive(source, target)
115+
106116
def test_create_archive_filter_exclude_dir(self):
107117
# Test packing a directory and using a filter to exclude a
108118
# subdirectory (ensures that the path supplied to include

Lib/zipapp.py

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -135,6 +135,26 @@ def create_archive(source, target=None, interpreter=None, main=None,
135135
# the target is being created in the source directory - we
136136
# don't want the target being added to itself
137137
files_to_add = sorted(source.rglob('*'))
138+
139+
# The target cannot be in the list of files to add. If it were, we'd
140+
# end up overwriting the source file and writing the archive into
141+
# itself, which is an error. We therefore check for that case and
142+
# provide a helpful message for the user.
143+
144+
# Note that we only do a simple path equality check. This won't
145+
# catch every case, but it will catch the common case where the
146+
# source is the CWD and the target is a file in the CWD. More
147+
# thorough checks don't provide enough value to justify the extra
148+
# cost.
149+
150+
# https://github.com/python/cpython/issues/104527 tracks making
151+
# the zipfile module catch writing an archive to itself at a
152+
# lower level, which could help here in cases that our check
153+
# doesn't catch.
154+
if target in files_to_add:
155+
raise ZipAppError(
156+
f"The target archive {target} overwrites one of the source files.")
157+
138158
with _maybe_open(target, 'wb') as fd:
139159
_write_file_prefix(fd, interpreter)
140160
compression = (zipfile.ZIP_DEFLATED if compressed else

0 commit comments

Comments
 (0)