Skip to content

Commit

Permalink
Fix mysteriously deleted issue #3197: Skip file formats that currentl…
Browse files Browse the repository at this point in the history
…y can only be loaded from a file when dealing with a file from a bundle or package.
  • Loading branch information
siegfriedpammer committed Jun 2, 2024
1 parent 399ba1c commit 77b237d
Show file tree
Hide file tree
Showing 8 changed files with 69 additions and 18 deletions.
21 changes: 19 additions & 2 deletions ICSharpCode.Decompiler/Metadata/WebCilFile.cs
Original file line number Diff line number Diff line change
Expand Up @@ -47,9 +47,14 @@ private WebCilFile(string fileName, long webcilOffset, long metadataOffset, Memo
this.WasmSections = wasmSections;
}

public static WebCilFile? FromStream(string fileName, MetadataReaderOptions metadataOptions = MetadataReaderOptions.Default)
public static WebCilFile? FromFile(string fileName, MetadataReaderOptions metadataOptions = MetadataReaderOptions.Default)
{
using var memoryMappedFile = MemoryMappedFile.CreateFromFile(fileName, FileMode.Open, null, 0, MemoryMappedFileAccess.Read);
using var memoryMappedFile = TryCreateFromFile(fileName);
if (memoryMappedFile == null)
{
return null;
}

var view = memoryMappedFile.CreateViewAccessor(0, 0, MemoryMappedFileAccess.Read);
try
{
Expand Down Expand Up @@ -124,6 +129,18 @@ private WebCilFile(string fileName, long webcilOffset, long metadataOffset, Memo
{
view?.Dispose();
}

static MemoryMappedFile? TryCreateFromFile(string fileName)
{
try
{
return MemoryMappedFile.CreateFromFile(fileName, FileMode.Open, null, 0, MemoryMappedFileAccess.Read);
}
catch (IOException)
{
return null;
}
}
}

static unsafe bool TryReadWebCilSegment(BinaryReader reader, out WebcilHeader webcilHeader, out long metadataOffset, out long webcilOffset, [NotNullWhen(true)] out SectionHeader[]? sectionHeaders)
Expand Down
7 changes: 6 additions & 1 deletion ICSharpCode.ILSpyX/FileLoaders/ArchiveFileLoader.cs
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,13 @@ namespace ICSharpCode.ILSpyX.FileLoaders
{
public sealed class ArchiveFileLoader : IFileLoader
{
public Task<LoadResult?> Load(string fileName, Stream stream, FileLoadSettings settings)
public Task<LoadResult?> Load(string fileName, Stream stream, FileLoadContext settings)
{
if (settings.ParentBundle != null)
{
return Task.FromResult<LoadResult?>(null);
}

try
{
var zip = LoadedPackage.FromZipFile(fileName);
Expand Down
7 changes: 6 additions & 1 deletion ICSharpCode.ILSpyX/FileLoaders/BundleFileLoader.cs
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,13 @@ namespace ICSharpCode.ILSpyX.FileLoaders
{
public sealed class BundleFileLoader : IFileLoader
{
public Task<LoadResult?> Load(string fileName, Stream stream, FileLoadSettings settings)
public Task<LoadResult?> Load(string fileName, Stream stream, FileLoadContext settings)
{
if (settings.ParentBundle != null)
{
return Task.FromResult<LoadResult?>(null);
}

var bundle = LoadedPackage.FromBundle(fileName);
var result = bundle != null ? new LoadResult { Package = bundle } : null;
return Task.FromResult(result);
Expand Down
6 changes: 4 additions & 2 deletions ICSharpCode.ILSpyX/FileLoaders/LoadResult.cs
Original file line number Diff line number Diff line change
Expand Up @@ -29,12 +29,14 @@ public sealed class LoadResult
public MetadataFile? MetadataFile { get; init; }
public Exception? FileLoadException { get; init; }
public LoadedPackage? Package { get; init; }

public bool IsSuccess => FileLoadException == null;
}

public record FileLoadSettings(bool ApplyWinRTProjections);
public record FileLoadContext(bool ApplyWinRTProjections, LoadedAssembly? ParentBundle);

public interface IFileLoader
{
Task<LoadResult?> Load(string fileName, Stream stream, FileLoadSettings settings);
Task<LoadResult?> Load(string fileName, Stream stream, FileLoadContext context);
}
}
2 changes: 1 addition & 1 deletion ICSharpCode.ILSpyX/FileLoaders/MetadataFileLoader.cs
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ namespace ICSharpCode.ILSpyX.FileLoaders
{
public sealed class MetadataFileLoader : IFileLoader
{
public Task<LoadResult?> Load(string fileName, Stream stream, FileLoadSettings settings)
public Task<LoadResult?> Load(string fileName, Stream stream, FileLoadContext settings)
{
try
{
Expand Down
13 changes: 9 additions & 4 deletions ICSharpCode.ILSpyX/FileLoaders/WebCilFileLoader.cs
Original file line number Diff line number Diff line change
Expand Up @@ -26,13 +26,18 @@ namespace ICSharpCode.ILSpyX.FileLoaders
{
public sealed class WebCilFileLoader : IFileLoader
{
public Task<LoadResult?> Load(string fileName, Stream stream, FileLoadSettings settings)
public Task<LoadResult?> Load(string fileName, Stream stream, FileLoadContext settings)
{
if (settings.ParentBundle != null)
{
return Task.FromResult<LoadResult?>(null);
}

MetadataReaderOptions options = settings.ApplyWinRTProjections
? MetadataReaderOptions.ApplyWindowsRuntimeProjections
: MetadataReaderOptions.None;
? MetadataReaderOptions.ApplyWindowsRuntimeProjections
: MetadataReaderOptions.None;

var wasm = WebCilFile.FromStream(fileName, options);
var wasm = WebCilFile.FromFile(fileName, options);
var result = wasm != null ? new LoadResult { MetadataFile = wasm } : null;
return Task.FromResult(result);
}
Expand Down
4 changes: 2 additions & 2 deletions ICSharpCode.ILSpyX/FileLoaders/XamarinCompressedFileLoader.cs
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ namespace ICSharpCode.ILSpyX.FileLoaders
{
public sealed class XamarinCompressedFileLoader : IFileLoader
{
public async Task<LoadResult?> Load(string fileName, Stream stream, FileLoadSettings settings)
public async Task<LoadResult?> Load(string fileName, Stream stream, FileLoadContext context)
{
const uint CompressedDataMagic = 0x5A4C4158; // Magic used for Xamarin compressed module header ('XALZ', little-endian)
using var fileReader = new BinaryReader(stream, Encoding.UTF8, leaveOpen: true);
Expand All @@ -54,7 +54,7 @@ public sealed class XamarinCompressedFileLoader : IFileLoader
// Load module from decompressed data buffer
using (var uncompressedStream = new MemoryStream(dst, writable: false))
{
MetadataReaderOptions options = settings.ApplyWinRTProjections
MetadataReaderOptions options = context.ApplyWinRTProjections
? MetadataReaderOptions.ApplyWindowsRuntimeProjections
: MetadataReaderOptions.None;

Expand Down
27 changes: 22 additions & 5 deletions ICSharpCode.ILSpyX/LoadedAssembly.cs
Original file line number Diff line number Diff line change
Expand Up @@ -314,24 +314,41 @@ public bool IsLoadedAsValidAssembly {
async Task<LoadResult> LoadAsync(Task<Stream?>? streamTask)
{
using var stream = await PrepareStream();
FileLoadSettings settings = new FileLoadSettings(applyWinRTProjections);
FileLoadContext settings = new FileLoadContext(applyWinRTProjections, ParentBundle);

LoadResult? result = null;

if (fileLoaders != null)
{
foreach (var loader in fileLoaders.RegisteredLoaders)
{
// In each iteration any of the following things may happen:
// Load returns null because the loader is unable to handle the file, we simply continue without recording the result.
// Load returns a non-null value that is either a valid result or an exception:
// - if it's a success, we use that and end the loop,
// - if it's an error, we remember the error, discarding any previous errors.
// Load throws an exception, remember the error, discarding any previous errors.
stream.Position = 0;
result = await loader.Load(fileName, stream, settings).ConfigureAwait(false);
if (result != null)
try
{
break;
var nextResult = await loader.Load(fileName, stream, settings).ConfigureAwait(false);
if (nextResult != null)
{
result = nextResult;
if (result.IsSuccess)
{
break;
}
}
}
catch (Exception ex)
{
result = new LoadResult { FileLoadException = ex };
}
}
}

if (result == null)
if (result?.IsSuccess != true)
{
stream.Position = 0;
try
Expand Down

0 comments on commit 77b237d

Please sign in to comment.