Skip to content

Commit 7bcd509

Browse files
mruslan97Ruslan Murtazin
and
Ruslan Murtazin
authored
Read StartDiskNumber as uint32 (#83923)
Fix #31825 Co-authored-by: Ruslan Murtazin <[email protected]>
1 parent 534d1df commit 7bcd509

File tree

4 files changed

+169
-9
lines changed

4 files changed

+169
-9
lines changed

src/libraries/System.IO.Compression/src/Resources/Strings.resx

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -230,9 +230,6 @@
230230
<data name="FieldTooBigOffsetToZip64EOCD" xml:space="preserve">
231231
<value>Offset to Zip64 End Of Central Directory record cannot be held in an Int64.</value>
232232
</data>
233-
<data name="FieldTooBigStartDiskNumber" xml:space="preserve">
234-
<value>Start Disk Number cannot be held in an Int64.</value>
235-
</data>
236233
<data name="FieldTooBigUncompressedSize" xml:space="preserve">
237234
<value>Uncompressed Size cannot be held in an Int64.</value>
238235
</data>

src/libraries/System.IO.Compression/src/System/IO/Compression/ZipArchiveEntry.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ public partial class ZipArchiveEntry
1818
{
1919
private ZipArchive _archive;
2020
private readonly bool _originallyInArchive;
21-
private readonly int _diskNumberStart;
21+
private readonly uint _diskNumberStart;
2222
private readonly ZipVersionMadeByPlatform _versionMadeByPlatform;
2323
private ZipVersionNeededValues _versionMadeBySpecification;
2424
internal ZipVersionNeededValues _versionToExtract;

src/libraries/System.IO.Compression/src/System/IO/Compression/ZipBlocks.cs

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -96,7 +96,7 @@ internal struct Zip64ExtraField
9696
private long? _uncompressedSize;
9797
private long? _compressedSize;
9898
private long? _localHeaderOffset;
99-
private int? _startDiskNumber;
99+
private uint? _startDiskNumber;
100100

101101
public ushort TotalSize => (ushort)(_size + 4);
102102

@@ -115,7 +115,7 @@ public long? LocalHeaderOffset
115115
get { return _localHeaderOffset; }
116116
set { _localHeaderOffset = value; UpdateSize(); }
117117
}
118-
public int? StartDiskNumber => _startDiskNumber;
118+
public uint? StartDiskNumber => _startDiskNumber;
119119

120120
private void UpdateSize()
121121
{
@@ -242,7 +242,7 @@ private static bool TryGetZip64BlockFromGenericExtraField(ZipGenericExtraField e
242242

243243
if (readStartDiskNumber)
244244
{
245-
zip64Block._startDiskNumber = reader.ReadInt32();
245+
zip64Block._startDiskNumber = reader.ReadUInt32();
246246
}
247247
else if (readAllFields)
248248
{
@@ -253,7 +253,6 @@ private static bool TryGetZip64BlockFromGenericExtraField(ZipGenericExtraField e
253253
if (zip64Block._uncompressedSize < 0) throw new InvalidDataException(SR.FieldTooBigUncompressedSize);
254254
if (zip64Block._compressedSize < 0) throw new InvalidDataException(SR.FieldTooBigCompressedSize);
255255
if (zip64Block._localHeaderOffset < 0) throw new InvalidDataException(SR.FieldTooBigLocalHeaderOffset);
256-
if (zip64Block._startDiskNumber < 0) throw new InvalidDataException(SR.FieldTooBigStartDiskNumber);
257256

258257
return true;
259258
}
@@ -480,7 +479,7 @@ internal struct ZipCentralDirectoryFileHeader
480479
public ushort FilenameLength;
481480
public ushort ExtraFieldLength;
482481
public ushort FileCommentLength;
483-
public int DiskNumberStart;
482+
public uint DiskNumberStart;
484483
public ushort InternalFileAttributes;
485484
public uint ExternalFileAttributes;
486485
public long RelativeOffsetOfLocalHeader;

src/libraries/System.IO.Compression/tests/ZipArchive/zip_InvalidParametersAndStrangeFiles.cs

Lines changed: 164 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33

44
using System.Buffers.Binary;
55
using System.Collections.Generic;
6+
using System.Linq;
67
using System.Text;
78
using System.Threading.Tasks;
89
using Xunit;
@@ -860,6 +861,20 @@ public void ReadArchive_WithUnexpectedZip64ExtraFieldSizeUncompressedSizeIn32Bit
860861
Assert.Equal(6, entry.CompressedLength); // it should have used 32-bit size
861862
}
862863

864+
/// <summary>
865+
/// This test checks behavior of ZipArchive when the startDiskNumber in the extraField is greater than IntMax
866+
/// </summary>
867+
[Fact]
868+
public void ReadArchive_WithDiskStartNumberGreaterThanIntMax()
869+
{
870+
byte[] input = (byte[])s_zip64WithBigStartDiskNumber.Clone();
871+
using var archive = new ZipArchive(new MemoryStream(input));
872+
873+
var exception = Record.Exception(() => archive.Entries.First());
874+
875+
Assert.Null(exception);
876+
}
877+
863878
private static readonly byte[] s_slightlyIncorrectZip64 =
864879
{
865880
// ===== Local file header signature 0x04034b50
@@ -1000,5 +1015,154 @@ public void ReadArchive_WithUnexpectedZip64ExtraFieldSizeUncompressedSizeIn32Bit
10001015
// comment length
10011016
0x00, 0x00
10021017
};
1018+
1019+
private static readonly byte[] s_zip64WithBigStartDiskNumber =
1020+
{
1021+
// ===== Local file header signature 0x04034b50
1022+
0x50, 0x4b, 0x03, 0x04,
1023+
// version to extract 4.5
1024+
0x2d, 0x00,
1025+
// general purpose flags
1026+
0x00, 0x08, // 0000_1000 'for enhanced deflating'
1027+
// Deflate
1028+
0x08, 0x00,
1029+
// Last mod file time
1030+
0x17, 0x9b,
1031+
// Last mod date
1032+
0x6d, 0x52,
1033+
// CRC32
1034+
0x0c, 0x7e, 0x7f, 0xd8,
1035+
// compressed size
1036+
0xff, 0xff, 0xff, 0xff,
1037+
// UNcompressed size
1038+
0xff, 0xff, 0xff, 0xff,
1039+
// file name length
1040+
1041+
0x08, 0x00,
1042+
// extra field length
1043+
0x20, 0x00,
1044+
// filename
1045+
0x66, 0x69, 0x6c, 0x65, 0x2e, 0x74, 0x78, 0x74,
1046+
// -----Zip64 extra field tag
1047+
0x01, 0x00,
1048+
// size of extra field block
1049+
0x20, 0x00,
1050+
// 8 byte Zip64 UNcompressed size, index 42
1051+
0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1052+
// 8 byte Zip64 compressed size, index 50
1053+
0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1054+
// 8 byte Relative Header Offset
1055+
0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1056+
// Disk Start Number
1057+
0xff, 0xff, 0xff, 0xfe,
1058+
// ----- NTFS extra field tag
1059+
0x0a, 0x00,
1060+
// size of extra field block
1061+
0x20, 0x00,
1062+
// reserved
1063+
0x00, 0x00, 0x00, 0x00,
1064+
// tag #1
1065+
0x01, 0x00,
1066+
// size of tag #1
1067+
0x18, 0x00,
1068+
// Mtime, CTime, Atime
1069+
0xa8, 0xb1, 0xf6, 0x61, 0x25, 0x18, 0xd7, 0x01,
1070+
0xa8, 0xb1, 0xf6, 0x61, 0x25, 0x18, 0xd7, 0x01,
1071+
0xa8, 0xb1, 0xf6, 0x61, 0x25, 0x18, 0xd7, 0x01,
1072+
// -------------
1073+
// Data!
1074+
0x2b, 0x49, 0x2d, 0x2e, 0x01, 0x00,
1075+
// -------- Central directory signature 0x02014b50
1076+
0x50, 0x4b, 0x01, 0x02,
1077+
// version made by 4.5
1078+
0x2d, 0x00,
1079+
// version to extract 4.5
1080+
0x2d, 0x00,
1081+
// general purpose flags
1082+
0x00, 0x08,
1083+
// Deflate
1084+
0x08, 0x00,
1085+
// Last mod file time
1086+
0x17, 0x9b,
1087+
// Last mod date
1088+
0x6d, 0x52,
1089+
// CRC32
1090+
0x0c, 0x7e, 0x7f, 0xd8,
1091+
// 4 byte compressed size, index 120 (-1 indicates refer to Zip64 extra field)
1092+
0xff, 0xff, 0xff, 0xff,
1093+
// 4 byte UNcompressed size, index 124 (-1 indicates refer to Zip64 extra field)
1094+
0xff, 0xff, 0xff, 0xff,
1095+
// file name length
1096+
0x08, 0x00,
1097+
// extra field length
1098+
0x44, 0x00,
1099+
// file comment length
1100+
0x00, 0x00,
1101+
// disk number start (-1 indicates refer to Zip64 extra field)
1102+
0xff, 0xff,
1103+
// internal file attributes
1104+
0x00, 0x00,
1105+
// external file attributes
1106+
0x00, 0x00, 0x00, 0x00,
1107+
// relative offset of local header (-1 indicates refer to Zip64 extra field)
1108+
0x00, 0x00, 0x00, 0x00,
1109+
// file name
1110+
0x66, 0x69, 0x6c, 0x65, 0x2e, 0x74, 0x78, 0x74,
1111+
// extra field, content similar to before
1112+
0x01, 0x00,
1113+
0x1c, 0x00,
1114+
0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1115+
0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1116+
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1117+
// Disk start number
1118+
0xff, 0xff, 0xff, 0xfe,
1119+
0x0a, 0x00,
1120+
0x20, 0x00,
1121+
0x00, 0x00, 0x00, 0x00,
1122+
0x01, 0x00, 0x18, 0x00,
1123+
0xa8, 0xb1, 0xf6, 0x61, 0x25, 0x18, 0xd7, 0x01,
1124+
0xa8, 0xb1, 0xf6, 0x61, 0x25, 0x18, 0xd7, 0x01,
1125+
0xa8, 0xb1, 0xf6, 0x61, 0x25, 0x18, 0xd7, 0x01,
1126+
// == 'end of zip64 central directory record' signature 0x06064b50
1127+
0x50, 0x4b, 0x06, 0x06,
1128+
// size
1129+
0x2c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1130+
// version made by, version needed
1131+
0x2d, 0x00, 0x2d, 0x00,
1132+
// disk number, disk number with CD
1133+
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1134+
// total number of CD records
1135+
0x01, 0x00, 0x00, 0x00,
1136+
// size of CD
1137+
0x00, 0x00, 0x00, 0x00,
1138+
// offset of start of CD wrt starting disk
1139+
0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1140+
// zip64 extensible data sector
1141+
0x7a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1142+
// offset of start cd
1143+
0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1144+
// == 'zip64 end of CD locator' signature 0x07064b50
1145+
0x50, 0x4b, 0x06, 0x07,
1146+
// number of disk with zip64 CD
1147+
0x00, 0x00, 0x00, 0x00,
1148+
// relative offset of zip64 ECD
1149+
0xea, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1150+
// total number of disks
1151+
0x01, 0x00, 0x00, 0x00,
1152+
// == 'end of CD' signature 0x06054b50
1153+
0x50, 0x4b, 0x05, 0x06,
1154+
// disk number, disk number with CD (-1 indicates refer to Zip64 extra field)
1155+
0x00, 0x00,
1156+
0x00, 0x00,
1157+
// total number of entries in CD on this disk, and overall (-1 indicates refer to Zip64 extra fields)
1158+
0xff, 0xff,
1159+
0xff, 0xff,
1160+
// size of CD (-1 indicates refer to Zip64 extra field)
1161+
0x7a, 0x00, 0x00, 0x00,
1162+
// offset of start of CD wrt start disk (-1 indicates refer to Zip64 extra field)
1163+
0x70, 0x00, 0x00, 0x00,
1164+
// comment length
1165+
0x00, 0x00
1166+
};
10031167
}
10041168
}

0 commit comments

Comments
 (0)