-
Notifications
You must be signed in to change notification settings - Fork 4.7k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
.NET 7 regression in ZipArchive #68734
Comments
Tagging subscribers to this area: @dotnet/area-system-io-compression Issue DetailsDescriptionI ran into this trying to get MAUI workloads running on .NET 7. Our CI caught some test failures here. Append to an existing 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:
Reproduction StepsHere is an xunit project targeting both .NET 6 and .NET 7: zippy.zip If you just unzip and run Expected behavior
Actual behavior
Regression?Yes, works in .NET 6. Known WorkaroundsThere may be a different way to write the above code, but I ported this example from existing code. Configuration
I'm running on Windows 11, but this also happens on macOS where I saw this on CI. Other informationI think this may have been introduced in: #60973
|
@jonathanpeppers Can you work around this or are you actively blocked? |
Let me check on Monday the actual number of test failures this causes. If it’s a small number we might be able to disable some tests for now. |
The docs do say " If an entry with the specified path and name already exists in the archive, a second entry is created with the same path and name." That should be considered (if it wasn't already) when we evaluate the breaking change. Although, it seems that the previous behavior was buggy, which is why it was disabled. I would imagine that the code above could be changed to write the old data into a MemoryStream (or even file) so that you could remove the old entry before writing the new one. |
So these tests are tricky, they are integration tests that fail in an MSBuild task inside a NuGet package. We'd have to patch the package and push it somewhere. It looked like I can just add a category on 4 tests to skip them for now. This should be ok, because we will continue running these tests for Xamarin.Android projects alongside .NET 7 Android tests. |
Cool. My inclination would be to leave the code as is, pending further feedback on previews. (And document the breaking change and fix the docs) cc @dotnet/area-system-io-compression |
I also believe the breaking change should stay cc @carlossanlop. @jonathanpeppers can you use a different implementation to append to a zip file (avoiding having a duplicated entry)? e.g: using var fileStream = File.Open(path, FileMode.Open, FileAccess.ReadWrite);
using var zip = new ZipArchive(fileStream, ZipArchiveMode.Update);
var entry = zip.GetEntry("foo.txt");
ArgumentNullException.ThrowIfNull(entry);
//var newEntry = zip.CreateEntry("foo.txt");
using var stream = entry.Open();
stream.Seek(0, SeekOrigin.End);
//using (var oldStream = oldEntry.Open())
//{
// oldStream.CopyTo(newStream);
//}
using var writer = new StreamWriter(stream);
writer.Write("foo");
//oldEntry.Delete(); |
Context: dotnet/runtime#68734 A breaking chang in in .NET 7 has uncovered an issue when using Xamarin.Build.Download: Renaming: AndroidManifest.xml to AndroidManifest.xml ... (_XamarinBuildDownloadCore target) -> /Users/runner/.nuget/packages/xamarin.build.download/0.11.0/buildTransitive/Xamarin.Build.Download.targets(52,3): error XBD001: Download failed. Please download https://dl.google.com/dl/android/maven2/com/google/android/gms/play-services-basement/17.6.0/play-services-basement-17.6.0.aar to a file called /Users/runner/Library/Caches/XamarinBuildDownload/playservicesbasement-17.6.0.aar. /Users/runner/.nuget/packages/xamarin.build.download/0.11.0/buildTransitive/Xamarin.Build.Download.targets(52,3): error XBD001: Download failed. Please download https://dl.google.com/dl/android/maven2/com/google/android/gms/play-services-tasks/17.2.1/play-services-tasks-17.2.1.aar to a file called /Users/runner/Library/Caches/XamarinBuildDownload/playservicestasks-17.2.1.aar. /Users/runner/.nuget/packages/xamarin.build.download/0.11.0/buildTransitive/Xamarin.Build.Download.targets(52,3): error XBD001: Download failed. Please download https://dl.google.com/dl/android/maven2/com/google/android/gms/play-services-base/17.6.0/play-services-base-17.6.0.aar to a file called /Users/runner/Library/Caches/XamarinBuildDownload/playservicesbase-17.6.0.aar. /Users/runner/.nuget/packages/xamarin.build.download/0.11.0/buildTransitive/Xamarin.Build.Download.targets(52,3): error XBD001: Download failed. Please download https://dl.google.com/dl/android/maven2/com/google/android/gms/play-services-maps/17.0.1/play-services-maps-17.0.1.aar to a file called /Users/runner/Library/Caches/XamarinBuildDownload/playservicesmaps-17.0.1.aar. 1 Warning(s) 4 Error(s) The exception is somewhat swallowed here, the underlying error is something like: System.InvalidOperationException : An entry named 'AndroidManifest.xml' already exists in the archive. This class had various "fixups" to workaround issues in Xamarin.Android. Many of these issues have long since been fixed. 1. Removal of `aapt/AndroidManifest.xml`. Xamarin.Android has been handling this since ~Sept 2018: dotnet/android@f6c3288 2. Removal of `internal_impl-*.jar`. Xamarin.Android has been handling this since ~Feb 2018: dotnet/android@6a8ea2b 3. Replacement of `android:name=".SomeService"` as shorthand for `androidx.foo.SomeService` in the `androidx.foo` package. The use of `manifest-merger` solves this issue completely. This setting is the default for .NET 6, and has been the default for AndroidX since ~July 2020: dotnet/android-libraries@c6c0e50
Context: dotnet/runtime#68734 A breaking chang in in .NET 7 has uncovered an issue when using Xamarin.Build.Download: Renaming: AndroidManifest.xml to AndroidManifest.xml ... (_XamarinBuildDownloadCore target) -> /Users/runner/.nuget/packages/xamarin.build.download/0.11.0/buildTransitive/Xamarin.Build.Download.targets(52,3): error XBD001: Download failed. Please download https://dl.google.com/dl/android/maven2/com/google/android/gms/play-services-basement/17.6.0/play-services-basement-17.6.0.aar to a file called /Users/runner/Library/Caches/XamarinBuildDownload/playservicesbasement-17.6.0.aar. /Users/runner/.nuget/packages/xamarin.build.download/0.11.0/buildTransitive/Xamarin.Build.Download.targets(52,3): error XBD001: Download failed. Please download https://dl.google.com/dl/android/maven2/com/google/android/gms/play-services-tasks/17.2.1/play-services-tasks-17.2.1.aar to a file called /Users/runner/Library/Caches/XamarinBuildDownload/playservicestasks-17.2.1.aar. /Users/runner/.nuget/packages/xamarin.build.download/0.11.0/buildTransitive/Xamarin.Build.Download.targets(52,3): error XBD001: Download failed. Please download https://dl.google.com/dl/android/maven2/com/google/android/gms/play-services-base/17.6.0/play-services-base-17.6.0.aar to a file called /Users/runner/Library/Caches/XamarinBuildDownload/playservicesbase-17.6.0.aar. /Users/runner/.nuget/packages/xamarin.build.download/0.11.0/buildTransitive/Xamarin.Build.Download.targets(52,3): error XBD001: Download failed. Please download https://dl.google.com/dl/android/maven2/com/google/android/gms/play-services-maps/17.0.1/play-services-maps-17.0.1.aar to a file called /Users/runner/Library/Caches/XamarinBuildDownload/playservicesmaps-17.0.1.aar. 1 Warning(s) 4 Error(s) The exception is somewhat swallowed here, the underlying error is something like: System.InvalidOperationException : An entry named 'AndroidManifest.xml' already exists in the archive. This class had various "fixups" to workaround issues in Xamarin.Android. Many of these issues have long since been fixed. 1. Removal of `aapt/AndroidManifest.xml`. Xamarin.Android has been handling this since ~Sept 2018: dotnet/android@f6c3288 2. Removal of `internal_impl-*.jar`. Xamarin.Android has been handling this since ~Feb 2018: dotnet/android@6a8ea2b 3. Replacement of `android:name=".SomeService"` as shorthand for `androidx.foo.SomeService` in the `androidx.foo` package. The use of `manifest-merger` solves this issue completely. This setting is the default for .NET 6, and has been the default for AndroidX since ~July 2020: dotnet/android-libraries@c6c0e50
Context: dotnet/runtime#56989 Context: dotnet/runtime#68734 Context: dotnet/runtime#68914 Context: dotnet/runtime#68701 Changes: dotnet/installer@04e40fa...c7afae6 % git diff --shortstat 04e40fa9...c7afae69 98 files changed, 1788 insertions(+), 1191 deletions(-) Changes: dotnet/runtime@a21b9a2...c5d40c9 % git diff --shortstat a21b9a2d...c5d40c9e 28347 files changed, 1609359 insertions(+), 1066473 deletions(-) Changes: dotnet/linker@01c4f59...04c49c9 % git diff --shortstat 01c4f590...04c49c9d 577 files changed, 28039 insertions(+), 10835 deletions(-) Updates to build with the .NET 7 SDK and use the runtime specified by the SDK. We no longer use different SDK & runtime versions. This produces a 7.0.100 Android workload. After this is merged we should be able to enable Maestro to consume future .NET 7 builds from dotnet/installer/main. ~~ Known Issues ~~ AOT+LLVM crashes on startup: * dotnet/runtime#68914 Xamarin.Build.Download hits a breaking change with `ZipEntry`: * dotnet/runtime#68734 * xamarin/XamarinComponents#1368 illink outputs different MVIDs per architecture: * dotnet/linker#2203 * dotnet/runtime#67660 Size of `libmonosgen-2.0.so` regressed: * dotnet/runtime#68330 * dotnet/runtime#68354 Newer .NET 7 builds crash on startup: * dotnet/runtime#68701 * This is worked around by *disabling* lazy loading of AOT'd assemblies 6dc426f. * TODO: re-enable once we get a fixed .NET 7 runtime. TODO: We can't yet push to the `dotnet7` feed. Working on this. Co-authored-by: Jonathan Peppers <[email protected]> Co-authored-by: Peter Collins <[email protected]>
Context: dotnet/runtime#68734 Context: xamarin/XamarinComponents#1368 We have a newer Xamarin.Build.Download package that shouldn't suffer from the duplicate `ZipArchive.CreateEntry()` issue were are hitting in .NET 7. Let's use it, and enable previously failing tests.
Context: dotnet/runtime#68734 Context: xamarin/XamarinComponents#1368 We have a newer Xamarin.Build.Download package that shouldn't suffer from the duplicate `ZipArchive.CreateEntry()` issue were are hitting in .NET 7. Let's use it, and enable previously failing tests.
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! |
Closing for now, we can reopen if someone brings a convincing scenario (unable to workaround, probably). |
@jozkee would you mind providing a bit more detail about why this breaking change is acceptable? E.g. does it violate the ZIP specs etc. and how widespread we think it is. Should we apply the |
@jozkee can you create the breaking change issue in dotnet/docs?https://github.com/dotnet/docs/issues/new?assignees=gewarren&labels=breaking-change%2CPri1%2Cdoc-idea&template=breaking-change.yml&title=%5BBreaking+change%5D%3A+ Here's the PR that introduced this breaking change: #60973 |
@akoeplinger the problem was that .NET's zip impl. allows to create multiple entries with the same name, but if you attempt multiple operations on archives in such state, some operations won't work e.g: if you attempt to extract the archive with ZipFile.ExtractToDirectory("archive.zip", "archive"); it will throw The file 'duplicate-entry.txt' already exists. archive.GetEntry(duplicateEntryName); also is unable to retrieve duplicate entries, because it is backed by a Dictionary<string, ZipArchiveEntry>. However duplicate entries are also OK in the spec. I have seen many libraries/tools disallowing this scenario, e.g. 7zip. The only way to see duplicate entries is on the actual entry list, ( Again, I think we can undo the change if there's an scenario for duplicate entries. From a quick search, I've seen mixed opinions on both sides. |
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. |
Glad to see this fixed! The change prohibiting duplicate entries broke interesting code used in steganographic contexts. |
Thanks to @jonathanpeppers for consuming our previews and reporting the issue. |
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:In .NET 6 the code works, in .NET 7 it throws:
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
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: #60973
The text was updated successfully, but these errors were encountered: