diff options
Diffstat (limited to 'contrib/tools/python3/Lib/zipapp.py')
| -rw-r--r-- | contrib/tools/python3/Lib/zipapp.py | 25 |
1 files changed, 24 insertions, 1 deletions
diff --git a/contrib/tools/python3/Lib/zipapp.py b/contrib/tools/python3/Lib/zipapp.py index d8ebfcb6c73..4ffacc49fa7 100644 --- a/contrib/tools/python3/Lib/zipapp.py +++ b/contrib/tools/python3/Lib/zipapp.py @@ -131,12 +131,35 @@ 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): z.write(child, arcname.as_posix()) |
