Skip to content

Conversation

@alinpahontu2912
Copy link
Member

Fix ZipFileExtensions.CreateEntryFromFile writing backslashes () into ZipArchive entries.

Per the ZIP spec, file paths stored in the central directory MUST use forward slashes (/). Using backslashes causes interoperability issues with some tools (Java, PHP).

This change normalizes entry names to use / only when creating new entries.

Fixes #41914

Copilot AI review requested due to automatic review settings September 1, 2025 14:32
@alinpahontu2912 alinpahontu2912 requested a review from a team September 1, 2025 14:33
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull Request Overview

Fixes path normalization in ZIP archive entry creation to ensure forward slashes are used as required by the ZIP specification. This resolves interoperability issues with Java and PHP tools that expect standard ZIP path separators.

  • Normalizes backslashes to forward slashes in entry names
  • Trims leading slashes from entry names to prevent invalid paths
  • Adds comprehensive test coverage for both direct entry creation and file-based entry creation

Reviewed Changes

Copilot reviewed 3 out of 3 changed files in this pull request and generated 4 comments.

File Description
src/libraries/System.IO.Compression/src/System/IO/Compression/ZipArchive.cs Adds path normalization logic to DoCreateEntry method
src/libraries/System.IO.Compression.ZipFile/src/System/IO/Compression/ZipFileExtensions.ZipArchive.Create.cs Adds path normalization logic to InitializeDoCreateEntryFromFile method
src/libraries/System.IO.Compression/tests/ZipArchive/zip_CreateTests.cs Adds test methods to verify path normalization behavior

@alinpahontu2912
Copy link
Member Author

alinpahontu2912 commented Sep 2, 2025

Hey @dotnet/area-system-io-compression @rzikm Now that I think again, maybe a better way to deal with this would be adding an extra parameter to coose to normalize entrynames, like specified in this comment here: #98247 (comment), so it wouldn't result in any breaking change, what do you think?

@rzikm
Copy link
Member

rzikm commented Sep 2, 2025

I am personally in favor of taking the breaking change. I am also okay with adding an option to override the normalization, but I would consider the normalization enabled to be the better default, as you cannot create a filename containing backslashes on Windows, and on Linux such names - while supported - are considered gross malpractice (as are names containing whitespace and control characters).

@rzikm
Copy link
Member

rzikm commented Sep 2, 2025

#113058 this also seems to be related

@alinpahontu2912
Copy link
Member Author

I also came across this issue: #1553, which seems related


FileStream fs = new FileStream(sourceFileName, FileMode.Open, FileAccess.Read, FileShare.Read, ZipFile.FileStreamBufferSize, useAsync);

entryName = entryName.TrimStart('/', '\\').Replace('\\', '/');
Copy link
Member

@ericstj ericstj Sep 8, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Here we know we're dealing with a path, so manipulating the string to normalize separators is consistent with other API at this layer. Consider sharing the logic that already exists for this normalization in https://github.com/dotnet/runtime/blob/0d1523350e6df0f18405a1d1c8bfcf8c0699d750/src/libraries/Common/src/System/IO/Archiving.Utils.Windows.cs#L53C37-L53C50

There is still a concern here that the user might actually have a file name that contains a backslash on linux. I wonder how you can deal with that?

(edit) Actually, upon closer inspection, the entryName is passed as a separate parameter from the file path in the host system, so while it may contain separators those came directly from the user and not from us and we don't know if they meant those as path separators (most-likely) or not.


ThrowIfDisposed();

entryName = entryName.TrimStart('/', '\\').Replace('\\', '/');
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I wonder if we can "know" we're dealing with a path and that the user wants this replacement done? What's going to happen for archives that might already use \ elsewhere? What if the user actually needs to preserve the slash for whatever reason?

It looks like this method is called for all calls to CreateEntry so any other logic that tries to do this slash replacement is probably redundant to this. We shouldn't be duplicating this replacement at multiple layers (if we do decide to keep it at this layer).

@alinpahontu2912
Copy link
Member Author

Closing the PR as we need to reconsider more things for these changes

@github-actions github-actions bot locked and limited conversation to collaborators Oct 11, 2025
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

ZipFileExtensions.CreateEntryFromFile doesn't change backward slashes to forward slashes

3 participants