haf / DotNetZip.Semverd

Please use System.IO.Compression! A fork of the DotNetZip project without signing with a solution that compiles cleanly. This project aims to follow semver to avoid versioning conflicts. DotNetZip is a FAST, FREE class library and toolset for manipulating zip files. Use VB, C# or any .NET language to easily create, extract, or update zip files.
Other
545 stars 218 forks source link

Defect in Inflate library causes trailing bytes to be lost #61

Closed kenkendk closed 8 years ago

kenkendk commented 8 years ago

Since you use the same source code ported from jzlib, you also have a bug in the Inflate.cs code that can cause certain files to be decompressed incorrectly.

Details, a test file and a patch file is here: https://github.com/adamhathcock/sharpcompress/pull/118

dosomder commented 8 years ago

Thanks for the report and bug fix. Are you going to do a pull request? If yes, please also include a test method.

kenkendk commented 8 years ago

I have not used the DotNetZip library directly, so I do not have any test code.

If you have an executable or similar that uses DotNetZip, you can simply attempt to decompress the test zip file, and see that it is 102.291 bytes long instead of the expected 102.400 bytes: https://dl.dropboxusercontent.com/u/15251537/inflate-bug-test-stream.zip

The patch attached to the issue can be applied directly to the source of DotNetZip.

dosomder commented 8 years ago

Seems this is correctly handled with the latest DotNetZip version though Here is my test code

        public void Extract_CheckTrailingBits()
        {
            string filename = Path.Combine(CurrentDir, "zips\\inflate-bug-test-stream.zip");
            using (ZipFile zip = ZipFile.Read(filename))
            {
                foreach (ZipEntry e in zip.Entries)
                    if (e.FileName == "inflate-test")
                        e.Extract(ExtractExistingFileAction.OverwriteSilently);
            }

            FileInfo fi = new FileInfo("inflate-test");
            Assert.AreEqual<int>((int)fi.Length, 102400, "Failed to extract file with trailing bits.");
        }

The file gets extracted correctly and has the md5 hash 287CC79F510D748681F39F7A1CF21A8E

kenkendk commented 8 years ago

Yes, the MD5 is correct.

I can confirm that the code you provided gives the correct result when using latest DotNetZip from NuGet.

I was unable to get DotNetZip to build with Xamarin Studio so I cannot track down why. The same problematic code is certainly present in DotNetZip: https://github.com/haf/DotNetZip.Semverd/blob/master/src/Zlib/Inflate.cs#L957

It checks k (number of bits left) agains j number of bits required, which is set to dbits in the case above. I my debugging session k == 5 and j == 6, because dbits was set to 6. This caused an early stop. There might be some handling at upper levels that simply retry this with a lower number of dbits.

Anyways, no need to spend more time on it, as it works :).