runtime: .NET 7 regression in ZipArchive

Description

I ran into this trying to get MAUI workloads running on .NET 7. Our CI caught some test failures here.

Append to an existing ZipEntry with code such as:

using var fileStream = File.Open(path, FileMode.Open, FileAccess.ReadWrite);
using var zip = new ZipArchive(fileStream, ZipArchiveMode.Update);

var oldEntry = zip.GetEntry("foo.txt");
ArgumentNullException.ThrowIfNull(oldEntry);
var newEntry = zip.CreateEntry("foo.txt");

using var newStream = newEntry.Open();

using (var oldStream = oldEntry.Open())
{
    oldStream.CopyTo(newStream);
}

using var writer = new StreamWriter(newStream);
writer.Write("foo");

oldEntry.Delete();

In .NET 6 the code works, in .NET 7 it throws:

Message: 
System.InvalidOperationException : An entry named 'foo.txt' already exists in the archive.

Stack Trace: 
ZipArchive.DoCreateEntry(String entryName, Nullable`1 compressionLevel)
ZipArchive.CreateEntry(String entryName)
ZipArchiveTest.AppendToZip(String path) line 42
ZipArchiveTest.Test1() line 17
RuntimeMethodHandle.InvokeMethod(Object target, Void** arguments, Signature sig, Boolean isConstructor)
RuntimeMethodInfo.InvokeNonEmitUnsafe(Object obj, IntPtr* arguments, Span`1 argsForTemporaryMonoSupport, BindingFlags invokeAttr)

Reproduction Steps

Here is an xunit project targeting both .NET 6 and .NET 7: zippy.zip

If you just unzip and run dotnet test you’ll see it passes on 6 and fails in 7.

Expected behavior

ZipEntry.CreateEntry() doesn’t throw in this example.

Actual behavior

ZipEntry.CreateEntry() throws an exception.

Regression?

Yes, works in .NET 6.

Known Workarounds

There may be a different way to write the above code, but I ported this example from existing code.

Configuration

> dotnet --version
7.0.100-preview.5.22229.2

I’m running on Windows 11, but this also happens on macOS where I saw this on CI.

Other information

I think this may have been introduced in: https://github.com/dotnet/runtime/pull/60973

About this issue

  • Original URL
  • State: closed
  • Created 2 years ago
  • Comments: 15 (14 by maintainers)

Commits related to this issue

Most upvoted comments

However duplicate entries are also OK in the spec

If it’s allowed by the spec, I don’t think we should be enforcing our own policy to the contrary. If we allow it, a higher level tool could choose its own policy here using our APIs, but if we prohibit it, there’s no wiggle room.

We ended up deleting the problematic code and updated the NuGet package.

We are unblocked here, so now it just depends on how many customers will hit this, and if it is an acceptable breaking change. Completely up to you, thanks!