From 41c46a041422259c5a30fd5117d92f6b0e70d772 Mon Sep 17 00:00:00 2001 From: vitek-karas Date: Sat, 17 Apr 2021 14:14:38 -0700 Subject: [PATCH] Support for single-file bundle from .NET 6. This supports the new version and also the new compressed files. --- ICSharpCode.Decompiler/SingleFileBundle.cs | 10 +++++++--- ILSpy/LoadedPackage.cs | 19 ++++++++++++++++++- 2 files changed, 25 insertions(+), 4 deletions(-) diff --git a/ICSharpCode.Decompiler/SingleFileBundle.cs b/ICSharpCode.Decompiler/SingleFileBundle.cs index a98701269..c92af8b35 100644 --- a/ICSharpCode.Decompiler/SingleFileBundle.cs +++ b/ICSharpCode.Decompiler/SingleFileBundle.cs @@ -99,6 +99,7 @@ namespace ICSharpCode.Decompiler { public long Offset; public long Size; + public long CompressedSize; // 0 if not compressed, otherwise the compressed size in the bundle public FileType Type; public string RelativePath; // Path of an embedded file, relative to the Bundle source-directory. } @@ -128,7 +129,9 @@ namespace ICSharpCode.Decompiler using var reader = new BinaryReader(stream, Encoding.UTF8, leaveOpen: true); header.MajorVersion = reader.ReadUInt32(); header.MinorVersion = reader.ReadUInt32(); - if (header.MajorVersion < 1 || header.MajorVersion > 2) + + // Major versions 3, 4 and 5 were skipped to align bundle versioning with .NET versioning scheme + if (header.MajorVersion < 1 || header.MajorVersion > 6) { throw new InvalidDataException($"Unsupported manifest version: {header.MajorVersion}.{header.MinorVersion}"); } @@ -145,17 +148,18 @@ namespace ICSharpCode.Decompiler var entries = ImmutableArray.CreateBuilder(header.FileCount); for (int i = 0; i < header.FileCount; i++) { - entries.Add(ReadEntry(reader)); + entries.Add(ReadEntry(reader, header.MajorVersion)); } header.Entries = entries.MoveToImmutable(); return header; } - private static Entry ReadEntry(BinaryReader reader) + private static Entry ReadEntry(BinaryReader reader, uint bundleMajorVersion) { Entry entry; entry.Offset = reader.ReadInt64(); entry.Size = reader.ReadInt64(); + entry.CompressedSize = bundleMajorVersion >= 6 ? reader.ReadInt64() : 0; entry.Type = (FileType)reader.ReadByte(); entry.RelativePath = reader.ReadString(); return entry; diff --git a/ILSpy/LoadedPackage.cs b/ILSpy/LoadedPackage.cs index 9a72d987c..c05e4e72d 100644 --- a/ILSpy/LoadedPackage.cs +++ b/ILSpy/LoadedPackage.cs @@ -197,7 +197,24 @@ namespace ICSharpCode.ILSpy public override Stream TryOpenStream() { Debug.WriteLine("Open bundle member " + Name); - return new UnmanagedMemoryStream(view.SafeMemoryMappedViewHandle, entry.Offset, entry.Size); + + if (entry.CompressedSize == 0) + { + return new UnmanagedMemoryStream(view.SafeMemoryMappedViewHandle, entry.Offset, entry.Size); + } + else + { + Stream compressedStream = new UnmanagedMemoryStream(view.SafeMemoryMappedViewHandle, entry.Offset, entry.CompressedSize); + using var deflateStream = new DeflateStream(compressedStream, CompressionMode.Decompress); + Stream decompressedStream = new MemoryStream((int)entry.Size); + deflateStream.CopyTo(decompressedStream); + if (decompressedStream.Length != entry.Size) + { + throw new InvalidDataException($"Corrupted single-file entry '${entry.RelativePath}'. Declared decompressed size '${entry.Size}' is not the same as actual decompressed size '${decompressedStream.Length}'."); + } + + return decompressedStream; + } } } }