diff --git a/ILSpy/ILSpy.csproj b/ILSpy/ILSpy.csproj index 3d09cdfe4..66bbb2c0d 100644 --- a/ILSpy/ILSpy.csproj +++ b/ILSpy/ILSpy.csproj @@ -55,6 +55,7 @@ + diff --git a/ILSpy/LoadedAssembly.cs b/ILSpy/LoadedAssembly.cs index 045b3816a..320a7f581 100644 --- a/ILSpy/LoadedAssembly.cs +++ b/ILSpy/LoadedAssembly.cs @@ -17,6 +17,7 @@ // DEALINGS IN THE SOFTWARE. using System; +using System.Buffers; using System.Collections.Generic; using System.Diagnostics; using System.IO; @@ -386,17 +387,28 @@ namespace ICSharpCode.ILSpy var magic = fileReader.ReadUInt32(); if (magic != CompressedDataMagic) throw new InvalidDataException($"Xamarin compressed module header magic {magic} does not match expected {CompressedDataMagic}"); - var descIdx = fileReader.ReadUInt32(); - var uncLen = fileReader.ReadUInt32(); - // fileReader stream position is now at compressed module data - var src = fileReader.ReadBytes((int)fileStream.Length); // Ensure we read all of compressed data - var dst = new byte[(int)uncLen]; - // Decompress - LZ4Codec.Decode(src, 0, src.Length, dst, 0, dst.Length); - // Load module from decompressed data buffer - using (var modData = new MemoryStream(dst, writable: false)) + _ = fileReader.ReadUInt32(); // skip index into descriptor table, unused + int uncompressedLength = (int)fileReader.ReadUInt32(); + int compressedLength = (int)fileStream.Length; // Ensure we read all of compressed data + ArrayPool pool = ArrayPool.Shared; + var src = pool.Rent(compressedLength); + var dst = pool.Rent(uncompressedLength); + try + { + // fileReader stream position is now at compressed module data + fileStream.Read(src, 0, compressedLength); + // Decompress + LZ4Codec.Decode(src, 0, compressedLength, dst, 0, uncompressedLength); + // Load module from decompressed data buffer + using (var uncompressedStream = new MemoryStream(dst, writable: false)) + { + return LoadAssembly(uncompressedStream, PEStreamOptions.PrefetchEntireImage); + } + } + finally { - return LoadAssembly(modData, PEStreamOptions.PrefetchEntireImage); + pool.Return(dst); + pool.Return(src); } } }