diff options
author | Paul Moore <p.f.moore@gmail.com> | 2025-02-26 11:25:30 +0000 |
---|---|---|
committer | GitHub <noreply@github.com> | 2025-02-26 11:25:30 +0000 |
commit | 64ccbbbf367c7510090a6f5faf826a21102a8bc6 (patch) | |
tree | 364f504dfd03848d78b1222fa5dc5b3f23cf523f /Lib/zipapp.py | |
parent | f976892b7db011f3f039be615f4a759b8c487db3 (diff) | |
download | cpython-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.py | 27 |
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')) |