Skip to content

add zip test for blob with negative size#127990

Open
wfurt wants to merge 1 commit intodotnet:mainfrom
wfurt:negativeZip
Open

add zip test for blob with negative size#127990
wfurt wants to merge 1 commit intodotnet:mainfrom
wfurt:negativeZip

Conversation

@wfurt
Copy link
Copy Markdown
Member

@wfurt wfurt commented May 9, 2026

verifies we throw on malformed zip entry.

Copilot AI review requested due to automatic review settings May 9, 2026 03:26
@dotnet-policy-service
Copy link
Copy Markdown
Contributor

Tagging subscribers to this area: @karelz, @dotnet/area-system-io-compression
See info in area-owners.md if you want to be subscribed.

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds a regression/security-hardening test to the System.IO.Compression ZipArchive test suite to exercise parsing of a ZIP64 extra field that encodes an invalid (negative) uncompressed size, ensuring consumption remains safe.

Changes:

  • Added a new test covering a ZIP64 extra field with UncompressedSize = -1.
  • Added a byte-level ZIP builder helper to generate the malformed archive payload used by the test.

Comment on lines +2423 to +2447
// Attempting to actually read the data must fail safely — either by throwing,
// or by returning zero bytes (matching the actual stored data). It must NOT
// crash, hang, allocate based on the negative size, or read past the end of
// the underlying stream. Defense-in-depth in CrcValidatingReadStream rejects
// a negative expected length on Open(), so an ArgumentOutOfRangeException or
// InvalidDataException is the expected outcome here.
try
{
using Stream s = entry.Open();
byte[] buffer = new byte[1024];
int totalRead = 0;
int read;
while ((read = s.Read(buffer, 0, buffer.Length)) > 0)
{
totalRead += read;
// Guard against the negative size being misinterpreted as a huge unsigned
// length that would let the read loop run forever.
Assert.True(totalRead <= 1024 * 1024, "Read returned more data than the archive contains.");
}
Assert.Equal(0, totalRead);
}
catch (Exception ex) when (ex is InvalidDataException or ArgumentOutOfRangeException)
{
// Acceptable: downstream code rejects the malformed entry on Open/Read.
}
Comment on lines +2406 to +2411
// Validation for IO-021: Zip64 extra field with negative UncompressedSize (-1).
// The minimal 16-byte Zip64 extra field bypasses the negative-value check in
// Zip64ExtraField.TryGetZip64BlockFromGenericExtraField (the check only runs after
// all four fields would have been read). This test verifies that the bypassed
// negative value does NOT lead to memory corruption, buffer over-read, infinite
// loop, or other harmful behavior — downstream code handles it safely.
Comment on lines +2506 to +2507
long negativeUncompressedSize = -1; // 0xFFFFFFFFFFFFFFFF in two's complement
long negativeCompressedSize = 0;
Comment on lines +2533 to +2536
// No file data
long dataOffset = ms.Position;

// Central Directory File Header
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants