Skip to content

Commit

Permalink
fix(zip): dont fail test on 0 sizes and descriptor (#736)
Browse files Browse the repository at this point in the history
  • Loading branch information
piksel authored Mar 23, 2022
1 parent 71fe846 commit cc8dd78
Show file tree
Hide file tree
Showing 2 changed files with 40 additions and 16 deletions.
24 changes: 24 additions & 0 deletions src/ICSharpCode.SharpZipLib/Zip/ZipConstants.cs
Original file line number Diff line number Diff line change
Expand Up @@ -472,4 +472,28 @@ public static class ZipConstants

#endregion Header Signatures
}

/// <summary>
/// GeneralBitFlags helper extensions
/// </summary>
public static class GenericBitFlagsExtensions
{
/// <summary>
/// Efficiently check if any of the <see cref="GeneralBitFlags">flags</see> are set without enum un-/boxing
/// </summary>
/// <param name="target"></param>
/// <param name="flags"></param>
/// <returns>Returns whether any of flags are set</returns>
public static bool HasAny(this GeneralBitFlags target, GeneralBitFlags flags)
=> ((int)target & (int)flags) != 0;

/// <summary>
/// Efficiently check if all the <see cref="GeneralBitFlags">flags</see> are set without enum un-/boxing
/// </summary>
/// <param name="target"></param>
/// <param name="flags"></param>
/// <returns>Returns whether the flags are all set</returns>
public static bool HasAll(this GeneralBitFlags target, GeneralBitFlags flags)
=> ((int)target & (int)flags) == (int)flags;
}
}
32 changes: 16 additions & 16 deletions src/ICSharpCode.SharpZipLib/Zip/ZipFile.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1115,7 +1115,7 @@ private long TestLocalHeader(ZipEntry entry, HeaderTest tests)
}

var extractVersion = (short)(ReadLEUshort() & 0x00ff);
var localFlags = (short)ReadLEUshort();
var localFlags = (GeneralBitFlags)ReadLEUshort();
var compressionMethod = (short)ReadLEUshort();
var fileTime = (short)ReadLEUshort();
var fileDate = (short)ReadLEUshort();
Expand All @@ -1142,15 +1142,15 @@ private long TestLocalHeader(ZipEntry entry, HeaderTest tests)
size = localExtraData.ReadLong();
compressedSize = localExtraData.ReadLong();

if ((localFlags & (int)GeneralBitFlags.Descriptor) != 0)
if (localFlags.HasAny(GeneralBitFlags.Descriptor))
{
// These may be valid if patched later
if ((size != -1) && (size != entry.Size))
if ((size > 0) && (size != entry.Size))
{
throw new ZipException("Size invalid for descriptor");
}

if ((compressedSize != -1) && (compressedSize != entry.CompressedSize))
if ((compressedSize > 0) && (compressedSize != entry.CompressedSize))
{
throw new ZipException("Compressed size invalid for descriptor");
}
Expand Down Expand Up @@ -1181,7 +1181,7 @@ private long TestLocalHeader(ZipEntry entry, HeaderTest tests)
throw new ZipException(string.Format("Version required to extract this entry not supported ({0})", extractVersion));
}

if ((localFlags & (int)(GeneralBitFlags.Patched | GeneralBitFlags.StrongEncryption | GeneralBitFlags.EnhancedCompress | GeneralBitFlags.HeaderMasked)) != 0)
if (localFlags.HasAny(GeneralBitFlags.Patched | GeneralBitFlags.StrongEncryption | GeneralBitFlags.EnhancedCompress | GeneralBitFlags.HeaderMasked))
{
throw new ZipException("The library does not support the zip version required to extract this entry");
}
Expand Down Expand Up @@ -1213,21 +1213,21 @@ private long TestLocalHeader(ZipEntry entry, HeaderTest tests)
var localEncoding = _stringCodec.ZipInputEncoding(localFlags);

// Local entry flags dont have reserved bit set on.
if ((localFlags & (int)(GeneralBitFlags.ReservedPKware4 | GeneralBitFlags.ReservedPkware14 | GeneralBitFlags.ReservedPkware15)) != 0)
if (localFlags.HasAny(GeneralBitFlags.ReservedPKware4 | GeneralBitFlags.ReservedPkware14 | GeneralBitFlags.ReservedPkware15))
{
throw new ZipException("Reserved bit flags cannot be set.");
}

// Encryption requires extract version >= 20
if (((localFlags & (int)GeneralBitFlags.Encrypted) != 0) && (extractVersion < 20))
if (localFlags.HasAny(GeneralBitFlags.Encrypted) && extractVersion < 20)
{
throw new ZipException(string.Format("Version required to extract this entry is too low for encryption ({0})", extractVersion));
}

// Strong encryption requires encryption flag to be set and extract version >= 50.
if ((localFlags & (int)GeneralBitFlags.StrongEncryption) != 0)
if (localFlags.HasAny(GeneralBitFlags.StrongEncryption))
{
if ((localFlags & (int)GeneralBitFlags.Encrypted) == 0)
if (!localFlags.HasAny(GeneralBitFlags.Encrypted))
{
throw new ZipException("Strong encryption flag set but encryption flag is not set");
}
Expand All @@ -1239,13 +1239,13 @@ private long TestLocalHeader(ZipEntry entry, HeaderTest tests)
}

// Patched entries require extract version >= 27
if (((localFlags & (int)GeneralBitFlags.Patched) != 0) && (extractVersion < 27))
if (localFlags.HasAny(GeneralBitFlags.Patched) && extractVersion < 27)
{
throw new ZipException(string.Format("Patched data requires higher version than ({0})", extractVersion));
}

// Central header flags match local entry flags.
if (localFlags != entry.Flags)
if ((int)localFlags != entry.Flags)
{
throw new ZipException("Central header/local header flags mismatch");
}
Expand All @@ -1262,23 +1262,23 @@ private long TestLocalHeader(ZipEntry entry, HeaderTest tests)
}

// Strong encryption and extract version match
if ((localFlags & (int)GeneralBitFlags.StrongEncryption) != 0)
if (localFlags.HasAny(GeneralBitFlags.StrongEncryption))
{
if (extractVersion < 62)
{
throw new ZipException("Strong encryption flag set but version not high enough");
}
}

if ((localFlags & (int)GeneralBitFlags.HeaderMasked) != 0)
if (localFlags.HasAny(GeneralBitFlags.HeaderMasked))
{
if ((fileTime != 0) || (fileDate != 0))
{
throw new ZipException("Header masked set but date/time values non-zero");
}
}

if ((localFlags & (int)GeneralBitFlags.Descriptor) == 0)
if (!localFlags.HasAny(GeneralBitFlags.Descriptor))
{
if (crcValue != (uint)entry.Crc)
{
Expand Down Expand Up @@ -1348,7 +1348,7 @@ private long TestLocalHeader(ZipEntry entry, HeaderTest tests)

// Size can be verified only if it is known in the local header.
// it will always be known in the central header.
if (((localFlags & (int)GeneralBitFlags.Descriptor) == 0) ||
if (!localFlags.HasAny(GeneralBitFlags.Descriptor) ||
((size > 0 || compressedSize > 0) && entry.Size > 0))
{
if ((size != 0)
Expand Down Expand Up @@ -2507,7 +2507,7 @@ private void CopyBytes(ZipUpdate update, Stream destination, Stream source,
/// <returns>The descriptor size, zero if there isn't one.</returns>
private static int GetDescriptorSize(ZipUpdate update, bool includingSignature)
{
if (!((GeneralBitFlags)update.Entry.Flags).HasFlag(GeneralBitFlags.Descriptor))
if (!((GeneralBitFlags)update.Entry.Flags).HasAny(GeneralBitFlags.Descriptor))
return 0;

var descriptorWithSignature = update.Entry.LocalHeaderRequiresZip64
Expand Down

0 comments on commit cc8dd78

Please sign in to comment.