aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/Lib/zipapp.py
diff options
context:
space:
mode:
authorPaul Moore <p.f.moore@gmail.com>2025-02-26 11:25:30 +0000
committerGitHub <noreply@github.com>2025-02-26 11:25:30 +0000
commit64ccbbbf367c7510090a6f5faf826a21102a8bc6 (patch)
tree364f504dfd03848d78b1222fa5dc5b3f23cf523f /Lib/zipapp.py
parentf976892b7db011f3f039be615f4a759b8c487db3 (diff)
downloadcpython-64ccbbbf367c7510090a6f5faf826a21102a8bc6.tar.gz
cpython-64ccbbbf367c7510090a6f5faf826a21102a8bc6.zip
gh-130379: Fix incorrect zipapp logic to avoid including the target in itself (gh-130509)
Diffstat (limited to 'Lib/zipapp.py')
-rw-r--r--Lib/zipapp.py27
1 files changed, 25 insertions, 2 deletions
diff --git a/Lib/zipapp.py b/Lib/zipapp.py
index 03a214efa10..4ffacc49fa7 100644
--- a/Lib/zipapp.py
+++ b/Lib/zipapp.py
@@ -131,14 +131,37 @@ def create_archive(source, target=None, interpreter=None, main=None,
elif not hasattr(target, 'write'):
target = pathlib.Path(target)
+ # Create the list of files to add to the archive now, in case
+ # the target is being created in the source directory - we
+ # don't want the target being added to itself
+ files_to_add = sorted(source.rglob('*'))
+
+ # The target cannot be in the list of files to add. If it were, we'd
+ # end up overwriting the source file and writing the archive into
+ # itself, which is an error. We therefore check for that case and
+ # provide a helpful message for the user.
+
+ # Note that we only do a simple path equality check. This won't
+ # catch every case, but it will catch the common case where the
+ # source is the CWD and the target is a file in the CWD. More
+ # thorough checks don't provide enough value to justify the extra
+ # cost.
+
+ # If target is a file-like object, it will simply fail to compare
+ # equal to any of the entries in files_to_add, so there's no need
+ # to add a special check for that.
+ if target in files_to_add:
+ raise ZipAppError(
+ f"The target archive {target} overwrites one of the source files.")
+
with _maybe_open(target, 'wb') as fd:
_write_file_prefix(fd, interpreter)
compression = (zipfile.ZIP_DEFLATED if compressed else
zipfile.ZIP_STORED)
with zipfile.ZipFile(fd, 'w', compression=compression) as z:
- for child in sorted(source.rglob('*')):
+ for child in files_to_add:
arcname = child.relative_to(source)
- if filter is None or filter(arcname) and child.resolve() != arcname.resolve():
+ if filter is None or filter(arcname):
z.write(child, arcname.as_posix())
if main_py:
z.writestr('__main__.py', main_py.encode('utf-8'))