SharpZipLib icon indicating copy to clipboard operation
SharpZipLib copied to clipboard

Data Descriptor Lost UncompressedSize

Open daroubing opened this issue 9 years ago • 2 comments

Steps to reproduce

1.Use ZipFile open android apk file 2.Do some Update 3.Data descriptor UncompressedSize is wrong 4.ZipFile.TestArchive(true) is return false

Expected behavior

It is equal ZipEntry's Size

Actual behavior

It is 0x504B0304

Version of SharpZipLib

0.85, 0.86

Obtained from (place an x between the brackets for all that apply)

  • [-] Compiled from source
    • branch: master
    • commit: _______
  • [ .] Downloaded DLL from GitHub
  • [ ] Downloaded DLL from SourceForge
  • [ ] Downloaded DLL from _______
  • [ ] DLL included as part of
  • Package installed using:
    • [ ] NuGet
    • [ ] MyGet
    • [ ] Chocolatey screenshot_20161017_043451

daroubing avatar Oct 16 '16 20:10 daroubing

example of a unit test that looks to hit the issue (or something very similar at least):

[Test]
[Category("Zip")]
public void TestDescriptorUpdate()
{
    MemoryStream msw = new MemoryStreamWithoutSeek();
    using (ZipOutputStream outStream = new ZipOutputStream(msw))
    {
        outStream.UseZip64 = UseZip64.Off;
        outStream.IsStreamOwner = false;
        outStream.PutNextEntry(new ZipEntry("StripedMarlin"));
        outStream.WriteByte(89);

        outStream.PutNextEntry(new ZipEntry("StripedMarlin2"));
        outStream.WriteByte(91);
    }

    var zipData = msw.ToArray();
    Assert.IsTrue(ZipTesting.TestArchive(zipData));

    using (var memoryStream = new MemoryStream(zipData))
    {
        using (var zipFile = new ZipFile(memoryStream, leaveOpen: true))
        {
            zipFile.BeginUpdate();
            zipFile.Delete("StripedMarlin");
            zipFile.CommitUpdate();
        }

        memoryStream.Position = 0;

        using (var zipFile = new ZipFile(memoryStream, leaveOpen: true))
        {
            Assert.That(zipFile.TestArchive(true), Is.True);
        }
    }
}

i tried debugging the zipfile update, and i'm wondering if there is an issue in the GetDescriptorSize function in ZipFile:

private int GetDescriptorSize(ZipUpdate update)
{
    int result = 0;
    if ((update.Entry.Flags & (int)GeneralBitFlags.Descriptor) != 0)
    {
        result = ZipConstants.DataDescriptorSize - 4;
        if (update.Entry.LocalHeaderRequiresZip64)
        {
            result = ZipConstants.Zip64DataDescriptorSize - 4;
        }
    }
    return result;
}

Where I don't know what those -4s are for?

The test passes if those are removed, so i'm not sure if the issue isn't just that it's slicing the end off the descriptor when doing the update? (though i'm not sure if there should really be a descriptor there after the update at all, given that the size fields for the entry are known at this point)

Numpsy avatar Jun 07 '20 22:06 Numpsy

Actually, posted that and then saw the

image

comment in CopyEntryDirect, which sounds a tad suspicious given that GetDescriptorSize takes 4 bytes off the size.

Numpsy avatar Jun 07 '20 22:06 Numpsy