diff --git a/src/libraries/System.IO.Compression/src/Resources/Strings.resx b/src/libraries/System.IO.Compression/src/Resources/Strings.resx
index 94fa155281d93..86e181e97ff13 100644
--- a/src/libraries/System.IO.Compression/src/Resources/Strings.resx
+++ b/src/libraries/System.IO.Compression/src/Resources/Strings.resx
@@ -230,9 +230,6 @@
Offset to Zip64 End Of Central Directory record cannot be held in an Int64.
-
- Start Disk Number cannot be held in an Int64.
-
Uncompressed Size cannot be held in an Int64.
diff --git a/src/libraries/System.IO.Compression/src/System/IO/Compression/ZipArchiveEntry.cs b/src/libraries/System.IO.Compression/src/System/IO/Compression/ZipArchiveEntry.cs
index 1fd84d715f6d5..3d415f8e3690f 100644
--- a/src/libraries/System.IO.Compression/src/System/IO/Compression/ZipArchiveEntry.cs
+++ b/src/libraries/System.IO.Compression/src/System/IO/Compression/ZipArchiveEntry.cs
@@ -18,7 +18,7 @@ public partial class ZipArchiveEntry
{
private ZipArchive _archive;
private readonly bool _originallyInArchive;
- private readonly int _diskNumberStart;
+ private readonly uint _diskNumberStart;
private readonly ZipVersionMadeByPlatform _versionMadeByPlatform;
private ZipVersionNeededValues _versionMadeBySpecification;
internal ZipVersionNeededValues _versionToExtract;
diff --git a/src/libraries/System.IO.Compression/src/System/IO/Compression/ZipBlocks.cs b/src/libraries/System.IO.Compression/src/System/IO/Compression/ZipBlocks.cs
index fb186dfcfc9f3..8bcb5495efe46 100644
--- a/src/libraries/System.IO.Compression/src/System/IO/Compression/ZipBlocks.cs
+++ b/src/libraries/System.IO.Compression/src/System/IO/Compression/ZipBlocks.cs
@@ -96,7 +96,7 @@ internal struct Zip64ExtraField
private long? _uncompressedSize;
private long? _compressedSize;
private long? _localHeaderOffset;
- private int? _startDiskNumber;
+ private uint? _startDiskNumber;
public ushort TotalSize => (ushort)(_size + 4);
@@ -115,7 +115,7 @@ public long? LocalHeaderOffset
get { return _localHeaderOffset; }
set { _localHeaderOffset = value; UpdateSize(); }
}
- public int? StartDiskNumber => _startDiskNumber;
+ public uint? StartDiskNumber => _startDiskNumber;
private void UpdateSize()
{
@@ -242,7 +242,7 @@ private static bool TryGetZip64BlockFromGenericExtraField(ZipGenericExtraField e
if (readStartDiskNumber)
{
- zip64Block._startDiskNumber = reader.ReadInt32();
+ zip64Block._startDiskNumber = reader.ReadUInt32();
}
else if (readAllFields)
{
@@ -253,7 +253,6 @@ private static bool TryGetZip64BlockFromGenericExtraField(ZipGenericExtraField e
if (zip64Block._uncompressedSize < 0) throw new InvalidDataException(SR.FieldTooBigUncompressedSize);
if (zip64Block._compressedSize < 0) throw new InvalidDataException(SR.FieldTooBigCompressedSize);
if (zip64Block._localHeaderOffset < 0) throw new InvalidDataException(SR.FieldTooBigLocalHeaderOffset);
- if (zip64Block._startDiskNumber < 0) throw new InvalidDataException(SR.FieldTooBigStartDiskNumber);
return true;
}
@@ -480,7 +479,7 @@ internal struct ZipCentralDirectoryFileHeader
public ushort FilenameLength;
public ushort ExtraFieldLength;
public ushort FileCommentLength;
- public int DiskNumberStart;
+ public uint DiskNumberStart;
public ushort InternalFileAttributes;
public uint ExternalFileAttributes;
public long RelativeOffsetOfLocalHeader;
diff --git a/src/libraries/System.IO.Compression/tests/ZipArchive/zip_InvalidParametersAndStrangeFiles.cs b/src/libraries/System.IO.Compression/tests/ZipArchive/zip_InvalidParametersAndStrangeFiles.cs
index ec67114972f4d..f8ab630ba1656 100644
--- a/src/libraries/System.IO.Compression/tests/ZipArchive/zip_InvalidParametersAndStrangeFiles.cs
+++ b/src/libraries/System.IO.Compression/tests/ZipArchive/zip_InvalidParametersAndStrangeFiles.cs
@@ -3,6 +3,7 @@
using System.Buffers.Binary;
using System.Collections.Generic;
+using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Xunit;
@@ -860,6 +861,20 @@ public void ReadArchive_WithUnexpectedZip64ExtraFieldSizeUncompressedSizeIn32Bit
Assert.Equal(6, entry.CompressedLength); // it should have used 32-bit size
}
+ ///
+ /// This test checks behavior of ZipArchive when the startDiskNumber in the extraField is greater than IntMax
+ ///
+ [Fact]
+ public void ReadArchive_WithDiskStartNumberGreaterThanIntMax()
+ {
+ byte[] input = (byte[])s_zip64WithBigStartDiskNumber.Clone();
+ using var archive = new ZipArchive(new MemoryStream(input));
+
+ var exception = Record.Exception(() => archive.Entries.First());
+
+ Assert.Null(exception);
+ }
+
private static readonly byte[] s_slightlyIncorrectZip64 =
{
// ===== Local file header signature 0x04034b50
@@ -1000,5 +1015,154 @@ public void ReadArchive_WithUnexpectedZip64ExtraFieldSizeUncompressedSizeIn32Bit
// comment length
0x00, 0x00
};
+
+ private static readonly byte[] s_zip64WithBigStartDiskNumber =
+ {
+ // ===== Local file header signature 0x04034b50
+ 0x50, 0x4b, 0x03, 0x04,
+ // version to extract 4.5
+ 0x2d, 0x00,
+ // general purpose flags
+ 0x00, 0x08, // 0000_1000 'for enhanced deflating'
+ // Deflate
+ 0x08, 0x00,
+ // Last mod file time
+ 0x17, 0x9b,
+ // Last mod date
+ 0x6d, 0x52,
+ // CRC32
+ 0x0c, 0x7e, 0x7f, 0xd8,
+ // compressed size
+ 0xff, 0xff, 0xff, 0xff,
+ // UNcompressed size
+ 0xff, 0xff, 0xff, 0xff,
+ // file name length
+
+ 0x08, 0x00,
+ // extra field length
+ 0x20, 0x00,
+ // filename
+ 0x66, 0x69, 0x6c, 0x65, 0x2e, 0x74, 0x78, 0x74,
+ // -----Zip64 extra field tag
+ 0x01, 0x00,
+ // size of extra field block
+ 0x20, 0x00,
+ // 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,
+ // 8 byte Relative Header Offset
+ 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ // Disk Start Number
+ 0xff, 0xff, 0xff, 0xfe,
+ // ----- NTFS extra field tag
+ 0x0a, 0x00,
+ // size of extra field block
+ 0x20, 0x00,
+ // reserved
+ 0x00, 0x00, 0x00, 0x00,
+ // tag #1
+ 0x01, 0x00,
+ // size of tag #1
+ 0x18, 0x00,
+ // Mtime, CTime, Atime
+ 0xa8, 0xb1, 0xf6, 0x61, 0x25, 0x18, 0xd7, 0x01,
+ 0xa8, 0xb1, 0xf6, 0x61, 0x25, 0x18, 0xd7, 0x01,
+ 0xa8, 0xb1, 0xf6, 0x61, 0x25, 0x18, 0xd7, 0x01,
+ // -------------
+ // Data!
+ 0x2b, 0x49, 0x2d, 0x2e, 0x01, 0x00,
+ // -------- Central directory signature 0x02014b50
+ 0x50, 0x4b, 0x01, 0x02,
+ // version made by 4.5
+ 0x2d, 0x00,
+ // version to extract 4.5
+ 0x2d, 0x00,
+ // general purpose flags
+ 0x00, 0x08,
+ // Deflate
+ 0x08, 0x00,
+ // Last mod file time
+ 0x17, 0x9b,
+ // Last mod date
+ 0x6d, 0x52,
+ // CRC32
+ 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)
+ 0xff, 0xff, 0xff, 0xff,
+ // file name length
+ 0x08, 0x00,
+ // extra field length
+ 0x44, 0x00,
+ // file comment length
+ 0x00, 0x00,
+ // disk number start (-1 indicates refer to Zip64 extra field)
+ 0xff, 0xff,
+ // internal file attributes
+ 0x00, 0x00,
+ // external file attributes
+ 0x00, 0x00, 0x00, 0x00,
+ // relative offset of local header (-1 indicates refer to Zip64 extra field)
+ 0x00, 0x00, 0x00, 0x00,
+ // file name
+ 0x66, 0x69, 0x6c, 0x65, 0x2e, 0x74, 0x78, 0x74,
+ // extra field, content similar to before
+ 0x01, 0x00,
+ 0x1c, 0x00,
+ 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ // Disk start number
+ 0xff, 0xff, 0xff, 0xfe,
+ 0x0a, 0x00,
+ 0x20, 0x00,
+ 0x00, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x18, 0x00,
+ 0xa8, 0xb1, 0xf6, 0x61, 0x25, 0x18, 0xd7, 0x01,
+ 0xa8, 0xb1, 0xf6, 0x61, 0x25, 0x18, 0xd7, 0x01,
+ 0xa8, 0xb1, 0xf6, 0x61, 0x25, 0x18, 0xd7, 0x01,
+ // == 'end of zip64 central directory record' signature 0x06064b50
+ 0x50, 0x4b, 0x06, 0x06,
+ // size
+ 0x2c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ // version made by, version needed
+ 0x2d, 0x00, 0x2d, 0x00,
+ // disk number, disk number with CD
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ // total number of CD records
+ 0x01, 0x00, 0x00, 0x00,
+ // size of CD
+ 0x00, 0x00, 0x00, 0x00,
+ // offset of start of CD wrt starting disk
+ 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ // zip64 extensible data sector
+ 0x7a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ // offset of start cd
+ 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ // == 'zip64 end of CD locator' signature 0x07064b50
+ 0x50, 0x4b, 0x06, 0x07,
+ // number of disk with zip64 CD
+ 0x00, 0x00, 0x00, 0x00,
+ // relative offset of zip64 ECD
+ 0xea, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ // total number of disks
+ 0x01, 0x00, 0x00, 0x00,
+ // == 'end of CD' signature 0x06054b50
+ 0x50, 0x4b, 0x05, 0x06,
+ // disk number, disk number with CD (-1 indicates refer to Zip64 extra field)
+ 0x00, 0x00,
+ 0x00, 0x00,
+ // total number of entries in CD on this disk, and overall (-1 indicates refer to Zip64 extra fields)
+ 0xff, 0xff,
+ 0xff, 0xff,
+ // size of CD (-1 indicates refer to Zip64 extra field)
+ 0x7a, 0x00, 0x00, 0x00,
+ // offset of start of CD wrt start disk (-1 indicates refer to Zip64 extra field)
+ 0x70, 0x00, 0x00, 0x00,
+ // comment length
+ 0x00, 0x00
+ };
}
}