Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[release/10.0-preview2] Revert "version needed to extract" fix #112923

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -53,15 +53,13 @@ internal ZipArchiveEntry(ZipArchive archive, ZipCentralDirectoryFileHeader cd)
_archive = archive;

_originallyInArchive = true;
Changes = ZipArchive.ChangeState.Unchanged;

_diskNumberStart = cd.DiskNumberStart;
_versionMadeByPlatform = (ZipVersionMadeByPlatform)cd.VersionMadeByCompatibility;
_versionMadeBySpecification = (ZipVersionNeededValues)cd.VersionMadeBySpecification;
_versionToExtract = (ZipVersionNeededValues)cd.VersionNeededToExtract;
_generalPurposeBitFlag = (BitFlagValues)cd.GeneralPurposeBitFlag;
_isEncrypted = (_generalPurposeBitFlag & BitFlagValues.IsEncrypted) != 0;
// Setting CompressionMethod can change the _versionToExtract variable, which can change the value of Changes
CompressionMethod = (CompressionMethodValues)cd.CompressionMethod;
_lastModified = new DateTimeOffset(ZipHelper.DosTimeToDateTime(cd.LastModified));
_compressedSize = cd.CompressedSize;
Expand Down Expand Up @@ -90,6 +88,8 @@ internal ZipArchiveEntry(ZipArchive archive, ZipCentralDirectoryFileHeader cd)
_fileComment = cd.FileComment;

_compressionLevel = MapCompressionLevel(_generalPurposeBitFlag, CompressionMethod);

Changes = ZipArchive.ChangeState.Unchanged;
}

// Initializes a ZipArchiveEntry instance for a new archive entry with a specified compression level.
Expand Down Expand Up @@ -1243,12 +1243,10 @@ private void VersionToExtractAtLeast(ZipVersionNeededValues value)
if (_versionToExtract < value)
{
_versionToExtract = value;
Changes |= ZipArchive.ChangeState.FixedLengthMetadata;
}
if (_versionMadeBySpecification < value)
{
_versionMadeBySpecification = value;
Changes |= ZipArchive.ChangeState.FixedLengthMetadata;
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -907,146 +907,6 @@ public static async Task ZipArchive_InvalidHuffmanData()
}
}

[Fact]
public static void ZipArchive_InvalidVersionToExtract()
{
using (MemoryStream updatedStream = new MemoryStream())
{
int originalLocalVersionToExtract = s_inconsistentVersionToExtract[4];
int originalCentralDirectoryVersionToExtract = s_inconsistentVersionToExtract[57];

// The existing archive will have a "version to extract" of 0.0, but will contain entries
// with deflate compression (which has a minimum version to extract of 2.0.)
Assert.Equal(0x00, originalLocalVersionToExtract);
Assert.Equal(0x00, originalCentralDirectoryVersionToExtract);

// Write the example data to the stream. We expect to be able to read it (and the entry contents) successfully.
updatedStream.Write(s_inconsistentVersionToExtract);
updatedStream.Seek(0, SeekOrigin.Begin);

using (ZipArchive originalArchive = new ZipArchive(updatedStream, ZipArchiveMode.Read, true))
{
Assert.Equal(1, originalArchive.Entries.Count);

ZipArchiveEntry firstEntry = originalArchive.Entries[0];

Assert.Equal("first.bin", firstEntry.Name);
Assert.Equal(10, firstEntry.Length);

using (Stream entryStream = firstEntry.Open())
{
Assert.Equal(10, firstEntry.Length);

byte[] uncompressedBytes = new byte[firstEntry.Length];
int bytesRead = entryStream.Read(uncompressedBytes);

Assert.Equal(10, bytesRead);

Assert.Equal(new byte[] { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09 }, uncompressedBytes);
}
}

updatedStream.Seek(0, SeekOrigin.Begin);

// Create a new entry, forcing the central directory headers to be rewritten. The local file header
// for first.bin would normally be skipped (because it hasn't changed) but it needs to be rewritten
// because the central directory headers will be rewritten with a valid value and the local file header
// needs to match.
using (ZipArchive updatedArchive = new ZipArchive(updatedStream, ZipArchiveMode.Update))
{
ZipArchiveEntry newEntry = updatedArchive.CreateEntry("second.bin", CompressionLevel.NoCompression);
}

byte[] updatedContents = updatedStream.ToArray();
int updatedLocalVersionToExtract = updatedContents[4];
int updatedCentralDirectoryVersionToExtract = updatedContents[97];

Assert.Equal(20, updatedCentralDirectoryVersionToExtract);
Assert.Equal(20, updatedLocalVersionToExtract);
}
}

private static readonly byte[] s_inconsistentVersionToExtract =
{
// ===== Local file header signature 0x04034b50
0x50, 0x4b, 0x03, 0x04,
// version to extract 0.0 (invalid - this should be at least 2.0 to make use of deflate compression)
0x00, 0x00,
// general purpose flags
0x02, 0x00, // 0000_0002 'for maximum-compression deflating'
// Deflate
0x08, 0x00,
// Last mod file time
0x3b, 0x33,
// Last mod date
0x3f, 0x5a,
// CRC32
0x46, 0xd7, 0x6c, 0x45,
// compressed size
0x0c, 0x00, 0x00, 0x00,
// uncompressed size
0x0a, 0x00, 0x00, 0x00,
// file name length
0x09, 0x00,
// extra field length
0x00, 0x00,
// filename
0x66, 0x69, 0x72, 0x73, 0x74, 0x2e, 0x62, 0x69, 0x6e,
// -------------
// Data!
0x63, 0x60, 0x64, 0x62, 0x66, 0x61, 0x65, 0x63, 0xe7, 0xe0, 0x04, 0x00,
// -------- Central directory signature 0x02014b50
0x50, 0x4b, 0x01, 0x02,
// version made by 2.0
0x14, 0x00,
// version to extract 0.0 (invalid - this should be at least 2.0 to make use of deflate compression)
0x00, 0x00,
// general purpose flags
0x02, 0x00,
// Deflate
0x08, 0x00,
// Last mod file time
0x3b, 0x33,
// Last mod date
0x3f, 0x5a,
// CRC32
0x46, 0xd7, 0x6c, 0x45,
// compressed size
0x0c, 0x00, 0x00, 0x00,
// uncompressed size
0x0a, 0x00, 0x00, 0x00,
// file name length
0x09, 0x00,
// extra field length
0x00, 0x00,
// file comment length
0x00, 0x00,
// disk number start
0x00, 0x00,
// internal file attributes
0x00, 0x00,
// external file attributes
0x00, 0x00, 0x00, 0x00,
// relative offset of local header
0x00, 0x00, 0x00, 0x00,
// file name
0x66, 0x69, 0x72, 0x73, 0x74, 0x2e, 0x62, 0x69, 0x6e,
// == 'end of CD' signature 0x06054b50
0x50, 0x4b, 0x05, 0x06,
// disk number, disk number with CD
0x00, 0x00,
0x00, 0x00,
// total number of entries in CD on this disk, and overall
0x01, 0x00,
0x01, 0x00,
// size of CD
0x37, 0x00, 0x00, 0x00,
// offset of start of CD wrt start disk
0x33, 0x00, 0x00, 0x00,
// comment length
0x00, 0x00
};

private static readonly byte[] s_slightlyIncorrectZip64 =
{
// ===== Local file header signature 0x04034b50
Expand All @@ -1065,7 +925,7 @@ public static void ZipArchive_InvalidVersionToExtract()
0x0c, 0x7e, 0x7f, 0xd8,
// compressed size
0xff, 0xff, 0xff, 0xff,
// uncompressed size
// UNcompressed size
0xff, 0xff, 0xff, 0xff,
// file name length
0x08, 0x00,
Expand Down Expand Up @@ -1116,7 +976,7 @@ public static void ZipArchive_InvalidVersionToExtract()
0x0c, 0x7e, 0x7f, 0xd8,
// 4 byte compressed size, index 120 (-1 indicates refer to Zip64 extra field)
0xff, 0xff, 0xff, 0xff,
// 4 byte uncompressed size, index 124 (-1 indicates refer to Zip64 extra field)
// 4 byte UNcompressed size, index 124 (-1 indicates refer to Zip64 extra field)
0xff, 0xff, 0xff, 0xff,
// file name length
0x08, 0x00,
Expand Down Expand Up @@ -1206,7 +1066,7 @@ public static void ZipArchive_InvalidVersionToExtract()
0x0c, 0x7e, 0x7f, 0xd8,
// compressed size
0xff, 0xff, 0xff, 0xff,
// uncompressed size
// UNcompressed size
0xff, 0xff, 0xff, 0xff,
// file name length

Expand All @@ -1219,7 +1079,7 @@ public static void ZipArchive_InvalidVersionToExtract()
0x01, 0x00,
// size of extra field block
0x20, 0x00,
// 8 byte Zip64 uncompressed size, index 42
// 8 byte Zip64 UNcompressed size, index 42
0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
// 8 byte Zip64 compressed size, index 50
0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
Expand Down Expand Up @@ -1262,7 +1122,7 @@ public static void ZipArchive_InvalidVersionToExtract()
0x0c, 0x7e, 0x7f, 0xd8,
// 4 byte compressed size, index 120 (-1 indicates refer to Zip64 extra field)
0xff, 0xff, 0xff, 0xff,
// 4 byte uncompressed size, index 124 (-1 indicates refer to Zip64 extra field)
// 4 byte UNcompressed size, index 124 (-1 indicates refer to Zip64 extra field)
0xff, 0xff, 0xff, 0xff,
// file name length
0x08, 0x00,
Expand Down
Loading