Skip to content

SharpCompress generates Zips that don't pass System.IO.Packaging validation #164

Description

@anaisbetts

I'm working on switching Squirrel.Windows to SharpCompress in Squirrel/Squirrel.Windows#803, and one thing I'm seeing is that files compressed with SharpCompress and then later opened via NuGet's code (which uses WPF's System.IO.Packaging code) blow up here:

    WindowsBase.dll!MS.Internal.IO.Zip.ZipIOLocalFileBlock.Validate(string fileName, MS.Internal.IO.Zip.ZipIOCentralDirectoryBlock centralDir, MS.Internal.IO.Zip.ZipIOCentralDirectoryFileHeader centralDirFileHeader) Unknown
    WindowsBase.dll!MS.Internal.IO.Zip.ZipIOLocalFileBlock.ParseRecord(System.IO.BinaryReader reader, string fileName, long position, MS.Internal.IO.Zip.ZipIOCentralDirectoryBlock centralDir, MS.Internal.IO.Zip.ZipIOCentralDirectoryFileHeader centralDirFileHeader)    Unknown
    WindowsBase.dll!MS.Internal.IO.Zip.ZipIOLocalFileBlock.SeekableLoad(MS.Internal.IO.Zip.ZipIOBlockManager blockManager, string fileName) Unknown
    WindowsBase.dll!MS.Internal.IO.Zip.ZipIOBlockManager.LoadLocalFileBlock(string zipFileName) Unknown
    WindowsBase.dll!MS.Internal.IO.Zip.ZipArchive.GetFile(string zipFileName)   Unknown
    WindowsBase.dll!MS.Internal.IO.Zip.ZipArchive.GetFiles()    Unknown
    WindowsBase.dll!System.IO.Packaging.ZipPackage.ContentTypeHelper.ContentTypeHelper(MS.Internal.IO.Zip.ZipArchive zipArchive, System.IO.Packaging.ZipPackage.IgnoredItemHelper ignoredItemHelper)    Unknown
    WindowsBase.dll!System.IO.Packaging.ZipPackage.ZipPackage(System.IO.Stream s, System.IO.FileMode mode, System.IO.FileAccess access, bool streaming) Unknown
    WindowsBase.dll!System.IO.Packaging.Package.Open(System.IO.Stream stream, System.IO.FileMode packageMode, System.IO.FileAccess packageAccess, bool streaming)   Unknown
    WindowsBase.dll!System.IO.Packaging.Package.Open(System.IO.Stream stream)   Unknown
>   NuGet.Squirrel.dll!NuGet.ZipPackage.EnsureManifest() Line 142   C#
    NuGet.Squirrel.dll!NuGet.ZipPackage.ZipPackage(string filePath, bool enableCaching) Line 53 C#

http://referencesource.microsoft.com/#WindowsBase/Base/MS/Internal/IO/Zip/ZipIOLocalFileBlock.cs,788

        private void Validate(string fileName, 
            ZipIOCentralDirectoryBlock centralDir,
            ZipIOCentralDirectoryFileHeader centralDirFileHeader)
        {
            // check that name matches parameter in a case sensitive culture neutral way
            if (0 != String.CompareOrdinal(_localFileHeader.FileName, fileName))
            {
                throw new FileFormatException(SR.Get(SRID.CorruptedData));
            }

            // compare compressed and uncompressed sizes, crc from central directory 
            if ((VersionNeededToExtract != centralDirFileHeader.VersionNeededToExtract) ||
                (GeneralPurposeBitFlag != centralDirFileHeader.GeneralPurposeBitFlag) ||
                (CompressedSize != centralDirFileHeader.CompressedSize) ||
                (UncompressedSize != centralDirFileHeader.UncompressedSize) ||
                (CompressionMethod != centralDirFileHeader.CompressionMethod) ||
                (Crc32 != centralDirFileHeader.Crc32))
            {
                throw new FileFormatException(SR.Get(SRID.CorruptedData));
            }

            // check for read into central directory (which would indicate file corruption)
            if (Offset + Size > centralDir.Offset)
                throw new FileFormatException(SR.Get(SRID.CorruptedData));

            // No CRC check here
            // delay validating the actual CRC until it is possible to do so without additional read operations
            // This is only for non-streaming mode (at this point we only support creation not consumption)
            // This is to avoid the forced reading of entire stream just for CRC check
            // CRC check is delegated  to ProgressiveCrcCalculatingStream and CRC is only validated
            //  once calculated CRC is available. This implies that CRC check operation is not
            //  guaranteed to be performed
        }

If you want a live repro, clone that PR and run the CreateFullPackagesFromDeltaSmokeTest test, or if you want a sample file to check out, https://cl.ly/0W3D3V1x0V2J

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions