Skip to content

Suggest using ZipArchiveMode.Create when compressing files without modifying their ZipArchivEntry objects #35815

Closed

Description

@carlossanlop

Consider the following code:

using System.IO;
using System.IO.Compression;

namespace ConsoleApp
{
    class Program
    {
        static void Main()
        {
            DirectoryInfo directory = new DirectoryInfo(@"C:\path\to\directory\with\huge\files\to\compress");

            using (FileStream stream = new FileStream(@"C:\path\to\new\Compressed.zip", FileMode.CreateNew))
            {
                using (ZipArchive archive = new ZipArchive(stream, ZipArchiveMode.Update /* this is the problem */, leaveOpen: false))
                {
                    foreach (FileInfo file in directory.EnumerateFiles("*", SearchOption.AllDirectories))
                    {
                        archive.CreateEntryFromFile(
                            sourceFileName: file.FullName,
                            entryName: file.Name,
                            CompressionLevel.Optimal); // throws
                    }
                }
            }
        }
    }
}

The exception would be:

Backup failed with exception System.IO.IOException: Stream was too long.
   at System.IO.MemoryStream.Write(Byte[] buffer, Int32 offset, Int32 count)
   at System.IO.Stream.InternalCopyTo(Stream destination, Int32 bufferSize)
   at System.IO.Compression.ZipFileExtensions.DoCreateEntryFromFile(ZipArchive destination, String sourceFileName, String entryName, Nullable`1 compressionLevel)

CreateEntryFromFile has this exception documented here.
The exception is thrown because we restrict the size of a file to Int32.MaxValue. The restriction is reached because the code is opening the ZipArchive with ZipArchiveMode.Update. That mode requires a stream that allows seeking, so we internally create a MemoryStream so that we can update the archive, but the size limit for the file is Int32.MaxValue.

The ZipArchiveMode remarks state that ZipArchiveMode.Update allows both reading and writing, but in this code, writing is not needed.

The Roslyn analyzer would only create a diagnostic if we can detect that the code:

  • Is creating a new ZipArchive with FileMode.Create or FileMode.CreateNew, and
    • Is either calling CreateEntryFromFile, which takes the file name and creates the ZipArchiveEntry internally (and it does not get updated), or
    • Is creating ZipArchiveEntry instances but does not manipulate them before adding them to the ZipArchive.

The Roslyn fixer would suggest changing ZipArchiveMode.Update to ZipArchiveMode.Create.

Is this a good candidate for a Roslyn analyzer/fixer?

Activity

  1. added
    api-suggestionEarly API idea and discussion, it is NOT ready for implementation
    on May 4, 2020
  2. bartonjs commented on May 5, 2020

    @bartonjs
    Member

    Do you believe that in the majority of scenarios that would hit this have all of the code in one method? In projects where I've previously worked with building zip files, opening the zipfile context and adding things / reading things were in different methods; which means the analyzer wouldn't be able to detect it.

    It seems like perhaps what's missing is just some accelerator API, like static ZipArchive.Create(string filename, bool overwrite=???), static ZipArchive.Update(string filename)

  3. added this to the Future milestone on Jun 29, 2020
  4. removed
    untriagedNew issue has not been triaged by the area owner
    on Jul 8, 2020
  5. buyaa-n commented on Oct 23, 2020

    @buyaa-n
    Contributor

    The Roslyn analyzer would only create a diagnostic if we can detect that the code:

    Is creating a new ZipArchive with FileMode.Create or FileMode.CreateNew, and
    Is either calling CreateEntryFromFile, which takes the file name and creates the ZipArchiveEntry internally (and it does not get updated), or
    Is creating ZipArchiveEntry instances but does not manipulate them before adding them to the ZipArchive.

    Sounds like the hardest part would be determining if it does not get updated might need more clarification/rule on how to determine that.

    Do you believe that in the majority of scenarios that would hit this have all of the code in one method? In projects where I've previously worked with building zip files, opening the zipfile context and adding things / reading things were in different methods; which means the analyzer wouldn't be able to detect it.

    For me, its better only account for operations in one method, if it is passed to a different method most likely its being processed more i.e has a high possibility of getting updated.

    It seems like perhaps what's missing is just some accelerator API, like static ZipArchive.Create(string filename, bool overwrite=???), static ZipArchive.Update(string filename)

    Can be helpful, but not sure how much that could prevent from using the existing old APIs that are causing the issue

  6. dotnet-policy-service commented on Apr 24, 2025

    @dotnet-policy-service
    Contributor

    Due to lack of recent activity, this issue has been marked as a candidate for backlog cleanup. It will be closed if no further activity occurs within 14 more days. Any new comment (by anyone, not necessarily the author) will undo this process.

    This process is part of our issue cleanup automation.

  7. dotnet-policy-service commented on May 9, 2025

    @dotnet-policy-service
    Contributor

    This issue will now be closed since it had been marked no-recent-activity but received no further activity in the past 14 days. It is still possible to reopen or comment on the issue, but please note that the issue will be locked if it remains inactive for another 30 days.

  8. removed this from the Future milestone on May 9, 2025
  9. locked and limited conversation to collaborators on Jun 8, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    api-suggestionEarly API idea and discussion, it is NOT ready for implementationarea-System.IO.Compressioncode-analyzerMarks an issue that suggests a Roslyn analyzercode-fixerMarks an issue that suggests a Roslyn code fixer

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions