Skip to content

Commit 3b33af9

Browse files
committed
Remove descriptors from zip entries when moving them during updates.
1 parent 5c09afb commit 3b33af9

File tree

2 files changed

+70
-16
lines changed

2 files changed

+70
-16
lines changed

src/ICSharpCode.SharpZipLib/Zip/ZipFile.cs

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2050,8 +2050,14 @@ private void WriteLocalEntryHeader(ZipUpdate update)
20502050
// TODO: Local offset will require adjusting for multi-disk zip files.
20512051
entry.Offset = baseStream_.Position;
20522052

2053-
// TODO: Need to clear any entry flags that dont make sense or throw an exception here.
2054-
if (update.Command != UpdateCommand.Copy)
2053+
// set flags based on the type of entry being written
2054+
if (update.Command == UpdateCommand.Copy)
2055+
{
2056+
// We're copying an existing entry during an update.
2057+
// In this case, we won't need descriptors as we should always know the size/CRC fields of the entry directly
2058+
entry.Flags &= ~(int)GeneralBitFlags.Descriptor;
2059+
}
2060+
else
20552061
{
20562062
if (entry.CompressionMethod == CompressionMethod.Deflated)
20572063
{

test/ICSharpCode.SharpZipLib.Tests/Zip/ZipFileHandling.cs

Lines changed: 62 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1616,10 +1616,10 @@ public void AddFileWithAlternateName()
16161616
/// Test for https://github.com/icsharpcode/SharpZipLib/issues/147, when deleting items in a zip
16171617
/// </summary>
16181618
/// <param name="useZip64">Whether Zip64 should be used in the test archive</param>
1619-
[TestCase(UseZip64.On)]
1620-
[TestCase(UseZip64.Off)]
1619+
/// <param name="updateMode">Whether safe or direct updates should be used</param>
1620+
[Test]
16211621
[Category("Zip")]
1622-
public void TestDescriptorUpdateOnDelete(UseZip64 useZip64)
1622+
public void TestDescriptorUpdateOnDelete([Values] UseZip64 useZip64, [Values] FileUpdateMode updateMode)
16231623
{
16241624
MemoryStream msw = new MemoryStreamWithoutSeek();
16251625
using (ZipOutputStream outStream = new ZipOutputStream(msw))
@@ -1640,15 +1640,10 @@ public void TestDescriptorUpdateOnDelete(UseZip64 useZip64)
16401640
{
16411641
using (var zipFile = new ZipFile(memoryStream, leaveOpen: true))
16421642
{
1643-
zipFile.BeginUpdate();
1643+
zipFile.BeginUpdate(new MemoryArchiveStorage(updateMode));
16441644
zipFile.Delete("StripedMarlin");
16451645
zipFile.CommitUpdate();
1646-
}
1647-
1648-
memoryStream.Position = 0;
16491646

1650-
using (var zipFile = new ZipFile(memoryStream, leaveOpen: true))
1651-
{
16521647
Assert.That(zipFile.TestArchive(true), Is.True);
16531648
}
16541649
}
@@ -1658,10 +1653,10 @@ public void TestDescriptorUpdateOnDelete(UseZip64 useZip64)
16581653
/// Test for https://github.com/icsharpcode/SharpZipLib/issues/147, when adding items to a zip
16591654
/// </summary>
16601655
/// <param name="useZip64">Whether Zip64 should be used in the test archive</param>
1661-
[TestCase(UseZip64.On)]
1662-
[TestCase(UseZip64.Off)]
1656+
/// <param name="updateMode">Whether safe or direct updates should be used</param>
1657+
[Test]
16631658
[Category("Zip")]
1664-
public void TestDescriptorUpdateOnAdd(UseZip64 useZip64)
1659+
public void TestDescriptorUpdateOnAdd([Values] UseZip64 useZip64, [Values] FileUpdateMode updateMode)
16651660
{
16661661
MemoryStream msw = new MemoryStreamWithoutSeek();
16671662
using (ZipOutputStream outStream = new ZipOutputStream(msw))
@@ -1681,16 +1676,69 @@ public void TestDescriptorUpdateOnAdd(UseZip64 useZip64)
16811676

16821677
using (var zipFile = new ZipFile(memoryStream, leaveOpen: true))
16831678
{
1684-
zipFile.BeginUpdate();
1679+
zipFile.BeginUpdate(new MemoryArchiveStorage(updateMode));
16851680
zipFile.Add(new StringMemoryDataSource("stripey"), "Zebra");
16861681
zipFile.CommitUpdate();
1682+
1683+
Assert.That(zipFile.TestArchive(true), Is.True);
16871684
}
1685+
}
1686+
}
1687+
1688+
/// <summary>
1689+
/// Test for https://github.com/icsharpcode/SharpZipLib/issues/147, when replacing items in a zip
1690+
/// </summary>
1691+
/// <param name="useZip64">Whether Zip64 should be used in the test archive</param>
1692+
/// <param name="updateMode">Whether safe or direct updates should be used</param>
1693+
[Test]
1694+
[Category("Zip")]
1695+
public void TestDescriptorUpdateOnReplacee([Values] UseZip64 useZip64, [Values] FileUpdateMode updateMode)
1696+
{
1697+
MemoryStream msw = new MemoryStreamWithoutSeek();
1698+
using (ZipOutputStream outStream = new ZipOutputStream(msw))
1699+
{
1700+
outStream.UseZip64 = useZip64;
1701+
outStream.IsStreamOwner = false;
1702+
outStream.PutNextEntry(new ZipEntry("StripedMarlin"));
1703+
outStream.WriteByte(89);
1704+
outStream.PutNextEntry(new ZipEntry("WhiteMarlin"));
1705+
outStream.WriteByte(91);
1706+
outStream.PutNextEntry(new ZipEntry("Sailfish"));
1707+
outStream.WriteByte(3);
1708+
}
16881709

1689-
memoryStream.Position = 0;
1710+
var zipData = msw.ToArray();
1711+
Assert.IsTrue(ZipTesting.TestArchive(zipData));
16901712

1713+
using (var memoryStream = new MemoryStream(zipData))
1714+
{
16911715
using (var zipFile = new ZipFile(memoryStream, leaveOpen: true))
16921716
{
1717+
zipFile.BeginUpdate(new MemoryArchiveStorage(updateMode));
1718+
zipFile.Delete("WhiteMarlin");
1719+
zipFile.Add(new StringMemoryDataSource("Kajikia albida"), "WhiteMarlin");
1720+
zipFile.CommitUpdate();
1721+
16931722
Assert.That(zipFile.TestArchive(true), Is.True);
1723+
Assert.That(zipFile.Count, Is.EqualTo(3));
1724+
1725+
// Test for expected descriptor states:
1726+
// 'StripedMarlin' should still have a descriptor in Direct update mode as the entry data will be kept, but won't have one
1727+
// in Safe update mode as that recreates the whole archive.
1728+
// 'WhiteMarlin' should no longer have one because the entry is new and didn't need one
1729+
// 'Sailfish' should have its descriptor removed.
1730+
var entry = zipFile.GetEntry("StripedMarlin");
1731+
1732+
if (updateMode == FileUpdateMode.Direct)
1733+
Assert.True(((GeneralBitFlags)entry.Flags).HasFlag(GeneralBitFlags.Descriptor));
1734+
else
1735+
Assert.False(((GeneralBitFlags)entry.Flags).HasFlag(GeneralBitFlags.Descriptor));
1736+
1737+
entry = zipFile.GetEntry("WhiteMarlin");
1738+
Assert.False(((GeneralBitFlags)entry.Flags).HasFlag(GeneralBitFlags.Descriptor));
1739+
1740+
entry = zipFile.GetEntry("Sailfish");
1741+
Assert.False(((GeneralBitFlags)entry.Flags).HasFlag(GeneralBitFlags.Descriptor));
16941742
}
16951743
}
16961744
}

0 commit comments

Comments
 (0)