Skip to content

Conversation

Copy link
Contributor

Copilot AI commented Nov 19, 2025

Plan: Fix Zip64 Version Mismatch Between LFH and CDFH

Problem

When UseZip64=true but files are small (< 4GB), there's a version mismatch:

  • Local File Header (LFH) writes version 45 (Zip64) or 63 (LZMA/PPMd)
  • Central Directory File Header (CDFH) writes version 20 (because actual sizes don't require Zip64)
  • This causes validation failures in System.IO.Packaging and potentially other readers

Root Cause

  • In ZipWriter.WriteHeader(): Version is set based on compression method and Zip64 usage
  • In ZipCentralDirectoryEntry.Write(): Version was set to 45 only when actual sizes/offsets exceed uint.MaxValue, ignoring compression method requirements

Solution

  • Understand the issue and existing code
  • Create tests to validate version consistency (5 comprehensive tests)
  • Fix ZipCentralDirectoryEntry.Write() to properly handle:
    • Version 63 for LZMA/PPMd/BZip2/ZStandard compression
    • Version 45 when Zip64HeaderOffset != 0 or actual sizes require it
    • Version 20 for standard Deflate/None compression
  • Run tests to ensure no regression (all 374 Zip tests pass)
  • Format code with CSharpier
  • Remove ZipCompressionMethod.None from version 63 check (per review feedback)

Changes Made

  1. Modified ZipCentralDirectoryEntry.cs:

    • Updated version calculation to check compression method first
    • Then check if Zip64 was used in LFH (Zip64HeaderOffset != 0)
    • Finally fallback to version 20 for standard compression
  2. Added Zip64VersionConsistencyTests.cs: Created 5 tests

    • Test with small file and UseZip64=true
    • Test with small file and UseZip64=false
    • Test with multiple small files and UseZip64=true
    • Test with LZMA compression (version 63)
    • Test with PPMd compression (version 63)

Test Results

  • ✅ All 5 new tests pass
  • ✅ All 374 Zip tests pass (including LZMA/PPMd)

This ensures archives created with UseZip64=true or advanced compression methods can be opened by System.IO.Packaging and other strict ZIP readers.

Original prompt

This section details on the original issue you should resolve

<issue_title>Failed validation when using Zip64 with System.IO.Packaging</issue_title>
<issue_description>Hi there, ran into this little problem when using SharpCompress.

A zip archive created with UseZip64 set to true will fail to open using ZipPackage (from System.IO.Packaging) with .NET Framework 4.8.

The exception occurs in ZipIOLocalFileBlock.Validate() here:

if (VersionNeededToExtract != centralDirFileHeader.VersionNeededToExtract || GeneralPurposeBitFlag != centralDirFileHeader.GeneralPurposeBitFlag || CompressedSize != centralDirFileHeader.CompressedSize || UncompressedSize != centralDirFileHeader.UncompressedSize || CompressionMethod != centralDirFileHeader.CompressionMethod || Crc32 != centralDirFileHeader.Crc32)
{
	throw new FileFormatException(SR.Get("CorruptedData"));
}

VersionNeededToExtract value is 45 while centralDirFileHeader.VersionNeededToExtract is 20.
This mismatch seems to come from the fact that in SharpCompress the Local File Header will always have its version set to 45 when UseZip64 is true, but the version in the Central Directory File Header will be 45 only if size/offset is over uint.MaxValue (which makes sense).

Not sure what's the best way to handle this, an easy one would probably be to set both versions to 45 as soon as the flag is true ? (but this may not be optimal/trivial).

In SharpCompress these parts seem to be in ZipWriter.WriteToStream() / ZipWriter.WriteHeader() for the LFH and in ZipCentralDirectoryEntry.Write() for the CDFH.

Small code to reproduce the issue:

using System.IO.Packaging;

using SharpCompress.Archives;
using SharpCompress.Archives.Zip;
using SharpCompress.Common;
using SharpCompress.Writers;
using SharpCompress.Writers.Zip;

WriterOptions writerOptions = new ZipWriterOptions(CompressionType.Deflate)
{
    LeaveStreamOpen = false,
    UseZip64 = true
};
string file = "test_zip64.zip";

ZipArchive zipArchive = ZipArchive.Create();
zipArchive.AddEntry("empty", new MemoryStream());
zipArchive.SaveTo(file, writerOptions);

using var package = ZipPackage.Open(file, FileMode.Open, FileAccess.Read);

Kind of related to #164</issue_description>

Comments on the Issue (you are @copilot in this section)


💡 You can make Copilot smarter by setting up custom instructions, customizing its development environment and configuring Model Context Protocol (MCP) servers. Learn more Copilot coding agent tips in the docs.

Copilot AI and others added 2 commits November 19, 2025 11:14
When UseZip64=true but files are small, ensure Central Directory File Header uses version 45 to match Local File Header. This fixes validation failures in System.IO.Packaging and other strict readers.

Co-authored-by: adamhathcock <527620+adamhathcock@users.noreply.github.com>
Also fixes pre-existing version mismatch for advanced compression methods that require version 63. Added tests for LZMA and PPMd to verify version consistency.

Co-authored-by: adamhathcock <527620+adamhathcock@users.noreply.github.com>
Copilot AI changed the title [WIP] Fix failed validation when using Zip64 with System.IO.Packaging Fix version mismatch between Local File Header and Central Directory File Header in Zip archives Nov 19, 2025
Copy link
Owner

@adamhathcock adamhathcock left a comment

Choose a reason for hiding this comment

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

Version to extract should be written as Zip64 when using it. Fix others

@adamhathcock adamhathcock marked this pull request as ready for review November 19, 2025 15:26
Copilot AI review requested due to automatic review settings November 19, 2025 15:26
Copy link
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

This pull request fixes a version mismatch between Local File Header (LFH) and Central Directory File Header (CDFH) in ZIP archives when UseZip64=true is set with small files. The mismatch caused strict ZIP readers like System.IO.Packaging.ZipPackage to fail validation.

Key Changes:

  • Modified version determination logic in ZipCentralDirectoryEntry.Write() to check for Zip64 extension usage via Zip64HeaderOffset
  • Added explicit version 63 handling for advanced compression methods (LZMA, PPMd, BZip2, ZStandard)
  • Added comprehensive test suite to verify version consistency across different scenarios

Reviewed Changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated 4 comments.

File Description
src/SharpCompress/Writers/Zip/ZipCentralDirectoryEntry.cs Updated version determination logic to prioritize compression method requirements, then Zip64 extension usage, then default to version 20
tests/SharpCompress.Test/Zip/Zip64VersionConsistencyTests.cs Added 5 new tests validating version consistency for Zip64 enabled/disabled scenarios and LZMA/PPMd compression methods

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

adamhathcock and others added 5 commits November 19, 2025 15:49
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Copy link
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

Copilot reviewed 3 out of 3 changed files in this pull request and generated 6 comments.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

None (stored) compression only requires version 10/20, not version 63.
Version 63 is specifically for advanced compression methods like LZMA,
PPMd, BZip2, and ZStandard.

Co-authored-by: adamhathcock <527620+adamhathcock@users.noreply.github.com>
Copilot AI requested a review from adamhathcock November 25, 2025 14:59
@adamhathcock adamhathcock merged commit 9433e06 into master Nov 25, 2025
7 checks passed
@adamhathcock adamhathcock deleted the copilot/fix-zip64-validation-issue branch November 25, 2025 15:30
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Failed validation when using Zip64 with System.IO.Packaging

2 participants