From f173520d0fe6156bf861eb00b36e385b2c3fa117 Mon Sep 17 00:00:00 2001 From: Siegfried Pammer Date: Sun, 8 Nov 2026 09:48:53 +0100 Subject: [PATCH] Bound embedded Portable PDB decompression Embedded Portable PDB metadata declares its decompressed size before the framework and Cecil readers inflate it. Reject oversized declarations before those readers allocate native or managed memory, keeping symbol loading and debug-directory inspection bounded. Assisted-by: OpenCode:gpt-5.6-luna:OpenCode --- ICSharpCode.ILSpyX/Metadata/PdbDumper.cs | 16 ++++++++++++++ .../PdbProvider/DebugInfoUtils.cs | 21 +++++++++++++++++++ ILSpy/Metadata/DebugDirectoryTreeNode.cs | 3 +++ 3 files changed, 40 insertions(+) diff --git a/ICSharpCode.ILSpyX/Metadata/PdbDumper.cs b/ICSharpCode.ILSpyX/Metadata/PdbDumper.cs index e0a94a8b401..9a7b675fb44 100644 --- a/ICSharpCode.ILSpyX/Metadata/PdbDumper.cs +++ b/ICSharpCode.ILSpyX/Metadata/PdbDumper.cs @@ -20,6 +20,7 @@ using System.Collections.Generic; using System.Globalization; using System.IO; +using System.Reflection.PortableExecutable; using System.Linq; using System.Text; using System.Text.Json; @@ -116,6 +117,13 @@ internal static ReaderParameters CreateReaderParameters(string? pdbFileName) static ModuleDefinition ReadModuleWithSymbols(string assemblyFileName, string? pdbFileName) { + using (var stream = File.OpenRead(assemblyFileName)) + using (var reader = new PEReader(stream)) + { + if (reader.ReadDebugDirectory().Any(e => e.Type == DebugDirectoryEntryType.EmbeddedPortablePdb + && DebugInfoUtils.IsEmbeddedPortablePdbTooLarge(reader, e))) + throw new NoDebugSymbolsException($"Embedded Portable PDB is too large for '{assemblyFileName}'."); + } var parameters = CreateReaderParameters(pdbFileName); ModuleDefinition module; try @@ -137,6 +145,14 @@ static ModuleDefinition ReadModuleWithSymbols(string assemblyFileName, string? p static ModuleDefinition ReadModuleWithSymbols(Stream assemblyStream, string assemblyName, string? pdbFileName) { + long position = assemblyStream.Position; + using (var reader = new PEReader(assemblyStream, PEStreamOptions.LeaveOpen)) + { + if (reader.ReadDebugDirectory().Any(e => e.Type == DebugDirectoryEntryType.EmbeddedPortablePdb + && DebugInfoUtils.IsEmbeddedPortablePdbTooLarge(reader, e))) + throw new NoDebugSymbolsException($"Embedded Portable PDB is too large for '{assemblyName}'."); + } + assemblyStream.Position = position; var parameters = new ReaderParameters { ReadSymbols = true, InMemory = true }; ApplyExplicitSymbolFile(parameters, pdbFileName); ModuleDefinition module; diff --git a/ICSharpCode.ILSpyX/PdbProvider/DebugInfoUtils.cs b/ICSharpCode.ILSpyX/PdbProvider/DebugInfoUtils.cs index 5605a941b82..a125343dbfb 100644 --- a/ICSharpCode.ILSpyX/PdbProvider/DebugInfoUtils.cs +++ b/ICSharpCode.ILSpyX/PdbProvider/DebugInfoUtils.cs @@ -17,6 +17,7 @@ // DEALINGS IN THE SOFTWARE. using System; +using System.Buffers.Binary; using System.Diagnostics.CodeAnalysis; using System.IO; using System.Reflection.Metadata; @@ -32,6 +33,23 @@ namespace ICSharpCode.ILSpyX.PdbProvider { public static class DebugInfoUtils { + internal const int MaxEmbeddedPortablePdbSize = 128 * 1024 * 1024; + + public static bool IsEmbeddedPortablePdbTooLarge(PEReader reader, DebugDirectoryEntry entry) + { + if (entry.DataSize < 8) + return false; + try + { + int offset = reader.IsLoadedImage ? entry.DataRelativeVirtualAddress : entry.DataPointer; + var data = reader.GetEntireImage().GetContent(offset, 8); + return BinaryPrimitives.ReadUInt32LittleEndian(data.AsSpan().Slice(4, 4)) > MaxEmbeddedPortablePdbSize; + } + catch (ArgumentOutOfRangeException) + { + return false; + } + } public static IDebugInfoProvider? LoadSymbols(PEFile module) { try @@ -131,6 +149,9 @@ static bool TryOpenPortablePdb(PEFile module, { if (entry.IsPortableCodeView) { + if (entry.Type == DebugDirectoryEntryType.EmbeddedPortablePdb + && IsEmbeddedPortablePdbTooLarge(reader, entry)) + return false; return reader.TryOpenAssociatedPortablePdb(module.FileName, OpenStream, out provider, out pdbFileName); } diff --git a/ILSpy/Metadata/DebugDirectoryTreeNode.cs b/ILSpy/Metadata/DebugDirectoryTreeNode.cs index 3e802b3303c..396b5117945 100644 --- a/ILSpy/Metadata/DebugDirectoryTreeNode.cs +++ b/ILSpy/Metadata/DebugDirectoryTreeNode.cs @@ -22,6 +22,7 @@ using System.Reflection.PortableExecutable; using ICSharpCode.Decompiler.Metadata; +using ICSharpCode.ILSpyX.PdbProvider; using ICSharpCode.ILSpy.TreeNodes; using ICSharpCode.ILSpy.ViewModels; @@ -104,6 +105,8 @@ protected override void LoadChildren() case DebugDirectoryEntryType.EmbeddedPortablePdb: try { + if (DebugInfoUtils.IsEmbeddedPortablePdbTooLarge(module.Reader, entry)) + break; var provider = module.Reader.ReadEmbeddedPortablePdbDebugDirectoryData(entry); var pdbMetadata = new MetadataFile( MetadataFile.MetadataFileKind.ProgramDebugDatabase,