Repository navigation
Breakage when files are added to archive in the "wrong" order #102
Description
Hi guys,
I have been battling for a few days with a curious issue. My use case is one where I need to replace the contents of one (JSON) text file after fetching it from the archive, deserializing it into a dedicated class instance, making the necessary changes and then serializing the class instance back to a new file and adding it to the archive as a new entry. When I do that, however, I get the following exception
Unhandled exception. System.IO.IOException: An attempt was made to move the position before the beginning of the stream.
at System.IO.MemoryStream.Seek(Int64 offset, SeekOrigin loc)
at Xamarin.Tools.Zip.ZipArchive.stream_callback(IntPtr state, IntPtr data, UInt64 len, SourceCommand cmd)
I have spent a good few hours getting a debug environment working and tracing through the native libzip library code. It does indeed try to seek to an apparently nonsensical position within the stream when trying to read extra fields for the archive entries at one point (we're talking position shifts by tens of thousands of bytes in an archive that is just barely over a kilobyte in compressed size). I don't have the details on the problematic spot in libzip with me at the moment, but I should be able to provide them easily if need be.
In addition to that, I have discovered that the order in which I add files to the archive does matter to LibZipSharp/libzip. To demonstrate that, I have put together a simple project. See this GitHub repository for the source code and test files. The info.json file is the one getting read and subsequently replaced in the archive.
During my experiments, I tried different orders of files on the command line to see the impact of those changes. I use the standard zip command in Linux. I have tried these permutations of files on the command line.
zip -9 object.zip characters_players.json info.json object_spawn.json,
zip -9 object.zip object_spawn.json info.json characters_players.json,
zip -9 object.zip info.json object_spawn.json characters_players.json, and
zip -9 object.zip object_spawn.json characters_players.json info.json
produce an archive file that the test application is able to successfully process and run to completion.
However, commands
zip -9 object.zip info.json characters_players.json object_spawn.json and
zip -9 object.zip characters_players.json object_spawn.json info.json
produce an archive file that the app fails to process and fails with the traceback listed above.
To complicate this even more, I found that when I try to iterate through the entries of the archive and then do the read/update/replace operation, most of the archive variations created by the commands above run to completion except
zip -9 object.zip info.json object_spawn.json characters_players.json and
zip -9 object.zip object_spawn.json characters_players.json info.json.
Lines 38-39 are commented out and uncommenting them will print the contents of the archive to stdout together with position information of the archive stream.
That's really all I can think of at the moment. I hope this helps. Let me know if you need anything else. 🙂
Activity
dellis1972 commentedon Jan 14, 2022
Given one of the problematic zip files you can narrow down the test case to
Interestingly. If you open the zip using
ZipArchive.Open (InputFile)directly rather than going through a stream, it works as expected as the file is deleted.Need to do some more investigation.
dellis1972 commentedon Jan 14, 2022
@mrclayman something to remember about how
libzipworks. Changes to zip files are not "committed" until the archive is closed. All modifications happen in memory.What this means is that until you call
archive.Close()none of the changes will take effect, close is called automatically by theDisposecall.We get around this in Xamarin.Android by closing then re-opening the archive. So something like
mrclayman commentedon Jan 14, 2022
Thanks for the feedback, guys. @dellis1972 , I thought as much since the library does not have any facility to obtain the end result (especially when working with an in-memory stream). Anyway, although it's not apparent from the traceback I showed in my original post, the exception that breaks the app is raised during the execution of the
Close()method ofZipArchive. I figure you will see the same when you try to trace the test app.I am tempted to write a small test C app with the same execution flow as the C# one, just to see if the same issue occurs while using only the pure libzip library. In the meantime, if you guys find something, I'm all ears. 🙂 Thanks very much for your time!
Initial code changes for Issue dotnet#102
dellis1972 commentedon Jan 18, 2022
@mrclayman just to keep you posted. I have managed to create a repo using the files you provided. You can track our progress at #103. It is beginning to look like its a bug in libzip itself, we will continue to investigate but we might need to a native repo so we can create an issue at https://github.com/nih-at/libzip.
So if you made any progress in creating a native repo please let us know :)
mrclayman commentedon Jan 18, 2022
Thanks very much for the update, @dellis1972 . 😊 I have not begun with it yet, but seeing as you guys are making progress, I will do my best to whip up one ASAP. I will let you know when I have it, for sure. 👍
dellis1972 commentedon Jan 18, 2022
@mrclayman don't worry abou the C example. I put one together.
Fix corrupt data when Deleting entries from zip files.
dellis1972 commentedon Jan 20, 2022
@mrclayman looks like we figured out the probem. Just going though the code review process now. Once that is done and its merged we'll be releasing a new Nuget with the fix, probably tomorrow.
mrclayman commentedon Jan 20, 2022
Awesome! Thanks for the heads-up, @dellis1972 . 😊
Fix corrupt data when Deleting entries from zip files.
Fix corrupt data when Deleting entries from zip files. (#103)
Bump to dotnet/android-libzipsharp@dbe32363, xamarin/xamarin-android-…
dellis1972 commentedon Jan 25, 2022
@mrclayman jsut a heads up we found a bug in 2.0.2 which we will be fixing in 2.0.3 via #104
mrclayman commentedon Jan 28, 2022
Thanks for the heads-up, @dellis1972 . 👍 I've been busy with other things, but hopefully sometime next week I should be able to get back to finishing the task that involved LibZipSharp. I'll be on the lookout for the new version. 😊