From cc8dd78ed989888f6685da4cc009c529158738b4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?nils=20m=C3=A5s=C3=A9n?= Date: Wed, 23 Mar 2022 13:44:02 +0100 Subject: [PATCH] fix(zip): dont fail test on 0 sizes and descriptor (#736) --- .../Zip/ZipConstants.cs | 24 ++++++++++++++ src/ICSharpCode.SharpZipLib/Zip/ZipFile.cs | 32 +++++++++---------- 2 files changed, 40 insertions(+), 16 deletions(-) diff --git a/src/ICSharpCode.SharpZipLib/Zip/ZipConstants.cs b/src/ICSharpCode.SharpZipLib/Zip/ZipConstants.cs index 6d4892d55..204196d85 100644 --- a/src/ICSharpCode.SharpZipLib/Zip/ZipConstants.cs +++ b/src/ICSharpCode.SharpZipLib/Zip/ZipConstants.cs @@ -472,4 +472,28 @@ public static class ZipConstants #endregion Header Signatures } + + /// + /// GeneralBitFlags helper extensions + /// + public static class GenericBitFlagsExtensions + { + /// + /// Efficiently check if any of the flags are set without enum un-/boxing + /// + /// + /// + /// Returns whether any of flags are set + public static bool HasAny(this GeneralBitFlags target, GeneralBitFlags flags) + => ((int)target & (int)flags) != 0; + + /// + /// Efficiently check if all the flags are set without enum un-/boxing + /// + /// + /// + /// Returns whether the flags are all set + public static bool HasAll(this GeneralBitFlags target, GeneralBitFlags flags) + => ((int)target & (int)flags) == (int)flags; + } } diff --git a/src/ICSharpCode.SharpZipLib/Zip/ZipFile.cs b/src/ICSharpCode.SharpZipLib/Zip/ZipFile.cs index 0a844916e..1e9bf43d3 100644 --- a/src/ICSharpCode.SharpZipLib/Zip/ZipFile.cs +++ b/src/ICSharpCode.SharpZipLib/Zip/ZipFile.cs @@ -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(); @@ -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"); } @@ -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"); } @@ -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"); } @@ -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"); } @@ -1262,7 +1262,7 @@ 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) { @@ -1270,7 +1270,7 @@ private long TestLocalHeader(ZipEntry entry, HeaderTest tests) } } - if ((localFlags & (int)GeneralBitFlags.HeaderMasked) != 0) + if (localFlags.HasAny(GeneralBitFlags.HeaderMasked)) { if ((fileTime != 0) || (fileDate != 0)) { @@ -1278,7 +1278,7 @@ private long TestLocalHeader(ZipEntry entry, HeaderTest tests) } } - if ((localFlags & (int)GeneralBitFlags.Descriptor) == 0) + if (!localFlags.HasAny(GeneralBitFlags.Descriptor)) { if (crcValue != (uint)entry.Crc) { @@ -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) @@ -2507,7 +2507,7 @@ private void CopyBytes(ZipUpdate update, Stream destination, Stream source, /// The descriptor size, zero if there isn't one. 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